Coverage Report

Created: 2026-10-31 06:21

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(__VXWORKS__)
315
#  include <vxCpuLib.h>
316
#  include <rtpLib.h>
317
#  include <wait.h>
318
#  include <taskLib.h>
319
#  ifndef _P_WAIT
320
#    define _P_WAIT          0
321
#    define _P_NOWAIT        1
322
#    define _P_NOWAITO       1
323
#  endif
324
#endif /* __VXWORKS__ */
325
326
327
#ifdef HAVE_DIRENT_H
328
#  include <dirent.h>             // opendir()
329
301k
#  define NAMLEN(dirent) strlen((dirent)->d_name)
330
#else
331
#  if defined(__WATCOMC__) && !defined(__QNX__)
332
#    include <direct.h>
333
#    define NAMLEN(dirent) strlen((dirent)->d_name)
334
#  else
335
#    define dirent direct
336
#    define NAMLEN(dirent) (dirent)->d_namlen
337
#  endif
338
#  ifdef HAVE_SYS_NDIR_H
339
#    include <sys/ndir.h>
340
#  endif
341
#  ifdef HAVE_SYS_DIR_H
342
#    include <sys/dir.h>
343
#  endif
344
#  ifdef HAVE_NDIR_H
345
#    include <ndir.h>
346
#  endif
347
#endif
348
349
350
#if defined(MAJOR_IN_MKDEV)
351
#  include <sys/mkdev.h>
352
#else
353
#  if defined(MAJOR_IN_SYSMACROS)
354
#    include <sys/sysmacros.h>
355
#  endif
356
#  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
357
#    include <sys/mkdev.h>
358
#  endif
359
#endif
360
361
362
// --- Macros ---------------------------------------------------------------
363
364
#ifndef MAXPATHLEN
365
#  if defined(PATH_MAX) && PATH_MAX > 1024
366
#    define MAXPATHLEN PATH_MAX
367
#  else
368
#    define MAXPATHLEN 1024
369
#  endif
370
#endif /* MAXPATHLEN */
371
372
373
#ifdef UNION_WAIT
374
   /* Emulate some macros on systems that have a union instead of macros */
375
#  ifndef WIFEXITED
376
#    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
377
#  endif
378
#  ifndef WEXITSTATUS
379
#    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
380
#  endif
381
#  ifndef WTERMSIG
382
#    define WTERMSIG(u_wait) ((u_wait).w_termsig)
383
#  endif
384
#  define WAIT_TYPE union wait
385
#  define WAIT_STATUS_INT(s) (s.w_status)
386
#else
387
   /* !UNION_WAIT */
388
0
#  define WAIT_TYPE int
389
0
#  define WAIT_STATUS_INT(s) (s)
390
#endif /* UNION_WAIT */
391
392
393
/* Don't use the "_r" form if we don't need it (also, won't have a
394
   prototype for it, at least on Solaris -- maybe others as well?). */
395
#if defined(HAVE_CTERMID_R)
396
#  define USE_CTERMID_R
397
#endif
398
399
400
/* choose the appropriate stat and fstat functions and return structs */
401
#undef STAT
402
#undef FSTAT
403
#undef STRUCT_STAT
404
#ifdef MS_WINDOWS
405
#  define STAT win32_stat
406
#  define LSTAT win32_lstat
407
#  define FSTAT _Py_fstat_noraise
408
#  define STRUCT_STAT struct _Py_stat_struct
409
#else
410
223k
#  define STAT stat
411
9.60k
#  define LSTAT lstat
412
88.4k
#  define FSTAT fstat
413
405k
#  define STRUCT_STAT struct stat
414
#endif
415
416
#ifdef HAVE_STATX
417
/* until we can assume glibc 2.28 at runtime, we must weakly link */
418
#  pragma weak statx
419
static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
420
#ifdef STATX_MNT_ID
421
                                             | STATX_MNT_ID
422
#endif
423
#ifdef STATX_DIOALIGN
424
                                             | STATX_DIOALIGN
425
#endif
426
#ifdef STATX_MNT_ID_UNIQUE
427
                                             | STATX_MNT_ID_UNIQUE
428
#endif
429
#ifdef STATX_SUBVOL
430
                                             | STATX_SUBVOL
431
#endif
432
#ifdef STATX_WRITE_ATOMIC
433
                                             | STATX_WRITE_ATOMIC
434
#endif
435
#ifdef STATX_DIO_READ_ALIGN
436
                                             | STATX_DIO_READ_ALIGN
437
#endif
438
                                            );
439
#endif /* HAVE_STATX */
440
441
442
#if !defined(EX_OK) && defined(EXIT_SUCCESS)
443
#  define EX_OK EXIT_SUCCESS
444
#endif
445
446
#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
447
#  undef HAVE_SCHED_SETAFFINITY
448
#endif
449
450
/* On android API level 21, 'AT_EACCESS' is not declared although
451
 * HAVE_FACCESSAT is defined. */
452
#ifdef __ANDROID__
453
#  undef HAVE_FACCESSAT
454
#endif
455
456
#if defined(__sun)
457
/* Something to implement in autoconf, not present in autoconf 2.69 */
458
#  define HAVE_STRUCT_STAT_ST_FSTYPE 1
459
#endif
460
461
462
// --- Apple __builtin_available() macros -----------------------------------
463
464
/*
465
 * A number of APIs are available on macOS from a certain macOS version.
466
 * To support building with a new SDK while deploying to older versions
467
 * the availability test is split into two:
468
 *   - HAVE_<FUNCTION>:  The configure check for compile time availability
469
 *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
470
 *
471
 * The latter is always true when not on macOS, or when using a compiler
472
 * that does not support __has_builtin (older versions of Xcode).
473
 *
474
 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
475
 *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
476
 *
477
 * In mixing the test with other tests or using negations will result in compile
478
 * errors.
479
 */
480
#if defined(__APPLE__)
481
482
#include <mach/mach.h>
483
484
#if defined(__has_builtin)
485
#if __has_builtin(__builtin_available)
486
#define HAVE_BUILTIN_AVAILABLE 1
487
#endif
488
#endif
489
490
#ifdef HAVE_BUILTIN_AVAILABLE
491
#  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
492
#  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
493
#  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
494
#  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
495
#  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
496
#  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
497
#  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
498
#  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
499
#  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
500
#  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
501
#  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
502
#  define HAVE_FREADLINK_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, *)
503
#  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
504
#  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
505
#  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
506
#  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
507
#  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
508
#  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
509
#  define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
510
#  define HAVE_DUP3_RUNTIME __builtin_available(macOS 27.0, iOS 27.0, tvOS 27.0, watchOS 27.0, visionOS 27.0, *)
511
#  define HAVE_PIPE2_RUNTIME __builtin_available(macOS 27.0, iOS 27.0, tvOS 27.0, watchOS 27.0, visionOS 27.0, *)
512
513
#  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
514
515
#else /* Xcode 8 or earlier */
516
517
   /* __builtin_available is not present in these compilers, but
518
    * some of the symbols might be weak linked (10.10 SDK or later
519
    * deploying on 10.9.
520
    *
521
    * Fall back to the older style of availability checking for
522
    * symbols introduced in macOS 10.10.
523
    */
524
525
#  ifdef HAVE_FSTATAT
526
#    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
527
#  endif
528
529
#  ifdef HAVE_FACCESSAT
530
#    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
531
#  endif
532
533
#  ifdef HAVE_FCHMODAT
534
#    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
535
#  endif
536
537
#  ifdef HAVE_FCHOWNAT
538
#    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
539
#  endif
540
541
#  ifdef HAVE_LINKAT
542
#    define HAVE_LINKAT_RUNTIME (linkat != NULL)
543
#  endif
544
545
#  ifdef HAVE_FDOPENDIR
546
#    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
547
#  endif
548
549
#  ifdef HAVE_MKDIRAT
550
#    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
551
#  endif
552
553
#  ifdef HAVE_RENAMEAT
554
#    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
555
#  endif
556
557
#  ifdef HAVE_UNLINKAT
558
#    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
559
#  endif
560
561
#  ifdef HAVE_OPENAT
562
#    define HAVE_OPENAT_RUNTIME (openat != NULL)
563
#  endif
564
565
#  ifdef HAVE_READLINKAT
566
#    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
567
#  endif
568
569
#  ifdef _Py_HAVE_FREADLINK
570
#    define HAVE_FREADLINK_RUNTIME (freadlink != NULL)
571
#  endif
572
573
#  ifdef HAVE_SYMLINKAT
574
#    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
575
#  endif
576
577
#  ifdef HAVE_UTIMENSAT
578
#    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
579
#  endif
580
581
#  ifdef HAVE_FUTIMENS
582
#    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
583
#  endif
584
585
#  ifdef HAVE_PWRITEV
586
#    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
587
#  endif
588
589
#  ifdef HAVE_MKFIFOAT
590
#    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
591
#  endif
592
593
#  ifdef HAVE_MKNODAT
594
#    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
595
#  endif
596
597
#  ifdef HAVE_PTSNAME_R
598
#    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
599
#  endif
600
601
#  ifdef HAVE_DUP3
602
#    define HAVE_DUP3_RUNTIME (dup3 != NULL)
603
#  endif
604
605
#  ifdef HAVE_PIPE2
606
#    define HAVE_PIPE2_RUNTIME (pipe2 != NULL)
607
#  endif
608
609
#endif
610
611
#ifdef HAVE_FUTIMESAT
612
/* Some of the logic for weak linking depends on this assertion */
613
# error "HAVE_FUTIMESAT unexpectedly defined"
614
#endif
615
616
#else
617
84.3k
#  define HAVE_FSTATAT_RUNTIME 1
618
0
#  define HAVE_FACCESSAT_RUNTIME 1
619
0
#  define HAVE_FCHMODAT_RUNTIME 1
620
0
#  define HAVE_FCHOWNAT_RUNTIME 1
621
#ifdef __wasi__
622
#  define HAVE_LINKAT_RUNTIME 0
623
# else
624
0
#  define HAVE_LINKAT_RUNTIME 1
625
# endif
626
88.4k
#  define HAVE_FDOPENDIR_RUNTIME 1
627
0
#  define HAVE_MKDIRAT_RUNTIME 1
628
0
#  define HAVE_RENAMEAT_RUNTIME 1
629
101k
#  define HAVE_UNLINKAT_RUNTIME 1
630
84.3k
#  define HAVE_OPENAT_RUNTIME 1
631
0
#  define HAVE_READLINKAT_RUNTIME 1
632
0
#  define HAVE_SYMLINKAT_RUNTIME 1
633
0
#  define HAVE_FUTIMENS_RUNTIME 1
634
0
#  define HAVE_UTIMENSAT_RUNTIME 1
635
37
#  define HAVE_PWRITEV_RUNTIME 1
636
0
#  define HAVE_MKFIFOAT_RUNTIME 1
637
0
#  define HAVE_MKNODAT_RUNTIME 1
638
0
#  define HAVE_PTSNAME_R_RUNTIME 1
639
0
#  define HAVE_DUP3_RUNTIME 1
640
37
#  define HAVE_PIPE2_RUNTIME 1
641
#  define HAVE_FREADLINK_RUNTIME 1
642
#endif
643
644
645
// --- os module ------------------------------------------------------------
646
647
#ifdef MS_WINDOWS
648
#  define INITFUNC PyInit_nt
649
#  define MODNAME "nt"
650
#  define MODNAME_OBJ &_Py_ID(nt)
651
#else
652
#  define INITFUNC PyInit_posix
653
#  define MODNAME "posix"
654
0
#  define MODNAME_OBJ &_Py_ID(posix)
655
#endif
656
657
/*[clinic input]
658
# one of the few times we lie about this name!
659
module os
660
[clinic start generated code]*/
661
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
662
663
PyDoc_STRVAR(posix__doc__,
664
"This module provides access to operating system functionality that is\n\
665
standardized by the C Standard and the POSIX standard (a thinly\n\
666
disguised Unix interface).  Refer to the library manual and\n\
667
corresponding Unix manual entries for more information on calls.");
668
669
670
// --- Functions ------------------------------------------------------------
671
672
#ifdef HAVE_FORK
673
static void
674
run_at_forkers(PyObject *lst, int reverse)
675
0
{
676
0
    Py_ssize_t i;
677
0
    PyObject *cpy;
678
679
0
    if (lst != NULL) {
680
0
        assert(PyList_CheckExact(lst));
681
682
        /* Use a list copy in case register_at_fork() is called from
683
         * one of the callbacks.
684
         */
685
0
        cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
686
0
        if (cpy == NULL) {
687
0
            PyErr_FormatUnraisable("Exception ignored in atfork callback "
688
0
                                   "while copying list %R", lst);
689
0
        }
690
0
        else {
691
0
            if (reverse)
692
0
                PyList_Reverse(cpy);
693
0
            for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
694
0
                PyObject *func, *res;
695
0
                func = PyList_GET_ITEM(cpy, i);
696
0
                res = _PyObject_CallNoArgs(func);
697
0
                if (res == NULL) {
698
0
                    PyErr_FormatUnraisable("Exception ignored "
699
0
                                           "in atfork callback %R", func);
700
0
                }
701
0
                else {
702
0
                    Py_DECREF(res);
703
0
                }
704
0
            }
705
0
            Py_DECREF(cpy);
706
0
        }
707
0
    }
708
0
}
709
710
void
711
PyOS_BeforeFork(void)
712
0
{
713
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
714
0
    run_at_forkers(interp->before_forkers, 1);
715
716
0
    _PyImport_AcquireLock(interp);
717
0
    _PyEval_StopTheWorldAll(&_PyRuntime);
718
0
    HEAD_LOCK(&_PyRuntime);
719
0
    _PyWarnings_BeforeFork(interp);
720
0
}
721
722
void
723
PyOS_AfterFork_Parent(void)
724
0
{
725
0
    HEAD_UNLOCK(&_PyRuntime);
726
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
727
728
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
729
0
    _PyImport_ReleaseLock(interp);
730
0
    run_at_forkers(interp->after_forkers_parent, 0);
731
0
}
732
733
static void
734
reset_remotedebug_data(PyThreadState *tstate)
735
0
{
736
0
    tstate->remote_debugger_support.debugger_pending_call = 0;
737
0
    memset(tstate->remote_debugger_support.debugger_script_path, 0,
738
0
           _Py_MAX_SCRIPT_PATH_SIZE);
739
0
}
740
741
static void
742
reset_asyncio_state(_PyThreadStateImpl *tstate)
743
0
{
744
0
    llist_init(&tstate->asyncio_tasks_head);
745
0
    tstate->asyncio_running_loop = NULL;
746
0
    tstate->asyncio_running_task = NULL;
747
0
}
748
749
750
void
751
PyOS_AfterFork_Child(void)
752
0
{
753
0
    PyStatus status;
754
0
    _PyRuntimeState *runtime = &_PyRuntime;
755
756
    // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
757
0
    status = _PyRuntimeState_ReInitThreads(runtime);
758
0
    if (_PyStatus_EXCEPTION(status)) {
759
0
        goto fatal_error;
760
0
    }
761
762
0
    PyThreadState *tstate = _PyThreadState_GET();
763
0
    _Py_EnsureTstateNotNULL(tstate);
764
765
0
    assert(tstate->thread_id == PyThread_get_thread_ident());
766
0
#ifdef PY_HAVE_THREAD_NATIVE_ID
767
0
    tstate->native_thread_id = PyThread_get_thread_native_id();
768
0
#endif
769
770
#ifdef Py_GIL_DISABLED
771
    _Py_brc_after_fork(tstate->interp);
772
    _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
773
#endif
774
775
    // Ideally we could guarantee tstate is running main.
776
0
    _PyInterpreterState_ReinitRunningMain(tstate);
777
778
0
    status = _PyEval_ReInitThreads(tstate);
779
0
    if (_PyStatus_EXCEPTION(status)) {
780
0
        goto fatal_error;
781
0
    }
782
783
#if defined(PY_HAVE_JIT_GDB_UNWIND)
784
    // The child can inherit this mutex locked if another thread held it at
785
    // fork(), but the child itself cannot be inside gdb_jit_register_code().
786
    // Reinitialize it before any executor cleanup can unregister JIT code.
787
    _Py_jit_debug_mutex = (PyMutex){0};
788
#endif
789
790
    // Thread-state cleanup can run finalizers that issue warnings.
791
0
    _PyWarnings_AfterFork(tstate->interp);
792
793
0
    reset_remotedebug_data(tstate);
794
795
0
    reset_asyncio_state((_PyThreadStateImpl *)tstate);
796
797
    // Remove the dead thread states. We "start the world" once we are the only
798
    // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
799
    // That needs to happen before `_PyThreadState_DeleteList`, because that
800
    // may call destructors.
801
0
    PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
802
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
803
0
    _PyThreadState_DeleteList(list, /*is_after_fork=*/1);
804
805
0
    _PyImport_ReInitLock(tstate->interp);
806
0
    _PyImport_ReleaseLock(tstate->interp);
807
808
0
    _PySignal_AfterFork();
809
810
0
    status = _PyInterpreterState_DeleteExceptMain(runtime);
811
0
    if (_PyStatus_EXCEPTION(status)) {
812
0
        goto fatal_error;
813
0
    }
814
0
    assert(_PyThreadState_GET() == tstate);
815
816
0
    status = _PyPerfTrampoline_AfterFork_Child();
817
0
    if (_PyStatus_EXCEPTION(status)) {
818
0
        goto fatal_error;
819
0
    }
820
821
0
    run_at_forkers(tstate->interp->after_forkers_child, 0);
822
0
    return;
823
824
0
fatal_error:
825
0
    Py_ExitStatusException(status);
826
0
}
827
828
static int
829
register_at_forker(PyObject **lst, PyObject *func)
830
60
{
831
60
    if (func == NULL)  /* nothing to register? do nothing. */
832
40
        return 0;
833
20
    if (*lst == NULL) {
834
10
        *lst = PyList_New(0);
835
10
        if (*lst == NULL)
836
0
            return -1;
837
10
    }
838
20
    return PyList_Append(*lst, func);
839
20
}
840
#endif  /* HAVE_FORK */
841
842
843
/* Legacy wrapper */
844
void
845
PyOS_AfterFork(void)
846
0
{
847
0
#ifdef HAVE_FORK
848
0
    PyOS_AfterFork_Child();
849
0
#endif
850
0
}
851
852
853
#ifdef MS_WINDOWS
854
/* defined in fileutils.c */
855
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
856
void _Py_attribute_data_to_stat(FILE_STANDARD_INFO*, ULONG,
857
                                FILE_BASIC_INFO*, FILE_ID_INFO*,
858
                                struct _Py_stat_struct*);
859
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
860
                                 struct _Py_stat_struct *);
861
#endif
862
863
864
#ifndef MS_WINDOWS
865
PyObject *
866
_PyLong_FromUid(uid_t uid)
867
233k
{
868
233k
    if (uid == (uid_t)-1)
869
0
        return PyLong_FromLong(-1);
870
233k
    return PyLong_FromUnsignedLong(uid);
871
233k
}
872
873
PyObject *
874
_PyLong_FromGid(gid_t gid)
875
233k
{
876
233k
    if (gid == (gid_t)-1)
877
0
        return PyLong_FromLong(-1);
878
233k
    return PyLong_FromUnsignedLong(gid);
879
233k
}
880
881
int
882
_Py_Uid_Converter(PyObject *obj, uid_t *p)
883
0
{
884
0
    uid_t uid;
885
0
    PyObject *index;
886
0
    int overflow;
887
0
    long result;
888
0
    unsigned long uresult;
889
890
0
    index = _PyNumber_Index(obj);
891
0
    if (index == NULL) {
892
0
        PyErr_Format(PyExc_TypeError,
893
0
                     "uid should be integer, not %.200s",
894
0
                     _PyType_Name(Py_TYPE(obj)));
895
0
        return 0;
896
0
    }
897
898
    /*
899
     * Handling uid_t is complicated for two reasons:
900
     *  * Although uid_t is (always?) unsigned, it still
901
     *    accepts -1.
902
     *  * We don't know its size in advance--it may be
903
     *    bigger than an int, or it may be smaller than
904
     *    a long.
905
     *
906
     * So a bit of defensive programming is in order.
907
     * Start with interpreting the value passed
908
     * in as a signed long and see if it works.
909
     */
910
911
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
912
913
0
    if (!overflow) {
914
0
        uid = (uid_t)result;
915
916
0
        if (result == -1) {
917
0
            if (PyErr_Occurred())
918
0
                goto fail;
919
            /* It's a legitimate -1, we're done. */
920
0
            goto success;
921
0
        }
922
923
        /* Any other negative number is disallowed. */
924
0
        if (result < 0)
925
0
            goto underflow;
926
927
        /* Ensure the value wasn't truncated. */
928
0
        if (sizeof(uid_t) < sizeof(long) &&
929
0
            (long)uid != result)
930
0
            goto underflow;
931
0
        goto success;
932
0
    }
933
934
0
    if (overflow < 0)
935
0
        goto underflow;
936
937
    /*
938
     * Okay, the value overflowed a signed long.  If it
939
     * fits in an *unsigned* long, it may still be okay,
940
     * as uid_t may be unsigned long on this platform.
941
     */
942
0
    uresult = PyLong_AsUnsignedLong(index);
943
0
    if (PyErr_Occurred()) {
944
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
945
0
            goto overflow;
946
0
        goto fail;
947
0
    }
948
949
0
    uid = (uid_t)uresult;
950
951
    /*
952
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
953
     * but this value would get interpreted as (uid_t)-1  by chown
954
     * and its siblings.   That's not what the user meant!  So we
955
     * throw an overflow exception instead.   (We already
956
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
957
     */
958
0
    if (uid == (uid_t)-1)
959
0
        goto overflow;
960
961
    /* Ensure the value wasn't truncated. */
962
0
    if (sizeof(uid_t) < sizeof(long) &&
963
0
        (unsigned long)uid != uresult)
964
0
        goto overflow;
965
    /* fallthrough */
966
967
0
success:
968
0
    Py_DECREF(index);
969
0
    *p = uid;
970
0
    return 1;
971
972
0
underflow:
973
0
    PyErr_SetString(PyExc_OverflowError,
974
0
                    "uid is less than minimum");
975
0
    goto fail;
976
977
0
overflow:
978
0
    PyErr_SetString(PyExc_OverflowError,
979
0
                    "uid is greater than maximum");
980
    /* fallthrough */
981
982
0
fail:
983
0
    Py_DECREF(index);
984
0
    return 0;
985
0
}
986
987
int
988
_Py_Gid_Converter(PyObject *obj, gid_t *p)
989
0
{
990
0
    gid_t gid;
991
0
    PyObject *index;
992
0
    int overflow;
993
0
    long result;
994
0
    unsigned long uresult;
995
996
0
    index = _PyNumber_Index(obj);
997
0
    if (index == NULL) {
998
0
        PyErr_Format(PyExc_TypeError,
999
0
                     "gid should be integer, not %.200s",
1000
0
                     _PyType_Name(Py_TYPE(obj)));
1001
0
        return 0;
1002
0
    }
1003
1004
    /*
1005
     * Handling gid_t is complicated for two reasons:
1006
     *  * Although gid_t is (always?) unsigned, it still
1007
     *    accepts -1.
1008
     *  * We don't know its size in advance--it may be
1009
     *    bigger than an int, or it may be smaller than
1010
     *    a long.
1011
     *
1012
     * So a bit of defensive programming is in order.
1013
     * Start with interpreting the value passed
1014
     * in as a signed long and see if it works.
1015
     */
1016
1017
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
1018
1019
0
    if (!overflow) {
1020
0
        gid = (gid_t)result;
1021
1022
0
        if (result == -1) {
1023
0
            if (PyErr_Occurred())
1024
0
                goto fail;
1025
            /* It's a legitimate -1, we're done. */
1026
0
            goto success;
1027
0
        }
1028
1029
        /* Any other negative number is disallowed. */
1030
0
        if (result < 0) {
1031
0
            goto underflow;
1032
0
        }
1033
1034
        /* Ensure the value wasn't truncated. */
1035
0
        if (sizeof(gid_t) < sizeof(long) &&
1036
0
            (long)gid != result)
1037
0
            goto underflow;
1038
0
        goto success;
1039
0
    }
1040
1041
0
    if (overflow < 0)
1042
0
        goto underflow;
1043
1044
    /*
1045
     * Okay, the value overflowed a signed long.  If it
1046
     * fits in an *unsigned* long, it may still be okay,
1047
     * as gid_t may be unsigned long on this platform.
1048
     */
1049
0
    uresult = PyLong_AsUnsignedLong(index);
1050
0
    if (PyErr_Occurred()) {
1051
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1052
0
            goto overflow;
1053
0
        goto fail;
1054
0
    }
1055
1056
0
    gid = (gid_t)uresult;
1057
1058
    /*
1059
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
1060
     * but this value would get interpreted as (gid_t)-1  by chown
1061
     * and its siblings.   That's not what the user meant!  So we
1062
     * throw an overflow exception instead.   (We already
1063
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
1064
     */
1065
0
    if (gid == (gid_t)-1)
1066
0
        goto overflow;
1067
1068
    /* Ensure the value wasn't truncated. */
1069
0
    if (sizeof(gid_t) < sizeof(long) &&
1070
0
        (unsigned long)gid != uresult)
1071
0
        goto overflow;
1072
    /* fallthrough */
1073
1074
0
success:
1075
0
    Py_DECREF(index);
1076
0
    *p = gid;
1077
0
    return 1;
1078
1079
0
underflow:
1080
0
    PyErr_SetString(PyExc_OverflowError,
1081
0
                    "gid is less than minimum");
1082
0
    goto fail;
1083
1084
0
overflow:
1085
0
    PyErr_SetString(PyExc_OverflowError,
1086
0
                    "gid is greater than maximum");
1087
    /* fallthrough */
1088
1089
0
fail:
1090
0
    Py_DECREF(index);
1091
0
    return 0;
1092
0
}
1093
#endif /* MS_WINDOWS */
1094
1095
1096
static PyObject *
1097
_PyLong_FromDev(dev_t dev)
1098
466k
{
1099
466k
#ifdef NODEV
1100
466k
    if (dev == NODEV) {
1101
37
        return PyLong_FromLongLong((long long)dev);
1102
37
    }
1103
466k
#endif
1104
466k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1105
466k
}
1106
1107
1108
#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
1109
static int
1110
_Py_Dev_Converter(PyObject *obj, void *p)
1111
0
{
1112
0
    if (!PyLong_Check(obj)) {
1113
0
        obj = _PyNumber_Index(obj);
1114
0
        if (obj == NULL) {
1115
0
            return 0;
1116
0
        }
1117
0
    }
1118
0
    else {
1119
0
        Py_INCREF(obj);
1120
0
    }
1121
0
    assert(PyLong_Check(obj));
1122
0
#ifdef NODEV
1123
0
    if (_PyLong_IsNegative((PyLongObject *)obj)) {
1124
0
        int overflow;
1125
0
        long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
1126
0
        if (result == -1 && PyErr_Occurred()) {
1127
0
            Py_DECREF(obj);
1128
0
            return 0;
1129
0
        }
1130
0
        if (!overflow && result == (long long)NODEV) {
1131
0
            *((dev_t *)p) = NODEV;
1132
0
            Py_DECREF(obj);
1133
0
            return 1;
1134
0
        }
1135
0
    }
1136
0
#endif
1137
1138
0
    unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1139
0
    Py_DECREF(obj);
1140
0
    if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1141
0
        return 0;
1142
0
    }
1143
0
    if ((unsigned long long)(dev_t)result != result) {
1144
0
        PyErr_SetString(PyExc_OverflowError,
1145
0
                        "Python int too large to convert to C dev_t");
1146
0
        return 0;
1147
0
    }
1148
0
    *((dev_t *)p) = (dev_t)result;
1149
0
    return 1;
1150
0
}
1151
#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1152
1153
1154
#ifdef AT_FDCWD
1155
/*
1156
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1157
 * without the int cast, the value gets interpreted as uint (4291925331),
1158
 * which doesn't play nicely with all the initializer lines in this file that
1159
 * look like this:
1160
 *      int dir_fd = DEFAULT_DIR_FD;
1161
 */
1162
1.79M
#define DEFAULT_DIR_FD (int)AT_FDCWD
1163
#else
1164
#define DEFAULT_DIR_FD (-100)
1165
#endif
1166
1167
static int
1168
_fd_converter(PyObject *o, int *p)
1169
274k
{
1170
274k
    int overflow;
1171
274k
    long long_value;
1172
1173
274k
    if (PyBool_Check(o)) {
1174
0
        if (PyErr_WarnEx(PyExc_RuntimeWarning,
1175
0
                "bool is used as a file descriptor", 1))
1176
0
        {
1177
0
            return 0;
1178
0
        }
1179
0
    }
1180
274k
    PyObject *index = _PyNumber_Index(o);
1181
274k
    if (index == NULL) {
1182
0
        return 0;
1183
0
    }
1184
1185
274k
    assert(PyLong_Check(index));
1186
274k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1187
274k
    Py_DECREF(index);
1188
274k
    assert(!PyErr_Occurred());
1189
274k
    if (overflow > 0 || long_value > INT_MAX) {
1190
0
        PyErr_SetString(PyExc_OverflowError,
1191
0
                        "fd is greater than maximum");
1192
0
        return 0;
1193
0
    }
1194
274k
    if (overflow < 0 || long_value < INT_MIN) {
1195
0
        PyErr_SetString(PyExc_OverflowError,
1196
0
                        "fd is less than minimum");
1197
0
        return 0;
1198
0
    }
1199
1200
274k
    *p = (int)long_value;
1201
274k
    return 1;
1202
274k
}
1203
1204
static int
1205
dir_fd_converter(PyObject *o, void *p)
1206
202k
{
1207
202k
    if (o == Py_None) {
1208
16.4k
        *(int *)p = DEFAULT_DIR_FD;
1209
16.4k
        return 1;
1210
16.4k
    }
1211
185k
    else if (PyIndex_Check(o)) {
1212
185k
        return _fd_converter(o, (int *)p);
1213
185k
    }
1214
0
    else {
1215
0
        PyErr_Format(PyExc_TypeError,
1216
0
                     "argument should be integer or None, not %.200s",
1217
0
                     _PyType_Name(Py_TYPE(o)));
1218
0
        return 0;
1219
0
    }
1220
202k
}
1221
1222
typedef struct {
1223
    PyObject *billion;
1224
    PyObject *DirEntryType;
1225
    PyObject *ScandirIteratorType;
1226
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1227
    PyObject *SchedParamType;
1228
#endif
1229
    newfunc statresult_new_orig;
1230
    PyObject *StatResultType;
1231
#ifdef HAVE_STATX
1232
    PyObject *StatxResultType;
1233
#endif
1234
    PyObject *StatVFSResultType;
1235
    PyObject *TerminalSizeType;
1236
    PyObject *TimesResultType;
1237
    PyObject *UnameResultType;
1238
#if defined(HAVE_WAITID)
1239
    PyObject *WaitidResultType;
1240
#endif
1241
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1242
    PyObject *struct_rusage;
1243
#endif
1244
    PyObject *st_mode;
1245
#ifndef MS_WINDOWS
1246
    // times() clock frequency in hertz; used by os.times()
1247
    long ticks_per_second;
1248
#endif
1249
} _posixstate;
1250
1251
1252
static inline _posixstate*
1253
get_posix_state(PyObject *module)
1254
424k
{
1255
424k
    void *state = _PyModule_GetState(module);
1256
424k
    assert(state != NULL);
1257
424k
    return (_posixstate *)state;
1258
424k
}
1259
1260
/*
1261
 * A PyArg_ParseTuple "converter" function
1262
 * that handles filesystem paths in the manner
1263
 * preferred by the os module.
1264
 *
1265
 * path_converter accepts (Unicode) strings and their
1266
 * subclasses, and bytes and their subclasses.  What
1267
 * it does with the argument depends on path.make_wide:
1268
 *
1269
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1270
 *     string we extract the wchar_t * and return it; if we
1271
 *     get bytes we decode to wchar_t * and return that.
1272
 *
1273
 *   * If path.make_wide is zero, if we get bytes we extract
1274
 *     the char_t * and return it; if we get a (Unicode)
1275
 *     string we encode to char_t * and return that.
1276
 *
1277
 * path_converter also optionally accepts signed
1278
 * integers (representing open file descriptors) instead
1279
 * of path strings.
1280
 *
1281
 * Input fields:
1282
 *   path.nullable
1283
 *     If nonzero, the path is permitted to be None.
1284
 *   path.nonstrict
1285
 *     If nonzero, the path is permitted to contain
1286
 *     embedded null characters and have any length.
1287
 *   path.make_wide
1288
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1289
 *     it always uses narrow, encoding if necessary. The default value is
1290
 *     nonzero on Windows, else zero.
1291
 *   path.suppress_value_error
1292
 *     If nonzero, raising ValueError is suppressed.
1293
 *   path.allow_fd
1294
 *     If nonzero, the path is permitted to be a file handle
1295
 *     (a signed int) instead of a string.
1296
 *   path.function_name
1297
 *     If non-NULL, path_converter will use that as the name
1298
 *     of the function in error messages.
1299
 *     (If path.function_name is NULL it omits the function name.)
1300
 *   path.argument_name
1301
 *     If non-NULL, path_converter will use that as the name
1302
 *     of the parameter in error messages.
1303
 *     (If path.argument_name is NULL it uses "path".)
1304
 *
1305
 * Output fields:
1306
 *   path.wide
1307
 *     Points to the path if it was expressed as Unicode
1308
 *     or if it was bytes and decoded to Unicode.
1309
 *   path.narrow
1310
 *     Points to the path if it was expressed as bytes,
1311
 *     or if it was Unicode and encoded to bytes.
1312
 *   path.fd
1313
 *     Contains a file descriptor if path.accept_fd was true
1314
 *     and the caller provided a signed integer instead of any
1315
 *     sort of string.
1316
 *   path.is_fd
1317
 *     True if path was provided as a file descriptor.
1318
 *
1319
 *     WARNING: if your "path" parameter is optional, and is
1320
 *     unspecified, path_converter will never get called.
1321
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1322
 *     yourself!
1323
 *   path.value_error
1324
 *     If nonzero, then suppress_value_error was specified and a ValueError
1325
 *     occurred.
1326
 *   path.length
1327
 *     The length of the path in characters, if specified as
1328
 *     a string.
1329
 *   path.object
1330
 *     The original object passed in (if get a PathLike object,
1331
 *     the result of PyOS_FSPath() is treated as the original object).
1332
 *     Own a reference to the object.
1333
 *   path.cleanup
1334
 *     For internal use only.  May point to a temporary object.
1335
 *     (Pay no attention to the man behind the curtain.)
1336
 *
1337
 *   At most one of path.wide or path.narrow will be non-NULL.
1338
 *   If path was None and path.nullable was set,
1339
 *     or if path was an integer and path.allow_fd was set,
1340
 *     both path.wide and path.narrow will be NULL
1341
 *     and path.length will be 0.
1342
 *
1343
 *   path_converter takes care to not write to the path_t
1344
 *   unless it's successful.  However it must reset the
1345
 *   "cleanup" field each time it's called.
1346
 *
1347
 * Use as follows:
1348
 *      path_t path;
1349
 *      memset(&path, 0, sizeof(path));
1350
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1351
 *      // ... use values from path ...
1352
 *      path_cleanup(&path);
1353
 *
1354
 * (Note that if PyArg_Parse fails you don't need to call
1355
 * path_cleanup().  However it is safe to do so.)
1356
 */
1357
typedef struct {
1358
    // Input fields
1359
    const char *function_name;
1360
    const char *argument_name;
1361
    int nullable;
1362
    int nonstrict;
1363
    int make_wide;
1364
    int suppress_value_error;
1365
    int allow_fd;
1366
    // Output fields
1367
    const wchar_t *wide;
1368
    const char *narrow;
1369
    int fd;
1370
    bool is_fd;
1371
    int value_error;
1372
    Py_ssize_t length;
1373
    PyObject *object;
1374
    PyObject *cleanup;
1375
} path_t;
1376
1377
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1378
                          make_wide, suppress_value_error, allow_fd) \
1379
757k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1380
757k
     suppress_value_error, allow_fd, NULL, NULL, -1, false, 0, 0, NULL, NULL}
1381
#ifdef MS_WINDOWS
1382
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1383
                            nonstrict, suppress_value_error, allow_fd) \
1384
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1385
                      suppress_value_error, allow_fd)
1386
#else
1387
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1388
                            nonstrict, suppress_value_error, allow_fd) \
1389
604k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1390
604k
                      suppress_value_error, allow_fd)
1391
#endif
1392
1393
static void
1394
path_cleanup(path_t *path)
1395
845k
{
1396
845k
    wchar_t *wide = (wchar_t *)path->wide;
1397
845k
    path->wide = NULL;
1398
845k
    PyMem_Free(wide);
1399
845k
    Py_CLEAR(path->object);
1400
845k
    Py_CLEAR(path->cleanup);
1401
845k
}
1402
1403
static int
1404
path_converter(PyObject *o, void *p)
1405
757k
{
1406
757k
    path_t *path = (path_t *)p;
1407
757k
    PyObject *bytes = NULL;
1408
757k
    Py_ssize_t length = 0;
1409
757k
    int is_index, is_bytes, is_unicode;
1410
757k
    const char *narrow;
1411
757k
    PyObject *wo = NULL;
1412
757k
    wchar_t *wide = NULL;
1413
1414
757k
#define FORMAT_EXCEPTION(exc, fmt) \
1415
757k
    PyErr_Format(exc, "%s%s" fmt, \
1416
0
        path->function_name ? path->function_name : "", \
1417
0
        path->function_name ? ": "                : "", \
1418
0
        path->argument_name ? path->argument_name : "path")
1419
1420
    /* Py_CLEANUP_SUPPORTED support */
1421
757k
    if (o == NULL) {
1422
0
        path_cleanup(path);
1423
0
        return 1;
1424
0
    }
1425
1426
    /* Ensure it's always safe to call path_cleanup(). */
1427
757k
    path->object = path->cleanup = NULL;
1428
    /* path->object owns a reference to the original object */
1429
757k
    Py_INCREF(o);
1430
1431
757k
    if ((o == Py_None) && path->nullable) {
1432
0
        path->wide = NULL;
1433
0
        path->narrow = NULL;
1434
0
        path->fd = -1;
1435
0
        goto success_exit;
1436
0
    }
1437
1438
    /* Only call this here so that we don't treat the return value of
1439
       os.fspath() as an fd or buffer. */
1440
757k
    is_index = path->allow_fd && PyIndex_Check(o);
1441
757k
    is_bytes = PyBytes_Check(o);
1442
757k
    is_unicode = PyUnicode_Check(o);
1443
1444
757k
    if (!is_index && !is_unicode && !is_bytes) {
1445
        /* Inline PyOS_FSPath() for better error messages. */
1446
17
        PyObject *func, *res;
1447
1448
17
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1449
17
        if ((NULL == func) || (func == Py_None)) {
1450
0
            goto error_format;
1451
0
        }
1452
17
        res = _PyObject_CallNoArgs(func);
1453
17
        Py_DECREF(func);
1454
17
        if (NULL == res) {
1455
0
            goto error_exit;
1456
0
        }
1457
17
        else if (PyUnicode_Check(res)) {
1458
17
            is_unicode = 1;
1459
17
        }
1460
0
        else if (PyBytes_Check(res)) {
1461
0
            is_bytes = 1;
1462
0
        }
1463
0
        else {
1464
0
            PyErr_Format(PyExc_TypeError,
1465
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1466
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1467
0
                 _PyType_Name(Py_TYPE(res)));
1468
0
            Py_DECREF(res);
1469
0
            goto error_exit;
1470
0
        }
1471
1472
        /* still owns a reference to the original object */
1473
17
        Py_SETREF(o, res);
1474
17
    }
1475
1476
757k
    if (is_unicode) {
1477
668k
        if (path->make_wide) {
1478
152k
            wide = PyUnicode_AsWideCharString(o, &length);
1479
152k
            if (!wide) {
1480
0
                goto error_exit;
1481
0
            }
1482
#ifdef MS_WINDOWS
1483
            if (!path->nonstrict && length > 32767) {
1484
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1485
                goto error_exit;
1486
            }
1487
#endif
1488
152k
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1489
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1490
0
                                 "embedded null character in %s");
1491
0
                goto error_exit;
1492
0
            }
1493
1494
152k
            path->wide = wide;
1495
152k
            path->narrow = NULL;
1496
152k
            path->fd = -1;
1497
152k
            wide = NULL;
1498
152k
            goto success_exit;
1499
152k
        }
1500
516k
        bytes = PyUnicode_EncodeFSDefault(o);
1501
516k
        if (!bytes) {
1502
0
            goto error_exit;
1503
0
        }
1504
516k
    }
1505
88.4k
    else if (is_bytes) {
1506
0
        bytes = Py_NewRef(o);
1507
0
    }
1508
88.4k
    else if (is_index) {
1509
88.4k
        if (!_fd_converter(o, &path->fd)) {
1510
0
            goto error_exit;
1511
0
        }
1512
88.4k
        path->wide = NULL;
1513
88.4k
        path->narrow = NULL;
1514
88.4k
        path->is_fd = true;
1515
88.4k
        goto success_exit;
1516
88.4k
    }
1517
0
    else {
1518
0
 error_format:
1519
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1520
0
            path->function_name ? path->function_name : "",
1521
0
            path->function_name ? ": "                : "",
1522
0
            path->argument_name ? path->argument_name : "path",
1523
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1524
0
                                               "integer or None" :
1525
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1526
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1527
0
                             "string, bytes or os.PathLike",
1528
0
            _PyType_Name(Py_TYPE(o)));
1529
0
        goto error_exit;
1530
0
    }
1531
1532
516k
    length = PyBytes_GET_SIZE(bytes);
1533
516k
    narrow = PyBytes_AS_STRING(bytes);
1534
516k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1535
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1536
0
        goto error_exit;
1537
0
    }
1538
1539
516k
    if (path->make_wide) {
1540
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1541
0
        if (!wo) {
1542
0
            goto error_exit;
1543
0
        }
1544
1545
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1546
0
        Py_DECREF(wo);
1547
0
        if (!wide) {
1548
0
            goto error_exit;
1549
0
        }
1550
#ifdef MS_WINDOWS
1551
        if (!path->nonstrict && length > 32767) {
1552
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1553
            goto error_exit;
1554
        }
1555
#endif
1556
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1557
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1558
0
                             "embedded null character in %s");
1559
0
            goto error_exit;
1560
0
        }
1561
0
        path->wide = wide;
1562
0
        path->narrow = NULL;
1563
0
        Py_DECREF(bytes);
1564
0
        wide = NULL;
1565
0
    }
1566
516k
    else {
1567
516k
        path->wide = NULL;
1568
516k
        path->narrow = narrow;
1569
516k
        if (bytes == o) {
1570
            /* Still a reference owned by path->object, don't have to
1571
            worry about path->narrow is used after free. */
1572
0
            Py_DECREF(bytes);
1573
0
        }
1574
516k
        else {
1575
516k
            path->cleanup = bytes;
1576
516k
        }
1577
516k
    }
1578
516k
    path->fd = -1;
1579
1580
757k
 success_exit:
1581
757k
    path->value_error = 0;
1582
757k
    path->length = length;
1583
757k
    path->object = o;
1584
757k
    return Py_CLEANUP_SUPPORTED;
1585
1586
0
 error_exit:
1587
0
    Py_XDECREF(o);
1588
0
    Py_XDECREF(bytes);
1589
0
    PyMem_Free(wide);
1590
0
    if (!path->suppress_value_error ||
1591
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1592
0
    {
1593
0
        return 0;
1594
0
    }
1595
0
    PyErr_Clear();
1596
0
    path->wide = NULL;
1597
0
    path->narrow = NULL;
1598
0
    path->fd = -1;
1599
0
    path->value_error = 1;
1600
0
    path->length = 0;
1601
0
    path->object = NULL;
1602
0
    return Py_CLEANUP_SUPPORTED;
1603
0
}
1604
1605
static void
1606
argument_unavailable_error(const char *function_name, const char *argument_name)
1607
0
{
1608
0
    PyErr_Format(PyExc_NotImplementedError,
1609
0
        "%s%s%s unavailable on this platform",
1610
0
        (function_name != NULL) ? function_name : "",
1611
0
        (function_name != NULL) ? ": ": "",
1612
0
        argument_name);
1613
0
}
1614
1615
static int
1616
dir_fd_unavailable(PyObject *o, void *p)
1617
37
{
1618
37
    int dir_fd;
1619
37
    if (!dir_fd_converter(o, &dir_fd))
1620
0
        return 0;
1621
37
    if (dir_fd != DEFAULT_DIR_FD) {
1622
0
        argument_unavailable_error(NULL, "dir_fd");
1623
0
        return 0;
1624
0
    }
1625
37
    *(int *)p = dir_fd;
1626
37
    return 1;
1627
37
}
1628
1629
static int
1630
fd_specified(const char *function_name, int fd)
1631
37
{
1632
37
    if (fd == -1)
1633
37
        return 0;
1634
1635
0
    argument_unavailable_error(function_name, "fd");
1636
0
    return 1;
1637
37
}
1638
1639
static int
1640
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1641
37
{
1642
37
    if (follow_symlinks)
1643
37
        return 0;
1644
1645
0
    argument_unavailable_error(function_name, "follow_symlinks");
1646
0
    return 1;
1647
37
}
1648
1649
static int
1650
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1651
232k
{
1652
232k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1653
0
        PyErr_Format(PyExc_ValueError,
1654
0
                     "%s: can't specify dir_fd without matching path",
1655
0
                     function_name);
1656
0
        return 1;
1657
0
    }
1658
232k
    return 0;
1659
232k
}
1660
1661
static int
1662
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1663
232k
{
1664
232k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1665
0
        PyErr_Format(PyExc_ValueError,
1666
0
                     "%s: can't specify both dir_fd and fd",
1667
0
                     function_name);
1668
0
        return 1;
1669
0
    }
1670
232k
    return 0;
1671
232k
}
1672
1673
static int
1674
fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
1675
                               int follow_symlinks)
1676
232k
{
1677
232k
    if (is_fd && (!follow_symlinks)) {
1678
0
        PyErr_Format(PyExc_ValueError,
1679
0
                     "%s: cannot use fd and follow_symlinks together",
1680
0
                     function_name);
1681
0
        return 1;
1682
0
    }
1683
232k
    return 0;
1684
232k
}
1685
1686
static int
1687
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1688
                                   int follow_symlinks)
1689
37
{
1690
37
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1691
0
        PyErr_Format(PyExc_ValueError,
1692
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1693
0
                     function_name);
1694
0
        return 1;
1695
0
    }
1696
37
    return 0;
1697
37
}
1698
1699
#if defined(HAVE_WAITID)
1700
static int
1701
idtype_t_converter(PyObject *arg, void *addr)
1702
0
{
1703
0
    int value = PyLong_AsInt(arg);
1704
0
    if (value == -1 && PyErr_Occurred()) {
1705
0
        return 0;
1706
0
    }
1707
0
    *((idtype_t *)addr) = (idtype_t)(value);
1708
0
    return 1;
1709
0
}
1710
#endif
1711
1712
static PyObject *
1713
PyLong_FromPy_off_t(Py_off_t offset)
1714
0
{
1715
#ifdef HAVE_LARGEFILE_SUPPORT
1716
    return PyLong_FromLongLong(offset);
1717
#else
1718
0
    return PyLong_FromLong(offset);
1719
0
#endif
1720
0
}
1721
1722
#ifdef HAVE_SIGSET_T
1723
/* Convert an iterable of integers to a sigset.
1724
   Return 1 on success, return 0 and raise an exception on error. */
1725
int
1726
_Py_Sigset_Converter(PyObject *obj, void *addr)
1727
0
{
1728
0
    sigset_t *mask = (sigset_t *)addr;
1729
0
    PyObject *iterator, *item;
1730
0
    long signum;
1731
0
    int overflow;
1732
1733
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1734
0
    if (sigemptyset(mask) < (0)) {
1735
        /* Probably only if mask == NULL. */
1736
0
        PyErr_SetFromErrno(PyExc_OSError);
1737
0
        return 0;
1738
0
    }
1739
1740
0
    iterator = PyObject_GetIter(obj);
1741
0
    if (iterator == NULL) {
1742
0
        return 0;
1743
0
    }
1744
1745
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1746
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1747
0
        Py_DECREF(item);
1748
0
        if (signum <= 0 || signum >= Py_NSIG) {
1749
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1750
0
                PyErr_Format(PyExc_ValueError,
1751
0
                             "signal number %ld out of range [1; %i]",
1752
0
                             signum, Py_NSIG - 1);
1753
0
            }
1754
0
            goto error;
1755
0
        }
1756
0
        if (sigaddset(mask, (int)signum)) {
1757
0
            if (errno != EINVAL) {
1758
                /* Probably impossible */
1759
0
                PyErr_SetFromErrno(PyExc_OSError);
1760
0
                goto error;
1761
0
            }
1762
            /* For backwards compatibility, allow idioms such as
1763
             * `range(1, NSIG)` but warn about invalid signal numbers
1764
             */
1765
0
            const char msg[] =
1766
0
                "invalid signal number %ld, please use valid_signals()";
1767
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1768
0
                goto error;
1769
0
            }
1770
0
        }
1771
0
    }
1772
0
    if (!PyErr_Occurred()) {
1773
0
        Py_DECREF(iterator);
1774
0
        return 1;
1775
0
    }
1776
1777
0
error:
1778
0
    Py_DECREF(iterator);
1779
0
    return 0;
1780
0
}
1781
#endif /* HAVE_SIGSET_T */
1782
1783
/* Return a dictionary corresponding to the POSIX environment table */
1784
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1785
/* On Darwin/MacOSX a shared library or framework has no access to
1786
** environ directly, we must obtain it with _NSGetEnviron(). See also
1787
** man environ(7).
1788
*/
1789
#include <crt_externs.h>
1790
#define USE_DARWIN_NS_GET_ENVIRON 1
1791
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1792
extern char **environ;
1793
#endif /* !_MSC_VER */
1794
1795
static PyObject *
1796
convertenviron(void)
1797
37
{
1798
37
    PyObject *d;
1799
#ifdef MS_WINDOWS
1800
    wchar_t **e;
1801
#else
1802
37
    char **e;
1803
37
#endif
1804
1805
37
    d = PyDict_New();
1806
37
    if (d == NULL)
1807
0
        return NULL;
1808
#ifdef MS_WINDOWS
1809
    /* _wenviron must be initialized in this way if the program is started
1810
       through main() instead of wmain(). */
1811
    (void)_wgetenv(L"");
1812
    e = _wenviron;
1813
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1814
    /* environ is not accessible as an extern in a shared object on OSX; use
1815
       _NSGetEnviron to resolve it. The value changes if you add environment
1816
       variables between calls to Py_Initialize, so don't cache the value. */
1817
    e = *_NSGetEnviron();
1818
#else
1819
37
    e = environ;
1820
37
#endif
1821
37
    if (e == NULL)
1822
0
        return d;
1823
1.29k
    for (; *e != NULL; e++) {
1824
1.25k
        PyObject *k;
1825
1.25k
        PyObject *v;
1826
#ifdef MS_WINDOWS
1827
        const wchar_t *p = wcschr(*e, L'=');
1828
#else
1829
1.25k
        const char *p = strchr(*e, '=');
1830
1.25k
#endif
1831
1.25k
        if (p == NULL)
1832
0
            continue;
1833
#ifdef MS_WINDOWS
1834
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1835
#else
1836
1.25k
        k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
1837
1.25k
#endif
1838
1.25k
        if (k == NULL) {
1839
0
            Py_DECREF(d);
1840
0
            return NULL;
1841
0
        }
1842
#ifdef MS_WINDOWS
1843
        v = PyUnicode_FromWideChar(p+1, -1);
1844
#else
1845
1.25k
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1846
1.25k
#endif
1847
1.25k
        if (v == NULL) {
1848
0
            Py_DECREF(k);
1849
0
            Py_DECREF(d);
1850
0
            return NULL;
1851
0
        }
1852
1.25k
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1853
0
            Py_DECREF(v);
1854
0
            Py_DECREF(k);
1855
0
            Py_DECREF(d);
1856
0
            return NULL;
1857
0
        }
1858
1.25k
        Py_DECREF(k);
1859
1.25k
        Py_DECREF(v);
1860
1.25k
    }
1861
37
    return d;
1862
37
}
1863
1864
/* Set a POSIX-specific error from errno, and return NULL */
1865
1866
static PyObject *
1867
posix_error(void)
1868
0
{
1869
0
    return PyErr_SetFromErrno(PyExc_OSError);
1870
0
}
1871
1872
#ifdef MS_WINDOWS
1873
static PyObject *
1874
win32_error(const char* function, const char* filename)
1875
{
1876
    /* XXX We should pass the function name along in the future.
1877
       (winreg.c also wants to pass the function name.)
1878
       This would however require an additional param to the
1879
       Windows error object, which is non-trivial.
1880
    */
1881
    errno = GetLastError();
1882
    if (filename)
1883
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1884
    else
1885
        return PyErr_SetFromWindowsErr(errno);
1886
}
1887
1888
static PyObject *
1889
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1890
{
1891
    /* XXX - see win32_error for comments on 'function' */
1892
    if (filename)
1893
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1894
                    PyExc_OSError,
1895
                    err,
1896
                    filename);
1897
    else
1898
        return PyErr_SetFromWindowsErr(err);
1899
}
1900
1901
static PyObject *
1902
win32_error_object(const char* function, PyObject* filename)
1903
{
1904
    errno = GetLastError();
1905
    return win32_error_object_err(function, filename, errno);
1906
}
1907
1908
#endif /* MS_WINDOWS */
1909
1910
static PyObject *
1911
posix_path_object_error(PyObject *path)
1912
172k
{
1913
172k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1914
172k
}
1915
1916
static PyObject *
1917
path_object_error(PyObject *path)
1918
172k
{
1919
#ifdef MS_WINDOWS
1920
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1921
                PyExc_OSError, 0, path);
1922
#else
1923
172k
    return posix_path_object_error(path);
1924
172k
#endif
1925
172k
}
1926
1927
static PyObject *
1928
path_object_error2(PyObject *path, PyObject *path2)
1929
0
{
1930
#ifdef MS_WINDOWS
1931
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1932
                PyExc_OSError, 0, path, path2);
1933
#else
1934
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1935
0
#endif
1936
0
}
1937
1938
static PyObject *
1939
path_error(path_t *path)
1940
172k
{
1941
172k
    return path_object_error(path->object);
1942
172k
}
1943
1944
static PyObject *
1945
posix_path_error(path_t *path)
1946
0
{
1947
0
    return posix_path_object_error(path->object);
1948
0
}
1949
1950
static PyObject *
1951
path_error2(path_t *path, path_t *path2)
1952
0
{
1953
0
    return path_object_error2(path->object, path2->object);
1954
0
}
1955
1956
1957
/* POSIX generic methods */
1958
1959
static PyObject *
1960
posix_fildes_fd(int fd, int (*func)(int))
1961
0
{
1962
0
    int res;
1963
0
    int async_err = 0;
1964
1965
0
    do {
1966
0
        Py_BEGIN_ALLOW_THREADS
1967
0
        _Py_BEGIN_SUPPRESS_IPH
1968
0
        res = (*func)(fd);
1969
0
        _Py_END_SUPPRESS_IPH
1970
0
        Py_END_ALLOW_THREADS
1971
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1972
0
    if (res != 0)
1973
0
        return (!async_err) ? posix_error() : NULL;
1974
0
    Py_RETURN_NONE;
1975
0
}
1976
1977
1978
#ifdef MS_WINDOWS
1979
/* This is a reimplementation of the C library's chdir function,
1980
   but one that produces Win32 errors instead of DOS error codes.
1981
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1982
   it also needs to set "magic" environment variables indicating
1983
   the per-drive current directory, which are of the form =<drive>: */
1984
static BOOL __stdcall
1985
win32_wchdir(LPCWSTR path)
1986
{
1987
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1988
    int result;
1989
    wchar_t env[4] = L"=x:";
1990
1991
    if(!SetCurrentDirectoryW(path))
1992
        return FALSE;
1993
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1994
    if (!result)
1995
        return FALSE;
1996
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1997
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1998
        if (!new_path) {
1999
            SetLastError(ERROR_OUTOFMEMORY);
2000
            return FALSE;
2001
        }
2002
        result = GetCurrentDirectoryW(result, new_path);
2003
        if (!result) {
2004
            PyMem_RawFree(new_path);
2005
            return FALSE;
2006
        }
2007
    }
2008
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
2009
                            wcsncmp(new_path, L"//", 2) == 0);
2010
    if (!is_unc_like_path) {
2011
        env[1] = new_path[0];
2012
        result = SetEnvironmentVariableW(env, new_path);
2013
    }
2014
    if (new_path != path_buf)
2015
        PyMem_RawFree(new_path);
2016
    return result ? TRUE : FALSE;
2017
}
2018
#endif
2019
2020
#ifdef MS_WINDOWS
2021
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2022
   - time stamps are restricted to second resolution
2023
   - file modification times suffer from forth-and-back conversions between
2024
     UTC and local time
2025
   Therefore, we implement our own stat, based on the Win32 API directly.
2026
*/
2027
#define HAVE_STAT_NSEC 1
2028
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2029
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2030
2031
/* The \\?\ prefix disables the path normalization, in particular
2032
   stripping of trailing dots and spaces. */
2033
static int
2034
is_extended_path(const wchar_t *path)
2035
{
2036
    return wcsncmp(path, L"\\\\?\\", 4) == 0;
2037
}
2038
2039
static void
2040
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2041
                       FILE_BASIC_INFO* basic_info,
2042
                       FILE_STANDARD_INFO* standard_info,
2043
                       ULONG *reparse_tag)
2044
{
2045
    memset(basic_info, 0, sizeof(*basic_info));
2046
    memset(standard_info, 0, sizeof(*standard_info));
2047
2048
    basic_info->FileAttributes = pFileData->dwFileAttributes;
2049
    basic_info->CreationTime.HighPart = pFileData->ftCreationTime.dwHighDateTime;
2050
    basic_info->CreationTime.LowPart = pFileData->ftCreationTime.dwLowDateTime;
2051
    basic_info->LastAccessTime.HighPart = pFileData->ftLastAccessTime.dwHighDateTime;
2052
    basic_info->LastAccessTime.LowPart = pFileData->ftLastAccessTime.dwLowDateTime;
2053
    basic_info->LastWriteTime.HighPart = pFileData->ftLastWriteTime.dwHighDateTime;
2054
    basic_info->LastWriteTime.LowPart = pFileData->ftLastWriteTime.dwLowDateTime;
2055
    standard_info->EndOfFile.HighPart = pFileData->nFileSizeHigh;
2056
    standard_info->EndOfFile.LowPart = pFileData->nFileSizeLow;
2057
2058
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2059
        *reparse_tag = pFileData->dwReserved0;
2060
    else
2061
        *reparse_tag = 0;
2062
}
2063
2064
static BOOL
2065
attributes_from_dir(LPCWSTR pszFile, FILE_BASIC_INFO* basic_info, FILE_STANDARD_INFO* standard_info, ULONG* reparse_tag)
2066
{
2067
    HANDLE hFindFile;
2068
    WIN32_FIND_DATAW FileData;
2069
    LPCWSTR filename = pszFile;
2070
    size_t n = wcslen(pszFile);
2071
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2072
        // cannot use PyMem_Malloc here because we do not hold the GIL
2073
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2074
        if(!filename) {
2075
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2076
            return FALSE;
2077
        }
2078
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2079
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2080
            ((LPWSTR)filename)[n] = L'\0';
2081
        }
2082
        if (!n || (n == 1 && filename[1] == L':')) {
2083
            // Nothing left to query
2084
            free((void *)filename);
2085
            return FALSE;
2086
        }
2087
    }
2088
    hFindFile = FindFirstFileW(filename, &FileData);
2089
    if (pszFile != filename) {
2090
        free((void *)filename);
2091
    }
2092
    if (hFindFile == INVALID_HANDLE_VALUE) {
2093
        return FALSE;
2094
    }
2095
    FindClose(hFindFile);
2096
    find_data_to_file_info(&FileData, basic_info, standard_info, reparse_tag);
2097
    return TRUE;
2098
}
2099
2100
2101
static void
2102
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2103
                         struct _Py_stat_struct *result)
2104
{
2105
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2106
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2107
           the filename has an extension that is commonly used by files
2108
           that CreateProcessW can execute. A real implementation calls
2109
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2110
           AccessCheck to check for generic read, write, and execute
2111
           access. */
2112
        size_t len = wcslen(path);
2113
        if (!is_extended_path(path)) {
2114
            /* Trailing dots and spaces are stripped from the last component
2115
               of the path. */
2116
            while (len > 0 && (path[len - 1] == L'.' || path[len - 1] == L' ')) {
2117
                len--;
2118
            }
2119
        }
2120
        if (len >= 4) {
2121
            const wchar_t *fileExtension = path + len - 4;
2122
            if (_wcsnicmp(fileExtension, L".exe", 4) == 0 ||
2123
                _wcsnicmp(fileExtension, L".bat", 4) == 0 ||
2124
                _wcsnicmp(fileExtension, L".cmd", 4) == 0 ||
2125
                _wcsnicmp(fileExtension, L".com", 4) == 0) {
2126
                result->st_mode |= 0111;
2127
            }
2128
        }
2129
    }
2130
}
2131
2132
2133
static int
2134
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2135
                      BOOL traverse)
2136
{
2137
    HANDLE hFile;
2138
    FILE_STANDARD_INFO standardInfo = {0};
2139
    FILE_BASIC_INFO basicInfo = {0};
2140
    FILE_ID_INFO idInfo = {0};
2141
    FILE_ID_INFO *pIdInfo = NULL;
2142
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2143
    DWORD fileType, error;
2144
    BOOL isUnhandledTag = FALSE;
2145
    int retval = 0;
2146
2147
    DWORD access = FILE_READ_ATTRIBUTES;
2148
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2149
    if (!traverse) {
2150
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2151
    }
2152
2153
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2154
    if (hFile == INVALID_HANDLE_VALUE) {
2155
        /* Either the path doesn't exist, or the caller lacks access. */
2156
        error = GetLastError();
2157
        switch (error) {
2158
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2159
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2160
            /* Try reading the parent directory. */
2161
            if (!attributes_from_dir(path, &basicInfo, &standardInfo, &tagInfo.ReparseTag)) {
2162
                /* Cannot read the parent directory. */
2163
                switch (GetLastError()) {
2164
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2165
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2166
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2167
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2168
                    break;
2169
                /* Restore the error from CreateFileW(). */
2170
                default:
2171
                    SetLastError(error);
2172
                }
2173
2174
                return -1;
2175
            }
2176
            if (basicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2177
                if (traverse ||
2178
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2179
                    /* The stat call has to traverse but cannot, so fail. */
2180
                    SetLastError(error);
2181
                    return -1;
2182
                }
2183
            }
2184
            break;
2185
2186
        case ERROR_INVALID_PARAMETER:
2187
            /* \\.\con requires read or write access. */
2188
            hFile = CreateFileW(path, access | GENERIC_READ,
2189
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2190
                        OPEN_EXISTING, flags, NULL);
2191
            if (hFile == INVALID_HANDLE_VALUE) {
2192
                SetLastError(error);
2193
                return -1;
2194
            }
2195
            break;
2196
2197
        case ERROR_CANT_ACCESS_FILE:
2198
            /* bpo37834: open unhandled reparse points if traverse fails. */
2199
            if (traverse) {
2200
                traverse = FALSE;
2201
                isUnhandledTag = TRUE;
2202
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2203
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2204
            }
2205
            if (hFile == INVALID_HANDLE_VALUE) {
2206
                SetLastError(error);
2207
                return -1;
2208
            }
2209
            break;
2210
2211
        default:
2212
            return -1;
2213
        }
2214
    }
2215
2216
    if (hFile != INVALID_HANDLE_VALUE) {
2217
        /* Handle types other than files on disk. */
2218
        fileType = GetFileType(hFile);
2219
        if (fileType != FILE_TYPE_DISK) {
2220
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2221
                retval = -1;
2222
                goto cleanup;
2223
            }
2224
            DWORD fileAttributes = GetFileAttributesW(path);
2225
            memset(result, 0, sizeof(*result));
2226
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2227
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2228
                /* \\.\pipe\ or \\.\mailslot\ */
2229
                result->st_mode = _S_IFDIR;
2230
            } else if (fileType == FILE_TYPE_CHAR) {
2231
                /* \\.\nul */
2232
                result->st_mode = _S_IFCHR;
2233
            } else if (fileType == FILE_TYPE_PIPE) {
2234
                /* \\.\pipe\spam */
2235
                result->st_mode = _S_IFIFO;
2236
            }
2237
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2238
            goto cleanup;
2239
        }
2240
2241
        /* Query the reparse tag, and traverse a non-link. */
2242
        if (!traverse) {
2243
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2244
                    &tagInfo, sizeof(tagInfo))) {
2245
                /* Allow devices that do not support FileAttributeTagInfo. */
2246
                switch (GetLastError()) {
2247
                case ERROR_INVALID_PARAMETER:
2248
                case ERROR_INVALID_FUNCTION:
2249
                case ERROR_NOT_SUPPORTED:
2250
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2251
                    tagInfo.ReparseTag = 0;
2252
                    break;
2253
                default:
2254
                    retval = -1;
2255
                    goto cleanup;
2256
                }
2257
            } else if (tagInfo.FileAttributes &
2258
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2259
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2260
                    if (isUnhandledTag) {
2261
                        /* Traversing previously failed for either this link
2262
                           or its target. */
2263
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2264
                        retval = -1;
2265
                        goto cleanup;
2266
                    }
2267
                /* Traverse a non-link, but not if traversing already failed
2268
                   for an unhandled tag. */
2269
                } else if (!isUnhandledTag) {
2270
                    CloseHandle(hFile);
2271
                    return win32_xstat_slow_impl(path, result, TRUE);
2272
                }
2273
            }
2274
        }
2275
2276
        if (!GetFileInformationByHandleEx(hFile, FileStandardInfo, &standardInfo, sizeof(standardInfo)) ||
2277
            !GetFileInformationByHandleEx(hFile, FileBasicInfo, &basicInfo, sizeof(basicInfo))) {
2278
            switch (GetLastError()) {
2279
            case ERROR_INVALID_PARAMETER:
2280
            case ERROR_INVALID_FUNCTION:
2281
            case ERROR_NOT_SUPPORTED:
2282
                /* Volumes and physical disks are block devices, e.g.
2283
                   \\.\C: and \\.\PhysicalDrive0. */
2284
                memset(result, 0, sizeof(*result));
2285
                result->st_mode = 0x6000; /* S_IFBLK */
2286
                goto cleanup;
2287
            }
2288
            retval = -1;
2289
            goto cleanup;
2290
        }
2291
2292
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2293
            /* Successfully got FileIdInfo, so pass it along */
2294
            pIdInfo = &idInfo;
2295
        }
2296
    }
2297
2298
    _Py_attribute_data_to_stat(&standardInfo, tagInfo.ReparseTag, &basicInfo, pIdInfo, result);
2299
    update_st_mode_from_path(path, basicInfo.FileAttributes, result);
2300
2301
cleanup:
2302
    if (hFile != INVALID_HANDLE_VALUE) {
2303
        /* Preserve last error if we are failing */
2304
        error = retval ? GetLastError() : 0;
2305
        if (!CloseHandle(hFile)) {
2306
            retval = -1;
2307
        } else if (retval) {
2308
            /* Restore last error */
2309
            SetLastError(error);
2310
        }
2311
    }
2312
2313
    return retval;
2314
}
2315
2316
static int
2317
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2318
                 BOOL traverse)
2319
{
2320
    FILE_STAT_BASIC_INFORMATION statInfo;
2321
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2322
                                     &statInfo, sizeof(statInfo))) {
2323
        if (// Cannot use fast path for reparse points ...
2324
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2325
            // ... unless it's a name surrogate (symlink) and we're not following
2326
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2327
        ) {
2328
            _Py_stat_basic_info_to_stat(&statInfo, result);
2329
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2330
            return 0;
2331
        }
2332
    } else {
2333
        switch(GetLastError()) {
2334
        case ERROR_FILE_NOT_FOUND:
2335
        case ERROR_PATH_NOT_FOUND:
2336
        case ERROR_NOT_READY:
2337
        case ERROR_BAD_NET_NAME:
2338
            /* These errors aren't worth retrying with the slow path */
2339
            return -1;
2340
        case ERROR_NOT_SUPPORTED:
2341
            /* indicates the API couldn't be loaded */
2342
            break;
2343
        }
2344
    }
2345
2346
    return win32_xstat_slow_impl(path, result, traverse);
2347
}
2348
2349
static int
2350
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2351
{
2352
    /* Protocol violation: we explicitly clear errno, instead of
2353
       setting it to a POSIX error. Callers should use GetLastError. */
2354
    int code = win32_xstat_impl(path, result, traverse);
2355
    errno = 0;
2356
2357
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2358
    result->st_ctime = result->st_birthtime;
2359
    result->st_ctime_nsec = result->st_birthtime_nsec;
2360
    return code;
2361
}
2362
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2363
2364
   In Posix, stat automatically traverses symlinks and returns the stat
2365
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2366
   default does not traverse symlinks and instead returns attributes for
2367
   the symlink.
2368
2369
   Instead, we will open the file (which *does* traverse symlinks by default)
2370
   and GetFileInformationByHandle(). */
2371
2372
static int
2373
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2374
{
2375
    return win32_xstat(path, result, FALSE);
2376
}
2377
2378
static int
2379
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2380
{
2381
    return win32_xstat(path, result, TRUE);
2382
}
2383
2384
#endif /* MS_WINDOWS */
2385
2386
PyDoc_STRVAR(stat_result__doc__,
2387
"stat_result: Result from stat, fstat, or lstat.\n\n\
2388
This object may be accessed either as a tuple of\n\
2389
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2390
or via the attributes st_mode, st_ino, st_dev, st_nlink, and so on.\n\
2391
\n\
2392
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2393
or st_flags, they are available as attributes only.\n\
2394
\n\
2395
See os.stat for more information.");
2396
2397
static PyStructSequence_Field stat_result_fields[] = {
2398
    {"st_mode",    "protection bits"},
2399
    {"st_ino",     "inode"},
2400
    {"st_dev",     "device"},
2401
    {"st_nlink",   "number of hard links"},
2402
    {"st_uid",     "user ID of owner"},
2403
    {"st_gid",     "group ID of owner"},
2404
    {"st_size",    "total size, in bytes"},
2405
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2406
    {NULL,   "integer time of last access"},
2407
    {NULL,   "integer time of last modification"},
2408
    {NULL,   "integer time of last change"},
2409
    {"st_atime",   "time of last access"},
2410
    {"st_mtime",   "time of last modification"},
2411
    {"st_ctime",   "time of last change"},
2412
    {"st_atime_ns",   "time of last access in nanoseconds"},
2413
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2414
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2415
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2416
    {"st_blksize", "blocksize for filesystem I/O"},
2417
#endif
2418
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2419
    {"st_blocks",  "number of blocks allocated"},
2420
#endif
2421
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2422
    {"st_rdev",    "device type (if inode device)"},
2423
#endif
2424
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2425
    {"st_flags",   "user defined flags for file"},
2426
#endif
2427
#ifdef HAVE_STRUCT_STAT_ST_GEN
2428
    {"st_gen",    "generation number"},
2429
#endif
2430
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2431
    {"st_birthtime",   "time of creation"},
2432
#endif
2433
#ifdef MS_WINDOWS
2434
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2435
#endif
2436
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2437
    {"st_file_attributes", "Windows file attribute bits"},
2438
#endif
2439
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2440
    {"st_fstype",  "Type of filesystem"},
2441
#endif
2442
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2443
    {"st_reparse_tag", "Windows reparse tag"},
2444
#endif
2445
    {0}
2446
};
2447
2448
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2449
#define ST_BLKSIZE_IDX 16
2450
#else
2451
#define ST_BLKSIZE_IDX 15
2452
#endif
2453
2454
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2455
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2456
#else
2457
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2458
#endif
2459
2460
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2461
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2462
#else
2463
#define ST_RDEV_IDX ST_BLOCKS_IDX
2464
#endif
2465
2466
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2467
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2468
#else
2469
#define ST_FLAGS_IDX ST_RDEV_IDX
2470
#endif
2471
2472
#ifdef HAVE_STRUCT_STAT_ST_GEN
2473
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2474
#else
2475
#define ST_GEN_IDX ST_FLAGS_IDX
2476
#endif
2477
2478
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2479
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2480
#else
2481
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2482
#endif
2483
2484
#ifdef MS_WINDOWS
2485
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2486
#else
2487
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2488
#endif
2489
2490
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2491
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2492
#else
2493
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2494
#endif
2495
2496
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2497
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2498
#else
2499
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2500
#endif
2501
2502
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2503
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2504
#else
2505
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2506
#endif
2507
2508
static PyStructSequence_Desc stat_result_desc = {
2509
    "os.stat_result", /* name; see issue gh-63408 */
2510
    stat_result__doc__, /* doc */
2511
    stat_result_fields,
2512
    10
2513
};
2514
2515
PyDoc_STRVAR(statvfs_result__doc__,
2516
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2517
This object may be accessed either as a tuple of\n\
2518
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2519
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2520
\n\
2521
See os.statvfs for more information.");
2522
2523
static PyStructSequence_Field statvfs_result_fields[] = {
2524
    {"f_bsize",  },
2525
    {"f_frsize", },
2526
    {"f_blocks", },
2527
    {"f_bfree",  },
2528
    {"f_bavail", },
2529
    {"f_files",  },
2530
    {"f_ffree",  },
2531
    {"f_favail", },
2532
    {"f_flag",   },
2533
    {"f_namemax",},
2534
    {"f_fsid",   },
2535
    {0}
2536
};
2537
2538
static PyStructSequence_Desc statvfs_result_desc = {
2539
    "os.statvfs_result", /* name; see issue gh-63408 */
2540
    statvfs_result__doc__, /* doc */
2541
    statvfs_result_fields,
2542
    10
2543
};
2544
2545
#if defined(HAVE_WAITID)
2546
PyDoc_STRVAR(waitid_result__doc__,
2547
"waitid_result: Result from waitid.\n\n\
2548
This object may be accessed either as a tuple of\n\
2549
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2550
or via the attributes si_pid, si_uid, and so on.\n\
2551
\n\
2552
See os.waitid for more information.");
2553
2554
static PyStructSequence_Field waitid_result_fields[] = {
2555
    {"si_pid",  },
2556
    {"si_uid", },
2557
    {"si_signo", },
2558
    {"si_status",  },
2559
    {"si_code", },
2560
    {0}
2561
};
2562
2563
static PyStructSequence_Desc waitid_result_desc = {
2564
    MODNAME ".waitid_result", /* name */
2565
    waitid_result__doc__, /* doc */
2566
    waitid_result_fields,
2567
    5
2568
};
2569
#endif
2570
2571
static PyObject *
2572
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2573
0
{
2574
0
    PyStructSequence *result;
2575
0
    int i;
2576
2577
    // ht_module doesn't get set in PyStructSequence_NewType(),
2578
    // so we can't use PyType_GetModule().
2579
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2580
0
    if (mod == NULL) {
2581
0
        return NULL;
2582
0
    }
2583
0
    _posixstate *state = get_posix_state(mod);
2584
0
    Py_DECREF(mod);
2585
0
    if (state == NULL) {
2586
0
        return NULL;
2587
0
    }
2588
0
#define structseq_new state->statresult_new_orig
2589
2590
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2591
0
    if (!result)
2592
0
        return NULL;
2593
    /* If we have been initialized from a tuple,
2594
       st_?time might be set to None. Initialize it
2595
       from the int slots.  */
2596
0
    for (i = 7; i <= 9; i++) {
2597
0
        if (result->ob_item[i+3] == Py_None) {
2598
0
            Py_DECREF(Py_None);
2599
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2600
0
        }
2601
0
    }
2602
0
    return (PyObject*)result;
2603
0
}
2604
2605
static int
2606
_posix_clear(PyObject *module)
2607
0
{
2608
0
    _posixstate *state = get_posix_state(module);
2609
0
    Py_CLEAR(state->billion);
2610
0
    Py_CLEAR(state->DirEntryType);
2611
0
    Py_CLEAR(state->ScandirIteratorType);
2612
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2613
0
    Py_CLEAR(state->SchedParamType);
2614
0
#endif
2615
0
    Py_CLEAR(state->StatResultType);
2616
0
#ifdef HAVE_STATX
2617
0
    Py_CLEAR(state->StatxResultType);
2618
0
#endif
2619
0
    Py_CLEAR(state->StatVFSResultType);
2620
0
    Py_CLEAR(state->TerminalSizeType);
2621
0
    Py_CLEAR(state->TimesResultType);
2622
0
    Py_CLEAR(state->UnameResultType);
2623
0
#if defined(HAVE_WAITID)
2624
0
    Py_CLEAR(state->WaitidResultType);
2625
0
#endif
2626
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2627
0
    Py_CLEAR(state->struct_rusage);
2628
0
#endif
2629
0
    Py_CLEAR(state->st_mode);
2630
0
    return 0;
2631
0
}
2632
2633
static int
2634
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2635
1.64k
{
2636
1.64k
    _posixstate *state = get_posix_state(module);
2637
1.64k
    Py_VISIT(state->billion);
2638
1.64k
    Py_VISIT(state->DirEntryType);
2639
1.64k
    Py_VISIT(state->ScandirIteratorType);
2640
1.64k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2641
1.64k
    Py_VISIT(state->SchedParamType);
2642
1.64k
#endif
2643
1.64k
    Py_VISIT(state->StatResultType);
2644
1.64k
#ifdef HAVE_STATX
2645
1.64k
    Py_VISIT(state->StatxResultType);
2646
1.64k
#endif
2647
1.64k
    Py_VISIT(state->StatVFSResultType);
2648
1.64k
    Py_VISIT(state->TerminalSizeType);
2649
1.64k
    Py_VISIT(state->TimesResultType);
2650
1.64k
    Py_VISIT(state->UnameResultType);
2651
1.64k
#if defined(HAVE_WAITID)
2652
1.64k
    Py_VISIT(state->WaitidResultType);
2653
1.64k
#endif
2654
1.64k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2655
1.64k
    Py_VISIT(state->struct_rusage);
2656
1.64k
#endif
2657
1.64k
    Py_VISIT(state->st_mode);
2658
1.64k
    return 0;
2659
1.64k
}
2660
2661
static void
2662
_posix_free(void *module)
2663
0
{
2664
0
   _posix_clear((PyObject *)module);
2665
0
}
2666
2667
2668
2.09M
#define SEC_TO_NS (1000000000LL)
2669
static PyObject *
2670
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2671
699k
{
2672
#if SIZEOF_TIME_T == 4
2673
    return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2674
#else
2675
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2676
699k
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2677
699k
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2678
699k
    }
2679
0
    else
2680
0
    {
2681
0
        PyObject *ns_total = NULL;
2682
0
        PyObject *s_in_ns = NULL;
2683
0
        PyObject *s = _PyLong_FromTime_t(sec);
2684
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2685
0
        if (s == NULL || ns_fractional == NULL) {
2686
0
            goto exit;
2687
0
        }
2688
2689
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2690
0
        if (s_in_ns == NULL) {
2691
0
            goto exit;
2692
0
        }
2693
2694
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2695
2696
0
    exit:
2697
0
        Py_XDECREF(s);
2698
0
        Py_XDECREF(ns_fractional);
2699
0
        Py_XDECREF(s_in_ns);
2700
0
        return ns_total;
2701
0
    }
2702
699k
#endif
2703
699k
}
2704
2705
static int
2706
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2707
          int ns_index, time_t sec, unsigned long nsec)
2708
699k
{
2709
699k
    assert(!PyErr_Occurred());
2710
699k
    assert(nsec < SEC_TO_NS);
2711
2712
699k
    if (s_index >= 0) {
2713
699k
        PyObject *s = _PyLong_FromTime_t(sec);
2714
699k
        if (s == NULL) {
2715
0
            return -1;
2716
0
        }
2717
699k
        PyStructSequence_SET_ITEM(v, s_index, s);
2718
699k
    }
2719
2720
699k
    if (f_index >= 0) {
2721
699k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2722
699k
        if (float_s == NULL) {
2723
0
            return -1;
2724
0
        }
2725
699k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2726
699k
    }
2727
2728
699k
    if (ns_index >= 0) {
2729
699k
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2730
699k
        if (ns_total == NULL) {
2731
0
            return -1;
2732
0
        }
2733
699k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2734
699k
    }
2735
2736
699k
    assert(!PyErr_Occurred());
2737
699k
    return 0;
2738
699k
}
2739
#undef SEC_TO_NS
2740
2741
#ifdef MS_WINDOWS
2742
static PyObject*
2743
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2744
{
2745
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2746
    if (!o_low || !high) {
2747
        return o_low;
2748
    }
2749
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2750
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2751
    if (!l64) {
2752
        Py_XDECREF(o_high);
2753
        Py_DECREF(o_low);
2754
        return NULL;
2755
    }
2756
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2757
    Py_DECREF(l64);
2758
    if (!o_high) {
2759
        Py_DECREF(o_low);
2760
        return NULL;
2761
    }
2762
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2763
    Py_DECREF(o_high);
2764
    return o_low;
2765
}
2766
#endif
2767
2768
/* pack a system stat C structure into the Python stat tuple
2769
   (used by posix_stat() and posix_fstat()) */
2770
static PyObject*
2771
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2772
233k
{
2773
233k
    assert(!PyErr_Occurred());
2774
2775
233k
    _posixstate *state = get_posix_state(module);
2776
233k
    PyObject *StatResultType = state->StatResultType;
2777
233k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2778
233k
    if (v == NULL) {
2779
0
        return NULL;
2780
0
    }
2781
2782
233k
#define SET_ITEM(pos, expr) \
2783
2.33M
    do { \
2784
2.33M
        PyObject *obj = (expr); \
2785
2.33M
        if (obj == NULL) { \
2786
0
            goto error; \
2787
0
        } \
2788
2.33M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2789
2.33M
    } while (0)
2790
2791
233k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2792
#ifdef MS_WINDOWS
2793
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2794
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2795
#else
2796
233k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2797
233k
                  "stat.st_ino is larger than unsigned long long");
2798
233k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2799
233k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2800
233k
#endif
2801
233k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2802
#if defined(MS_WINDOWS)
2803
    SET_ITEM(4, PyLong_FromLong(0));
2804
    SET_ITEM(5, PyLong_FromLong(0));
2805
#else
2806
233k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2807
233k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2808
233k
#endif
2809
233k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2810
233k
                  "stat.st_size is larger than long long");
2811
233k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2812
2813
    // Set st_atime, st_mtime and st_ctime
2814
233k
    unsigned long ansec, mnsec, cnsec;
2815
233k
#if defined(HAVE_STAT_TV_NSEC)
2816
233k
    ansec = st->st_atim.tv_nsec;
2817
233k
    mnsec = st->st_mtim.tv_nsec;
2818
233k
    cnsec = st->st_ctim.tv_nsec;
2819
#elif defined(HAVE_STAT_TV_NSEC2)
2820
    ansec = st->st_atimespec.tv_nsec;
2821
    mnsec = st->st_mtimespec.tv_nsec;
2822
    cnsec = st->st_ctimespec.tv_nsec;
2823
#elif defined(HAVE_STAT_NSEC)
2824
    ansec = st->st_atime_nsec;
2825
    mnsec = st->st_mtime_nsec;
2826
    cnsec = st->st_ctime_nsec;
2827
#else
2828
    ansec = mnsec = cnsec = 0;
2829
#endif
2830
233k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2831
0
        goto error;
2832
0
    }
2833
233k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2834
0
        goto error;
2835
0
    }
2836
233k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2837
0
        goto error;
2838
0
    }
2839
2840
233k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2841
233k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2842
233k
#endif
2843
233k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2844
233k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2845
233k
#endif
2846
233k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2847
233k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2848
233k
#endif
2849
#ifdef HAVE_STRUCT_STAT_ST_GEN
2850
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2851
#endif
2852
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2853
    {
2854
      unsigned long bsec, bnsec;
2855
      bsec = (long)st->st_birthtime;
2856
#ifdef HAVE_STAT_TV_NSEC2
2857
      bnsec = st->st_birthtimespec.tv_nsec;
2858
#else
2859
      bnsec = 0;
2860
#endif
2861
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2862
    }
2863
#elif defined(MS_WINDOWS)
2864
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2865
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2866
        goto error;
2867
    }
2868
#endif
2869
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2870
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2871
#endif
2872
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2873
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2874
             PyLong_FromUnsignedLong(st->st_file_attributes));
2875
#endif
2876
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2877
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2878
#endif
2879
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2880
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2881
#endif
2882
2883
233k
    assert(!PyErr_Occurred());
2884
233k
    return v;
2885
2886
0
error:
2887
0
    Py_DECREF(v);
2888
0
    return NULL;
2889
2890
233k
#undef SET_ITEM
2891
233k
}
2892
2893
/* POSIX methods */
2894
2895
2896
static PyObject *
2897
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2898
              int dir_fd, int follow_symlinks)
2899
232k
{
2900
232k
    STRUCT_STAT st;
2901
232k
    int result;
2902
2903
232k
#ifdef HAVE_FSTATAT
2904
232k
    int fstatat_unavailable = 0;
2905
232k
#endif
2906
2907
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2908
    if (follow_symlinks_specified(function_name, follow_symlinks))
2909
        return NULL;
2910
#endif
2911
2912
232k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2913
232k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2914
232k
        fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
2915
0
        return NULL;
2916
2917
232k
    Py_BEGIN_ALLOW_THREADS
2918
232k
    if (path->is_fd) {
2919
0
        result = FSTAT(path->fd, &st);
2920
0
    }
2921
#ifdef MS_WINDOWS
2922
    else if (follow_symlinks)
2923
        result = win32_stat(path->wide, &st);
2924
    else
2925
        result = win32_lstat(path->wide, &st);
2926
#else
2927
232k
    else
2928
232k
#if defined(HAVE_LSTAT)
2929
232k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2930
9.60k
        result = LSTAT(path->narrow, &st);
2931
223k
    else
2932
223k
#endif /* HAVE_LSTAT */
2933
223k
#ifdef HAVE_FSTATAT
2934
223k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2935
0
        if (HAVE_FSTATAT_RUNTIME) {
2936
0
            result = fstatat(dir_fd, path->narrow, &st,
2937
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2938
2939
0
        } else {
2940
0
            fstatat_unavailable = 1;
2941
0
        }
2942
0
    } else
2943
223k
#endif /* HAVE_FSTATAT */
2944
223k
        result = STAT(path->narrow, &st);
2945
232k
#endif /* MS_WINDOWS */
2946
232k
    Py_END_ALLOW_THREADS
2947
2948
232k
#ifdef HAVE_FSTATAT
2949
232k
    if (fstatat_unavailable) {
2950
0
        argument_unavailable_error("stat", "dir_fd");
2951
0
        return NULL;
2952
0
    }
2953
232k
#endif
2954
2955
232k
    if (result != 0) {
2956
172k
        return path_error(path);
2957
172k
    }
2958
2959
60.2k
    return _pystat_fromstructstat(module, &st);
2960
232k
}
2961
2962
/*[python input]
2963
2964
for s in """
2965
2966
FACCESSAT
2967
FCHMODAT
2968
FCHOWNAT
2969
FSTATAT
2970
LINKAT
2971
MKDIRAT
2972
MKFIFOAT
2973
MKNODAT
2974
OPENAT
2975
READLINKAT
2976
SYMLINKAT
2977
UNLINKAT
2978
2979
""".strip().split():
2980
    s = s.strip()
2981
    print("""
2982
#ifdef HAVE_{s}
2983
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2984
#else
2985
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2986
#endif
2987
""".rstrip().format(s=s))
2988
2989
for s in """
2990
2991
FCHDIR
2992
FCHMOD
2993
FCHOWN
2994
FDOPENDIR
2995
FEXECVE
2996
FPATHCONF
2997
FSTATVFS
2998
FTRUNCATE
2999
3000
""".strip().split():
3001
    s = s.strip()
3002
    print("""
3003
#ifdef HAVE_{s}
3004
    #define PATH_HAVE_{s} 1
3005
#else
3006
    #define PATH_HAVE_{s} 0
3007
#endif
3008
3009
""".rstrip().format(s=s))
3010
[python start generated code]*/
3011
3012
#ifdef HAVE_FACCESSAT
3013
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
3014
#else
3015
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
3016
#endif
3017
3018
#ifdef HAVE_FCHMODAT
3019
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
3020
#else
3021
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
3022
#endif
3023
3024
#ifdef HAVE_FCHOWNAT
3025
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
3026
#else
3027
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
3028
#endif
3029
3030
#ifdef HAVE_FSTATAT
3031
8.20k
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
3032
#else
3033
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
3034
#endif
3035
3036
#ifdef HAVE_LINKAT
3037
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
3038
#else
3039
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3040
#endif
3041
3042
#ifdef HAVE_MKDIRAT
3043
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3044
#else
3045
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3046
#endif
3047
3048
#ifdef HAVE_MKFIFOAT
3049
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3050
#else
3051
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3052
#endif
3053
3054
#ifdef HAVE_MKNODAT
3055
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3056
#else
3057
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3058
#endif
3059
3060
#ifdef HAVE_OPENAT
3061
88.4k
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3062
#else
3063
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3064
#endif
3065
3066
#ifdef HAVE_READLINKAT
3067
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3068
#else
3069
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3070
#endif
3071
3072
#ifdef HAVE_SYMLINKAT
3073
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3074
#else
3075
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3076
#endif
3077
3078
#ifdef HAVE_UNLINKAT
3079
105k
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3080
#else
3081
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3082
#endif
3083
3084
#ifdef HAVE_FCHDIR
3085
    #define PATH_HAVE_FCHDIR 1
3086
#else
3087
    #define PATH_HAVE_FCHDIR 0
3088
#endif
3089
3090
#ifdef HAVE_FCHMOD
3091
    #define PATH_HAVE_FCHMOD 1
3092
#else
3093
    #define PATH_HAVE_FCHMOD 0
3094
#endif
3095
3096
#ifdef HAVE_FCHOWN
3097
    #define PATH_HAVE_FCHOWN 1
3098
#else
3099
    #define PATH_HAVE_FCHOWN 0
3100
#endif
3101
3102
#ifdef HAVE_FDOPENDIR
3103
    #define PATH_HAVE_FDOPENDIR 1
3104
#else
3105
    #define PATH_HAVE_FDOPENDIR 0
3106
#endif
3107
3108
#ifdef HAVE_FEXECVE
3109
    #define PATH_HAVE_FEXECVE 1
3110
#else
3111
    #define PATH_HAVE_FEXECVE 0
3112
#endif
3113
3114
#ifdef HAVE_FPATHCONF
3115
    #define PATH_HAVE_FPATHCONF 1
3116
#else
3117
    #define PATH_HAVE_FPATHCONF 0
3118
#endif
3119
3120
#ifdef HAVE_FSTATVFS
3121
    #define PATH_HAVE_FSTATVFS 1
3122
#else
3123
    #define PATH_HAVE_FSTATVFS 0
3124
#endif
3125
3126
#ifdef HAVE_FTRUNCATE
3127
    #define PATH_HAVE_FTRUNCATE 1
3128
#else
3129
    #define PATH_HAVE_FTRUNCATE 0
3130
#endif
3131
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3132
3133
#ifdef MS_WINDOWS
3134
    #undef PATH_HAVE_FTRUNCATE
3135
    #define PATH_HAVE_FTRUNCATE 1
3136
    #undef PATH_HAVE_FCHMOD
3137
    #define PATH_HAVE_FCHMOD 1
3138
#endif
3139
3140
/*[python input]
3141
3142
class path_t_converter(CConverter):
3143
3144
    type = "path_t"
3145
    impl_by_reference = True
3146
    parse_by_reference = True
3147
    default_type = ()
3148
    c_init_default = "<placeholder>"  # overridden in pre_render()
3149
3150
    converter = 'path_converter'
3151
3152
    def converter_init(self, *, allow_fd=False, make_wide=None,
3153
                       nonstrict=False, nullable=False,
3154
                       suppress_value_error=False):
3155
3156
        self.nullable = nullable
3157
        self.nonstrict = nonstrict
3158
        self.make_wide = make_wide
3159
        self.suppress_value_error = suppress_value_error
3160
        self.allow_fd = allow_fd
3161
        if nullable:
3162
            self.default_type = NoneType
3163
3164
    def pre_render(self):
3165
        def strify(value):
3166
            if isinstance(value, str):
3167
                return value
3168
            return str(int(bool(value)))
3169
3170
        # add self.py_name here when merging with posixmodule conversion
3171
        if self.make_wide is None:
3172
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3173
                self.function.name,
3174
                self.name,
3175
                strify(self.nullable),
3176
                strify(self.nonstrict),
3177
                strify(self.suppress_value_error),
3178
                strify(self.allow_fd),
3179
            )
3180
        else:
3181
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3182
                self.function.name,
3183
                self.name,
3184
                strify(self.nullable),
3185
                strify(self.nonstrict),
3186
                strify(self.make_wide),
3187
                strify(self.suppress_value_error),
3188
                strify(self.allow_fd),
3189
            )
3190
3191
    def cleanup(self):
3192
        return "path_cleanup(&" + self.name + ");\n"
3193
3194
3195
class dir_fd_converter(CConverter):
3196
    type = 'int'
3197
    default_type = NoneType
3198
    c_init_default = 'DEFAULT_DIR_FD'
3199
3200
    def converter_init(self, requires=None):
3201
        if self.default in (unspecified, None):
3202
            self.c_default = 'DEFAULT_DIR_FD'
3203
        if isinstance(requires, str):
3204
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3205
        else:
3206
            self.converter = 'dir_fd_converter'
3207
3208
    def c_default_init(self):
3209
        self.c_default = 'DEFAULT_DIR_FD'
3210
3211
class dev_t_converter(CConverter):
3212
    type = 'dev_t'
3213
    converter = '_Py_Dev_Converter'
3214
3215
class dev_t_return_converter(unsigned_long_return_converter):
3216
    type = 'dev_t'
3217
    conversion_fn = '_PyLong_FromDev'
3218
    unsigned_cast = '(dev_t)'
3219
3220
class idtype_t_converter(CConverter):
3221
    type = 'idtype_t'
3222
    converter = 'idtype_t_converter'
3223
3224
class id_t_converter(CConverter):
3225
    type = 'id_t'
3226
    format_unit = '" _Py_PARSE_PID "'
3227
3228
    def parse_arg(self, argname, displayname, *, limited_capi):
3229
        return self.format_code("""
3230
            {paramname} = (id_t)PyLong_AsPid({argname});
3231
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3232
                goto exit;
3233
            }}}}
3234
            """, argname=argname)
3235
3236
class intptr_t_converter(CConverter):
3237
    type = 'intptr_t'
3238
    format_unit = '" _Py_PARSE_INTPTR "'
3239
3240
    def parse_arg(self, argname, displayname, *, limited_capi):
3241
        return self.format_code("""
3242
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3243
            if (!{paramname} && PyErr_Occurred()) {{{{
3244
                goto exit;
3245
            }}}}
3246
            """, argname=argname)
3247
3248
class Py_off_t_return_converter(long_return_converter):
3249
    type = 'Py_off_t'
3250
    conversion_fn = 'PyLong_FromPy_off_t'
3251
3252
class confname_converter(CConverter):
3253
    type="int"
3254
    converter="conv_confname"
3255
3256
    def converter_init(self, *, table):
3257
        self.table = table
3258
3259
    def parse_arg(self, argname, displayname, *, limited_capi):
3260
        return self.format_code("""
3261
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3262
                goto exit;
3263
            }}}}
3264
        """, argname=argname, converter=self.converter, table=self.table)
3265
3266
[python start generated code]*/
3267
/*[python end generated code: output=da39a3ee5e6b4b0d input=7ceccf55bb600f61]*/
3268
3269
/*[clinic input]
3270
3271
os.stat
3272
3273
    path : path_t(allow_fd=True)
3274
        Path to be examined; can be string, bytes, a path-like object or
3275
        open-file-descriptor int.
3276
3277
    *
3278
3279
    dir_fd : dir_fd(requires='fstatat') = None
3280
        If not None, it should be a file descriptor open to a directory,
3281
        and path should be a relative string; path will then be relative to
3282
        that directory.
3283
3284
    follow_symlinks: bool = True
3285
        If False, and the last element of the path is a symbolic link,
3286
        stat will examine the symbolic link itself instead of the file
3287
        the link points to.
3288
3289
Perform a stat system call on the given path.
3290
3291
dir_fd and follow_symlinks may not be implemented
3292
  on your platform.  If they are unavailable, using them will raise a
3293
  NotImplementedError.
3294
3295
It's an error to use dir_fd or follow_symlinks when specifying path as
3296
  an open file descriptor.
3297
3298
[clinic start generated code]*/
3299
3300
static PyObject *
3301
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3302
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3303
223k
{
3304
223k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3305
223k
}
3306
3307
3308
/*[clinic input]
3309
@permit_long_summary
3310
os.lstat
3311
3312
    path : path_t
3313
3314
    *
3315
3316
    dir_fd : dir_fd(requires='fstatat') = None
3317
3318
Perform a stat system call on the given path, without following symbolic links.
3319
3320
Like stat(), but do not follow symbolic links.
3321
Equivalent to stat(path, follow_symlinks=False).
3322
[clinic start generated code]*/
3323
3324
static PyObject *
3325
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3326
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3327
9.60k
{
3328
9.60k
    int follow_symlinks = 0;
3329
9.60k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3330
9.60k
}
3331
3332
3333
#ifdef HAVE_STATX
3334
typedef struct {
3335
    PyObject_HEAD
3336
    dev_t rdev, dev;
3337
    struct statx stx;
3338
} Py_statx_result;
3339
3340
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3341
3342
#define M(attr, type, offset, doc) \
3343
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3344
#define MM(attr, type, member, doc) \
3345
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3346
#define MX(attr, type, member, doc) \
3347
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3348
3349
static PyMemberDef pystatx_result_members[] = {
3350
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3351
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3352
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3353
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3354
        "Mask of supported bits in stx_attributes"),
3355
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3356
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3357
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3358
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3359
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3360
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3361
    {NULL},
3362
};
3363
3364
#undef MX
3365
#undef MM
3366
#undef M
3367
3368
3369
#define STATX_GET_UINT(ATTR, MASK) \
3370
    static PyObject* \
3371
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3372
0
    { \
3373
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3374
0
        if (!(self->stx.stx_mask & MASK)) { \
3375
0
            Py_RETURN_NONE; \
3376
0
        } \
3377
0
        unsigned long value = self->stx.ATTR; \
3378
0
        return PyLong_FromUnsignedLong(value); \
3379
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
3380
3381
STATX_GET_UINT(stx_uid, STATX_UID)
3382
STATX_GET_UINT(stx_gid, STATX_GID)
3383
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3384
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3385
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3386
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3387
#endif
3388
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3389
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3390
#endif
3391
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3392
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3393
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3394
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3395
#endif
3396
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3397
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3398
#endif
3399
3400
3401
static PyObject*
3402
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3403
0
{
3404
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3405
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3406
0
        Py_RETURN_NONE;
3407
0
    }
3408
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3409
0
}
3410
3411
3412
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3413
    static PyObject* \
3414
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3415
0
    { \
3416
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3417
0
        if (!(self->stx.stx_mask & MASK)) { \
3418
0
            Py_RETURN_NONE; \
3419
0
        } \
3420
0
        unsigned long long value = self->stx.ATTR; \
3421
0
        return PyLong_FromUnsignedLongLong(value); \
3422
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
3423
3424
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3425
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3426
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3427
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3428
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3429
#endif
3430
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3431
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3432
#endif
3433
3434
3435
#define STATX_GET_DOUBLE(ATTR, MASK) \
3436
    static PyObject* \
3437
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3438
0
    { \
3439
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3440
0
        if (!(self->stx.stx_mask & MASK)) { \
3441
0
            Py_RETURN_NONE; \
3442
0
        } \
3443
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3444
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3445
0
        return PyFloat_FromDouble(sec); \
3446
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
3447
3448
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3449
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3450
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3451
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3452
3453
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3454
    static PyObject* \
3455
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3456
0
    { \
3457
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3458
0
        if (!(self->stx.stx_mask & MASK)) { \
3459
0
            Py_RETURN_NONE; \
3460
0
        } \
3461
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3462
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3463
0
        assert(state != NULL); \
3464
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3465
0
    }
3466
3467
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3468
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3469
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3470
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3471
3472
#define G(attr, doc) \
3473
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3474
3475
static PyGetSetDef pystatx_result_getset[] = {
3476
    G(stx_mode, "protection bits"),
3477
    G(stx_nlink, "number of hard links"),
3478
    G(stx_uid, "user ID of owner"),
3479
    G(stx_gid, "group ID of owner"),
3480
    G(stx_ino, "inode"),
3481
    G(stx_size, "total size, in bytes"),
3482
    G(stx_blocks, "number of blocks allocated"),
3483
    G(stx_atime, "time of last access"),
3484
    G(stx_atime_ns, "time of last access in nanoseconds"),
3485
    G(stx_btime, "time of creation"),
3486
    G(stx_btime_ns, "time of creation in nanoseconds"),
3487
    G(stx_ctime, "time of last change"),
3488
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3489
    G(stx_mtime, "time of last modification"),
3490
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3491
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3492
    G(stx_mnt_id, "mount ID"),
3493
#endif
3494
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3495
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3496
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3497
#endif
3498
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3499
    G(stx_subvol, "subvolume ID"),
3500
#endif
3501
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3502
    G(stx_atomic_write_unit_min,
3503
      "minimum size for direct I/O with torn-write protection"),
3504
    G(stx_atomic_write_unit_max,
3505
        "maximum size for direct I/O with torn-write protection"),
3506
    G(stx_atomic_write_segments_max,
3507
        "maximum iovecs for direct I/O with torn-write protection"),
3508
#endif
3509
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3510
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3511
#endif
3512
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3513
    G(stx_atomic_write_unit_max_opt,
3514
        "maximum optimized size for direct I/O with torn-write protection"),
3515
#endif
3516
    {NULL},
3517
};
3518
3519
#undef G
3520
3521
static PyObject *
3522
pystatx_result_repr(PyObject *op)
3523
0
{
3524
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3525
0
    if (writer == NULL) {
3526
0
        return NULL;
3527
0
    }
3528
0
#define WRITE_ASCII(s) \
3529
0
    do { \
3530
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3531
0
            goto error; \
3532
0
        } \
3533
0
    } while (0)
3534
3535
0
    WRITE_ASCII("os.statx_result(");
3536
3537
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3538
0
        if (i > 0) {
3539
0
            WRITE_ASCII(", ");
3540
0
        }
3541
3542
0
        PyMemberDef *d = &pystatx_result_members[i];
3543
0
        WRITE_ASCII(d->name);
3544
0
        WRITE_ASCII("=");
3545
3546
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3547
0
        if (o == NULL) {
3548
0
            goto error;
3549
0
        }
3550
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3551
0
            Py_DECREF(o);
3552
0
            goto error;
3553
0
        }
3554
0
        Py_DECREF(o);
3555
0
    }
3556
3557
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3558
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3559
0
        PyObject *o = d->get(op, d->closure);
3560
0
        if (o == NULL) {
3561
0
            goto error;
3562
0
        }
3563
0
        if (o == Py_None) {
3564
0
            continue;
3565
0
        }
3566
3567
0
        WRITE_ASCII(", ");
3568
0
        WRITE_ASCII(d->name);
3569
0
        WRITE_ASCII("=");
3570
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3571
0
            Py_DECREF(o);
3572
0
            goto error;
3573
0
        }
3574
0
        Py_DECREF(o);
3575
0
    }
3576
3577
0
    WRITE_ASCII(")");
3578
0
    return PyUnicodeWriter_Finish(writer);
3579
0
#undef WRITE_ASCII
3580
3581
0
error:
3582
0
    PyUnicodeWriter_Discard(writer);
3583
0
    return NULL;
3584
0
}
3585
3586
static int
3587
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3588
0
{
3589
0
    Py_VISIT(Py_TYPE(self));
3590
0
    return 0;
3591
0
}
3592
3593
static void
3594
pystatx_result_dealloc(PyObject *op)
3595
0
{
3596
0
    Py_statx_result *self = (Py_statx_result *) op;
3597
0
    PyTypeObject *tp = Py_TYPE(self);
3598
0
    PyObject_GC_UnTrack(self);
3599
0
    tp->tp_free(self);
3600
0
    Py_DECREF(tp);
3601
0
}
3602
3603
static PyType_Slot pystatx_result_slots[] = {
3604
    {Py_tp_repr, pystatx_result_repr},
3605
    {Py_tp_traverse, pystatx_result_traverse},
3606
    {Py_tp_dealloc, pystatx_result_dealloc},
3607
    {Py_tp_members, pystatx_result_members},
3608
    {Py_tp_getset, pystatx_result_getset},
3609
    {0, NULL},
3610
};
3611
3612
static PyType_Spec pystatx_result_spec = {
3613
    .name = "os.statx_result",
3614
    .basicsize = sizeof(Py_statx_result),
3615
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3616
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3617
    .slots = pystatx_result_slots,
3618
};
3619
3620
/*[clinic input]
3621
3622
os.statx
3623
3624
    path : path_t(allow_fd=True)
3625
        Path to be examined; can be string, bytes, a path-like object or
3626
        open-file-descriptor int.
3627
3628
    mask: unsigned_int(bitwise=True)
3629
        A bitmask of STATX_* constants defining the requested information.
3630
3631
    *
3632
3633
    flags: int = 0
3634
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3635
3636
    dir_fd : dir_fd = None
3637
        If not None, it should be a file descriptor open to a directory,
3638
        and path should be a relative string; path will then be relative to
3639
        that directory.
3640
3641
    follow_symlinks: bool = True
3642
        If False, and the last element of the path is a symbolic link,
3643
        statx will examine the symbolic link itself instead of the file
3644
        the link points to.
3645
3646
Perform a statx system call on the given path.
3647
3648
It's an error to use dir_fd or follow_symlinks when specifying path as
3649
  an open file descriptor.
3650
3651
[clinic start generated code]*/
3652
3653
static PyObject *
3654
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3655
              int dir_fd, int follow_symlinks)
3656
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3657
0
{
3658
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3659
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3660
0
        fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) {
3661
0
        return NULL;
3662
0
    }
3663
3664
    /* reject flags covered by kwargs, but allow unknown flags that may be
3665
       future AT_STATX_* extensions */
3666
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3667
0
        PyErr_Format(PyExc_ValueError,
3668
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3669
0
        return NULL;
3670
0
    }
3671
0
    if (flags & AT_EMPTY_PATH) {
3672
0
        PyErr_Format(PyExc_ValueError,
3673
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3674
0
        return NULL;
3675
0
    }
3676
3677
    /* Future bits may refer to members beyond the current size of struct
3678
       statx, so we need to mask them off to prevent memory corruption. */
3679
0
    mask &= _Py_STATX_KNOWN;
3680
3681
0
    _posixstate *state = get_posix_state(module);
3682
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3683
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3684
0
    if (v == NULL) {
3685
0
        return NULL;
3686
0
    }
3687
3688
0
    int result;
3689
0
    Py_BEGIN_ALLOW_THREADS
3690
0
    if (path->is_fd) {
3691
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3692
0
    }
3693
0
    else {
3694
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3695
0
    }
3696
0
    Py_END_ALLOW_THREADS
3697
3698
0
    if (result != 0) {
3699
0
        Py_DECREF(v);
3700
0
        return path_error(path);
3701
0
    }
3702
3703
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3704
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3705
3706
0
    assert(!PyErr_Occurred());
3707
0
    return (PyObject *)v;
3708
0
}
3709
#endif /* HAVE_STATX */
3710
3711
3712
/*[clinic input]
3713
os.access -> bool
3714
3715
    path: path_t
3716
        Path to be tested; can be string, bytes, or a path-like object.
3717
3718
    mode: int
3719
        Operating-system mode bitfield.  Can be F_OK to test existence,
3720
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3721
3722
    *
3723
3724
    dir_fd : dir_fd(requires='faccessat') = None
3725
        If not None, it should be a file descriptor open to a directory,
3726
        and path should be relative; path will then be relative to that
3727
        directory.
3728
3729
    effective_ids: bool = False
3730
        If True, access will use the effective uid/gid instead of
3731
        the real uid/gid.
3732
3733
    follow_symlinks: bool = True
3734
        If False, and the last element of the path is a symbolic link,
3735
        access will examine the symbolic link itself instead of the file
3736
        the link points to.
3737
3738
Use the real uid/gid to test for access to a path.
3739
3740
{parameters}
3741
dir_fd, effective_ids, and follow_symlinks may not be implemented
3742
  on your platform.  If they are unavailable, using them will raise a
3743
  NotImplementedError.
3744
3745
Note that most operations will use the effective uid/gid, therefore this
3746
  routine can be used in a suid/sgid environment to test if the invoking
3747
  user has the specified access to the path.
3748
3749
[clinic start generated code]*/
3750
3751
static int
3752
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3753
               int effective_ids, int follow_symlinks)
3754
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3755
0
{
3756
0
    int return_value;
3757
3758
#ifdef MS_WINDOWS
3759
    DWORD attr;
3760
#else
3761
0
    int result;
3762
0
#endif
3763
3764
0
#ifdef HAVE_FACCESSAT
3765
0
    int faccessat_unavailable = 0;
3766
0
#endif
3767
3768
#ifndef HAVE_FACCESSAT
3769
    if (follow_symlinks_specified("access", follow_symlinks))
3770
        return -1;
3771
3772
    if (effective_ids) {
3773
        argument_unavailable_error("access", "effective_ids");
3774
        return -1;
3775
    }
3776
#endif
3777
3778
#ifdef MS_WINDOWS
3779
    Py_BEGIN_ALLOW_THREADS
3780
    attr = GetFileAttributesW(path->wide);
3781
    Py_END_ALLOW_THREADS
3782
3783
    /*
3784
     * Access is possible if
3785
     *   * we didn't get a -1, and
3786
     *     * write access wasn't requested,
3787
     *     * or the file isn't read-only,
3788
     *     * or it's a directory.
3789
     * (Directories cannot be read-only on Windows.)
3790
    */
3791
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3792
            (!(mode & 2) ||
3793
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3794
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3795
#else
3796
3797
0
    Py_BEGIN_ALLOW_THREADS
3798
0
#ifdef HAVE_FACCESSAT
3799
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3800
0
        effective_ids ||
3801
0
        !follow_symlinks) {
3802
3803
0
        if (HAVE_FACCESSAT_RUNTIME) {
3804
0
            int flags = 0;
3805
0
            if (!follow_symlinks)
3806
0
                flags |= AT_SYMLINK_NOFOLLOW;
3807
0
            if (effective_ids)
3808
0
                flags |= AT_EACCESS;
3809
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3810
0
        } else {
3811
0
            faccessat_unavailable = 1;
3812
0
        }
3813
0
    }
3814
0
    else
3815
0
#endif
3816
0
        result = access(path->narrow, mode);
3817
0
    Py_END_ALLOW_THREADS
3818
3819
0
#ifdef HAVE_FACCESSAT
3820
0
    if (faccessat_unavailable) {
3821
0
        if (dir_fd != DEFAULT_DIR_FD) {
3822
0
            argument_unavailable_error("access", "dir_fd");
3823
0
            return -1;
3824
0
        }
3825
0
        if (follow_symlinks_specified("access", follow_symlinks))
3826
0
            return -1;
3827
3828
0
        if (effective_ids) {
3829
0
            argument_unavailable_error("access", "effective_ids");
3830
0
            return -1;
3831
0
        }
3832
        /* should be unreachable */
3833
0
        return -1;
3834
0
    }
3835
0
#endif
3836
0
    return_value = !result;
3837
0
#endif
3838
3839
0
    return return_value;
3840
0
}
3841
3842
#ifndef F_OK
3843
#define F_OK 0
3844
#endif
3845
#ifndef R_OK
3846
#define R_OK 4
3847
#endif
3848
#ifndef W_OK
3849
#define W_OK 2
3850
#endif
3851
#ifndef X_OK
3852
#define X_OK 1
3853
#endif
3854
3855
3856
#ifdef HAVE_TTYNAME_R
3857
/*[clinic input]
3858
os.ttyname
3859
3860
    fd: int
3861
        Integer file descriptor handle.
3862
3863
    /
3864
3865
Return the name of the terminal device connected to 'fd'.
3866
[clinic start generated code]*/
3867
3868
static PyObject *
3869
os_ttyname_impl(PyObject *module, int fd)
3870
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3871
0
{
3872
3873
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3874
0
    if (size == -1) {
3875
0
        return posix_error();
3876
0
    }
3877
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3878
0
    if (buffer == NULL) {
3879
0
        return PyErr_NoMemory();
3880
0
    }
3881
0
    int ret = ttyname_r(fd, buffer, size);
3882
0
    if (ret != 0) {
3883
0
        PyMem_RawFree(buffer);
3884
0
        errno = ret;
3885
0
        return posix_error();
3886
0
    }
3887
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3888
0
    PyMem_RawFree(buffer);
3889
0
    return res;
3890
0
}
3891
#endif
3892
3893
#ifdef HAVE_CTERMID
3894
/*[clinic input]
3895
os.ctermid
3896
3897
Return the name of the controlling terminal for this process.
3898
[clinic start generated code]*/
3899
3900
static PyObject *
3901
os_ctermid_impl(PyObject *module)
3902
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3903
0
{
3904
0
    char *ret;
3905
0
    char buffer[L_ctermid];
3906
3907
#ifdef USE_CTERMID_R
3908
    ret = ctermid_r(buffer);
3909
#else
3910
0
    ret = ctermid(buffer);
3911
0
#endif
3912
0
    if (ret == NULL)
3913
0
        return posix_error();
3914
0
    return PyUnicode_DecodeFSDefault(buffer);
3915
0
}
3916
#endif /* HAVE_CTERMID */
3917
3918
3919
/*[clinic input]
3920
os.chdir
3921
3922
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3923
3924
Change the current working directory to the specified path.
3925
3926
path may always be specified as a string.  On some platforms, path may
3927
also be specified as an open file descriptor.  If this functionality is
3928
unavailable, using it raises an exception.
3929
[clinic start generated code]*/
3930
3931
static PyObject *
3932
os_chdir_impl(PyObject *module, path_t *path)
3933
/*[clinic end generated code: output=3be6400eee26eaae input=64673c342e4369f1]*/
3934
0
{
3935
0
    int result;
3936
3937
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3938
0
        return NULL;
3939
0
    }
3940
3941
0
    Py_BEGIN_ALLOW_THREADS
3942
#ifdef MS_WINDOWS
3943
    /* on unix, success = 0, on windows, success = !0 */
3944
    result = !win32_wchdir(path->wide);
3945
#else
3946
0
#ifdef HAVE_FCHDIR
3947
0
    if (path->is_fd)
3948
0
        result = fchdir(path->fd);
3949
0
    else
3950
0
#endif
3951
0
        result = chdir(path->narrow);
3952
0
#endif
3953
0
    Py_END_ALLOW_THREADS
3954
3955
0
    if (result) {
3956
0
        return path_error(path);
3957
0
    }
3958
3959
0
    Py_RETURN_NONE;
3960
0
}
3961
3962
3963
#ifdef HAVE_FCHDIR
3964
/*[clinic input]
3965
os.fchdir
3966
3967
    fd: fildes
3968
3969
Change to the directory of the given file descriptor.
3970
3971
fd must be opened on a directory, not a file.
3972
Equivalent to os.chdir(fd).
3973
3974
[clinic start generated code]*/
3975
3976
static PyObject *
3977
os_fchdir_impl(PyObject *module, int fd)
3978
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3979
0
{
3980
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3981
0
        return NULL;
3982
0
    }
3983
0
    return posix_fildes_fd(fd, fchdir);
3984
0
}
3985
#endif /* HAVE_FCHDIR */
3986
3987
#ifdef MS_WINDOWS
3988
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3989
#else
3990
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3991
#endif
3992
3993
#ifdef MS_WINDOWS
3994
static int
3995
win32_lchmod(LPCWSTR path, int mode)
3996
{
3997
    DWORD attr = GetFileAttributesW(path);
3998
    if (attr == INVALID_FILE_ATTRIBUTES) {
3999
        return 0;
4000
    }
4001
    if (mode & _S_IWRITE) {
4002
        attr &= ~FILE_ATTRIBUTE_READONLY;
4003
    }
4004
    else {
4005
        attr |= FILE_ATTRIBUTE_READONLY;
4006
    }
4007
    return SetFileAttributesW(path, attr);
4008
}
4009
4010
static int
4011
win32_hchmod(HANDLE hfile, int mode)
4012
{
4013
    FILE_BASIC_INFO info;
4014
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4015
                                      &info, sizeof(info)))
4016
    {
4017
        return 0;
4018
    }
4019
    if (mode & _S_IWRITE) {
4020
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4021
    }
4022
    else {
4023
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4024
    }
4025
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4026
                                      &info, sizeof(info));
4027
}
4028
4029
static int
4030
win32_fchmod(int fd, int mode)
4031
{
4032
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4033
    if (hfile == INVALID_HANDLE_VALUE) {
4034
        SetLastError(ERROR_INVALID_HANDLE);
4035
        return 0;
4036
    }
4037
    return win32_hchmod(hfile, mode);
4038
}
4039
4040
#endif /* MS_WINDOWS */
4041
4042
/*[clinic input]
4043
os.chmod
4044
4045
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4046
        Path to be modified.  May always be specified as a str, bytes, or
4047
        a path-like object.  On some platforms, path may also be specified
4048
        as an open file descriptor.  If this functionality is unavailable,
4049
        using it raises an exception.
4050
4051
    mode: int
4052
        Operating-system mode bitfield.
4053
        Be careful when using number literals for *mode*. The conventional
4054
        UNIX notation for numeric modes uses an octal base, which needs to
4055
        be indicated with a ``0o`` prefix in Python.
4056
4057
    *
4058
4059
    dir_fd : dir_fd(requires='fchmodat') = None
4060
        If not None, it should be a file descriptor open to a directory,
4061
        and path should be relative; path will then be relative to that
4062
        directory.
4063
4064
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4065
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4066
        If False, and the last element of the path is a symbolic link,
4067
        chmod will modify the symbolic link itself instead of the file
4068
        the link points to.
4069
4070
Change the access permissions of a file.
4071
4072
It is an error to use dir_fd or follow_symlinks when specifying path as
4073
  an open file descriptor.
4074
dir_fd and follow_symlinks may not be implemented on your platform.
4075
  If they are unavailable, using them will raise a NotImplementedError.
4076
4077
[clinic start generated code]*/
4078
4079
static PyObject *
4080
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4081
              int follow_symlinks)
4082
/*[clinic end generated code: output=5cf6a94915cc7bff input=7b6e2eeadd8bf199]*/
4083
0
{
4084
0
    int result;
4085
4086
0
#ifdef HAVE_FCHMODAT
4087
0
    int fchmodat_nofollow_unsupported = 0;
4088
0
    int fchmodat_unsupported = 0;
4089
0
#endif
4090
4091
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4092
    if (follow_symlinks_specified("chmod", follow_symlinks))
4093
        return NULL;
4094
#endif
4095
4096
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4097
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4098
0
        return NULL;
4099
0
    }
4100
4101
#ifdef MS_WINDOWS
4102
    result = 0;
4103
    Py_BEGIN_ALLOW_THREADS
4104
    if (path->is_fd) {
4105
        result = win32_fchmod(path->fd, mode);
4106
    }
4107
    else if (follow_symlinks) {
4108
        HANDLE hfile = CreateFileW(path->wide,
4109
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4110
                                   0, NULL,
4111
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4112
        if (hfile != INVALID_HANDLE_VALUE) {
4113
            result = win32_hchmod(hfile, mode);
4114
            (void)CloseHandle(hfile);
4115
        }
4116
    }
4117
    else {
4118
        result = win32_lchmod(path->wide, mode);
4119
    }
4120
    Py_END_ALLOW_THREADS
4121
    if (!result) {
4122
        return path_error(path);
4123
    }
4124
#else /* MS_WINDOWS */
4125
0
    Py_BEGIN_ALLOW_THREADS
4126
0
#ifdef HAVE_FCHMOD
4127
0
    if (path->is_fd) {
4128
0
        result = fchmod(path->fd, mode);
4129
0
    }
4130
0
    else
4131
0
#endif /* HAVE_CHMOD */
4132
#ifdef HAVE_LCHMOD
4133
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4134
        result = lchmod(path->narrow, mode);
4135
    else
4136
#endif /* HAVE_LCHMOD */
4137
0
#ifdef HAVE_FCHMODAT
4138
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4139
0
        if (HAVE_FCHMODAT_RUNTIME) {
4140
            /*
4141
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4142
             * The documentation specifically shows how to use it,
4143
             * and then says it isn't implemented yet.
4144
             * (true on linux with glibc 2.15, and openindiana 3.x)
4145
             *
4146
             * Once it is supported, os.chmod will automatically
4147
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4148
             * Until then, we need to be careful what exception we raise.
4149
             */
4150
0
            result = fchmodat(dir_fd, path->narrow, mode,
4151
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4152
            /*
4153
             * But wait!  We can't throw the exception without allowing threads,
4154
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4155
             */
4156
0
            fchmodat_nofollow_unsupported =
4157
0
                             result &&
4158
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4159
0
                             !follow_symlinks;
4160
0
        } else {
4161
0
            fchmodat_unsupported = 1;
4162
0
            fchmodat_nofollow_unsupported = 1;
4163
4164
0
            result = -1;
4165
0
        }
4166
0
    }
4167
0
    else
4168
0
#endif /* HAVE_FHCMODAT */
4169
0
    {
4170
0
#ifdef HAVE_CHMOD
4171
0
        result = chmod(path->narrow, mode);
4172
#elif defined(__wasi__)
4173
        // WASI SDK 15.0 does not support chmod.
4174
        // Ignore missing syscall for now.
4175
        result = 0;
4176
#else
4177
        result = -1;
4178
        errno = ENOSYS;
4179
#endif
4180
0
    }
4181
0
    Py_END_ALLOW_THREADS
4182
4183
0
    if (result) {
4184
0
#ifdef HAVE_FCHMODAT
4185
0
        if (fchmodat_unsupported) {
4186
0
            if (dir_fd != DEFAULT_DIR_FD) {
4187
0
                argument_unavailable_error("chmod", "dir_fd");
4188
0
                return NULL;
4189
0
            }
4190
0
        }
4191
4192
0
        if (fchmodat_nofollow_unsupported) {
4193
0
            if (dir_fd != DEFAULT_DIR_FD)
4194
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4195
0
                                                   dir_fd, follow_symlinks);
4196
0
            else
4197
0
                follow_symlinks_specified("chmod", follow_symlinks);
4198
0
            return NULL;
4199
0
        }
4200
0
        else
4201
0
#endif /* HAVE_FCHMODAT */
4202
0
        return path_error(path);
4203
0
    }
4204
0
#endif /* MS_WINDOWS */
4205
4206
0
    Py_RETURN_NONE;
4207
0
}
4208
4209
4210
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4211
/*[clinic input]
4212
os.fchmod
4213
4214
    fd: int
4215
        The file descriptor of the file to be modified.
4216
    mode: int
4217
        Operating-system mode bitfield.
4218
        Be careful when using number literals for *mode*.  The conventional
4219
        UNIX notation for numeric modes uses an octal base, which needs to
4220
        be indicated with a ``0o`` prefix in Python.
4221
4222
Change the access permissions of the file given by file descriptor fd.
4223
4224
Equivalent to os.chmod(fd, mode).
4225
[clinic start generated code]*/
4226
4227
static PyObject *
4228
os_fchmod_impl(PyObject *module, int fd, int mode)
4229
/*[clinic end generated code: output=afd9bc05b4e426b3 input=d24331f9fdc17f49]*/
4230
0
{
4231
0
    int res;
4232
4233
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4234
0
        return NULL;
4235
0
    }
4236
4237
#ifdef MS_WINDOWS
4238
    res = 0;
4239
    Py_BEGIN_ALLOW_THREADS
4240
    res = win32_fchmod(fd, mode);
4241
    Py_END_ALLOW_THREADS
4242
    if (!res) {
4243
        return PyErr_SetFromWindowsErr(0);
4244
    }
4245
#else /* MS_WINDOWS */
4246
0
    int async_err = 0;
4247
0
    do {
4248
0
        Py_BEGIN_ALLOW_THREADS
4249
0
        res = fchmod(fd, mode);
4250
0
        Py_END_ALLOW_THREADS
4251
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4252
0
    if (res != 0)
4253
0
        return (!async_err) ? posix_error() : NULL;
4254
0
#endif /* MS_WINDOWS */
4255
4256
0
    Py_RETURN_NONE;
4257
0
}
4258
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4259
4260
4261
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4262
/*[clinic input]
4263
@permit_long_summary
4264
os.lchmod
4265
4266
    path: path_t
4267
    mode: int
4268
4269
Change the access permissions of a file, without following symbolic links.
4270
4271
If path is a symlink, this affects the link itself rather than the
4272
target.  Equivalent to chmod(path, mode, follow_symlinks=False).
4273
[clinic start generated code]*/
4274
4275
static PyObject *
4276
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4277
/*[clinic end generated code: output=082344022b51a1d5 input=13110fb62911b015]*/
4278
{
4279
    int res;
4280
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4281
        return NULL;
4282
    }
4283
#ifdef MS_WINDOWS
4284
    Py_BEGIN_ALLOW_THREADS
4285
    res = win32_lchmod(path->wide, mode);
4286
    Py_END_ALLOW_THREADS
4287
    if (!res) {
4288
        path_error(path);
4289
        return NULL;
4290
    }
4291
#else /* MS_WINDOWS */
4292
    Py_BEGIN_ALLOW_THREADS
4293
    res = lchmod(path->narrow, mode);
4294
    Py_END_ALLOW_THREADS
4295
    if (res < 0) {
4296
        path_error(path);
4297
        return NULL;
4298
    }
4299
#endif /* MS_WINDOWS */
4300
    Py_RETURN_NONE;
4301
}
4302
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4303
4304
4305
#ifdef HAVE_CHFLAGS
4306
/*[clinic input]
4307
os.chflags
4308
4309
    path: path_t
4310
    flags: unsigned_long(bitwise=True)
4311
    follow_symlinks: bool=True
4312
4313
Set file flags.
4314
4315
If follow_symlinks is False, and the last element of the path is
4316
a symbolic link, chflags() will change flags on the symbolic link itself
4317
instead of the file the link points to.
4318
follow_symlinks may not be implemented on your platform.  If it is
4319
unavailable, using it will raise a NotImplementedError.
4320
4321
[clinic start generated code]*/
4322
4323
static PyObject *
4324
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4325
                int follow_symlinks)
4326
/*[clinic end generated code: output=85571c6737661ce9 input=31391927707be1de]*/
4327
{
4328
    int result;
4329
4330
#ifndef HAVE_LCHFLAGS
4331
    if (follow_symlinks_specified("chflags", follow_symlinks))
4332
        return NULL;
4333
#endif
4334
4335
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4336
        return NULL;
4337
    }
4338
4339
    Py_BEGIN_ALLOW_THREADS
4340
#ifdef HAVE_LCHFLAGS
4341
    if (!follow_symlinks)
4342
        result = lchflags(path->narrow, flags);
4343
    else
4344
#endif
4345
        result = chflags(path->narrow, flags);
4346
    Py_END_ALLOW_THREADS
4347
4348
    if (result)
4349
        return path_error(path);
4350
4351
    Py_RETURN_NONE;
4352
}
4353
#endif /* HAVE_CHFLAGS */
4354
4355
4356
#ifdef HAVE_LCHFLAGS
4357
/*[clinic input]
4358
os.lchflags
4359
4360
    path: path_t
4361
    flags: unsigned_long(bitwise=True)
4362
4363
Set file flags.
4364
4365
This function will not follow symbolic links.
4366
Equivalent to chflags(path, flags, follow_symlinks=False).
4367
[clinic start generated code]*/
4368
4369
static PyObject *
4370
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4371
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4372
{
4373
    int res;
4374
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4375
        return NULL;
4376
    }
4377
    Py_BEGIN_ALLOW_THREADS
4378
    res = lchflags(path->narrow, flags);
4379
    Py_END_ALLOW_THREADS
4380
    if (res < 0) {
4381
        return path_error(path);
4382
    }
4383
    Py_RETURN_NONE;
4384
}
4385
#endif /* HAVE_LCHFLAGS */
4386
4387
4388
#ifdef HAVE_CHROOT
4389
/*[clinic input]
4390
os.chroot
4391
    path: path_t
4392
4393
Change root directory to path.
4394
4395
[clinic start generated code]*/
4396
4397
static PyObject *
4398
os_chroot_impl(PyObject *module, path_t *path)
4399
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4400
0
{
4401
#ifdef __ANDROID__
4402
    // On Android, calling this function as a non-root user leads to a process crash
4403
    // rather than returning a permission error.
4404
    if (getuid() != 0) {
4405
        errno = EPERM;
4406
        return path_error(path);
4407
    }
4408
#endif
4409
0
    int res;
4410
0
    Py_BEGIN_ALLOW_THREADS
4411
0
    res = chroot(path->narrow);
4412
0
    Py_END_ALLOW_THREADS
4413
0
    if (res < 0)
4414
0
        return path_error(path);
4415
0
    Py_RETURN_NONE;
4416
0
}
4417
#endif /* HAVE_CHROOT */
4418
4419
4420
#ifdef HAVE_FSYNC
4421
/*[clinic input]
4422
os.fsync
4423
4424
    fd: fildes
4425
4426
Force write of fd to disk.
4427
[clinic start generated code]*/
4428
4429
static PyObject *
4430
os_fsync_impl(PyObject *module, int fd)
4431
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4432
0
{
4433
0
    return posix_fildes_fd(fd, fsync);
4434
0
}
4435
#endif /* HAVE_FSYNC */
4436
4437
4438
#ifdef HAVE_SYNC
4439
/*[clinic input]
4440
os.sync
4441
4442
Force write of everything to disk.
4443
[clinic start generated code]*/
4444
4445
static PyObject *
4446
os_sync_impl(PyObject *module)
4447
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4448
0
{
4449
0
    Py_BEGIN_ALLOW_THREADS
4450
0
    sync();
4451
0
    Py_END_ALLOW_THREADS
4452
0
    Py_RETURN_NONE;
4453
0
}
4454
#endif /* HAVE_SYNC */
4455
4456
4457
#ifdef HAVE_FDATASYNC
4458
#ifdef __hpux
4459
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4460
#endif
4461
4462
/*[clinic input]
4463
os.fdatasync
4464
4465
    fd: fildes
4466
4467
Force write of fd to disk without forcing update of metadata.
4468
[clinic start generated code]*/
4469
4470
static PyObject *
4471
os_fdatasync_impl(PyObject *module, int fd)
4472
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4473
0
{
4474
0
    return posix_fildes_fd(fd, fdatasync);
4475
0
}
4476
#endif /* HAVE_FDATASYNC */
4477
4478
4479
#ifdef HAVE_CHOWN
4480
/*[clinic input]
4481
os.chown
4482
4483
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4484
        Path to be examined; can be string, bytes, a path-like object, or
4485
        open-file-descriptor int.
4486
4487
    uid: uid_t
4488
4489
    gid: gid_t
4490
4491
    *
4492
4493
    dir_fd: dir_fd(requires='fchownat') = None
4494
        If not None, it should be a file descriptor open to a directory,
4495
        and path should be relative; path will then be relative to that
4496
        directory.
4497
4498
    follow_symlinks: bool = True
4499
        If False, and the last element of the path is a symbolic link,
4500
        stat will examine the symbolic link itself instead of the file
4501
        the link points to.
4502
4503
Change the owner and group id of path to the numeric uid and gid.
4504
4505
path may always be specified as a string.  On some platforms, path may
4506
also be specified as an open file descriptor.  If this functionality is
4507
unavailable, using it raises an exception.
4508
If dir_fd is not None, it should be a file descriptor open to
4509
a directory, and path should be relative; path will then be relative to
4510
that directory.
4511
If follow_symlinks is False, and the last element of the path is
4512
a symbolic link, chown will modify the symbolic link itself instead of
4513
the file the link points to.
4514
It is an error to use dir_fd or follow_symlinks when specifying path as
4515
an open file descriptor.
4516
dir_fd and follow_symlinks may not be implemented on your platform.  If
4517
they are unavailable, using them will raise a NotImplementedError.
4518
4519
[clinic start generated code]*/
4520
4521
static PyObject *
4522
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4523
              int dir_fd, int follow_symlinks)
4524
/*[clinic end generated code: output=4beadab0db5f70cd input=509c91b7a0e72f52]*/
4525
0
{
4526
0
    int result;
4527
4528
0
#if defined(HAVE_FCHOWNAT)
4529
0
    int fchownat_unsupported = 0;
4530
0
#endif
4531
4532
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4533
    if (follow_symlinks_specified("chown", follow_symlinks))
4534
        return NULL;
4535
#endif
4536
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4537
0
        fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
4538
0
        return NULL;
4539
4540
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4541
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4542
0
        return NULL;
4543
0
    }
4544
4545
0
    Py_BEGIN_ALLOW_THREADS
4546
0
#ifdef HAVE_FCHOWN
4547
0
    if (path->is_fd)
4548
0
        result = fchown(path->fd, uid, gid);
4549
0
    else
4550
0
#endif
4551
0
#ifdef HAVE_LCHOWN
4552
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4553
0
        result = lchown(path->narrow, uid, gid);
4554
0
    else
4555
0
#endif
4556
0
#ifdef HAVE_FCHOWNAT
4557
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4558
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4559
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4560
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4561
0
      } else {
4562
0
         fchownat_unsupported = 1;
4563
0
      }
4564
0
    } else
4565
0
#endif
4566
0
        result = chown(path->narrow, uid, gid);
4567
0
    Py_END_ALLOW_THREADS
4568
4569
0
#ifdef HAVE_FCHOWNAT
4570
0
    if (fchownat_unsupported) {
4571
        /* This would be incorrect if the current platform
4572
         * doesn't support lchown.
4573
         */
4574
0
        argument_unavailable_error(NULL, "dir_fd");
4575
0
        return NULL;
4576
0
    }
4577
0
#endif
4578
4579
0
    if (result)
4580
0
        return path_error(path);
4581
4582
0
    Py_RETURN_NONE;
4583
0
}
4584
#endif /* HAVE_CHOWN */
4585
4586
4587
#ifdef HAVE_FCHOWN
4588
/*[clinic input]
4589
os.fchown
4590
4591
    fd: int
4592
    uid: uid_t
4593
    gid: gid_t
4594
4595
Change the owner and group id of the file specified by file descriptor.
4596
4597
Equivalent to os.chown(fd, uid, gid).
4598
4599
[clinic start generated code]*/
4600
4601
static PyObject *
4602
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4603
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4604
0
{
4605
0
    int res;
4606
0
    int async_err = 0;
4607
4608
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4609
0
        return NULL;
4610
0
    }
4611
4612
0
    do {
4613
0
        Py_BEGIN_ALLOW_THREADS
4614
0
        res = fchown(fd, uid, gid);
4615
0
        Py_END_ALLOW_THREADS
4616
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4617
0
    if (res != 0)
4618
0
        return (!async_err) ? posix_error() : NULL;
4619
4620
0
    Py_RETURN_NONE;
4621
0
}
4622
#endif /* HAVE_FCHOWN */
4623
4624
4625
#ifdef HAVE_LCHOWN
4626
/*[clinic input]
4627
os.lchown
4628
4629
    path : path_t
4630
    uid: uid_t
4631
    gid: gid_t
4632
4633
Change the owner and group id of path to the numeric uid and gid.
4634
4635
This function will not follow symbolic links.
4636
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4637
[clinic start generated code]*/
4638
4639
static PyObject *
4640
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4641
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4642
0
{
4643
0
    int res;
4644
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4645
0
        return NULL;
4646
0
    }
4647
0
    Py_BEGIN_ALLOW_THREADS
4648
0
    res = lchown(path->narrow, uid, gid);
4649
0
    Py_END_ALLOW_THREADS
4650
0
    if (res < 0) {
4651
0
        return path_error(path);
4652
0
    }
4653
0
    Py_RETURN_NONE;
4654
0
}
4655
#endif /* HAVE_LCHOWN */
4656
4657
4658
static PyObject *
4659
posix_getcwd(int use_bytes)
4660
8
{
4661
#ifdef MS_WINDOWS
4662
    wchar_t wbuf[MAXPATHLEN];
4663
    wchar_t *wbuf2 = wbuf;
4664
    DWORD len;
4665
4666
    Py_BEGIN_ALLOW_THREADS
4667
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4668
    /* If the buffer is large enough, len does not include the
4669
       terminating \0. If the buffer is too small, len includes
4670
       the space needed for the terminator. */
4671
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4672
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4673
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4674
        }
4675
        else {
4676
            wbuf2 = NULL;
4677
        }
4678
        if (wbuf2) {
4679
            len = GetCurrentDirectoryW(len, wbuf2);
4680
        }
4681
    }
4682
    Py_END_ALLOW_THREADS
4683
4684
    if (!wbuf2) {
4685
        PyErr_NoMemory();
4686
        return NULL;
4687
    }
4688
    if (!len) {
4689
        PyErr_SetFromWindowsErr(0);
4690
        if (wbuf2 != wbuf)
4691
            PyMem_RawFree(wbuf2);
4692
        return NULL;
4693
    }
4694
4695
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4696
    if (wbuf2 != wbuf) {
4697
        PyMem_RawFree(wbuf2);
4698
    }
4699
4700
    if (use_bytes) {
4701
        if (resobj == NULL) {
4702
            return NULL;
4703
        }
4704
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4705
    }
4706
4707
    return resobj;
4708
#else
4709
8
    const size_t chunk = 1024;
4710
4711
8
    char *buf = NULL;
4712
8
    char *cwd = NULL;
4713
8
    size_t buflen = 0;
4714
4715
8
    Py_BEGIN_ALLOW_THREADS
4716
8
    do {
4717
8
        char *newbuf;
4718
8
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4719
8
            buflen += chunk;
4720
8
            newbuf = PyMem_RawRealloc(buf, buflen);
4721
8
        }
4722
0
        else {
4723
0
            newbuf = NULL;
4724
0
        }
4725
8
        if (newbuf == NULL) {
4726
0
            PyMem_RawFree(buf);
4727
0
            buf = NULL;
4728
0
            break;
4729
0
        }
4730
8
        buf = newbuf;
4731
4732
8
        cwd = getcwd(buf, buflen);
4733
8
    } while (cwd == NULL && errno == ERANGE);
4734
8
    Py_END_ALLOW_THREADS
4735
4736
8
    if (buf == NULL) {
4737
0
        return PyErr_NoMemory();
4738
0
    }
4739
8
    if (cwd == NULL) {
4740
0
        posix_error();
4741
0
        PyMem_RawFree(buf);
4742
0
        return NULL;
4743
0
    }
4744
4745
8
    PyObject *obj;
4746
8
    if (use_bytes) {
4747
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4748
0
    }
4749
8
    else {
4750
8
        obj = PyUnicode_DecodeFSDefault(buf);
4751
8
    }
4752
8
#ifdef __linux__
4753
8
    if (buf[0] != '/') {
4754
        /*
4755
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4756
         * relative pathname starting with '(unreachable)'. We detect this
4757
         * and fail with ENOENT, matching newer glibc behaviour.
4758
         */
4759
0
        errno = ENOENT;
4760
0
        path_object_error(obj);
4761
0
        PyMem_RawFree(buf);
4762
0
        return NULL;
4763
0
    }
4764
8
#endif
4765
8
    assert(buf[0] == '/');
4766
8
    PyMem_RawFree(buf);
4767
4768
8
    return obj;
4769
8
#endif   /* !MS_WINDOWS */
4770
8
}
4771
4772
4773
/*[clinic input]
4774
os.getcwd
4775
4776
Return a unicode string representing the current working directory.
4777
[clinic start generated code]*/
4778
4779
static PyObject *
4780
os_getcwd_impl(PyObject *module)
4781
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4782
8
{
4783
8
    return posix_getcwd(0);
4784
8
}
4785
4786
4787
/*[clinic input]
4788
os.getcwdb
4789
4790
Return a bytes string representing the current working directory.
4791
[clinic start generated code]*/
4792
4793
static PyObject *
4794
os_getcwdb_impl(PyObject *module)
4795
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4796
0
{
4797
0
    return posix_getcwd(1);
4798
0
}
4799
4800
4801
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4802
#define HAVE_LINK 1
4803
#endif
4804
4805
#ifdef HAVE_LINK
4806
/*[clinic input]
4807
4808
os.link
4809
4810
    src : path_t
4811
    dst : path_t
4812
    *
4813
    src_dir_fd : dir_fd = None
4814
    dst_dir_fd : dir_fd = None
4815
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4816
4817
Create a hard link to a file.
4818
4819
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4820
descriptor open to a directory, and the respective path string (src or
4821
dst) should be relative; the path will then be relative to that
4822
directory.
4823
If follow_symlinks is False, and the last element of src is a symbolic
4824
link, link will create a link to the symbolic link itself instead of the
4825
file the link points to.
4826
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on
4827
your platform.  If they are unavailable, using them will raise
4828
a NotImplementedError.
4829
[clinic start generated code]*/
4830
4831
static PyObject *
4832
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4833
             int dst_dir_fd, int follow_symlinks)
4834
/*[clinic end generated code: output=7f00f6007fd5269a input=a28e6866fbd20a01]*/
4835
0
{
4836
#ifdef MS_WINDOWS
4837
    BOOL result = FALSE;
4838
#else
4839
0
    int result;
4840
0
#endif
4841
4842
0
#ifdef HAVE_LINKAT
4843
0
    if (HAVE_LINKAT_RUNTIME) {
4844
0
        if (follow_symlinks < 0) {
4845
0
            follow_symlinks = 1;
4846
0
        }
4847
0
    }
4848
0
    else
4849
0
#endif
4850
0
    {
4851
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4852
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4853
0
            return NULL;
4854
0
        }
4855
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4856
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4857
0
#if defined(MS_WINDOWS) || defined(__linux__)
4858
0
        if (follow_symlinks == 1) {
4859
0
            argument_unavailable_error("link", "follow_symlinks=True");
4860
0
            return NULL;
4861
0
        }
4862
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4863
        if (follow_symlinks == 0) {
4864
            argument_unavailable_error("link", "follow_symlinks=False");
4865
            return NULL;
4866
        }
4867
#else
4868
        if (follow_symlinks >= 0) {
4869
            argument_unavailable_error("link", "follow_symlinks");
4870
            return NULL;
4871
        }
4872
#endif
4873
0
    }
4874
4875
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4876
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4877
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4878
0
        return NULL;
4879
0
    }
4880
4881
#ifdef MS_WINDOWS
4882
    Py_BEGIN_ALLOW_THREADS
4883
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4884
    Py_END_ALLOW_THREADS
4885
4886
    if (!result)
4887
        return path_error2(src, dst);
4888
#else
4889
0
    Py_BEGIN_ALLOW_THREADS
4890
0
#ifdef HAVE_LINKAT
4891
0
    if (HAVE_LINKAT_RUNTIME) {
4892
0
        result = linkat(src_dir_fd, src->narrow,
4893
0
            dst_dir_fd, dst->narrow,
4894
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4895
0
    }
4896
0
    else
4897
0
#endif
4898
0
    {
4899
        /* linkat not available */
4900
0
        result = link(src->narrow, dst->narrow);
4901
0
    }
4902
0
    Py_END_ALLOW_THREADS
4903
4904
0
    if (result)
4905
0
        return path_error2(src, dst);
4906
0
#endif /* MS_WINDOWS */
4907
4908
0
    Py_RETURN_NONE;
4909
0
}
4910
#endif
4911
4912
4913
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4914
static wchar_t *
4915
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,
4916
                    int normalize);
4917
4918
static PyObject *
4919
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4920
{
4921
    PyObject *v;
4922
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4923
    BOOL result, return_bytes;
4924
    wchar_t *wnamebuf = NULL;
4925
4926
    WIN32_FIND_DATAW wFileData;
4927
    const wchar_t *po_wchars;
4928
4929
    if (!path->wide) { /* Default arg: "." */
4930
        po_wchars = L".";
4931
        return_bytes = 0;
4932
    } else {
4933
        po_wchars = path->wide;
4934
        return_bytes = PyBytes_Check(path->object);
4935
    }
4936
4937
    wnamebuf = join_path_filenameW(po_wchars, L"*.*", 1);
4938
    if (wnamebuf == NULL) {
4939
        goto exit;
4940
    }
4941
4942
    if ((list = PyList_New(0)) == NULL) {
4943
        goto exit;
4944
    }
4945
    Py_BEGIN_ALLOW_THREADS
4946
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4947
    Py_END_ALLOW_THREADS
4948
    if (hFindFile == INVALID_HANDLE_VALUE) {
4949
        int error = GetLastError();
4950
        if (error == ERROR_FILE_NOT_FOUND)
4951
            goto exit;
4952
        path_error(path);
4953
        Py_CLEAR(list);
4954
        goto exit;
4955
    }
4956
    do {
4957
        /* Skip over . and .. */
4958
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4959
            wcscmp(wFileData.cFileName, L"..") != 0) {
4960
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4961
                                       wcslen(wFileData.cFileName));
4962
            if (return_bytes && v) {
4963
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4964
            }
4965
            if (v == NULL) {
4966
                Py_CLEAR(list);
4967
                break;
4968
            }
4969
            if (PyList_Append(list, v) != 0) {
4970
                Py_DECREF(v);
4971
                Py_CLEAR(list);
4972
                break;
4973
            }
4974
            Py_DECREF(v);
4975
        }
4976
        Py_BEGIN_ALLOW_THREADS
4977
        result = FindNextFileW(hFindFile, &wFileData);
4978
        Py_END_ALLOW_THREADS
4979
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4980
           it got to the end of the directory. */
4981
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4982
            path_error(path);
4983
            Py_CLEAR(list);
4984
            goto exit;
4985
        }
4986
    } while (result == TRUE);
4987
4988
exit:
4989
    if (hFindFile != INVALID_HANDLE_VALUE) {
4990
        if (FindClose(hFindFile) == FALSE) {
4991
            if (list != NULL) {
4992
                path_error(path);
4993
                Py_CLEAR(list);
4994
            }
4995
        }
4996
    }
4997
    PyMem_Free(wnamebuf);
4998
4999
    return list;
5000
}  /* end of _listdir_windows_no_opendir */
5001
5002
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
5003
5004
static PyObject *
5005
_posix_listdir(path_t *path, PyObject *list)
5006
397
{
5007
397
    PyObject *v;
5008
397
    DIR *dirp = NULL;
5009
397
    struct dirent *ep;
5010
397
    int return_str; /* if false, return bytes */
5011
397
#ifdef HAVE_FDOPENDIR
5012
397
    int fd = -1;
5013
397
#endif
5014
5015
397
    errno = 0;
5016
397
#ifdef HAVE_FDOPENDIR
5017
397
    if (path->is_fd) {
5018
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5019
        /* closedir() closes the FD, so we duplicate it */
5020
0
        fd = _Py_dup(path->fd);
5021
0
        if (fd == -1)
5022
0
            return NULL;
5023
5024
0
        return_str = 1;
5025
5026
0
        Py_BEGIN_ALLOW_THREADS
5027
0
        dirp = fdopendir(fd);
5028
0
        Py_END_ALLOW_THREADS
5029
0
      } else {
5030
0
        PyErr_SetString(PyExc_TypeError,
5031
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5032
0
        return NULL;
5033
0
      }
5034
0
    }
5035
397
    else
5036
397
#endif
5037
397
    {
5038
397
        const char *name;
5039
397
        if (path->narrow) {
5040
397
            name = path->narrow;
5041
            /* only return bytes if they specified a bytes object */
5042
397
            return_str = !PyBytes_Check(path->object);
5043
397
        }
5044
0
        else {
5045
0
            name = ".";
5046
0
            return_str = 1;
5047
0
        }
5048
5049
397
        Py_BEGIN_ALLOW_THREADS
5050
397
        dirp = opendir(name);
5051
397
        Py_END_ALLOW_THREADS
5052
397
    }
5053
5054
397
    if (dirp == NULL) {
5055
4
        path_error(path);
5056
4
        list = NULL;
5057
4
#ifdef HAVE_FDOPENDIR
5058
4
        if (fd != -1) {
5059
0
            Py_BEGIN_ALLOW_THREADS
5060
0
            close(fd);
5061
0
            Py_END_ALLOW_THREADS
5062
0
        }
5063
4
#endif
5064
4
        goto exit;
5065
4
    }
5066
393
    if ((list = PyList_New(0)) == NULL) {
5067
0
        goto exit;
5068
0
    }
5069
23.2k
    for (;;) {
5070
23.2k
        errno = 0;
5071
23.2k
        Py_BEGIN_ALLOW_THREADS
5072
23.2k
        ep = readdir(dirp);
5073
23.2k
        Py_END_ALLOW_THREADS
5074
23.2k
        if (ep == NULL) {
5075
393
            if (errno == 0) {
5076
393
                break;
5077
393
            } else {
5078
0
                path_error(path);
5079
0
                Py_CLEAR(list);
5080
0
                goto exit;
5081
0
            }
5082
393
        }
5083
22.9k
        if (ep->d_name[0] == '.' &&
5084
822
            (NAMLEN(ep) == 1 ||
5085
429
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5086
786
            continue;
5087
22.1k
        if (return_str)
5088
22.1k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5089
0
        else
5090
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5091
22.1k
        if (v == NULL) {
5092
0
            Py_CLEAR(list);
5093
0
            break;
5094
0
        }
5095
22.1k
        if (PyList_Append(list, v) != 0) {
5096
0
            Py_DECREF(v);
5097
0
            Py_CLEAR(list);
5098
0
            break;
5099
0
        }
5100
22.1k
        Py_DECREF(v);
5101
22.1k
    }
5102
5103
397
exit:
5104
397
    if (dirp != NULL) {
5105
393
        Py_BEGIN_ALLOW_THREADS
5106
393
#ifdef HAVE_FDOPENDIR
5107
393
        if (fd > -1)
5108
0
            rewinddir(dirp);
5109
393
#endif
5110
393
        closedir(dirp);
5111
393
        Py_END_ALLOW_THREADS
5112
393
    }
5113
5114
397
    return list;
5115
393
}  /* end of _posix_listdir */
5116
#endif  /* which OS */
5117
5118
5119
/*[clinic input]
5120
os.listdir
5121
5122
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5123
5124
Return a list containing the names of the files in the directory.
5125
5126
path can be specified as either str, bytes, or a path-like object.  If
5127
path is bytes, the filenames returned will also be bytes; in all other
5128
circumstances the filenames returned will be str.
5129
If path is None, uses the path='.'.
5130
On some platforms, path may also be specified as an open file
5131
descriptor; the file descriptor must refer to a directory.  If this
5132
functionality is unavailable, using it raises NotImplementedError.
5133
5134
The list is in arbitrary order.  It does not include the special
5135
entries '.' and '..' even if they are present in the directory.
5136
5137
[clinic start generated code]*/
5138
5139
static PyObject *
5140
os_listdir_impl(PyObject *module, path_t *path)
5141
/*[clinic end generated code: output=293045673fcd1a75 input=4eefe7c6a42ec9b2]*/
5142
397
{
5143
397
    if (PySys_Audit("os.listdir", "O",
5144
397
                    path->object ? path->object : Py_None) < 0) {
5145
0
        return NULL;
5146
0
    }
5147
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5148
    return _listdir_windows_no_opendir(path, NULL);
5149
#else
5150
397
    return _posix_listdir(path, NULL);
5151
397
#endif
5152
397
}
5153
5154
5155
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5156
5157
/*[clinic input]
5158
os.listdrives
5159
5160
Return a list containing the names of drives in the system.
5161
5162
A drive name typically looks like 'C:\\'.
5163
5164
[clinic start generated code]*/
5165
5166
static PyObject *
5167
os_listdrives_impl(PyObject *module)
5168
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5169
{
5170
    /* Number of possible drives is limited, so 256 should always be enough.
5171
       On the day when it is not, listmounts() will have to be used. */
5172
    wchar_t buffer[256];
5173
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5174
    PyObject *result = NULL;
5175
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5176
        return NULL;
5177
    }
5178
5179
    Py_BEGIN_ALLOW_THREADS;
5180
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5181
    Py_END_ALLOW_THREADS;
5182
5183
    if (!buflen) {
5184
        PyErr_SetFromWindowsErr(0);
5185
        return NULL;
5186
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5187
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5188
        return NULL;
5189
    }
5190
5191
    /* buflen includes a null terminator, so remove it */
5192
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5193
    if (str) {
5194
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5195
        if (nullchar) {
5196
            result = PyUnicode_Split(str, nullchar, -1);
5197
            Py_DECREF(nullchar);
5198
        }
5199
        Py_DECREF(str);
5200
    }
5201
    return result;
5202
}
5203
5204
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5205
5206
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5207
5208
/*[clinic input]
5209
os.listvolumes
5210
5211
Return a list containing the volumes in the system.
5212
5213
Volumes are typically represented as a GUID path.
5214
5215
[clinic start generated code]*/
5216
5217
static PyObject *
5218
os_listvolumes_impl(PyObject *module)
5219
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5220
{
5221
    PyObject *result = PyList_New(0);
5222
    HANDLE find = INVALID_HANDLE_VALUE;
5223
    wchar_t buffer[MAX_PATH + 1];
5224
    if (!result) {
5225
        return NULL;
5226
    }
5227
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5228
        Py_DECREF(result);
5229
        return NULL;
5230
    }
5231
5232
    int err = 0;
5233
    Py_BEGIN_ALLOW_THREADS;
5234
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5235
    if (find == INVALID_HANDLE_VALUE) {
5236
        err = GetLastError();
5237
    }
5238
    Py_END_ALLOW_THREADS;
5239
5240
    while (!err) {
5241
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5242
        if (!s || PyList_Append(result, s) < 0) {
5243
            Py_XDECREF(s);
5244
            Py_CLEAR(result);
5245
            break;
5246
        }
5247
        Py_DECREF(s);
5248
5249
        Py_BEGIN_ALLOW_THREADS;
5250
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5251
            err = GetLastError();
5252
        }
5253
        Py_END_ALLOW_THREADS;
5254
    }
5255
5256
    if (find != INVALID_HANDLE_VALUE) {
5257
        Py_BEGIN_ALLOW_THREADS;
5258
        FindVolumeClose(find);
5259
        Py_END_ALLOW_THREADS;
5260
    }
5261
    if (err && err != ERROR_NO_MORE_FILES) {
5262
        PyErr_SetFromWindowsErr(err);
5263
        Py_XDECREF(result);
5264
        result = NULL;
5265
    }
5266
    return result;
5267
}
5268
5269
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5270
5271
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5272
5273
/*[clinic input]
5274
os.listmounts
5275
5276
    volume: path_t
5277
5278
Return a list containing mount points for a particular volume.
5279
5280
'volume' should be a GUID path as returned from os.listvolumes.
5281
5282
[clinic start generated code]*/
5283
5284
static PyObject *
5285
os_listmounts_impl(PyObject *module, path_t *volume)
5286
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5287
{
5288
    wchar_t default_buffer[MAX_PATH + 1];
5289
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5290
    LPWSTR buffer = default_buffer;
5291
    DWORD attributes;
5292
    PyObject *str = NULL;
5293
    PyObject *nullchar = NULL;
5294
    PyObject *result = NULL;
5295
5296
    /* Ensure we have a valid volume path before continuing */
5297
    Py_BEGIN_ALLOW_THREADS
5298
    attributes = GetFileAttributesW(volume->wide);
5299
    Py_END_ALLOW_THREADS
5300
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5301
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5302
    {
5303
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5304
    }
5305
5306
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5307
        return NULL;
5308
    }
5309
5310
    while (1) {
5311
        BOOL success;
5312
        Py_BEGIN_ALLOW_THREADS
5313
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5314
                                                   buflen, &buflen);
5315
        Py_END_ALLOW_THREADS
5316
        if (success) {
5317
            break;
5318
        }
5319
        if (GetLastError() != ERROR_MORE_DATA) {
5320
            PyErr_SetFromWindowsErr(0);
5321
            goto exit;
5322
        }
5323
        if (buffer != default_buffer) {
5324
            PyMem_Free((void *)buffer);
5325
        }
5326
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5327
        if (!buffer) {
5328
            PyErr_NoMemory();
5329
            goto exit;
5330
        }
5331
    }
5332
    if (buflen < 2) {
5333
        result = PyList_New(0);
5334
        goto exit;
5335
    }
5336
    // buflen includes two null terminators, one for the last string
5337
    // and one for the array of strings.
5338
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5339
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5340
    if (str && nullchar) {
5341
        result = PyUnicode_Split(str, nullchar, -1);
5342
    }
5343
exit:
5344
    if (buffer != default_buffer) {
5345
        PyMem_Free(buffer);
5346
    }
5347
    Py_XDECREF(nullchar);
5348
    Py_XDECREF(str);
5349
    return result;
5350
}
5351
5352
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5353
5354
#ifdef MS_WINDOWS
5355
5356
/*[clinic input]
5357
os._path_isdevdrive
5358
5359
    path: path_t
5360
5361
Determines whether the specified path is on a Windows Dev Drive.
5362
5363
[clinic start generated code]*/
5364
5365
static PyObject *
5366
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5367
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5368
{
5369
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5370
    /* This flag will be documented at
5371
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5372
       after release, and will be available in the latest WinSDK.
5373
       We include the flag to avoid a specific version dependency
5374
       on the latest WinSDK. */
5375
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5376
#endif
5377
    int err = 0;
5378
    PyObject *r = NULL;
5379
    wchar_t volume[MAX_PATH];
5380
5381
    Py_BEGIN_ALLOW_THREADS
5382
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5383
        /* invalid path of some kind */
5384
        /* Note that this also includes the case where a volume is mounted
5385
           in a path longer than 260 characters. This is likely to be rare
5386
           and problematic for other reasons, so a (soft) failure in this
5387
           check seems okay. */
5388
        err = GetLastError();
5389
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5390
        /* only care about local dev drives */
5391
        r = Py_False;
5392
    } else {
5393
        HANDLE hVolume = CreateFileW(
5394
            volume,
5395
            FILE_READ_ATTRIBUTES,
5396
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5397
            NULL,
5398
            OPEN_EXISTING,
5399
            FILE_FLAG_BACKUP_SEMANTICS,
5400
            NULL
5401
        );
5402
        if (hVolume == INVALID_HANDLE_VALUE) {
5403
            err = GetLastError();
5404
        } else {
5405
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5406
            volumeState.Version = 1;
5407
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5408
            if (!DeviceIoControl(
5409
                hVolume,
5410
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5411
                &volumeState,
5412
                sizeof(volumeState),
5413
                &volumeState,
5414
                sizeof(volumeState),
5415
                NULL,
5416
                NULL
5417
            )) {
5418
                err = GetLastError();
5419
            }
5420
            CloseHandle(hVolume);
5421
            if (err == ERROR_INVALID_PARAMETER) {
5422
                /* not supported on this platform */
5423
                r = Py_False;
5424
            } else if (!err) {
5425
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5426
                    ? Py_True : Py_False;
5427
            }
5428
        }
5429
    }
5430
    Py_END_ALLOW_THREADS
5431
5432
    if (err) {
5433
        PyErr_SetFromWindowsErr(err);
5434
        return NULL;
5435
    }
5436
5437
    if (r) {
5438
        return Py_NewRef(r);
5439
    }
5440
5441
    return NULL;
5442
}
5443
5444
5445
int
5446
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5447
{
5448
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5449
    DWORD result;
5450
5451
    result = GetFullPathNameW(path,
5452
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5453
                              NULL);
5454
    if (!result) {
5455
        return -1;
5456
    }
5457
5458
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5459
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5460
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5461
        }
5462
        else {
5463
            woutbufp = NULL;
5464
        }
5465
        if (!woutbufp) {
5466
            *abspath_p = NULL;
5467
            return 0;
5468
        }
5469
5470
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5471
        if (!result) {
5472
            PyMem_RawFree(woutbufp);
5473
            return -1;
5474
        }
5475
    }
5476
5477
    if (woutbufp != woutbuf) {
5478
        *abspath_p = woutbufp;
5479
        return 0;
5480
    }
5481
5482
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5483
    return 0;
5484
}
5485
5486
5487
/* A helper function for abspath on win32 */
5488
/*[clinic input]
5489
os._getfullpathname
5490
5491
    path: path_t
5492
    /
5493
5494
[clinic start generated code]*/
5495
5496
static PyObject *
5497
os__getfullpathname_impl(PyObject *module, path_t *path)
5498
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5499
{
5500
    wchar_t *abspath;
5501
5502
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5503
        return win32_error_object("GetFullPathNameW", path->object);
5504
    }
5505
    if (abspath == NULL) {
5506
        return PyErr_NoMemory();
5507
    }
5508
5509
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5510
    PyMem_RawFree(abspath);
5511
    if (str == NULL) {
5512
        return NULL;
5513
    }
5514
    if (PyBytes_Check(path->object)) {
5515
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5516
    }
5517
    return str;
5518
}
5519
5520
5521
/*[clinic input]
5522
os._getfinalpathname
5523
5524
    path: path_t
5525
    /
5526
5527
A helper function for samepath on windows.
5528
[clinic start generated code]*/
5529
5530
static PyObject *
5531
os__getfinalpathname_impl(PyObject *module, path_t *path)
5532
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5533
{
5534
    HANDLE hFile;
5535
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5536
    int buf_size = Py_ARRAY_LENGTH(buf);
5537
    int result_length;
5538
    PyObject *result;
5539
5540
    Py_BEGIN_ALLOW_THREADS
5541
    hFile = CreateFileW(
5542
        path->wide,
5543
        0, /* desired access */
5544
        0, /* share mode */
5545
        NULL, /* security attributes */
5546
        OPEN_EXISTING,
5547
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5548
        FILE_FLAG_BACKUP_SEMANTICS,
5549
        NULL);
5550
    Py_END_ALLOW_THREADS
5551
5552
    if (hFile == INVALID_HANDLE_VALUE) {
5553
        return win32_error_object("CreateFileW", path->object);
5554
    }
5555
5556
    /* We have a good handle to the target, use it to determine the
5557
       target path name. */
5558
    while (1) {
5559
        Py_BEGIN_ALLOW_THREADS
5560
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5561
                                                  buf_size, VOLUME_NAME_DOS);
5562
        Py_END_ALLOW_THREADS
5563
5564
        if (!result_length) {
5565
            result = win32_error_object("GetFinalPathNameByHandleW",
5566
                                         path->object);
5567
            goto cleanup;
5568
        }
5569
5570
        if (result_length < buf_size) {
5571
            break;
5572
        }
5573
5574
        wchar_t *tmp;
5575
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5576
                            result_length * sizeof(*tmp));
5577
        if (!tmp) {
5578
            result = PyErr_NoMemory();
5579
            goto cleanup;
5580
        }
5581
5582
        buf_size = result_length;
5583
        target_path = tmp;
5584
    }
5585
5586
    result = PyUnicode_FromWideChar(target_path, result_length);
5587
    if (result && PyBytes_Check(path->object)) {
5588
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5589
    }
5590
5591
cleanup:
5592
    if (target_path != buf) {
5593
        PyMem_Free(target_path);
5594
    }
5595
    CloseHandle(hFile);
5596
    return result;
5597
}
5598
5599
/*[clinic input]
5600
@permit_long_summary
5601
os._findfirstfile
5602
    path: path_t
5603
    /
5604
A function to get the real file name without accessing the file in Windows.
5605
[clinic start generated code]*/
5606
5607
static PyObject *
5608
os__findfirstfile_impl(PyObject *module, path_t *path)
5609
/*[clinic end generated code: output=106dd3f0779c83dd input=48c319aaa48d05d4]*/
5610
{
5611
    PyObject *result;
5612
    HANDLE hFindFile;
5613
    WIN32_FIND_DATAW wFileData;
5614
    WCHAR *wRealFileName;
5615
5616
    Py_BEGIN_ALLOW_THREADS
5617
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5618
    Py_END_ALLOW_THREADS
5619
5620
    if (hFindFile == INVALID_HANDLE_VALUE) {
5621
        path_error(path);
5622
        return NULL;
5623
    }
5624
5625
    wRealFileName = wFileData.cFileName;
5626
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5627
    FindClose(hFindFile);
5628
    return result;
5629
}
5630
5631
5632
/*[clinic input]
5633
os._getvolumepathname
5634
5635
    path: path_t
5636
5637
A helper function for ismount on Win32.
5638
[clinic start generated code]*/
5639
5640
static PyObject *
5641
os__getvolumepathname_impl(PyObject *module, path_t *path)
5642
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5643
{
5644
    PyObject *result;
5645
    wchar_t *mountpath=NULL;
5646
    size_t buflen;
5647
    BOOL ret;
5648
5649
    /* Volume path should be shorter than entire path */
5650
    buflen = Py_MAX(path->length, MAX_PATH);
5651
5652
    if (buflen > PY_DWORD_MAX) {
5653
        PyErr_SetString(PyExc_OverflowError, "path too long");
5654
        return NULL;
5655
    }
5656
5657
    mountpath = PyMem_New(wchar_t, buflen);
5658
    if (mountpath == NULL)
5659
        return PyErr_NoMemory();
5660
5661
    Py_BEGIN_ALLOW_THREADS
5662
    ret = GetVolumePathNameW(path->wide, mountpath,
5663
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5664
    Py_END_ALLOW_THREADS
5665
5666
    if (!ret) {
5667
        result = win32_error_object("_getvolumepathname", path->object);
5668
        goto exit;
5669
    }
5670
    result = PyUnicode_FromWideChar(mountpath, -1);
5671
    if (result != NULL && PyBytes_Check(path->object)) {
5672
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5673
    }
5674
5675
exit:
5676
    PyMem_Free(mountpath);
5677
    return result;
5678
}
5679
5680
5681
/*[clinic input]
5682
os._path_splitroot
5683
5684
    path: path_t
5685
    /
5686
5687
Removes everything after the root on Win32.
5688
[clinic start generated code]*/
5689
5690
static PyObject *
5691
os__path_splitroot_impl(PyObject *module, path_t *path)
5692
/*[clinic end generated code: output=ab7f1a88b654581c input=d356de1edb6050a2]*/
5693
{
5694
    wchar_t *buffer;
5695
    wchar_t *end;
5696
    PyObject *result = NULL;
5697
    HRESULT ret;
5698
5699
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5700
    if (!buffer) {
5701
        return PyErr_NoMemory();
5702
    }
5703
    wcscpy(buffer, path->wide);
5704
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5705
        *p = L'\\';
5706
    }
5707
5708
    Py_BEGIN_ALLOW_THREADS
5709
    ret = PathCchSkipRoot(buffer, &end);
5710
    Py_END_ALLOW_THREADS
5711
    if (FAILED(ret)) {
5712
        result = Py_BuildValue("sO", "", path->object);
5713
    } else if (end != buffer) {
5714
        size_t rootLen = (size_t)(end - buffer);
5715
        result = Py_BuildValue("NN",
5716
            PyUnicode_FromWideChar(path->wide, rootLen),
5717
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5718
        );
5719
    } else {
5720
        result = Py_BuildValue("Os", path->object, "");
5721
    }
5722
    PyMem_Free(buffer);
5723
5724
    return result;
5725
}
5726
5727
5728
#define PY_IFREG  1 // Regular file
5729
#define PY_IFDIR  2 // Directory
5730
#define PY_IFLNK  4 // Symlink
5731
#define PY_IFMNT  8 // Mount Point (junction)
5732
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5733
#define PY_IFRRP 32 // Regular Reparse Point
5734
5735
static inline BOOL
5736
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5737
{
5738
    switch (testedType) {
5739
    case PY_IFREG:
5740
        return diskDevice && attributes &&
5741
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5742
    case PY_IFDIR:
5743
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5744
    case PY_IFLNK:
5745
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5746
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5747
    case PY_IFMNT:
5748
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5749
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5750
    case PY_IFLRP:
5751
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5752
               IsReparseTagNameSurrogate(reparseTag);
5753
    case PY_IFRRP:
5754
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5755
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5756
    }
5757
5758
    return FALSE;
5759
}
5760
5761
static BOOL
5762
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5763
{
5764
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5765
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5766
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5767
5768
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5769
    if (diskOnly && !diskDevice) {
5770
        return FALSE;
5771
    }
5772
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5773
        FILE_ATTRIBUTE_TAG_INFO info;
5774
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5775
                                            sizeof(info)) &&
5776
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5777
                         testedType);
5778
    }
5779
    FILE_BASIC_INFO info;
5780
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5781
                                        sizeof(info)) &&
5782
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5783
}
5784
5785
static BOOL
5786
_testFileTypeByName(LPCWSTR path, int testedType)
5787
{
5788
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5789
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5790
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5791
5792
    FILE_STAT_BASIC_INFORMATION info;
5793
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5794
                                     sizeof(info)))
5795
    {
5796
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5797
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5798
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5799
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5800
                                diskDevice, testedType);
5801
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5802
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5803
        {
5804
            return result;
5805
        }
5806
    }
5807
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5808
                GetLastError()))
5809
    {
5810
        return FALSE;
5811
    }
5812
5813
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5814
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5815
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5816
    }
5817
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5818
                               OPEN_EXISTING, flags, NULL);
5819
    if (hfile != INVALID_HANDLE_VALUE) {
5820
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5821
        CloseHandle(hfile);
5822
        return result;
5823
    }
5824
5825
    switch (GetLastError()) {
5826
    case ERROR_ACCESS_DENIED:
5827
    case ERROR_SHARING_VIOLATION:
5828
    case ERROR_CANT_ACCESS_FILE:
5829
    case ERROR_INVALID_PARAMETER:
5830
        int rc;
5831
        STRUCT_STAT st;
5832
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5833
            rc = STAT(path, &st);
5834
        }
5835
        else {
5836
            // PY_IFRRP is not generally supported in this case, except for
5837
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5838
            rc = LSTAT(path, &st);
5839
        }
5840
        if (!rc) {
5841
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5842
                             st.st_mode & S_IFREG, testedType);
5843
        }
5844
    }
5845
5846
    return FALSE;
5847
}
5848
5849
5850
static BOOL
5851
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5852
{
5853
    FILE_STAT_BASIC_INFORMATION info;
5854
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5855
                                     sizeof(info)))
5856
    {
5857
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5858
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5859
        {
5860
            return TRUE;
5861
        }
5862
    }
5863
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5864
                    GetLastError()))
5865
    {
5866
        return FALSE;
5867
    }
5868
5869
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5870
    if (!followLinks) {
5871
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5872
    }
5873
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5874
                               OPEN_EXISTING, flags, NULL);
5875
    if (hfile != INVALID_HANDLE_VALUE) {
5876
        if (followLinks) {
5877
            CloseHandle(hfile);
5878
            return TRUE;
5879
        }
5880
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5881
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5882
        CloseHandle(hfile);
5883
        if (!result) {
5884
            return TRUE;
5885
        }
5886
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5887
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5888
        if (hfile != INVALID_HANDLE_VALUE) {
5889
            CloseHandle(hfile);
5890
            return TRUE;
5891
        }
5892
    }
5893
5894
    switch (GetLastError()) {
5895
    case ERROR_ACCESS_DENIED:
5896
    case ERROR_SHARING_VIOLATION:
5897
    case ERROR_CANT_ACCESS_FILE:
5898
    case ERROR_INVALID_PARAMETER:
5899
        STRUCT_STAT _st;
5900
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5901
    }
5902
5903
    return FALSE;
5904
}
5905
5906
5907
static BOOL
5908
_testFileExists(path_t *path, BOOL followLinks)
5909
{
5910
    BOOL result = FALSE;
5911
    if (path->value_error) {
5912
        return FALSE;
5913
    }
5914
5915
    Py_BEGIN_ALLOW_THREADS
5916
    if (path->is_fd) {
5917
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5918
        if (hfile != INVALID_HANDLE_VALUE) {
5919
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5920
                result = TRUE;
5921
            }
5922
        }
5923
    }
5924
    else if (path->wide) {
5925
        result = _testFileExistsByName(path->wide, followLinks);
5926
    }
5927
    Py_END_ALLOW_THREADS
5928
5929
    return result;
5930
}
5931
5932
5933
static BOOL
5934
_testFileType(path_t *path, int testedType)
5935
{
5936
    BOOL result = FALSE;
5937
    if (path->value_error) {
5938
        return FALSE;
5939
    }
5940
5941
    Py_BEGIN_ALLOW_THREADS
5942
    if (path->is_fd) {
5943
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5944
        if (hfile != INVALID_HANDLE_VALUE) {
5945
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5946
        }
5947
    }
5948
    else if (path->wide) {
5949
        result = _testFileTypeByName(path->wide, testedType);
5950
    }
5951
    Py_END_ALLOW_THREADS
5952
5953
    return result;
5954
}
5955
5956
5957
/*[clinic input]
5958
os._path_exists -> bool
5959
5960
    path: path_t(allow_fd=True, suppress_value_error=True)
5961
5962
Test whether a path exists.  Returns False for broken symbolic links.
5963
5964
[clinic start generated code]*/
5965
5966
static int
5967
os__path_exists_impl(PyObject *module, path_t *path)
5968
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5969
{
5970
    return _testFileExists(path, TRUE);
5971
}
5972
5973
5974
/*[clinic input]
5975
os._path_lexists -> bool
5976
5977
    path: path_t(allow_fd=True, suppress_value_error=True)
5978
5979
Test whether a path exists.  Returns True for broken symbolic links.
5980
5981
[clinic start generated code]*/
5982
5983
static int
5984
os__path_lexists_impl(PyObject *module, path_t *path)
5985
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5986
{
5987
    return _testFileExists(path, FALSE);
5988
}
5989
5990
5991
/*[clinic input]
5992
os._path_isdir -> bool
5993
5994
    path: path_t(allow_fd=True, suppress_value_error=True)
5995
    /
5996
5997
Return true if the pathname refers to an existing directory.
5998
5999
[clinic start generated code]*/
6000
6001
static int
6002
os__path_isdir_impl(PyObject *module, path_t *path)
6003
/*[clinic end generated code: output=d5786196f9e2fa7a input=b15f9b697a7a759f]*/
6004
{
6005
    return _testFileType(path, PY_IFDIR);
6006
}
6007
6008
6009
/*[clinic input]
6010
os._path_isfile -> bool
6011
6012
    path: path_t(allow_fd=True, suppress_value_error=True)
6013
6014
Test whether a path is a regular file
6015
6016
[clinic start generated code]*/
6017
6018
static int
6019
os__path_isfile_impl(PyObject *module, path_t *path)
6020
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6021
{
6022
    return _testFileType(path, PY_IFREG);
6023
}
6024
6025
6026
/*[clinic input]
6027
os._path_islink -> bool
6028
6029
    path: path_t(allow_fd=True, suppress_value_error=True)
6030
6031
Test whether a path is a symbolic link
6032
6033
[clinic start generated code]*/
6034
6035
static int
6036
os__path_islink_impl(PyObject *module, path_t *path)
6037
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6038
{
6039
    return _testFileType(path, PY_IFLNK);
6040
}
6041
6042
6043
/*[clinic input]
6044
os._path_isjunction -> bool
6045
6046
    path: path_t(allow_fd=True, suppress_value_error=True)
6047
6048
Test whether a path is a junction
6049
6050
[clinic start generated code]*/
6051
6052
static int
6053
os__path_isjunction_impl(PyObject *module, path_t *path)
6054
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6055
{
6056
    return _testFileType(path, PY_IFMNT);
6057
}
6058
6059
#undef PY_IFREG
6060
#undef PY_IFDIR
6061
#undef PY_IFLNK
6062
#undef PY_IFMNT
6063
#undef PY_IFLRP
6064
#undef PY_IFRRP
6065
6066
#endif /* MS_WINDOWS */
6067
6068
6069
/*[clinic input]
6070
os._path_splitroot_ex
6071
6072
    path: path_t(make_wide=True, nonstrict=True)
6073
    /
6074
6075
Split a pathname into drive, root and tail.
6076
6077
The tail contains anything after the root.
6078
[clinic start generated code]*/
6079
6080
static PyObject *
6081
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6082
/*[clinic end generated code: output=4b0072b6cdf4b611 input=012fbfad14888b2b]*/
6083
127k
{
6084
127k
    Py_ssize_t drvsize, rootsize;
6085
127k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6086
6087
127k
    const wchar_t *buffer = path->wide;
6088
127k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6089
127k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6090
127k
    if (drv == NULL) {
6091
0
        goto exit;
6092
0
    }
6093
127k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6094
127k
    if (root == NULL) {
6095
0
        goto exit;
6096
0
    }
6097
127k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6098
127k
                                  path->length - drvsize - rootsize);
6099
127k
    if (tail == NULL) {
6100
0
        goto exit;
6101
0
    }
6102
127k
    if (PyBytes_Check(path->object)) {
6103
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6104
0
        if (drv == NULL) {
6105
0
            goto exit;
6106
0
        }
6107
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6108
0
        if (root == NULL) {
6109
0
            goto exit;
6110
0
        }
6111
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6112
0
        if (tail == NULL) {
6113
0
            goto exit;
6114
0
        }
6115
0
    }
6116
127k
    result = PyTuple_Pack(3, drv, root, tail);
6117
127k
exit:
6118
127k
    Py_XDECREF(drv);
6119
127k
    Py_XDECREF(root);
6120
127k
    Py_XDECREF(tail);
6121
127k
    return result;
6122
127k
}
6123
6124
6125
/*[clinic input]
6126
os._path_normpath
6127
6128
    path: path_t(make_wide=True, nonstrict=True)
6129
6130
Normalize path, eliminating double slashes, etc.
6131
[clinic start generated code]*/
6132
6133
static PyObject *
6134
os__path_normpath_impl(PyObject *module, path_t *path)
6135
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6136
25.3k
{
6137
25.3k
    PyObject *result;
6138
25.3k
    Py_ssize_t norm_len;
6139
25.3k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6140
25.3k
                                               path->length, &norm_len);
6141
25.3k
    if (!norm_len) {
6142
0
        result = PyUnicode_FromOrdinal('.');
6143
0
    }
6144
25.3k
    else {
6145
25.3k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6146
25.3k
    }
6147
25.3k
    if (result == NULL) {
6148
0
        return NULL;
6149
0
    }
6150
25.3k
    if (PyBytes_Check(path->object)) {
6151
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6152
0
    }
6153
25.3k
    return result;
6154
25.3k
}
6155
6156
/*[clinic input]
6157
os.mkdir
6158
6159
    path : path_t
6160
6161
    mode: int = 0o777
6162
6163
    *
6164
6165
    dir_fd : dir_fd(requires='mkdirat') = None
6166
6167
Create a directory.
6168
6169
If dir_fd is not None, it should be a file descriptor open to
6170
a directory, and path should be relative; path will then be relative to
6171
that directory.
6172
dir_fd may not be implemented on your platform.  If it is unavailable,
6173
using it will raise a NotImplementedError.
6174
6175
The mode argument is ignored on Windows.  Where it is used, the current
6176
umask value is first masked out.
6177
[clinic start generated code]*/
6178
6179
static PyObject *
6180
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6181
/*[clinic end generated code: output=a70446903abe821f input=30270d369599634b]*/
6182
88.8k
{
6183
88.8k
    int result;
6184
#ifdef MS_WINDOWS
6185
    int error = 0;
6186
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6187
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6188
#endif
6189
88.8k
#ifdef HAVE_MKDIRAT
6190
88.8k
    int mkdirat_unavailable = 0;
6191
88.8k
#endif
6192
6193
88.8k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6194
88.8k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6195
0
        return NULL;
6196
0
    }
6197
6198
#ifdef MS_WINDOWS
6199
    Py_BEGIN_ALLOW_THREADS
6200
    // For API sets that don't support these APIs, we have no choice
6201
    // but to silently create a directory with default ACL.
6202
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6203
    if (mode == 0700 /* 0o700 */) {
6204
        ULONG sdSize;
6205
        pSecAttr = &secAttr;
6206
        // Set a discretionary ACL (D) that is protected (P) and includes
6207
        // inheritable (OICI) entries that allow (A) full control (FA) to
6208
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6209
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6210
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6211
            SDDL_REVISION_1,
6212
            &secAttr.lpSecurityDescriptor,
6213
            &sdSize
6214
        )) {
6215
            error = GetLastError();
6216
        }
6217
    }
6218
#endif
6219
    if (!error) {
6220
        result = CreateDirectoryW(path->wide, pSecAttr);
6221
        if (secAttr.lpSecurityDescriptor &&
6222
            // uncommonly, LocalFree returns non-zero on error, but still uses
6223
            // GetLastError() to see what the error code is
6224
            LocalFree(secAttr.lpSecurityDescriptor)) {
6225
            error = GetLastError();
6226
        }
6227
    }
6228
    Py_END_ALLOW_THREADS
6229
6230
    if (error) {
6231
        return PyErr_SetFromWindowsErr(error);
6232
    }
6233
    if (!result) {
6234
        return path_error(path);
6235
    }
6236
#else
6237
88.8k
    Py_BEGIN_ALLOW_THREADS
6238
88.8k
#if HAVE_MKDIRAT
6239
88.8k
    if (dir_fd != DEFAULT_DIR_FD) {
6240
0
      if (HAVE_MKDIRAT_RUNTIME) {
6241
0
        result = mkdirat(dir_fd, path->narrow, mode);
6242
6243
0
      } else {
6244
0
        mkdirat_unavailable = 1;
6245
0
      }
6246
0
    } else
6247
88.8k
#endif
6248
#if defined(__WATCOMC__) && !defined(__QNX__)
6249
        result = mkdir(path->narrow);
6250
#else
6251
88.8k
        result = mkdir(path->narrow, mode);
6252
88.8k
#endif
6253
88.8k
    Py_END_ALLOW_THREADS
6254
6255
88.8k
#if HAVE_MKDIRAT
6256
88.8k
    if (mkdirat_unavailable) {
6257
0
        argument_unavailable_error(NULL, "dir_fd");
6258
0
        return NULL;
6259
0
    }
6260
88.8k
#endif
6261
6262
88.8k
    if (result < 0)
6263
347
        return path_error(path);
6264
88.4k
#endif /* MS_WINDOWS */
6265
88.8k
    Py_RETURN_NONE;
6266
88.8k
}
6267
6268
6269
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6270
#if defined(HAVE_SYS_RESOURCE_H)
6271
#include <sys/resource.h>
6272
#endif
6273
6274
6275
#ifdef HAVE_NICE
6276
/*[clinic input]
6277
os.nice
6278
6279
    increment: int
6280
    /
6281
6282
Add increment to the priority of process and return the new priority.
6283
[clinic start generated code]*/
6284
6285
static PyObject *
6286
os_nice_impl(PyObject *module, int increment)
6287
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6288
0
{
6289
0
    int value;
6290
6291
    /* There are two flavours of 'nice': one that returns the new
6292
       priority (as required by almost all standards out there) and the
6293
       Linux/FreeBSD one, which returns '0' on success and advices
6294
       the use of getpriority() to get the new priority.
6295
6296
       If we are of the nice family that returns the new priority, we
6297
       need to clear errno before the call, and check if errno is filled
6298
       before calling posix_error() on a returnvalue of -1, because the
6299
       -1 may be the actual new priority! */
6300
6301
0
    errno = 0;
6302
0
    value = nice(increment);
6303
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6304
    if (value == 0)
6305
        value = getpriority(PRIO_PROCESS, 0);
6306
#endif
6307
0
    if (value == -1 && errno != 0)
6308
        /* either nice() or getpriority() returned an error */
6309
0
        return posix_error();
6310
0
    return PyLong_FromLong((long) value);
6311
0
}
6312
#endif /* HAVE_NICE */
6313
6314
6315
#ifdef HAVE_GETPRIORITY
6316
/*[clinic input]
6317
os.getpriority
6318
6319
    which: int
6320
    who: int
6321
6322
Return program scheduling priority.
6323
[clinic start generated code]*/
6324
6325
static PyObject *
6326
os_getpriority_impl(PyObject *module, int which, int who)
6327
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6328
0
{
6329
0
    int retval;
6330
6331
0
    errno = 0;
6332
0
    retval = getpriority(which, who);
6333
0
    if (errno != 0)
6334
0
        return posix_error();
6335
0
    return PyLong_FromLong((long)retval);
6336
0
}
6337
#endif /* HAVE_GETPRIORITY */
6338
6339
6340
#ifdef HAVE_SETPRIORITY
6341
/*[clinic input]
6342
os.setpriority
6343
6344
    which: int
6345
    who: int
6346
    priority: int
6347
6348
Set program scheduling priority.
6349
[clinic start generated code]*/
6350
6351
static PyObject *
6352
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6353
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6354
0
{
6355
0
    int retval;
6356
6357
0
    retval = setpriority(which, who, priority);
6358
0
    if (retval == -1)
6359
0
        return posix_error();
6360
0
    Py_RETURN_NONE;
6361
0
}
6362
#endif /* HAVE_SETPRIORITY */
6363
6364
6365
static PyObject *
6366
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6367
146
{
6368
146
    const char *function_name = is_replace ? "replace" : "rename";
6369
146
    int dir_fd_specified;
6370
6371
146
#ifdef HAVE_RENAMEAT
6372
146
    int renameat_unavailable = 0;
6373
146
#endif
6374
6375
#ifdef MS_WINDOWS
6376
    BOOL result;
6377
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6378
#else
6379
146
    int result;
6380
146
#endif
6381
6382
146
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6383
146
                       (dst_dir_fd != DEFAULT_DIR_FD);
6384
#ifndef HAVE_RENAMEAT
6385
    if (dir_fd_specified) {
6386
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6387
        return NULL;
6388
    }
6389
#endif
6390
6391
146
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6392
146
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6393
146
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6394
0
        return NULL;
6395
0
    }
6396
6397
#ifdef MS_WINDOWS
6398
    Py_BEGIN_ALLOW_THREADS
6399
    result = MoveFileExW(src->wide, dst->wide, flags);
6400
    Py_END_ALLOW_THREADS
6401
6402
    if (!result)
6403
        return path_error2(src, dst);
6404
6405
#else
6406
146
    Py_BEGIN_ALLOW_THREADS
6407
146
#ifdef HAVE_RENAMEAT
6408
146
    if (dir_fd_specified) {
6409
0
        if (HAVE_RENAMEAT_RUNTIME) {
6410
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6411
0
        } else {
6412
0
            renameat_unavailable = 1;
6413
0
        }
6414
0
    } else
6415
146
#endif
6416
146
    result = rename(src->narrow, dst->narrow);
6417
146
    Py_END_ALLOW_THREADS
6418
6419
6420
146
#ifdef HAVE_RENAMEAT
6421
146
    if (renameat_unavailable) {
6422
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6423
0
        return NULL;
6424
0
    }
6425
146
#endif
6426
6427
146
    if (result)
6428
0
        return path_error2(src, dst);
6429
146
#endif
6430
146
    Py_RETURN_NONE;
6431
146
}
6432
6433
6434
/*[clinic input]
6435
os.rename
6436
6437
    src : path_t
6438
    dst : path_t
6439
    *
6440
    src_dir_fd : dir_fd = None
6441
    dst_dir_fd : dir_fd = None
6442
6443
Rename a file or directory.
6444
6445
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6446
descriptor open to a directory, and the respective path string (src or
6447
dst) should be relative; the path will then be relative to that
6448
directory.
6449
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6450
If they are unavailable, using them will raise a NotImplementedError.
6451
[clinic start generated code]*/
6452
6453
static PyObject *
6454
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6455
               int dst_dir_fd)
6456
/*[clinic end generated code: output=59e803072cf41230 input=7d320d687c715fd6]*/
6457
5
{
6458
5
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6459
5
}
6460
6461
6462
/*[clinic input]
6463
os.replace = os.rename
6464
6465
Rename a file or directory, overwriting the destination.
6466
6467
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6468
descriptor open to a directory, and the respective path string (src or
6469
dst) should be relative; the path will then be relative to that
6470
directory.
6471
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6472
If they are unavailable, using them will raise a NotImplementedError.
6473
[clinic start generated code]*/
6474
6475
static PyObject *
6476
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6477
                int dst_dir_fd)
6478
/*[clinic end generated code: output=1968c02e7857422b input=44ed6b762d5953fc]*/
6479
141
{
6480
141
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6481
141
}
6482
6483
6484
/*[clinic input]
6485
os.rmdir
6486
6487
    path: path_t
6488
    *
6489
    dir_fd: dir_fd(requires='unlinkat') = None
6490
6491
Remove a directory.
6492
6493
If dir_fd is not None, it should be a file descriptor open to
6494
a directory, and path should be relative; path will then be relative
6495
to that directory.
6496
dir_fd may not be implemented on your platform.
6497
If it is unavailable, using it will raise a NotImplementedError.
6498
[clinic start generated code]*/
6499
6500
static PyObject *
6501
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6502
/*[clinic end generated code: output=080eb54f506e8301 input=84325211e33a98e0]*/
6503
88.4k
{
6504
88.4k
    int result;
6505
88.4k
#ifdef HAVE_UNLINKAT
6506
88.4k
    int unlinkat_unavailable = 0;
6507
88.4k
#endif
6508
6509
88.4k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6510
88.4k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6511
0
        return NULL;
6512
0
    }
6513
6514
88.4k
    Py_BEGIN_ALLOW_THREADS
6515
#ifdef MS_WINDOWS
6516
    /* Windows, success=1, UNIX, success=0 */
6517
    result = !RemoveDirectoryW(path->wide);
6518
#else
6519
88.4k
#ifdef HAVE_UNLINKAT
6520
88.4k
    if (dir_fd != DEFAULT_DIR_FD) {
6521
84.3k
      if (HAVE_UNLINKAT_RUNTIME) {
6522
84.3k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6523
84.3k
      } else {
6524
0
        unlinkat_unavailable = 1;
6525
0
        result = -1;
6526
0
      }
6527
84.3k
    } else
6528
4.11k
#endif
6529
4.11k
        result = rmdir(path->narrow);
6530
88.4k
#endif
6531
88.4k
    Py_END_ALLOW_THREADS
6532
6533
88.4k
#ifdef HAVE_UNLINKAT
6534
88.4k
    if (unlinkat_unavailable) {
6535
0
        argument_unavailable_error("rmdir", "dir_fd");
6536
0
        return NULL;
6537
0
    }
6538
88.4k
#endif
6539
6540
88.4k
    if (result)
6541
5
        return path_error(path);
6542
6543
88.4k
    Py_RETURN_NONE;
6544
88.4k
}
6545
6546
6547
#ifdef HAVE_SYSTEM
6548
#ifdef MS_WINDOWS
6549
/*[clinic input]
6550
os.system -> long
6551
6552
    command: Py_UNICODE
6553
6554
Execute the command in a subshell.
6555
[clinic start generated code]*/
6556
6557
static long
6558
os_system_impl(PyObject *module, const wchar_t *command)
6559
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6560
{
6561
    long result;
6562
6563
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6564
        return -1;
6565
    }
6566
6567
    Py_BEGIN_ALLOW_THREADS
6568
    _Py_BEGIN_SUPPRESS_IPH
6569
    result = _wsystem(command);
6570
    _Py_END_SUPPRESS_IPH
6571
    Py_END_ALLOW_THREADS
6572
    return result;
6573
}
6574
#else /* MS_WINDOWS */
6575
/*[clinic input]
6576
os.system -> long
6577
6578
    command: unicode_fs_encoded
6579
6580
Execute the command in a subshell.
6581
[clinic start generated code]*/
6582
6583
static long
6584
os_system_impl(PyObject *module, PyObject *command)
6585
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6586
0
{
6587
0
    long result;
6588
0
    const char *bytes = PyBytes_AsString(command);
6589
6590
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6591
0
        return -1;
6592
0
    }
6593
6594
0
    Py_BEGIN_ALLOW_THREADS
6595
0
    result = system(bytes);
6596
0
    Py_END_ALLOW_THREADS
6597
0
    return result;
6598
0
}
6599
#endif
6600
#endif /* HAVE_SYSTEM */
6601
6602
6603
#ifdef HAVE_UMASK
6604
/*[clinic input]
6605
os.umask
6606
6607
    mask: int
6608
    /
6609
6610
Set the current numeric umask and return the previous umask.
6611
[clinic start generated code]*/
6612
6613
static PyObject *
6614
os_umask_impl(PyObject *module, int mask)
6615
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6616
0
{
6617
0
    int i = (int)umask(mask);
6618
0
    if (i < 0)
6619
0
        return posix_error();
6620
0
    return PyLong_FromLong((long)i);
6621
0
}
6622
#endif
6623
6624
#ifdef MS_WINDOWS
6625
6626
/* override the default DeleteFileW behavior so that directory
6627
symlinks can be removed with this function, the same as with
6628
Unix symlinks */
6629
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6630
{
6631
    WIN32_FILE_ATTRIBUTE_DATA info;
6632
    WIN32_FIND_DATAW find_data;
6633
    HANDLE find_data_handle;
6634
    int is_directory = 0;
6635
    int is_link = 0;
6636
6637
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6638
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6639
6640
        /* Get WIN32_FIND_DATA structure for the path to determine if
6641
           it is a symlink */
6642
        if(is_directory &&
6643
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6644
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6645
6646
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6647
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6648
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6649
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6650
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6651
                FindClose(find_data_handle);
6652
            }
6653
        }
6654
    }
6655
6656
    if (is_directory && is_link)
6657
        return RemoveDirectoryW(lpFileName);
6658
6659
    return DeleteFileW(lpFileName);
6660
}
6661
#endif /* MS_WINDOWS */
6662
6663
6664
/*[clinic input]
6665
os.unlink
6666
6667
    path: path_t
6668
    *
6669
    dir_fd: dir_fd(requires='unlinkat')=None
6670
6671
Remove a file (same as remove()).
6672
6673
If dir_fd is not None, it should be a file descriptor open to
6674
a directory, and path should be relative; path will then be relative to
6675
that directory.
6676
dir_fd may not be implemented on your platform.
6677
If it is unavailable, using it will raise a NotImplementedError.
6678
6679
[clinic start generated code]*/
6680
6681
static PyObject *
6682
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6683
/*[clinic end generated code: output=621797807b9963b1 input=1a2ef2579207eab1]*/
6684
17.0k
{
6685
17.0k
    int result;
6686
17.0k
#ifdef HAVE_UNLINKAT
6687
17.0k
    int unlinkat_unavailable = 0;
6688
17.0k
#endif
6689
6690
17.0k
    if (PySys_Audit("os.remove", "Oi", path->object,
6691
17.0k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6692
0
        return NULL;
6693
0
    }
6694
6695
17.0k
    Py_BEGIN_ALLOW_THREADS
6696
17.0k
    _Py_BEGIN_SUPPRESS_IPH
6697
#ifdef MS_WINDOWS
6698
    /* Windows, success=1, UNIX, success=0 */
6699
    result = !Py_DeleteFileW(path->wide);
6700
#else
6701
17.0k
#ifdef HAVE_UNLINKAT
6702
17.0k
    if (dir_fd != DEFAULT_DIR_FD) {
6703
17.0k
      if (HAVE_UNLINKAT_RUNTIME) {
6704
6705
17.0k
        result = unlinkat(dir_fd, path->narrow, 0);
6706
17.0k
      } else {
6707
0
        unlinkat_unavailable = 1;
6708
0
      }
6709
17.0k
    } else
6710
2
#endif /* HAVE_UNLINKAT */
6711
2
        result = unlink(path->narrow);
6712
17.0k
#endif
6713
17.0k
    _Py_END_SUPPRESS_IPH
6714
17.0k
    Py_END_ALLOW_THREADS
6715
6716
17.0k
#ifdef HAVE_UNLINKAT
6717
17.0k
    if (unlinkat_unavailable) {
6718
0
        argument_unavailable_error(NULL, "dir_fd");
6719
0
        return NULL;
6720
0
    }
6721
17.0k
#endif
6722
6723
17.0k
    if (result)
6724
0
        return path_error(path);
6725
6726
17.0k
    Py_RETURN_NONE;
6727
17.0k
}
6728
6729
6730
/*[clinic input]
6731
os.remove = os.unlink
6732
6733
Remove a file (same as unlink()).
6734
6735
If dir_fd is not None, it should be a file descriptor open to
6736
a directory, and path should be relative; path will then be relative
6737
to that directory.
6738
dir_fd may not be implemented on your platform.
6739
If it is unavailable, using it will raise a NotImplementedError.
6740
[clinic start generated code]*/
6741
6742
static PyObject *
6743
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6744
/*[clinic end generated code: output=a8535b28f0068883 input=9f6e66912126bd56]*/
6745
0
{
6746
0
    return os_unlink_impl(module, path, dir_fd);
6747
0
}
6748
6749
6750
static PyStructSequence_Field uname_result_fields[] = {
6751
    {"sysname",    "operating system name"},
6752
    {"nodename",   "name of machine on network (implementation-defined)"},
6753
    {"release",    "operating system release"},
6754
    {"version",    "operating system version"},
6755
    {"machine",    "hardware identifier"},
6756
    {NULL}
6757
};
6758
6759
PyDoc_STRVAR(uname_result__doc__,
6760
"uname_result: Result from os.uname().\n\n\
6761
This object may be accessed either as a tuple of\n\
6762
  (sysname, nodename, release, version, machine),\n\
6763
or via the attributes sysname, nodename, release, version, and machine.\n\
6764
\n\
6765
See os.uname for more information.");
6766
6767
static PyStructSequence_Desc uname_result_desc = {
6768
    MODNAME ".uname_result", /* name */
6769
    uname_result__doc__, /* doc */
6770
    uname_result_fields,
6771
    5
6772
};
6773
6774
#ifdef HAVE_UNAME
6775
/*[clinic input]
6776
os.uname
6777
6778
Return an object identifying the current operating system.
6779
6780
The object behaves like a named tuple with the following fields:
6781
  (sysname, nodename, release, version, machine)
6782
6783
[clinic start generated code]*/
6784
6785
static PyObject *
6786
os_uname_impl(PyObject *module)
6787
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6788
4
{
6789
4
    struct utsname u;
6790
4
    int res;
6791
4
    PyObject *value;
6792
6793
4
    Py_BEGIN_ALLOW_THREADS
6794
4
    res = uname(&u);
6795
4
    Py_END_ALLOW_THREADS
6796
4
    if (res < 0)
6797
0
        return posix_error();
6798
6799
4
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6800
4
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6801
4
    if (value == NULL)
6802
0
        return NULL;
6803
6804
4
#define SET(i, field) \
6805
20
    { \
6806
20
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6807
20
    if (!o) { \
6808
0
        Py_DECREF(value); \
6809
0
        return NULL; \
6810
0
    } \
6811
20
    PyStructSequence_SET_ITEM(value, i, o); \
6812
20
    } \
6813
4
6814
8
    SET(0, u.sysname);
6815
8
    SET(1, u.nodename);
6816
4
    SET(2, u.release);
6817
4
    SET(3, u.version);
6818
4
    SET(4, u.machine);
6819
6820
4
#undef SET
6821
6822
4
    return value;
6823
4
}
6824
#endif /* HAVE_UNAME */
6825
6826
6827
6828
typedef struct {
6829
    int    now;
6830
    time_t atime_s;
6831
    long   atime_ns;
6832
    time_t mtime_s;
6833
    long   mtime_ns;
6834
} utime_t;
6835
6836
/*
6837
 * these macros assume that "ut" is a pointer to a utime_t
6838
 * they also intentionally leak the declaration of a pointer named "time"
6839
 */
6840
#define UTIME_TO_TIMESPEC \
6841
0
    struct timespec ts[2]; \
6842
0
    struct timespec *time; \
6843
0
    if (ut->now) \
6844
0
        time = NULL; \
6845
0
    else { \
6846
0
        ts[0].tv_sec = ut->atime_s; \
6847
0
        ts[0].tv_nsec = ut->atime_ns; \
6848
0
        ts[1].tv_sec = ut->mtime_s; \
6849
0
        ts[1].tv_nsec = ut->mtime_ns; \
6850
0
        time = ts; \
6851
0
    } \
6852
6853
#define UTIME_TO_TIMEVAL \
6854
0
    struct timeval tv[2]; \
6855
0
    struct timeval *time; \
6856
0
    if (ut->now) \
6857
0
        time = NULL; \
6858
0
    else { \
6859
0
        tv[0].tv_sec = ut->atime_s; \
6860
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6861
0
        tv[1].tv_sec = ut->mtime_s; \
6862
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6863
0
        time = tv; \
6864
0
    } \
6865
6866
#define UTIME_TO_UTIMBUF \
6867
    struct utimbuf u; \
6868
    struct utimbuf *time; \
6869
    if (ut->now) \
6870
        time = NULL; \
6871
    else { \
6872
        u.actime = ut->atime_s; \
6873
        u.modtime = ut->mtime_s; \
6874
        time = &u; \
6875
    }
6876
6877
#define UTIME_TO_TIME_T \
6878
    time_t timet[2]; \
6879
    time_t *time; \
6880
    if (ut->now) \
6881
        time = NULL; \
6882
    else { \
6883
        timet[0] = ut->atime_s; \
6884
        timet[1] = ut->mtime_s; \
6885
        time = timet; \
6886
    } \
6887
6888
6889
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6890
6891
static int
6892
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6893
0
{
6894
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6895
    if (HAVE_UTIMENSAT_RUNTIME) {
6896
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6897
        UTIME_TO_TIMESPEC;
6898
        return utimensat(dir_fd, path, time, flags);
6899
    }  else {
6900
        errno = ENOSYS;
6901
        return -1;
6902
    }
6903
#elif defined(HAVE_UTIMENSAT)
6904
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6905
0
    UTIME_TO_TIMESPEC;
6906
0
    return utimensat(dir_fd, path, time, flags);
6907
#elif defined(HAVE_FUTIMESAT)
6908
    UTIME_TO_TIMEVAL;
6909
    /*
6910
     * follow_symlinks will never be false here;
6911
     * we only allow !follow_symlinks and dir_fd together
6912
     * if we have utimensat()
6913
     */
6914
    assert(follow_symlinks);
6915
    return futimesat(dir_fd, path, time);
6916
#endif
6917
0
}
6918
6919
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6920
#else
6921
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6922
#endif
6923
6924
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6925
6926
static int
6927
utime_fd(utime_t *ut, int fd)
6928
0
{
6929
0
#ifdef HAVE_FUTIMENS
6930
6931
0
    if (HAVE_FUTIMENS_RUNTIME) {
6932
6933
0
    UTIME_TO_TIMESPEC;
6934
0
    return futimens(fd, time);
6935
6936
0
    } else
6937
#ifndef HAVE_FUTIMES
6938
    {
6939
        /* Not sure if this can happen */
6940
        PyErr_SetString(
6941
            PyExc_RuntimeError,
6942
            "neither futimens nor futimes are supported"
6943
            " on this system");
6944
        return -1;
6945
    }
6946
#endif
6947
6948
0
#endif
6949
0
#ifdef HAVE_FUTIMES
6950
0
    {
6951
0
    UTIME_TO_TIMEVAL;
6952
0
    return futimes(fd, time);
6953
0
    }
6954
0
#endif
6955
0
}
6956
6957
    #define PATH_UTIME_HAVE_FD 1
6958
#else
6959
    #define PATH_UTIME_HAVE_FD 0
6960
#endif
6961
6962
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6963
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6964
#endif
6965
6966
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6967
6968
static int
6969
utime_nofollow_symlinks(utime_t *ut, const char *path)
6970
0
{
6971
0
#ifdef HAVE_UTIMENSAT
6972
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6973
0
        UTIME_TO_TIMESPEC;
6974
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6975
0
    } else
6976
#ifndef HAVE_LUTIMES
6977
    {
6978
        /* Not sure if this can happen */
6979
        PyErr_SetString(
6980
            PyExc_RuntimeError,
6981
            "neither utimensat nor lutimes are supported"
6982
            " on this system");
6983
        return -1;
6984
    }
6985
#endif
6986
0
#endif
6987
6988
0
#ifdef HAVE_LUTIMES
6989
0
    {
6990
0
    UTIME_TO_TIMEVAL;
6991
0
    return lutimes(path, time);
6992
0
    }
6993
0
#endif
6994
0
}
6995
6996
#endif
6997
6998
#ifndef MS_WINDOWS
6999
7000
static int
7001
utime_default(utime_t *ut, const char *path)
7002
0
{
7003
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7004
    if (HAVE_UTIMENSAT_RUNTIME) {
7005
        UTIME_TO_TIMESPEC;
7006
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
7007
    } else {
7008
        UTIME_TO_TIMEVAL;
7009
        return utimes(path, time);
7010
    }
7011
#elif defined(HAVE_UTIMENSAT)
7012
0
    UTIME_TO_TIMESPEC;
7013
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
7014
#elif defined(HAVE_UTIMES)
7015
    UTIME_TO_TIMEVAL;
7016
    return utimes(path, time);
7017
#elif defined(HAVE_UTIME_H)
7018
    UTIME_TO_UTIMBUF;
7019
    return utime(path, time);
7020
#else
7021
    UTIME_TO_TIME_T;
7022
    return utime(path, time);
7023
#endif
7024
0
}
7025
7026
#endif
7027
7028
static int
7029
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7030
0
{
7031
0
    int result = 0;
7032
0
    PyObject *divmod;
7033
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7034
0
    if (!divmod)
7035
0
        goto exit;
7036
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7037
0
        PyErr_Format(PyExc_TypeError,
7038
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7039
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7040
0
        goto exit;
7041
0
    }
7042
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7043
0
    if ((*s == -1) && PyErr_Occurred())
7044
0
        goto exit;
7045
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7046
0
    if ((*ns == -1) && PyErr_Occurred())
7047
0
        goto exit;
7048
7049
0
    result = 1;
7050
0
exit:
7051
0
    Py_XDECREF(divmod);
7052
0
    return result;
7053
0
}
7054
7055
7056
/*[clinic input]
7057
os.utime
7058
7059
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7060
    times: object = None
7061
    *
7062
    ns: object = NULL
7063
    dir_fd: dir_fd(requires='futimensat') = None
7064
    follow_symlinks: bool=True
7065
7066
Set the access and modified time of path.
7067
7068
path may always be specified as a string.  On some platforms, path may
7069
also be specified as an open file descriptor.  If this functionality is
7070
unavailable, using it raises an exception.
7071
7072
If times is not None, it must be a tuple (atime, mtime);
7073
atime and mtime should be expressed as float seconds since the epoch.
7074
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7075
atime_ns and mtime_ns should be expressed as integer nanoseconds
7076
since the epoch.
7077
If times is None and ns is unspecified, utime uses the current time.
7078
Specifying tuples for both times and ns is an error.
7079
7080
If dir_fd is not None, it should be a file descriptor open to
7081
a directory, and path should be relative; path will then be relative to
7082
that directory.
7083
If follow_symlinks is False, and the last element of the path is
7084
a symbolic link, utime will modify the symbolic link itself instead of
7085
the file the link points to.
7086
It is an error to use dir_fd or follow_symlinks when specifying path as
7087
an open file descriptor.
7088
dir_fd and follow_symlinks may not be available on your platform.
7089
If they are unavailable, using them will raise a NotImplementedError.
7090
7091
[clinic start generated code]*/
7092
7093
static PyObject *
7094
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7095
              int dir_fd, int follow_symlinks)
7096
/*[clinic end generated code: output=cfcac69d027b82cf input=5ab470b2bc250788]*/
7097
0
{
7098
#ifdef MS_WINDOWS
7099
    HANDLE hFile;
7100
    FILETIME atime, mtime;
7101
#else
7102
0
    int result;
7103
0
#endif
7104
7105
0
    utime_t utime;
7106
7107
0
    memset(&utime, 0, sizeof(utime_t));
7108
7109
0
    if (times != Py_None && ns) {
7110
0
        PyErr_SetString(PyExc_ValueError,
7111
0
                     "utime: you may specify either 'times'"
7112
0
                     " or 'ns' but not both");
7113
0
        return NULL;
7114
0
    }
7115
7116
0
    if (times != Py_None) {
7117
0
        time_t a_sec, m_sec;
7118
0
        long a_nsec, m_nsec;
7119
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7120
0
            PyErr_SetString(PyExc_TypeError,
7121
0
                         "utime: 'times' must be either"
7122
0
                         " a tuple of two numbers or None");
7123
0
            return NULL;
7124
0
        }
7125
0
        utime.now = 0;
7126
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7127
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7128
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7129
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7130
0
            return NULL;
7131
0
        }
7132
0
        utime.atime_s = a_sec;
7133
0
        utime.atime_ns = a_nsec;
7134
0
        utime.mtime_s = m_sec;
7135
0
        utime.mtime_ns = m_nsec;
7136
0
    }
7137
0
    else if (ns) {
7138
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7139
0
            PyErr_SetString(PyExc_TypeError,
7140
0
                         "utime: 'ns' must be a tuple of two ints");
7141
0
            return NULL;
7142
0
        }
7143
0
        utime.now = 0;
7144
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7145
0
                                      &utime.atime_s, &utime.atime_ns) ||
7146
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7147
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7148
0
            return NULL;
7149
0
        }
7150
0
    }
7151
0
    else {
7152
        /* times and ns are both None/unspecified. use "now". */
7153
0
        utime.now = 1;
7154
0
    }
7155
7156
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7157
    if (follow_symlinks_specified("utime", follow_symlinks))
7158
        return NULL;
7159
#endif
7160
7161
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7162
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7163
0
        fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
7164
0
        return NULL;
7165
7166
#if !defined(HAVE_UTIMENSAT)
7167
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7168
        PyErr_SetString(PyExc_ValueError,
7169
                     "utime: cannot use dir_fd and follow_symlinks "
7170
                     "together on this platform");
7171
        return NULL;
7172
    }
7173
#endif
7174
7175
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7176
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7177
0
        return NULL;
7178
0
    }
7179
7180
#ifdef MS_WINDOWS
7181
    Py_BEGIN_ALLOW_THREADS
7182
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7183
                        NULL, OPEN_EXISTING,
7184
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7185
    Py_END_ALLOW_THREADS
7186
    if (hFile == INVALID_HANDLE_VALUE) {
7187
        path_error(path);
7188
        return NULL;
7189
    }
7190
7191
    if (utime.now) {
7192
        GetSystemTimeAsFileTime(&mtime);
7193
        atime = mtime;
7194
    }
7195
    else {
7196
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7197
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7198
    }
7199
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7200
        path_error(path);
7201
        CloseHandle(hFile);
7202
        return NULL;
7203
    }
7204
    CloseHandle(hFile);
7205
#else /* MS_WINDOWS */
7206
0
    Py_BEGIN_ALLOW_THREADS
7207
7208
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7209
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7210
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7211
0
    else
7212
0
#endif
7213
7214
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7215
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7216
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7217
7218
0
    } else
7219
0
#endif
7220
7221
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7222
0
    if (path->is_fd)
7223
0
        result = utime_fd(&utime, path->fd);
7224
0
    else
7225
0
#endif
7226
7227
0
    result = utime_default(&utime, path->narrow);
7228
7229
0
    Py_END_ALLOW_THREADS
7230
7231
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7232
    /* See utime_dir_fd implementation */
7233
    if (result == -1 && errno == ENOSYS) {
7234
        argument_unavailable_error(NULL, "dir_fd");
7235
        return NULL;
7236
    }
7237
#endif
7238
7239
0
    if (result < 0) {
7240
0
        path_error(path);
7241
0
        return NULL;
7242
0
    }
7243
7244
0
#endif /* MS_WINDOWS */
7245
7246
0
    Py_RETURN_NONE;
7247
0
}
7248
7249
/* Process operations */
7250
7251
7252
/*[clinic input]
7253
@permit_long_summary
7254
os._exit
7255
7256
    status: int
7257
7258
Exit to the system with specified status, without normal exit processing.
7259
[clinic start generated code]*/
7260
7261
static PyObject *
7262
os__exit_impl(PyObject *module, int status)
7263
/*[clinic end generated code: output=116e52d9c2260d54 input=c35d282acfebe8fd]*/
7264
0
{
7265
0
    _exit(status);
7266
0
    return NULL; /* Make gcc -Wall happy */
7267
0
}
7268
7269
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7270
#define EXECV_CHAR wchar_t
7271
#else
7272
0
#define EXECV_CHAR char
7273
#endif
7274
7275
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7276
static void
7277
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7278
0
{
7279
0
    Py_ssize_t i;
7280
0
    for (i = 0; i < count; i++)
7281
0
        PyMem_Free(array[i]);
7282
0
    PyMem_Free(array);
7283
0
}
7284
7285
static int
7286
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7287
0
{
7288
0
    Py_ssize_t size;
7289
0
    PyObject *ub;
7290
0
    int result = 0;
7291
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7292
    if (!PyUnicode_FSDecoder(o, &ub))
7293
        return 0;
7294
    *out = PyUnicode_AsWideCharString(ub, &size);
7295
    if (*out)
7296
        result = 1;
7297
#else
7298
0
    if (!PyUnicode_FSConverter(o, &ub))
7299
0
        return 0;
7300
0
    size = PyBytes_GET_SIZE(ub);
7301
0
    *out = PyMem_Malloc(size + 1);
7302
0
    if (*out) {
7303
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7304
0
        result = 1;
7305
0
    } else
7306
0
        PyErr_NoMemory();
7307
0
#endif
7308
0
    Py_DECREF(ub);
7309
0
    return result;
7310
0
}
7311
#endif
7312
7313
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7314
static EXECV_CHAR**
7315
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7316
0
{
7317
0
    Py_ssize_t i, pos, envc;
7318
0
    PyObject *keys = NULL, *vals = NULL;
7319
0
    PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
7320
0
    EXECV_CHAR **envlist;
7321
7322
0
    i = PyMapping_Size(env);
7323
0
    if (i < 0)
7324
0
        return NULL;
7325
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7326
0
    if (envlist == NULL) {
7327
0
        PyErr_NoMemory();
7328
0
        return NULL;
7329
0
    }
7330
0
    envc = 0;
7331
0
    keys = PyMapping_Keys(env);
7332
0
    if (!keys)
7333
0
        goto error;
7334
0
    vals = PyMapping_Values(env);
7335
0
    if (!vals)
7336
0
        goto error;
7337
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7338
0
        PyErr_Format(PyExc_TypeError,
7339
0
                     "env.keys() or env.values() is not a list");
7340
0
        goto error;
7341
0
    }
7342
7343
0
    for (pos = 0; pos < i; pos++) {
7344
        // The 'key' and 'val' must be strong references because of
7345
        // possible side-effects by PyUnicode_FS{Converter,Decoder}().
7346
0
        key = PyList_GetItemRef(keys, pos);
7347
0
        if (key == NULL) {
7348
0
            goto error;
7349
0
        }
7350
0
        val = PyList_GetItemRef(vals, pos);
7351
0
        if (val == NULL) {
7352
0
            goto error;
7353
0
        }
7354
7355
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7356
        if (!PyUnicode_FSDecoder(key, &key2)) {
7357
            goto error;
7358
        }
7359
        if (!PyUnicode_FSDecoder(val, &val2)) {
7360
            goto error;
7361
        }
7362
        /* Search from index 1 because on Windows starting '=' is allowed for
7363
           defining hidden environment variables. */
7364
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7365
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7366
        {
7367
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7368
            goto error;
7369
        }
7370
        PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7371
#else
7372
0
        if (!PyUnicode_FSConverter(key, &key2)) {
7373
0
            goto error;
7374
0
        }
7375
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7376
0
            goto error;
7377
0
        }
7378
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7379
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7380
0
        {
7381
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7382
0
            goto error;
7383
0
        }
7384
0
        PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7385
0
                                              PyBytes_AS_STRING(val2));
7386
0
#endif
7387
0
        if (!keyval) {
7388
0
            goto error;
7389
0
        }
7390
7391
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7392
0
            Py_DECREF(keyval);
7393
0
            goto error;
7394
0
        }
7395
7396
0
        Py_CLEAR(key);
7397
0
        Py_CLEAR(val);
7398
0
        Py_CLEAR(key2);
7399
0
        Py_CLEAR(val2);
7400
0
        Py_DECREF(keyval);
7401
0
    }
7402
0
    Py_DECREF(vals);
7403
0
    Py_DECREF(keys);
7404
7405
0
    envlist[envc] = 0;
7406
0
    *envc_ptr = envc;
7407
0
    return envlist;
7408
7409
0
error:
7410
0
    Py_XDECREF(key);
7411
0
    Py_XDECREF(val);
7412
0
    Py_XDECREF(key2);
7413
0
    Py_XDECREF(val2);
7414
0
    Py_XDECREF(keys);
7415
0
    Py_XDECREF(vals);
7416
0
    free_string_array(envlist, envc);
7417
0
    return NULL;
7418
0
}
7419
7420
static EXECV_CHAR**
7421
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7422
0
{
7423
0
    int i;
7424
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7425
0
    if (argvlist == NULL) {
7426
0
        PyErr_NoMemory();
7427
0
        return NULL;
7428
0
    }
7429
0
    for (i = 0; i < *argc; i++) {
7430
0
        PyObject* item = PySequence_ITEM(argv, i);
7431
0
        if (item == NULL)
7432
0
            goto fail;
7433
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7434
0
            Py_DECREF(item);
7435
0
            goto fail;
7436
0
        }
7437
0
        Py_DECREF(item);
7438
0
    }
7439
0
    argvlist[*argc] = NULL;
7440
0
    return argvlist;
7441
0
fail:
7442
0
    *argc = i;
7443
0
    free_string_array(argvlist, *argc);
7444
0
    return NULL;
7445
0
}
7446
7447
#endif
7448
7449
7450
#ifdef HAVE_EXECV
7451
/*[clinic input]
7452
os.execv
7453
7454
    path: path_t
7455
        Path of executable file.
7456
    argv: object
7457
        Tuple or list of strings.
7458
    /
7459
7460
Execute an executable path with arguments, replacing current process.
7461
[clinic start generated code]*/
7462
7463
static PyObject *
7464
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7465
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7466
0
{
7467
0
    EXECV_CHAR **argvlist;
7468
0
    Py_ssize_t argc;
7469
7470
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7471
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7472
0
        PyErr_SetString(PyExc_RuntimeError,
7473
0
                        "exec not supported for isolated subinterpreters");
7474
0
        return NULL;
7475
0
    }
7476
7477
    /* execv has two arguments: (path, argv), where
7478
       argv is a list or tuple of strings. */
7479
7480
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7481
0
        PyErr_SetString(PyExc_TypeError,
7482
0
                        "execv() arg 2 must be a tuple or list");
7483
0
        return NULL;
7484
0
    }
7485
0
    argc = PySequence_Size(argv);
7486
0
    if (argc < 1) {
7487
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7488
0
        return NULL;
7489
0
    }
7490
7491
0
    argvlist = parse_arglist(argv, &argc);
7492
0
    if (argvlist == NULL) {
7493
0
        return NULL;
7494
0
    }
7495
0
    if (!argvlist[0][0]) {
7496
0
        PyErr_SetString(PyExc_ValueError,
7497
0
            "execv() arg 2 first element cannot be empty");
7498
0
        free_string_array(argvlist, argc);
7499
0
        return NULL;
7500
0
    }
7501
7502
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7503
0
        free_string_array(argvlist, argc);
7504
0
        return NULL;
7505
0
    }
7506
7507
0
    _Py_BEGIN_SUPPRESS_IPH
7508
#ifdef HAVE_WEXECV
7509
    _wexecv(path->wide, argvlist);
7510
#else
7511
0
    execv(path->narrow, argvlist);
7512
0
#endif
7513
0
    _Py_END_SUPPRESS_IPH
7514
7515
    /* If we get here it's definitely an error */
7516
7517
0
    posix_path_error(path);
7518
0
    free_string_array(argvlist, argc);
7519
0
    return NULL;
7520
0
}
7521
7522
7523
/*[clinic input]
7524
os.execve
7525
7526
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7527
        Path of executable file.
7528
    argv: object
7529
        Tuple or list of strings.
7530
    env: object
7531
        Dictionary of strings mapping to strings.
7532
7533
Execute an executable path with arguments, replacing current process.
7534
[clinic start generated code]*/
7535
7536
static PyObject *
7537
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7538
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7539
0
{
7540
0
    EXECV_CHAR **argvlist = NULL;
7541
0
    EXECV_CHAR **envlist;
7542
0
    Py_ssize_t argc, envc;
7543
7544
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7545
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7546
0
        PyErr_SetString(PyExc_RuntimeError,
7547
0
                        "exec not supported for isolated subinterpreters");
7548
0
        return NULL;
7549
0
    }
7550
7551
    /* execve has three arguments: (path, argv, env), where
7552
       argv is a list or tuple of strings and env is a dictionary
7553
       like posix.environ. */
7554
7555
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7556
0
        PyErr_SetString(PyExc_TypeError,
7557
0
                        "execve: argv must be a tuple or list");
7558
0
        goto fail_0;
7559
0
    }
7560
0
    argc = PySequence_Size(argv);
7561
0
    if (argc < 1) {
7562
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7563
0
        return NULL;
7564
0
    }
7565
7566
0
    if (!PyMapping_Check(env)) {
7567
0
        PyErr_SetString(PyExc_TypeError,
7568
0
                        "execve: environment must be a mapping object");
7569
0
        goto fail_0;
7570
0
    }
7571
7572
0
    argvlist = parse_arglist(argv, &argc);
7573
0
    if (argvlist == NULL) {
7574
0
        goto fail_0;
7575
0
    }
7576
0
    if (!argvlist[0][0]) {
7577
0
        PyErr_SetString(PyExc_ValueError,
7578
0
            "execve: argv first element cannot be empty");
7579
0
        goto fail_0;
7580
0
    }
7581
7582
0
    envlist = parse_envlist(env, &envc);
7583
0
    if (envlist == NULL)
7584
0
        goto fail_0;
7585
7586
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7587
0
        goto fail_1;
7588
0
    }
7589
7590
0
    _Py_BEGIN_SUPPRESS_IPH
7591
0
#ifdef HAVE_FEXECVE
7592
0
    if (path->is_fd)
7593
0
        fexecve(path->fd, argvlist, envlist);
7594
0
    else
7595
0
#endif
7596
#ifdef HAVE_WEXECV
7597
        _wexecve(path->wide, argvlist, envlist);
7598
#else
7599
0
        execve(path->narrow, argvlist, envlist);
7600
0
#endif
7601
0
    _Py_END_SUPPRESS_IPH
7602
7603
    /* If we get here it's definitely an error */
7604
7605
0
    posix_path_error(path);
7606
0
  fail_1:
7607
0
    free_string_array(envlist, envc);
7608
0
  fail_0:
7609
0
    if (argvlist)
7610
0
        free_string_array(argvlist, argc);
7611
0
    return NULL;
7612
0
}
7613
7614
#endif /* HAVE_EXECV */
7615
7616
#ifdef HAVE_POSIX_SPAWN
7617
7618
enum posix_spawn_file_actions_identifier {
7619
    POSIX_SPAWN_OPEN,
7620
    POSIX_SPAWN_CLOSE,
7621
    POSIX_SPAWN_DUP2
7622
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7623
    ,POSIX_SPAWN_CLOSEFROM
7624
#endif
7625
};
7626
7627
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7628
static int
7629
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7630
#endif
7631
7632
static int
7633
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7634
                        int resetids, int setsid, PyObject *setsigmask,
7635
                        PyObject *setsigdef, PyObject *scheduler,
7636
                        posix_spawnattr_t *attrp)
7637
0
{
7638
0
    assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
7639
0
    long all_flags = 0;
7640
7641
0
    errno = posix_spawnattr_init(attrp);
7642
0
    if (errno) {
7643
0
        posix_error();
7644
0
        return -1;
7645
0
    }
7646
7647
0
    if (setpgroup && setpgroup != Py_None) {
7648
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7649
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7650
0
            goto fail;
7651
0
        }
7652
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7653
0
        if (errno) {
7654
0
            posix_error();
7655
0
            goto fail;
7656
0
        }
7657
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7658
0
    }
7659
7660
0
    if (resetids) {
7661
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7662
0
    }
7663
7664
0
    if (setsid) {
7665
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7666
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7667
#endif
7668
0
#ifdef POSIX_SPAWN_SETSID
7669
0
        all_flags |= POSIX_SPAWN_SETSID;
7670
#elif defined(POSIX_SPAWN_SETSID_NP)
7671
        all_flags |= POSIX_SPAWN_SETSID_NP;
7672
#else
7673
        argument_unavailable_error(func_name, "setsid");
7674
        return -1;
7675
#endif
7676
7677
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7678
        } else {
7679
            argument_unavailable_error(func_name, "setsid");
7680
            return -1;
7681
        }
7682
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7683
7684
0
    }
7685
7686
0
#ifdef HAVE_SIGSET_T
7687
0
   if (setsigmask) {
7688
0
        sigset_t set;
7689
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7690
0
            goto fail;
7691
0
        }
7692
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7693
0
        if (errno) {
7694
0
            posix_error();
7695
0
            goto fail;
7696
0
        }
7697
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7698
0
    }
7699
7700
0
    if (setsigdef) {
7701
0
        sigset_t set;
7702
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7703
0
            goto fail;
7704
0
        }
7705
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7706
0
        if (errno) {
7707
0
            posix_error();
7708
0
            goto fail;
7709
0
        }
7710
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7711
0
    }
7712
#else
7713
    if (setsigmask || setsigdef) {
7714
        PyErr_SetString(PyExc_NotImplementedError,
7715
                        "sigset is not supported on this platform");
7716
        goto fail;
7717
    }
7718
#endif
7719
7720
0
    if (scheduler && scheduler != Py_None) {
7721
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7722
0
        PyObject *py_schedpolicy;
7723
0
        PyObject *schedparam_obj;
7724
0
        struct sched_param schedparam;
7725
7726
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7727
0
                        ";A scheduler tuple must have two elements",
7728
0
                        &py_schedpolicy, &schedparam_obj)) {
7729
0
            goto fail;
7730
0
        }
7731
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7732
0
            goto fail;
7733
0
        }
7734
0
        if (py_schedpolicy != Py_None) {
7735
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7736
7737
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7738
0
                goto fail;
7739
0
            }
7740
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7741
0
            if (errno) {
7742
0
                posix_error();
7743
0
                goto fail;
7744
0
            }
7745
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7746
0
        }
7747
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7748
0
        if (errno) {
7749
0
            posix_error();
7750
0
            goto fail;
7751
0
        }
7752
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7753
#else
7754
        PyErr_SetString(PyExc_NotImplementedError,
7755
                "The scheduler option is not supported in this system.");
7756
        goto fail;
7757
#endif
7758
0
    }
7759
7760
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7761
0
    if (errno) {
7762
0
        posix_error();
7763
0
        goto fail;
7764
0
    }
7765
7766
0
    return 0;
7767
7768
0
fail:
7769
0
    (void)posix_spawnattr_destroy(attrp);
7770
0
    return -1;
7771
0
}
7772
7773
static int
7774
parse_file_actions(PyObject *file_actions,
7775
                   posix_spawn_file_actions_t *file_actionsp,
7776
                   PyObject *temp_buffer)
7777
0
{
7778
0
    PyObject *seq;
7779
0
    PyObject *file_action = NULL;
7780
0
    PyObject *tag_obj;
7781
7782
0
    seq = PySequence_Fast(file_actions,
7783
0
                          "file_actions must be a sequence or None");
7784
0
    if (seq == NULL) {
7785
0
        return -1;
7786
0
    }
7787
7788
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7789
0
    if (errno) {
7790
0
        posix_error();
7791
0
        Py_DECREF(seq);
7792
0
        return -1;
7793
0
    }
7794
7795
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7796
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7797
0
        Py_INCREF(file_action);
7798
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7799
0
            PyErr_SetString(PyExc_TypeError,
7800
0
                "Each file_actions element must be a non-empty tuple");
7801
0
            goto fail;
7802
0
        }
7803
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7804
0
        if (tag == -1 && PyErr_Occurred()) {
7805
0
            goto fail;
7806
0
        }
7807
7808
        /* Populate the file_actions object */
7809
0
        switch (tag) {
7810
0
            case POSIX_SPAWN_OPEN: {
7811
0
                int fd, oflag;
7812
0
                PyObject *path;
7813
0
                unsigned long mode;
7814
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7815
0
                        ";A open file_action tuple must have 5 elements",
7816
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7817
0
                        &oflag, &mode))
7818
0
                {
7819
0
                    goto fail;
7820
0
                }
7821
0
                if (PyList_Append(temp_buffer, path)) {
7822
0
                    Py_DECREF(path);
7823
0
                    goto fail;
7824
0
                }
7825
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7826
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7827
0
                if (errno) {
7828
0
                    posix_error();
7829
0
                    Py_DECREF(path);
7830
0
                    goto fail;
7831
0
                }
7832
0
                Py_DECREF(path);
7833
0
                break;
7834
0
            }
7835
0
            case POSIX_SPAWN_CLOSE: {
7836
0
                int fd;
7837
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7838
0
                        ";A close file_action tuple must have 2 elements",
7839
0
                        &tag_obj, &fd))
7840
0
                {
7841
0
                    goto fail;
7842
0
                }
7843
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7844
0
                if (errno) {
7845
0
                    posix_error();
7846
0
                    goto fail;
7847
0
                }
7848
0
                break;
7849
0
            }
7850
0
            case POSIX_SPAWN_DUP2: {
7851
0
                int fd1, fd2;
7852
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7853
0
                        ";A dup2 file_action tuple must have 3 elements",
7854
0
                        &tag_obj, &fd1, &fd2))
7855
0
                {
7856
0
                    goto fail;
7857
0
                }
7858
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7859
0
                                                         fd1, fd2);
7860
0
                if (errno) {
7861
0
                    posix_error();
7862
0
                    goto fail;
7863
0
                }
7864
0
                break;
7865
0
            }
7866
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7867
            case POSIX_SPAWN_CLOSEFROM: {
7868
                int fd;
7869
                if (!PyArg_ParseTuple(file_action, "Oi"
7870
                        ";A closefrom file_action tuple must have 2 elements",
7871
                        &tag_obj, &fd))
7872
                {
7873
                    goto fail;
7874
                }
7875
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7876
                                                                 fd);
7877
                if (errno) {
7878
                    posix_error();
7879
                    goto fail;
7880
                }
7881
                break;
7882
            }
7883
#endif
7884
0
            default: {
7885
0
                PyErr_SetString(PyExc_TypeError,
7886
0
                                "Unknown file_actions identifier");
7887
0
                goto fail;
7888
0
            }
7889
0
        }
7890
0
        Py_DECREF(file_action);
7891
0
    }
7892
7893
0
    Py_DECREF(seq);
7894
0
    return 0;
7895
7896
0
fail:
7897
0
    Py_DECREF(seq);
7898
0
    Py_DECREF(file_action);
7899
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7900
0
    return -1;
7901
0
}
7902
7903
7904
static PyObject *
7905
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7906
               PyObject *env, PyObject *file_actions,
7907
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7908
               PyObject *setsigdef, PyObject *scheduler)
7909
0
{
7910
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7911
0
    EXECV_CHAR **argvlist = NULL;
7912
0
    EXECV_CHAR **envlist = NULL;
7913
0
    posix_spawn_file_actions_t file_actions_buf;
7914
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7915
0
    posix_spawnattr_t attr;
7916
0
    posix_spawnattr_t *attrp = NULL;
7917
0
    Py_ssize_t argc, envc;
7918
0
    PyObject *result = NULL;
7919
0
    PyObject *temp_buffer = NULL;
7920
0
    pid_t pid;
7921
0
    int err_code;
7922
7923
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7924
       argv is a list or tuple of strings and env is a dictionary
7925
       like posix.environ. */
7926
7927
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7928
0
        PyErr_Format(PyExc_TypeError,
7929
0
                     "%s: argv must be a tuple or list", func_name);
7930
0
        goto exit;
7931
0
    }
7932
0
    argc = PySequence_Size(argv);
7933
0
    if (argc < 1) {
7934
0
        PyErr_Format(PyExc_ValueError,
7935
0
                     "%s: argv must not be empty", func_name);
7936
0
        goto exit;
7937
0
    }
7938
7939
0
    if (!PyMapping_Check(env) && env != Py_None) {
7940
0
        PyErr_Format(PyExc_TypeError,
7941
0
                     "%s: environment must be a mapping object or None", func_name);
7942
0
        goto exit;
7943
0
    }
7944
7945
0
    if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7946
0
        PyErr_Format(PyExc_TypeError,
7947
0
                     "%s: scheduler must be a tuple or None", func_name);
7948
0
        goto exit;
7949
0
    }
7950
7951
0
    argvlist = parse_arglist(argv, &argc);
7952
0
    if (argvlist == NULL) {
7953
0
        goto exit;
7954
0
    }
7955
0
    if (!argvlist[0][0]) {
7956
0
        PyErr_Format(PyExc_ValueError,
7957
0
                     "%s: argv first element cannot be empty", func_name);
7958
0
        goto exit;
7959
0
    }
7960
7961
#ifdef USE_DARWIN_NS_GET_ENVIRON
7962
    // There is no environ global in this situation.
7963
    char **environ = NULL;
7964
#endif
7965
7966
0
    if (env == Py_None) {
7967
#ifdef USE_DARWIN_NS_GET_ENVIRON
7968
        environ = *_NSGetEnviron();
7969
#endif
7970
0
        envlist = environ;
7971
0
    } else {
7972
0
        envlist = parse_envlist(env, &envc);
7973
0
        if (envlist == NULL) {
7974
0
            goto exit;
7975
0
        }
7976
0
    }
7977
7978
0
    if (file_actions != NULL && file_actions != Py_None) {
7979
        /* There is a bug in old versions of glibc that makes some of the
7980
         * helper functions for manipulating file actions not copy the provided
7981
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7982
         * copy the value of path for some old versions of glibc (<2.20).
7983
         * The use of temp_buffer here is a workaround that keeps the
7984
         * python objects that own the buffers alive until posix_spawn gets called.
7985
         * Check https://bugs.python.org/issue33630 and
7986
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7987
0
        temp_buffer = PyList_New(0);
7988
0
        if (!temp_buffer) {
7989
0
            goto exit;
7990
0
        }
7991
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7992
0
            goto exit;
7993
0
        }
7994
0
        file_actionsp = &file_actions_buf;
7995
0
    }
7996
7997
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7998
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7999
0
        goto exit;
8000
0
    }
8001
0
    attrp = &attr;
8002
8003
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
8004
0
        goto exit;
8005
0
    }
8006
8007
0
    _Py_BEGIN_SUPPRESS_IPH
8008
0
#ifdef HAVE_POSIX_SPAWNP
8009
0
    if (use_posix_spawnp) {
8010
0
        err_code = posix_spawnp(&pid, path->narrow,
8011
0
                                file_actionsp, attrp, argvlist, envlist);
8012
0
    }
8013
0
    else
8014
0
#endif /* HAVE_POSIX_SPAWNP */
8015
0
    {
8016
0
        err_code = posix_spawn(&pid, path->narrow,
8017
0
                               file_actionsp, attrp, argvlist, envlist);
8018
0
    }
8019
0
    _Py_END_SUPPRESS_IPH
8020
8021
0
    if (err_code) {
8022
0
        errno = err_code;
8023
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8024
0
        goto exit;
8025
0
    }
8026
#ifdef _Py_MEMORY_SANITIZER
8027
    __msan_unpoison(&pid, sizeof(pid));
8028
#endif
8029
0
    result = PyLong_FromPid(pid);
8030
8031
0
exit:
8032
0
    if (file_actionsp) {
8033
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
8034
0
    }
8035
0
    if (attrp) {
8036
0
        (void)posix_spawnattr_destroy(attrp);
8037
0
    }
8038
0
    if (envlist && envlist != environ) {
8039
0
        free_string_array(envlist, envc);
8040
0
    }
8041
0
    if (argvlist) {
8042
0
        free_string_array(argvlist, argc);
8043
0
    }
8044
0
    Py_XDECREF(temp_buffer);
8045
0
    return result;
8046
0
}
8047
8048
8049
/*[clinic input]
8050
8051
os.posix_spawn
8052
    path: path_t
8053
        Path of executable file.
8054
    argv: object
8055
        Tuple or list of strings.
8056
    env: object
8057
        Dictionary of strings mapping to strings.
8058
    /
8059
    *
8060
    file_actions: object(c_default='NULL') = ()
8061
        A sequence of file action tuples.
8062
    setpgroup: object(c_default='NULL') = None
8063
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8064
    resetids: bool = False
8065
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8066
    setsid: bool = False
8067
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP
8068
        will be activated.
8069
    setsigmask: object(c_default='NULL') = ()
8070
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8071
    setsigdef: object(c_default='NULL') = ()
8072
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8073
    scheduler: object(c_default='NULL') = None
8074
        A tuple with the scheduler policy (optional) and parameters.
8075
8076
Execute the program specified by path in a new process.
8077
[clinic start generated code]*/
8078
8079
static PyObject *
8080
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8081
                    PyObject *env, PyObject *file_actions,
8082
                    PyObject *setpgroup, int resetids, int setsid,
8083
                    PyObject *setsigmask, PyObject *setsigdef,
8084
                    PyObject *scheduler)
8085
/*[clinic end generated code: output=14a1098c566bc675 input=c7592dcbc96e8114]*/
8086
0
{
8087
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8088
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8089
0
                          scheduler);
8090
0
}
8091
 #endif /* HAVE_POSIX_SPAWN */
8092
8093
8094
8095
#ifdef HAVE_POSIX_SPAWNP
8096
/*[clinic input]
8097
8098
os.posix_spawnp
8099
    path: path_t
8100
        Path of executable file.
8101
    argv: object
8102
        Tuple or list of strings.
8103
    env: object
8104
        Dictionary of strings mapping to strings.
8105
    /
8106
    *
8107
    file_actions: object(c_default='NULL') = ()
8108
        A sequence of file action tuples.
8109
    setpgroup: object(c_default='NULL') = None
8110
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8111
    resetids: bool = False
8112
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8113
    setsid: bool = False
8114
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP
8115
        will be activated.
8116
    setsigmask: object(c_default='NULL') = ()
8117
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8118
    setsigdef: object(c_default='NULL') = ()
8119
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8120
    scheduler: object(c_default='NULL') = None
8121
        A tuple with the scheduler policy (optional) and parameters.
8122
8123
Execute the program specified by path in a new process.
8124
[clinic start generated code]*/
8125
8126
static PyObject *
8127
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8128
                     PyObject *env, PyObject *file_actions,
8129
                     PyObject *setpgroup, int resetids, int setsid,
8130
                     PyObject *setsigmask, PyObject *setsigdef,
8131
                     PyObject *scheduler)
8132
/*[clinic end generated code: output=7b9aaefe3031238d input=43ccc1452cae2be3]*/
8133
0
{
8134
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8135
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8136
0
                          scheduler);
8137
0
}
8138
#endif /* HAVE_POSIX_SPAWNP */
8139
8140
#ifdef HAVE_RTPSPAWN
8141
static intptr_t
8142
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8143
               const char  *envp[])
8144
{
8145
     RTP_ID rtpid;
8146
     int status;
8147
     pid_t res;
8148
     int async_err = 0;
8149
8150
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8151
        uStackSize=0 cannot be used, the default stack size is too small for
8152
        Python. */
8153
     if (envp) {
8154
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8155
                          100, 0x1000000, 0, VX_FP_TASK);
8156
     }
8157
     else {
8158
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8159
                          100, 0x1000000, 0, VX_FP_TASK);
8160
     }
8161
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8162
         do {
8163
             res = waitpid((pid_t)rtpid, &status, 0);
8164
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8165
8166
         if (res < 0)
8167
             return RTP_ID_ERROR;
8168
         return ((intptr_t)status);
8169
     }
8170
     return ((intptr_t)rtpid);
8171
}
8172
#endif
8173
8174
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8175
/*[clinic input]
8176
os.spawnv
8177
8178
    mode: int
8179
        Mode of process creation.
8180
    path: path_t
8181
        Path of executable file.
8182
    argv: object
8183
        Tuple or list of strings.
8184
    /
8185
8186
Execute the program specified by path in a new process.
8187
[clinic start generated code]*/
8188
8189
static PyObject *
8190
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8191
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8192
{
8193
    EXECV_CHAR **argvlist;
8194
    int i;
8195
    Py_ssize_t argc;
8196
    intptr_t spawnval;
8197
8198
    /* spawnv has three arguments: (mode, path, argv), where
8199
       argv is a list or tuple of strings. */
8200
8201
    if (PyList_Check(argv)) {
8202
        argc = PyList_Size(argv);
8203
    }
8204
    else if (PyTuple_Check(argv)) {
8205
        argc = PyTuple_Size(argv);
8206
    }
8207
    else {
8208
        PyErr_SetString(PyExc_TypeError,
8209
                        "spawnv() arg 2 must be a tuple or list");
8210
        return NULL;
8211
    }
8212
    if (argc == 0) {
8213
        PyErr_SetString(PyExc_ValueError,
8214
            "spawnv() arg 2 cannot be empty");
8215
        return NULL;
8216
    }
8217
8218
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8219
    if (argvlist == NULL) {
8220
        return PyErr_NoMemory();
8221
    }
8222
    for (i = 0; i < argc; i++) {
8223
        // The item must be a strong reference because of possible
8224
        // side-effects of PyUnicode_FS{Converter,Decoder}() in
8225
        // fsconvert_strdup(): an item's __fspath__() can mutate a list
8226
        // *argv*, releasing the list's reference to the item (gh-151416).
8227
        PyObject *item = PySequence_ITEM(argv, i);
8228
        if (item == NULL) {
8229
            free_string_array(argvlist, i);
8230
            return NULL;
8231
        }
8232
        if (!fsconvert_strdup(item, &argvlist[i])) {
8233
            Py_DECREF(item);
8234
            free_string_array(argvlist, i);
8235
            // Add argument context to the converter's terse TypeError, but
8236
            // let MemoryError, codec errors, embedded-null ValueError, etc.
8237
            // propagate unmasked.
8238
            if (PyErr_ExceptionMatches(PyExc_TypeError)) {
8239
                PyErr_SetString(
8240
                    PyExc_TypeError,
8241
                    "spawnv() arg 2 must contain only strings");
8242
            }
8243
            return NULL;
8244
        }
8245
        Py_DECREF(item);
8246
        if (i == 0 && !argvlist[0][0]) {
8247
            free_string_array(argvlist, i + 1);
8248
            PyErr_SetString(
8249
                PyExc_ValueError,
8250
                "spawnv() arg 2 first element cannot be empty");
8251
            return NULL;
8252
        }
8253
    }
8254
    argvlist[argc] = NULL;
8255
8256
#if !defined(HAVE_RTPSPAWN)
8257
    if (mode == _OLD_P_OVERLAY)
8258
        mode = _P_OVERLAY;
8259
#endif
8260
8261
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8262
                    Py_None) < 0) {
8263
        free_string_array(argvlist, argc);
8264
        return NULL;
8265
    }
8266
8267
    Py_BEGIN_ALLOW_THREADS
8268
    _Py_BEGIN_SUPPRESS_IPH
8269
#ifdef HAVE_WSPAWNV
8270
    spawnval = _wspawnv(mode, path->wide, argvlist);
8271
#elif defined(HAVE_RTPSPAWN)
8272
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8273
#else
8274
    spawnval = _spawnv(mode, path->narrow, argvlist);
8275
#endif
8276
    _Py_END_SUPPRESS_IPH
8277
    Py_END_ALLOW_THREADS
8278
8279
    int saved_errno = errno;
8280
    free_string_array(argvlist, argc);
8281
8282
    if (spawnval == -1) {
8283
        errno = saved_errno;
8284
        posix_error();
8285
        return NULL;
8286
    }
8287
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8288
}
8289
8290
/*[clinic input]
8291
os.spawnve
8292
8293
    mode: int
8294
        Mode of process creation.
8295
    path: path_t
8296
        Path of executable file.
8297
    argv: object
8298
        Tuple or list of strings.
8299
    env: object
8300
        Dictionary of strings mapping to strings.
8301
    /
8302
8303
Execute the program specified by path in a new process.
8304
[clinic start generated code]*/
8305
8306
static PyObject *
8307
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8308
                PyObject *env)
8309
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8310
{
8311
    EXECV_CHAR **argvlist;
8312
    EXECV_CHAR **envlist;
8313
    PyObject *res = NULL;
8314
    Py_ssize_t argc, i, envc;
8315
    intptr_t spawnval;
8316
    Py_ssize_t lastarg = 0;
8317
8318
    /* spawnve has four arguments: (mode, path, argv, env), where
8319
       argv is a list or tuple of strings and env is a dictionary
8320
       like posix.environ. */
8321
8322
    if (PyList_Check(argv)) {
8323
        argc = PyList_Size(argv);
8324
    }
8325
    else if (PyTuple_Check(argv)) {
8326
        argc = PyTuple_Size(argv);
8327
    }
8328
    else {
8329
        PyErr_SetString(PyExc_TypeError,
8330
                        "spawnve() arg 2 must be a tuple or list");
8331
        goto fail_0;
8332
    }
8333
    if (argc == 0) {
8334
        PyErr_SetString(PyExc_ValueError,
8335
            "spawnve() arg 2 cannot be empty");
8336
        goto fail_0;
8337
    }
8338
    if (!PyMapping_Check(env)) {
8339
        PyErr_SetString(PyExc_TypeError,
8340
                        "spawnve() arg 3 must be a mapping object");
8341
        goto fail_0;
8342
    }
8343
8344
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8345
    if (argvlist == NULL) {
8346
        PyErr_NoMemory();
8347
        goto fail_0;
8348
    }
8349
    for (i = 0; i < argc; i++) {
8350
        // The item must be a strong reference because of possible
8351
        // side-effects of PyUnicode_FS{Converter,Decoder}() in
8352
        // fsconvert_strdup(): an item's __fspath__() can mutate a list
8353
        // *argv*, releasing the list's reference to the item (gh-151416).
8354
        PyObject *item = PySequence_ITEM(argv, i);
8355
        if (item == NULL) {
8356
            lastarg = i;
8357
            goto fail_1;
8358
        }
8359
        if (!fsconvert_strdup(item, &argvlist[i])) {
8360
            Py_DECREF(item);
8361
            lastarg = i;
8362
            goto fail_1;
8363
        }
8364
        Py_DECREF(item);
8365
        if (i == 0 && !argvlist[0][0]) {
8366
            lastarg = i + 1;
8367
            PyErr_SetString(
8368
                PyExc_ValueError,
8369
                "spawnv() arg 2 first element cannot be empty");
8370
            goto fail_1;
8371
        }
8372
    }
8373
    lastarg = argc;
8374
    argvlist[argc] = NULL;
8375
8376
    envlist = parse_envlist(env, &envc);
8377
    if (envlist == NULL)
8378
        goto fail_1;
8379
8380
#if !defined(HAVE_RTPSPAWN)
8381
    if (mode == _OLD_P_OVERLAY)
8382
        mode = _P_OVERLAY;
8383
#endif
8384
8385
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8386
        goto fail_2;
8387
    }
8388
8389
    Py_BEGIN_ALLOW_THREADS
8390
    _Py_BEGIN_SUPPRESS_IPH
8391
#ifdef HAVE_WSPAWNV
8392
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8393
#elif defined(HAVE_RTPSPAWN)
8394
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8395
                           (const char **)envlist);
8396
#else
8397
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8398
#endif
8399
    _Py_END_SUPPRESS_IPH
8400
    Py_END_ALLOW_THREADS
8401
8402
    if (spawnval == -1)
8403
        (void) posix_error();
8404
    else
8405
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8406
8407
  fail_2:
8408
    while (--envc >= 0) {
8409
        PyMem_Free(envlist[envc]);
8410
    }
8411
    PyMem_Free(envlist);
8412
  fail_1:
8413
    free_string_array(argvlist, lastarg);
8414
  fail_0:
8415
    return res;
8416
}
8417
8418
#endif /* HAVE_SPAWNV */
8419
8420
#ifdef HAVE_FORK
8421
8422
/* Helper function to validate arguments.
8423
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8424
   If obj is non-NULL it must be callable.  */
8425
static int
8426
check_null_or_callable(PyObject *obj, const char* obj_name)
8427
60
{
8428
60
    if (obj && !PyCallable_Check(obj)) {
8429
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8430
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8431
0
        return -1;
8432
0
    }
8433
60
    return 0;
8434
60
}
8435
8436
/*[clinic input]
8437
os.register_at_fork
8438
8439
    *
8440
    before: object=NULL
8441
        A callable to be called in the parent before the fork() syscall.
8442
    after_in_child: object=NULL
8443
        A callable to be called in the child after fork().
8444
    after_in_parent: object=NULL
8445
        A callable to be called in the parent after fork().
8446
8447
Register callables to be called when forking a new process.
8448
8449
'before' callbacks are called in reverse order.
8450
'after_in_child' and 'after_in_parent' callbacks are called in order.
8451
8452
[clinic start generated code]*/
8453
8454
static PyObject *
8455
os_register_at_fork_impl(PyObject *module, PyObject *before,
8456
                         PyObject *after_in_child, PyObject *after_in_parent)
8457
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8458
20
{
8459
20
    PyInterpreterState *interp;
8460
8461
20
    if (!before && !after_in_child && !after_in_parent) {
8462
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8463
0
        return NULL;
8464
0
    }
8465
20
    if (check_null_or_callable(before, "before") ||
8466
20
        check_null_or_callable(after_in_child, "after_in_child") ||
8467
20
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8468
0
        return NULL;
8469
0
    }
8470
20
    interp = _PyInterpreterState_GET();
8471
8472
20
    if (register_at_forker(&interp->before_forkers, before)) {
8473
0
        return NULL;
8474
0
    }
8475
20
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8476
0
        return NULL;
8477
0
    }
8478
20
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8479
0
        return NULL;
8480
0
    }
8481
20
    Py_RETURN_NONE;
8482
20
}
8483
#endif /* HAVE_FORK */
8484
8485
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8486
// Common code to raise a warning if we detect there is more than one thread
8487
// running in the process. Best effort, silent if unable to count threads.
8488
// Constraint: Quick. Never overcounts. Never leaves an error set.
8489
//
8490
// This MUST only be called from the parent process after
8491
// PyOS_AfterFork_Parent().
8492
static int
8493
warn_about_fork_with_threads(
8494
    const char* name,  // Name of the API to use in the warning message.
8495
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8496
)
8497
0
{
8498
    // It's not safe to issue the warning while the world is stopped, because
8499
    // other threads might be holding locks that we need, which would deadlock.
8500
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8501
8502
0
    Py_ssize_t num_python_threads = num_os_threads;
8503
0
    if (num_python_threads <= 0) {
8504
        // Fall back to just the number our threading module knows about.
8505
        // An incomplete view of the world, but better than nothing.
8506
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8507
0
        if (!threading) {
8508
0
            PyErr_Clear();
8509
0
            return 0;
8510
0
        }
8511
0
        PyObject *threading_active =
8512
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8513
0
        if (!threading_active) {
8514
0
            PyErr_Clear();
8515
0
            Py_DECREF(threading);
8516
0
            return 0;
8517
0
        }
8518
0
        PyObject *threading_limbo =
8519
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8520
0
        if (!threading_limbo) {
8521
0
            PyErr_Clear();
8522
0
            Py_DECREF(threading);
8523
0
            Py_DECREF(threading_active);
8524
0
            return 0;
8525
0
        }
8526
0
        Py_DECREF(threading);
8527
        // Duplicating what threading.active_count() does but without holding
8528
        // threading._active_limbo_lock so our count could be inaccurate if
8529
        // these dicts are mid-update from another thread.  Not a big deal.
8530
        // Worst case if someone replaced threading._active or threading._limbo
8531
        // with non-dicts, we get -1 from *Length() below and undercount.
8532
        // Nobody should, but we're best effort so we clear errors and move on.
8533
0
        num_python_threads = (PyMapping_Length(threading_active)
8534
0
                              + PyMapping_Length(threading_limbo));
8535
0
        PyErr_Clear();
8536
0
        Py_DECREF(threading_active);
8537
0
        Py_DECREF(threading_limbo);
8538
0
    }
8539
0
    if (num_python_threads > 1) {
8540
0
        return PyErr_WarnFormat(
8541
0
                PyExc_DeprecationWarning, 1,
8542
0
#ifdef HAVE_GETPID
8543
0
                "This process (pid=%d) is multi-threaded, "
8544
#else
8545
                "This process is multi-threaded, "
8546
#endif
8547
0
                "use of %s() may lead to deadlocks in the child.",
8548
0
#ifdef HAVE_GETPID
8549
0
                getpid(),
8550
0
#endif
8551
0
                name);
8552
0
    }
8553
0
    return 0;
8554
0
}
8555
8556
// If this returns <= 0, we were unable to successfully use any OS APIs.
8557
// Returns a positive number of threads otherwise.
8558
static Py_ssize_t get_number_of_os_threads(void)
8559
0
{
8560
    // TODO: Consider making an `os` module API to return the current number
8561
    // of threads in the process. That'd presumably use this platform code but
8562
    // raise an error rather than using the inaccurate fallback.
8563
0
    Py_ssize_t num_python_threads = 0;
8564
#if defined(__APPLE__) && defined(HAVE_GETPID)
8565
    mach_port_t macos_self = mach_task_self();
8566
    mach_port_t macos_task;
8567
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8568
        thread_array_t macos_threads;
8569
        mach_msg_type_number_t macos_n_threads;
8570
        if (task_threads(macos_task, &macos_threads,
8571
                         &macos_n_threads) == KERN_SUCCESS) {
8572
            num_python_threads = macos_n_threads;
8573
        }
8574
    }
8575
#elif defined(__linux__)
8576
    // Linux /proc/self/stat 20th field is the number of threads.
8577
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8578
0
    if (proc_stat) {
8579
0
        size_t n;
8580
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8581
        // observed on the author's workstation.
8582
0
        char stat_line[160];
8583
0
        n = fread(&stat_line, 1, 159, proc_stat);
8584
0
        stat_line[n] = '\0';
8585
0
        fclose(proc_stat);
8586
8587
0
        char *saveptr = NULL;
8588
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8589
0
        unsigned int idx;
8590
0
        for (idx = 19; idx && field; --idx) {
8591
0
            field = strtok_r(NULL, " ", &saveptr);
8592
0
        }
8593
0
        if (idx == 0 && field) {  // found the 20th field
8594
0
            num_python_threads = atoi(field);  // 0 on error
8595
0
        }
8596
0
    }
8597
0
#endif
8598
0
    return num_python_threads;
8599
0
}
8600
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8601
8602
#ifdef HAVE_FORK1
8603
/*[clinic input]
8604
os.fork1
8605
8606
Fork a child process with a single multiplexed (i.e., not bound) thread.
8607
8608
Return 0 to child process and PID of child to parent process.
8609
[clinic start generated code]*/
8610
8611
static PyObject *
8612
os_fork1_impl(PyObject *module)
8613
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8614
{
8615
    pid_t pid;
8616
8617
    PyInterpreterState *interp = _PyInterpreterState_GET();
8618
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8619
        PyErr_SetString(PyExc_PythonFinalizationError,
8620
                        "can't fork at interpreter shutdown");
8621
        return NULL;
8622
    }
8623
    if (!_Py_IsMainInterpreter(interp)) {
8624
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8625
        return NULL;
8626
    }
8627
    PyOS_BeforeFork();
8628
    pid = fork1();
8629
    int saved_errno = errno;
8630
    if (pid == 0) {
8631
        /* child: this clobbers and resets the import lock. */
8632
        PyOS_AfterFork_Child();
8633
    } else {
8634
        // Called before AfterFork_Parent in case those hooks start threads.
8635
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8636
        /* parent: release the import lock. */
8637
        PyOS_AfterFork_Parent();
8638
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8639
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8640
            return NULL;
8641
        }
8642
    }
8643
    if (pid == -1) {
8644
        errno = saved_errno;
8645
        return posix_error();
8646
    }
8647
    return PyLong_FromPid(pid);
8648
}
8649
#endif /* HAVE_FORK1 */
8650
8651
8652
#ifdef HAVE_FORK
8653
/*[clinic input]
8654
os.fork
8655
8656
Fork a child process.
8657
8658
Return 0 to child process and PID of child to parent process.
8659
[clinic start generated code]*/
8660
8661
static PyObject *
8662
os_fork_impl(PyObject *module)
8663
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8664
0
{
8665
0
    pid_t pid;
8666
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8667
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8668
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8669
0
                        "can't fork at interpreter shutdown");
8670
0
        return NULL;
8671
0
    }
8672
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8673
0
        PyErr_SetString(PyExc_RuntimeError,
8674
0
                        "fork not supported for isolated subinterpreters");
8675
0
        return NULL;
8676
0
    }
8677
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8678
0
        return NULL;
8679
0
    }
8680
0
    PyOS_BeforeFork();
8681
0
    pid = fork();
8682
0
    int saved_errno = errno;
8683
0
    if (pid == 0) {
8684
        /* child: this clobbers and resets the import lock. */
8685
0
        PyOS_AfterFork_Child();
8686
0
    } else {
8687
        // Called before AfterFork_Parent in case those hooks start threads.
8688
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8689
        /* parent: release the import lock. */
8690
0
        PyOS_AfterFork_Parent();
8691
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8692
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8693
0
            return NULL;
8694
0
    }
8695
0
    if (pid == -1) {
8696
0
        errno = saved_errno;
8697
0
        return posix_error();
8698
0
    }
8699
0
    return PyLong_FromPid(pid);
8700
0
}
8701
#endif /* HAVE_FORK */
8702
8703
8704
#ifdef HAVE_SCHED_H
8705
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8706
/*[clinic input]
8707
os.sched_get_priority_max
8708
8709
    policy: int
8710
8711
Get the maximum scheduling priority for policy.
8712
[clinic start generated code]*/
8713
8714
static PyObject *
8715
os_sched_get_priority_max_impl(PyObject *module, int policy)
8716
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8717
0
{
8718
    /* make sure that errno is cleared before the call */
8719
0
    errno = 0;
8720
0
    int max = sched_get_priority_max(policy);
8721
0
    if (max == -1 && errno)
8722
0
        return posix_error();
8723
0
    return PyLong_FromLong(max);
8724
0
}
8725
8726
8727
/*[clinic input]
8728
os.sched_get_priority_min
8729
8730
    policy: int
8731
8732
Get the minimum scheduling priority for policy.
8733
[clinic start generated code]*/
8734
8735
static PyObject *
8736
os_sched_get_priority_min_impl(PyObject *module, int policy)
8737
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8738
0
{
8739
    /* make sure that errno is cleared before the call */
8740
0
    errno = 0;
8741
0
    int min = sched_get_priority_min(policy);
8742
0
    if (min == -1 && errno)
8743
0
        return posix_error();
8744
0
    return PyLong_FromLong(min);
8745
0
}
8746
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8747
8748
8749
#ifdef HAVE_SCHED_SETSCHEDULER
8750
/*[clinic input]
8751
os.sched_getscheduler
8752
    pid: pid_t
8753
    /
8754
8755
Get the scheduling policy for the process identified by pid.
8756
8757
Passing 0 for pid returns the scheduling policy for the calling process.
8758
[clinic start generated code]*/
8759
8760
static PyObject *
8761
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8762
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8763
0
{
8764
0
    int policy;
8765
8766
0
    policy = sched_getscheduler(pid);
8767
0
    if (policy < 0)
8768
0
        return posix_error();
8769
0
    return PyLong_FromLong(policy);
8770
0
}
8771
#endif /* HAVE_SCHED_SETSCHEDULER */
8772
8773
8774
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8775
/*[clinic input]
8776
class os.sched_param "PyObject *" "SchedParamType"
8777
8778
@classmethod
8779
os.sched_param.__new__
8780
8781
    sched_priority: object
8782
        A scheduling parameter.
8783
8784
Currently has only one field: sched_priority
8785
[clinic start generated code]*/
8786
8787
static PyObject *
8788
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8789
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8790
0
{
8791
0
    PyObject *res;
8792
8793
0
    res = PyStructSequence_New(type);
8794
0
    if (!res)
8795
0
        return NULL;
8796
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8797
0
    return res;
8798
0
}
8799
8800
static PyObject *
8801
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8802
0
{
8803
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8804
0
}
8805
8806
static PyMethodDef os_sched_param_reduce_method = {
8807
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8808
};
8809
8810
PyDoc_VAR(os_sched_param__doc__);
8811
8812
static PyStructSequence_Field sched_param_fields[] = {
8813
    {"sched_priority", "the scheduling priority"},
8814
    {0}
8815
};
8816
8817
static PyStructSequence_Desc sched_param_desc = {
8818
    MODNAME ".sched_param", /* name */
8819
    os_sched_param__doc__, /* doc */
8820
    sched_param_fields,
8821
    1
8822
};
8823
8824
static int
8825
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8826
0
{
8827
0
    long priority;
8828
8829
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8830
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8831
0
        return 0;
8832
0
    }
8833
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8834
0
    if (priority == -1 && PyErr_Occurred())
8835
0
        return 0;
8836
0
    if (priority > INT_MAX || priority < INT_MIN) {
8837
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8838
0
        return 0;
8839
0
    }
8840
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8841
0
    return 1;
8842
0
}
8843
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8844
8845
8846
#ifdef HAVE_SCHED_SETSCHEDULER
8847
/*[clinic input]
8848
os.sched_setscheduler
8849
8850
    pid: pid_t
8851
    policy: int
8852
    param as param_obj: object
8853
    /
8854
8855
Set the scheduling policy for the process identified by pid.
8856
8857
If pid is 0, the calling process is changed.
8858
param is an instance of sched_param.
8859
[clinic start generated code]*/
8860
8861
static PyObject *
8862
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8863
                           PyObject *param_obj)
8864
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8865
0
{
8866
0
    struct sched_param param;
8867
0
    if (!convert_sched_param(module, param_obj, &param)) {
8868
0
        return NULL;
8869
0
    }
8870
8871
    /*
8872
    ** sched_setscheduler() returns 0 in Linux, but the previous
8873
    ** scheduling policy under Solaris/Illumos, and others.
8874
    ** On error, -1 is returned in all Operating Systems.
8875
    */
8876
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8877
0
        return posix_error();
8878
0
    Py_RETURN_NONE;
8879
0
}
8880
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8881
8882
8883
#ifdef HAVE_SCHED_SETPARAM
8884
/*[clinic input]
8885
os.sched_getparam
8886
    pid: pid_t
8887
    /
8888
8889
Returns scheduling parameters for the process identified by pid.
8890
8891
If pid is 0, returns parameters for the calling process.
8892
Return value is an instance of sched_param.
8893
[clinic start generated code]*/
8894
8895
static PyObject *
8896
os_sched_getparam_impl(PyObject *module, pid_t pid)
8897
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8898
0
{
8899
0
    struct sched_param param;
8900
0
    PyObject *result;
8901
0
    PyObject *priority;
8902
8903
0
    if (sched_getparam(pid, &param))
8904
0
        return posix_error();
8905
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8906
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8907
0
    if (!result)
8908
0
        return NULL;
8909
0
    priority = PyLong_FromLong(param.sched_priority);
8910
0
    if (!priority) {
8911
0
        Py_DECREF(result);
8912
0
        return NULL;
8913
0
    }
8914
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8915
0
    return result;
8916
0
}
8917
8918
8919
/*[clinic input]
8920
os.sched_setparam
8921
    pid: pid_t
8922
    param as param_obj: object
8923
    /
8924
8925
Set scheduling parameters for the process identified by pid.
8926
8927
If pid is 0, sets parameters for the calling process.
8928
param should be an instance of sched_param.
8929
[clinic start generated code]*/
8930
8931
static PyObject *
8932
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8933
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8934
0
{
8935
0
    struct sched_param param;
8936
0
    if (!convert_sched_param(module, param_obj, &param)) {
8937
0
        return NULL;
8938
0
    }
8939
8940
0
    if (sched_setparam(pid, &param))
8941
0
        return posix_error();
8942
0
    Py_RETURN_NONE;
8943
0
}
8944
#endif /* HAVE_SCHED_SETPARAM */
8945
8946
8947
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8948
/*[clinic input]
8949
@permit_long_summary
8950
os.sched_rr_get_interval -> double
8951
    pid: pid_t
8952
    /
8953
8954
Return the round-robin quantum for the process identified by pid, in seconds.
8955
8956
Value returned is a float.
8957
[clinic start generated code]*/
8958
8959
static double
8960
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8961
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8962
0
{
8963
0
    struct timespec interval;
8964
0
    if (sched_rr_get_interval(pid, &interval)) {
8965
0
        posix_error();
8966
0
        return -1.0;
8967
0
    }
8968
#ifdef _Py_MEMORY_SANITIZER
8969
    __msan_unpoison(&interval, sizeof(interval));
8970
#endif
8971
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8972
0
}
8973
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8974
8975
8976
/*[clinic input]
8977
os.sched_yield
8978
8979
Voluntarily relinquish the CPU.
8980
[clinic start generated code]*/
8981
8982
static PyObject *
8983
os_sched_yield_impl(PyObject *module)
8984
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8985
0
{
8986
0
    int result;
8987
0
    Py_BEGIN_ALLOW_THREADS
8988
0
    result = sched_yield();
8989
0
    Py_END_ALLOW_THREADS
8990
0
    if (result < 0) {
8991
0
        return posix_error();
8992
0
    }
8993
0
    Py_RETURN_NONE;
8994
0
}
8995
8996
#ifdef HAVE_SCHED_SETAFFINITY
8997
/* The minimum number of CPUs allocated in a cpu_set_t */
8998
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8999
9000
/*[clinic input]
9001
os.sched_setaffinity
9002
    pid: pid_t
9003
    mask : object
9004
    /
9005
9006
Set the CPU affinity of the process identified by pid to mask.
9007
9008
mask should be an iterable of integers identifying CPUs.
9009
[clinic start generated code]*/
9010
9011
static PyObject *
9012
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
9013
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
9014
0
{
9015
0
    int ncpus;
9016
0
    size_t setsize;
9017
0
    cpu_set_t *cpu_set = NULL;
9018
0
    PyObject *iterator = NULL, *item;
9019
9020
0
    iterator = PyObject_GetIter(mask);
9021
0
    if (iterator == NULL)
9022
0
        return NULL;
9023
9024
0
    ncpus = NCPUS_START;
9025
0
    setsize = CPU_ALLOC_SIZE(ncpus);
9026
0
    cpu_set = CPU_ALLOC(ncpus);
9027
0
    if (cpu_set == NULL) {
9028
0
        PyErr_NoMemory();
9029
0
        goto error;
9030
0
    }
9031
0
    CPU_ZERO_S(setsize, cpu_set);
9032
9033
0
    while ((item = PyIter_Next(iterator))) {
9034
0
        long cpu;
9035
0
        if (!PyIndex_Check(item)) {
9036
0
            PyErr_Format(PyExc_TypeError,
9037
0
                        "expected an iterator of ints, "
9038
0
                        "but iterator yielded %R",
9039
0
                        Py_TYPE(item));
9040
0
            Py_DECREF(item);
9041
0
            goto error;
9042
0
        }
9043
0
        cpu = PyLong_AsLong(item);
9044
0
        Py_DECREF(item);
9045
0
        if (cpu < 0) {
9046
0
            if (!PyErr_Occurred())
9047
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9048
0
            goto error;
9049
0
        }
9050
0
        if (cpu > INT_MAX - 1) {
9051
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9052
0
            goto error;
9053
0
        }
9054
0
        if (cpu >= ncpus) {
9055
            /* Grow CPU mask to fit the CPU number */
9056
0
            int newncpus = ncpus;
9057
0
            cpu_set_t *newmask;
9058
0
            size_t newsetsize;
9059
0
            while (newncpus <= cpu) {
9060
0
                if (newncpus > INT_MAX / 2)
9061
0
                    newncpus = cpu + 1;
9062
0
                else
9063
0
                    newncpus = newncpus * 2;
9064
0
            }
9065
0
            newmask = CPU_ALLOC(newncpus);
9066
0
            if (newmask == NULL) {
9067
0
                PyErr_NoMemory();
9068
0
                goto error;
9069
0
            }
9070
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9071
0
            CPU_ZERO_S(newsetsize, newmask);
9072
0
            memcpy(newmask, cpu_set, setsize);
9073
0
            CPU_FREE(cpu_set);
9074
0
            setsize = newsetsize;
9075
0
            cpu_set = newmask;
9076
0
            ncpus = newncpus;
9077
0
        }
9078
0
        CPU_SET_S(cpu, setsize, cpu_set);
9079
0
    }
9080
0
    if (PyErr_Occurred()) {
9081
0
        goto error;
9082
0
    }
9083
0
    Py_CLEAR(iterator);
9084
9085
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9086
0
        posix_error();
9087
0
        goto error;
9088
0
    }
9089
0
    CPU_FREE(cpu_set);
9090
0
    Py_RETURN_NONE;
9091
9092
0
error:
9093
0
    if (cpu_set)
9094
0
        CPU_FREE(cpu_set);
9095
0
    Py_XDECREF(iterator);
9096
0
    return NULL;
9097
0
}
9098
9099
9100
/*[clinic input]
9101
@permit_long_summary
9102
os.sched_getaffinity
9103
    pid: pid_t
9104
    /
9105
9106
Return the affinity of the process identified by pid (or the current process if zero).
9107
9108
The affinity is returned as a set of CPU identifiers.
9109
[clinic start generated code]*/
9110
9111
static PyObject *
9112
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9113
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9114
0
{
9115
0
    int ncpus = NCPUS_START;
9116
0
    size_t setsize;
9117
0
    cpu_set_t *mask;
9118
9119
0
    while (1) {
9120
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9121
0
        mask = CPU_ALLOC(ncpus);
9122
0
        if (mask == NULL) {
9123
0
            return PyErr_NoMemory();
9124
0
        }
9125
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9126
0
            break;
9127
0
        }
9128
0
        CPU_FREE(mask);
9129
0
        if (errno != EINVAL) {
9130
0
            return posix_error();
9131
0
        }
9132
0
        if (ncpus > INT_MAX / 2) {
9133
0
            PyErr_SetString(PyExc_OverflowError,
9134
0
                            "could not allocate a large enough CPU set");
9135
0
            return NULL;
9136
0
        }
9137
0
        ncpus *= 2;
9138
0
    }
9139
9140
0
    PyObject *res = PySet_New(NULL);
9141
0
    if (res == NULL) {
9142
0
        goto error;
9143
0
    }
9144
9145
0
    int cpu = 0;
9146
0
    int count = CPU_COUNT_S(setsize, mask);
9147
0
    for (; count; cpu++) {
9148
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9149
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9150
0
            --count;
9151
0
            if (cpu_num == NULL) {
9152
0
                goto error;
9153
0
            }
9154
0
            if (PySet_Add(res, cpu_num)) {
9155
0
                Py_DECREF(cpu_num);
9156
0
                goto error;
9157
0
            }
9158
0
            Py_DECREF(cpu_num);
9159
0
        }
9160
0
    }
9161
0
    CPU_FREE(mask);
9162
0
    return res;
9163
9164
0
error:
9165
0
    if (mask) {
9166
0
        CPU_FREE(mask);
9167
0
    }
9168
0
    Py_XDECREF(res);
9169
0
    return NULL;
9170
0
}
9171
#endif /* HAVE_SCHED_SETAFFINITY */
9172
9173
#endif /* HAVE_SCHED_H */
9174
9175
9176
#ifdef HAVE_POSIX_OPENPT
9177
/*[clinic input]
9178
os.posix_openpt -> int
9179
9180
    oflag: int
9181
    /
9182
9183
Open and return a file descriptor for a master pseudo-terminal device.
9184
9185
Performs a posix_openpt() C function call. The oflag argument is used to
9186
set file status flags and file access modes as specified in the manual
9187
page of posix_openpt() of your system.
9188
[clinic start generated code]*/
9189
9190
static int
9191
os_posix_openpt_impl(PyObject *module, int oflag)
9192
/*[clinic end generated code: output=ee0bc2624305fc79 input=3ce4eb297fa64307]*/
9193
0
{
9194
0
    int fd;
9195
9196
    // OpenBSD posix_openpt() rejects any flag other than O_RDWR and
9197
    // O_NOCTTY; the fd is made non-inheritable below in any case.
9198
0
#if defined(O_CLOEXEC) && !defined(__OpenBSD__)
9199
0
    oflag |= O_CLOEXEC;
9200
0
#endif
9201
9202
0
    fd = posix_openpt(oflag);
9203
0
    if (fd == -1) {
9204
0
        posix_error();
9205
0
        return -1;
9206
0
    }
9207
9208
    // Just in case, likely a no-op given O_CLOEXEC above.
9209
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9210
0
        close(fd);
9211
0
        return -1;
9212
0
    }
9213
9214
0
    return fd;
9215
0
}
9216
#endif /* HAVE_POSIX_OPENPT */
9217
9218
#ifdef HAVE_GRANTPT
9219
/*[clinic input]
9220
os.grantpt
9221
9222
    fd: fildes
9223
        File descriptor of a master pseudo-terminal device.
9224
    /
9225
9226
Grant access to the slave pseudo-terminal device.
9227
9228
Performs a grantpt() C function call.
9229
[clinic start generated code]*/
9230
9231
static PyObject *
9232
os_grantpt_impl(PyObject *module, int fd)
9233
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9234
0
{
9235
0
    int ret;
9236
0
    int saved_errno;
9237
0
    PyOS_sighandler_t sig_saved;
9238
9239
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9240
9241
0
    ret = grantpt(fd);
9242
0
    if (ret == -1)
9243
0
        saved_errno = errno;
9244
9245
0
    PyOS_setsig(SIGCHLD, sig_saved);
9246
9247
0
    if (ret == -1) {
9248
0
        errno = saved_errno;
9249
0
        return posix_error();
9250
0
    }
9251
9252
0
    Py_RETURN_NONE;
9253
0
}
9254
#endif /* HAVE_GRANTPT */
9255
9256
#ifdef HAVE_UNLOCKPT
9257
/*[clinic input]
9258
os.unlockpt
9259
9260
    fd: fildes
9261
        File descriptor of a master pseudo-terminal device.
9262
    /
9263
9264
Unlock a pseudo-terminal master/slave pair.
9265
9266
Performs an unlockpt() C function call.
9267
[clinic start generated code]*/
9268
9269
static PyObject *
9270
os_unlockpt_impl(PyObject *module, int fd)
9271
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9272
0
{
9273
0
    if (unlockpt(fd) == -1)
9274
0
        return posix_error();
9275
9276
0
    Py_RETURN_NONE;
9277
0
}
9278
#endif /* HAVE_UNLOCKPT */
9279
9280
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9281
static PyObject *
9282
py_ptsname(int fd)
9283
0
{
9284
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9285
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9286
0
    errno = 0;
9287
0
    char *name = ptsname(fd);
9288
0
    if (name == NULL) {
9289
0
        return posix_error();
9290
0
    }
9291
0
    return PyUnicode_DecodeFSDefault(name);
9292
0
}
9293
9294
/*[clinic input]
9295
os.ptsname
9296
9297
    fd: fildes
9298
        File descriptor of a master pseudo-terminal device.
9299
    /
9300
9301
Return the name of the slave pseudo-terminal device.
9302
9303
If the ptsname_r() C function is available, it is called;
9304
otherwise, performs a ptsname() C function call.
9305
[clinic start generated code]*/
9306
9307
static PyObject *
9308
os_ptsname_impl(PyObject *module, int fd)
9309
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9310
0
{
9311
0
#ifdef HAVE_PTSNAME_R
9312
0
    int ret;
9313
0
    char name[MAXPATHLEN+1];
9314
9315
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9316
0
        ret = ptsname_r(fd, name, sizeof(name));
9317
0
    }
9318
0
    else {
9319
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9320
0
        return py_ptsname(fd);
9321
0
    }
9322
0
    if (ret != 0) {
9323
0
        errno = ret;
9324
0
        return posix_error();
9325
0
    }
9326
9327
0
    return PyUnicode_DecodeFSDefault(name);
9328
#else
9329
    return py_ptsname(fd);
9330
#endif /* HAVE_PTSNAME_R */
9331
0
}
9332
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9333
9334
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9335
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9336
#  define DEV_PTY_FILE "/dev/ptc"
9337
#  define HAVE_DEV_PTMX
9338
#else
9339
#  define DEV_PTY_FILE "/dev/ptmx"
9340
#endif
9341
9342
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9343
#ifdef HAVE_PTY_H
9344
#include <pty.h>
9345
#elif defined(HAVE_LIBUTIL_H)
9346
#include <libutil.h>
9347
#elif defined(HAVE_UTIL_H)
9348
#include <util.h>
9349
#endif /* HAVE_PTY_H */
9350
#ifdef HAVE_UTMP_H
9351
#include <utmp.h>
9352
#endif /* HAVE_UTMP_H */
9353
#ifdef HAVE_STROPTS_H
9354
#include <stropts.h>
9355
#endif
9356
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9357
9358
9359
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9360
/*[clinic input]
9361
os.openpty
9362
9363
Open a pseudo-terminal.
9364
9365
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9366
for both the master and slave ends.
9367
[clinic start generated code]*/
9368
9369
static PyObject *
9370
os_openpty_impl(PyObject *module)
9371
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9372
0
{
9373
0
    int master_fd = -1, slave_fd = -1;
9374
#ifndef HAVE_OPENPTY
9375
    char * slave_name;
9376
#endif
9377
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9378
    PyOS_sighandler_t sig_saved;
9379
#if defined(__sun) && defined(__SVR4)
9380
    extern char *ptsname(int fildes);
9381
#endif
9382
#endif
9383
9384
0
#ifdef HAVE_OPENPTY
9385
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9386
0
        goto posix_error;
9387
9388
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9389
0
        goto error;
9390
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9391
0
        goto error;
9392
9393
#elif defined(HAVE__GETPTY)
9394
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9395
    if (slave_name == NULL)
9396
        goto posix_error;
9397
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9398
        goto error;
9399
9400
    slave_fd = _Py_open(slave_name, O_RDWR);
9401
    if (slave_fd < 0)
9402
        goto error;
9403
9404
#else
9405
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9406
    if (master_fd < 0)
9407
        goto posix_error;
9408
9409
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9410
9411
    /* change permission of slave */
9412
    if (grantpt(master_fd) < 0) {
9413
        int saved_errno = errno;
9414
        PyOS_setsig(SIGCHLD, sig_saved);
9415
        errno = saved_errno;
9416
        goto posix_error;
9417
    }
9418
9419
    /* unlock slave */
9420
    if (unlockpt(master_fd) < 0) {
9421
        int saved_errno = errno;
9422
        PyOS_setsig(SIGCHLD, sig_saved);
9423
        errno = saved_errno;
9424
        goto posix_error;
9425
    }
9426
9427
    PyOS_setsig(SIGCHLD, sig_saved);
9428
9429
    slave_name = ptsname(master_fd); /* get name of slave */
9430
    if (slave_name == NULL)
9431
        goto posix_error;
9432
9433
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9434
    if (slave_fd == -1)
9435
        goto error;
9436
9437
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9438
        goto posix_error;
9439
9440
#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC)
9441
    // Pushing "ptem" makes the slave a terminal, which a session leader
9442
    // without a controlling terminal then acquires as one despite O_NOCTTY.
9443
    // Note whether we already had one, so a new one can be disowned below.
9444
    int had_ctty = 0;
9445
#ifdef TIOCNOTTY
9446
    int tty_fd = open("/dev/tty", O_RDONLY | O_NOCTTY);
9447
    if (tty_fd >= 0) {
9448
        had_ctty = 1;
9449
        close(tty_fd);
9450
    }
9451
#endif
9452
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9453
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9454
#ifndef __hpux
9455
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9456
#endif /* __hpux */
9457
#ifdef TIOCNOTTY
9458
    if (!had_ctty && getsid(0) == getpid()) {
9459
        // Disown it; TIOCNOTTY sends SIGHUP to the session leader.
9460
        PyOS_sighandler_t sig_saved = PyOS_setsig(SIGHUP, SIG_IGN);
9461
        ioctl(slave_fd, TIOCNOTTY);
9462
        PyOS_setsig(SIGHUP, sig_saved);
9463
    }
9464
#endif
9465
#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
9466
#endif /* HAVE_OPENPTY */
9467
9468
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9469
9470
0
posix_error:
9471
0
    posix_error();
9472
0
error:
9473
0
    if (master_fd != -1)
9474
0
        close(master_fd);
9475
0
    if (slave_fd != -1)
9476
0
        close(slave_fd);
9477
0
    return NULL;
9478
0
}
9479
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9480
9481
9482
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9483
#define HAVE_FALLBACK_LOGIN_TTY 1
9484
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9485
9486
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9487
/*[clinic input]
9488
@permit_long_summary
9489
os.login_tty
9490
9491
    fd: fildes
9492
    /
9493
9494
Prepare the tty of which fd is a file descriptor for a new login session.
9495
9496
Make the calling process a session leader; make the tty the
9497
controlling tty, the stdin, the stdout, and the stderr of the
9498
calling process; close fd.
9499
[clinic start generated code]*/
9500
9501
static PyObject *
9502
os_login_tty_impl(PyObject *module, int fd)
9503
/*[clinic end generated code: output=495a79911b4cc1bc input=b102a7c36e8baf00]*/
9504
0
{
9505
0
#ifdef HAVE_LOGIN_TTY
9506
0
    if (login_tty(fd) == -1) {
9507
0
        return posix_error();
9508
0
    }
9509
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9510
    /* Establish a new session. */
9511
    if (setsid() == -1) {
9512
        return posix_error();
9513
    }
9514
9515
    /* The tty becomes the controlling terminal. */
9516
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9517
        return posix_error();
9518
    }
9519
9520
    /* The tty becomes stdin/stdout/stderr */
9521
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9522
        return posix_error();
9523
    }
9524
    if (fd > 2) {
9525
        close(fd);
9526
    }
9527
#endif /* HAVE_LOGIN_TTY */
9528
0
    Py_RETURN_NONE;
9529
0
}
9530
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9531
9532
9533
#ifdef HAVE_FORKPTY
9534
/*[clinic input]
9535
os.forkpty
9536
9537
Fork a new process with a new pseudo-terminal as controlling tty.
9538
9539
Returns a tuple of (pid, master_fd).
9540
Like fork(), return pid of 0 to the child process,
9541
and pid of child to the parent process.
9542
To both, return fd of newly opened pseudo-terminal.
9543
The master_fd is non-inheritable.
9544
[clinic start generated code]*/
9545
9546
static PyObject *
9547
os_forkpty_impl(PyObject *module)
9548
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9549
0
{
9550
0
    int master_fd = -1;
9551
0
    pid_t pid;
9552
9553
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9554
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9555
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9556
0
                        "can't fork at interpreter shutdown");
9557
0
        return NULL;
9558
0
    }
9559
0
    if (!_Py_IsMainInterpreter(interp)) {
9560
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9561
0
        return NULL;
9562
0
    }
9563
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9564
0
        return NULL;
9565
0
    }
9566
0
    PyOS_BeforeFork();
9567
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9568
0
    if (pid == 0) {
9569
        /* child: this clobbers and resets the import lock. */
9570
0
        PyOS_AfterFork_Child();
9571
0
    } else {
9572
        // Called before AfterFork_Parent in case those hooks start threads.
9573
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9574
        /* parent: release the import lock. */
9575
0
        PyOS_AfterFork_Parent();
9576
        /* set O_CLOEXEC on master_fd */
9577
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9578
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9579
0
                                   "non-inheritable in forkpty()");
9580
0
        }
9581
9582
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9583
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9584
0
            return NULL;
9585
0
    }
9586
0
    if (pid == -1) {
9587
0
        return posix_error();
9588
0
    }
9589
9590
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9591
0
}
9592
#endif /* HAVE_FORKPTY */
9593
9594
9595
#ifdef HAVE_GETEGID
9596
/*[clinic input]
9597
os.getegid
9598
9599
Return the current process's effective group id.
9600
[clinic start generated code]*/
9601
9602
static PyObject *
9603
os_getegid_impl(PyObject *module)
9604
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9605
37
{
9606
37
    return _PyLong_FromGid(getegid());
9607
37
}
9608
#endif /* HAVE_GETEGID */
9609
9610
9611
#ifdef HAVE_GETEUID
9612
/*[clinic input]
9613
os.geteuid
9614
9615
Return the current process's effective user id.
9616
[clinic start generated code]*/
9617
9618
static PyObject *
9619
os_geteuid_impl(PyObject *module)
9620
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9621
37
{
9622
37
    return _PyLong_FromUid(geteuid());
9623
37
}
9624
#endif /* HAVE_GETEUID */
9625
9626
9627
#ifdef HAVE_GETGID
9628
/*[clinic input]
9629
os.getgid
9630
9631
Return the current process's group id.
9632
[clinic start generated code]*/
9633
9634
static PyObject *
9635
os_getgid_impl(PyObject *module)
9636
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9637
37
{
9638
37
    return _PyLong_FromGid(getgid());
9639
37
}
9640
#endif /* HAVE_GETGID */
9641
9642
9643
#if defined(HAVE_GETPID)
9644
/*[clinic input]
9645
os.getpid
9646
9647
Return the current process id.
9648
[clinic start generated code]*/
9649
9650
static PyObject *
9651
os_getpid_impl(PyObject *module)
9652
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9653
4.11k
{
9654
4.11k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9655
4.11k
    return PyLong_FromPid(getpid());
9656
#else
9657
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9658
#endif
9659
4.11k
}
9660
#endif /* defined(HAVE_GETPID) */
9661
9662
#ifdef NGROUPS_MAX
9663
0
#define MAX_GROUPS NGROUPS_MAX
9664
#else
9665
    /* defined to be 16 on Solaris7, so this should be a small number */
9666
#define MAX_GROUPS 64
9667
#endif
9668
9669
#ifdef HAVE_GETGROUPLIST
9670
9671
#ifdef __APPLE__
9672
/*[clinic input]
9673
os.getgrouplist
9674
9675
    user: str
9676
        username to lookup
9677
    group as basegid: int
9678
        base group id of the user
9679
    /
9680
9681
Returns a list of groups to which a user belongs.
9682
[clinic start generated code]*/
9683
9684
static PyObject *
9685
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9686
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9687
#else
9688
/*[clinic input]
9689
os.getgrouplist
9690
9691
    user: str
9692
        username to lookup
9693
    group as basegid: gid_t
9694
        base group id of the user
9695
    /
9696
9697
Returns a list of groups to which a user belongs.
9698
[clinic start generated code]*/
9699
9700
static PyObject *
9701
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9702
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9703
#endif
9704
0
{
9705
0
    int i, ngroups;
9706
0
    PyObject *list;
9707
#ifdef __APPLE__
9708
    int *groups;
9709
#else
9710
0
    gid_t *groups;
9711
0
#endif
9712
9713
    /*
9714
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9715
     * number of supplemental groups a users can belong to.
9716
     * We have to increment it by one because
9717
     * getgrouplist() returns both the supplemental groups
9718
     * and the primary group, i.e. all of the groups the
9719
     * user belongs to.
9720
     */
9721
0
    ngroups = 1 + MAX_GROUPS;
9722
9723
0
    while (1) {
9724
#ifdef __APPLE__
9725
        groups = PyMem_New(int, ngroups);
9726
#else
9727
0
        groups = PyMem_New(gid_t, ngroups);
9728
0
#endif
9729
0
        if (groups == NULL) {
9730
0
            return PyErr_NoMemory();
9731
0
        }
9732
9733
0
        int old_ngroups = ngroups;
9734
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9735
            /* Success */
9736
0
            break;
9737
0
        }
9738
9739
        /* getgrouplist() fails if the group list is too small */
9740
0
        PyMem_Free(groups);
9741
9742
0
        if (ngroups > old_ngroups) {
9743
            /* If the group list is too small, the glibc implementation of
9744
               getgrouplist() sets ngroups to the total number of groups and
9745
               returns -1. */
9746
0
        }
9747
0
        else {
9748
            /* Double the group list size */
9749
0
            if (ngroups > INT_MAX / 2) {
9750
0
                return PyErr_NoMemory();
9751
0
            }
9752
0
            ngroups *= 2;
9753
0
        }
9754
9755
        /* Retry getgrouplist() with a larger group list */
9756
0
    }
9757
9758
#ifdef _Py_MEMORY_SANITIZER
9759
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9760
    __msan_unpoison(&ngroups, sizeof(ngroups));
9761
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9762
#endif
9763
9764
0
    list = PyList_New(ngroups);
9765
0
    if (list == NULL) {
9766
0
        PyMem_Free(groups);
9767
0
        return NULL;
9768
0
    }
9769
9770
0
    for (i = 0; i < ngroups; i++) {
9771
#ifdef __APPLE__
9772
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9773
#else
9774
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9775
0
#endif
9776
0
        if (o == NULL) {
9777
0
            Py_DECREF(list);
9778
0
            PyMem_Free(groups);
9779
0
            return NULL;
9780
0
        }
9781
0
        PyList_SET_ITEM(list, i, o);
9782
0
    }
9783
9784
0
    PyMem_Free(groups);
9785
9786
0
    return list;
9787
0
}
9788
#endif /* HAVE_GETGROUPLIST */
9789
9790
9791
#ifdef HAVE_GETGROUPS
9792
/*[clinic input]
9793
os.getgroups
9794
9795
Return list of supplemental group IDs for the process.
9796
[clinic start generated code]*/
9797
9798
static PyObject *
9799
os_getgroups_impl(PyObject *module)
9800
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9801
0
{
9802
    // Call getgroups with length 0 to get the actual number of groups
9803
0
    int n = getgroups(0, NULL);
9804
0
    if (n < 0) {
9805
0
        return posix_error();
9806
0
    }
9807
9808
0
    if (n == 0) {
9809
0
        return PyList_New(0);
9810
0
    }
9811
9812
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9813
0
    if (grouplist == NULL) {
9814
0
        return PyErr_NoMemory();
9815
0
    }
9816
9817
0
    n = getgroups(n, grouplist);
9818
0
    if (n == -1) {
9819
0
        posix_error();
9820
0
        PyMem_Free(grouplist);
9821
0
        return NULL;
9822
0
    }
9823
9824
0
    PyObject *result = PyList_New(n);
9825
0
    if (result == NULL) {
9826
0
        goto error;
9827
0
    }
9828
9829
0
    for (int i = 0; i < n; ++i) {
9830
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9831
0
        if (group == NULL) {
9832
0
            goto error;
9833
0
        }
9834
0
        PyList_SET_ITEM(result, i, group);
9835
0
    }
9836
0
    PyMem_Free(grouplist);
9837
9838
0
    return result;
9839
9840
0
error:
9841
0
    PyMem_Free(grouplist);
9842
0
    Py_XDECREF(result);
9843
0
    return NULL;
9844
0
}
9845
#endif /* HAVE_GETGROUPS */
9846
9847
#ifdef HAVE_INITGROUPS
9848
#ifdef __APPLE__
9849
/*[clinic input]
9850
os.initgroups
9851
9852
    username as oname: unicode_fs_encoded
9853
    gid: int
9854
    /
9855
9856
Initialize the group access list.
9857
9858
Call the system initgroups() to initialize the group access list with
9859
all of the groups of which the specified username is a member, plus the
9860
specified group id.
9861
[clinic start generated code]*/
9862
9863
static PyObject *
9864
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9865
/*[clinic end generated code: output=7f074d30a425fd3a input=35f2d4fb7fcc0bdf]*/
9866
#else
9867
/*[clinic input]
9868
os.initgroups
9869
9870
    username as oname: unicode_fs_encoded
9871
    gid: gid_t
9872
    /
9873
9874
Initialize the group access list.
9875
9876
Call the system initgroups() to initialize the group access list with
9877
all of the groups of which the specified username is a member, plus the
9878
specified group id.
9879
[clinic start generated code]*/
9880
9881
static PyObject *
9882
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9883
/*[clinic end generated code: output=59341244521a9e3f input=7e4514dff4526a95]*/
9884
#endif
9885
0
{
9886
#ifdef __ANDROID__
9887
    // On Android, calling this function as a non-root user leads to a process crash
9888
    // rather than returning a permission error.
9889
    if (getuid() != 0) {
9890
        errno = EPERM;
9891
        return posix_error();
9892
    }
9893
#endif
9894
0
    const char *username = PyBytes_AS_STRING(oname);
9895
9896
0
    if (initgroups(username, gid) == -1)
9897
0
        return PyErr_SetFromErrno(PyExc_OSError);
9898
9899
0
    Py_RETURN_NONE;
9900
0
}
9901
#endif /* HAVE_INITGROUPS */
9902
9903
9904
#ifdef HAVE_GETPGID
9905
/*[clinic input]
9906
os.getpgid
9907
9908
    pid: pid_t
9909
9910
Call the system call getpgid(), and return the result.
9911
[clinic start generated code]*/
9912
9913
static PyObject *
9914
os_getpgid_impl(PyObject *module, pid_t pid)
9915
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9916
0
{
9917
0
    pid_t pgid = getpgid(pid);
9918
0
    if (pgid < 0)
9919
0
        return posix_error();
9920
0
    return PyLong_FromPid(pgid);
9921
0
}
9922
#endif /* HAVE_GETPGID */
9923
9924
9925
#ifdef HAVE_GETPGRP
9926
/*[clinic input]
9927
os.getpgrp
9928
9929
Return the current process group id.
9930
[clinic start generated code]*/
9931
9932
static PyObject *
9933
os_getpgrp_impl(PyObject *module)
9934
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9935
0
{
9936
#ifdef GETPGRP_HAVE_ARG
9937
    return PyLong_FromPid(getpgrp(0));
9938
#else /* GETPGRP_HAVE_ARG */
9939
0
    return PyLong_FromPid(getpgrp());
9940
0
#endif /* GETPGRP_HAVE_ARG */
9941
0
}
9942
#endif /* HAVE_GETPGRP */
9943
9944
9945
#ifdef HAVE_SETPGRP
9946
/*[clinic input]
9947
os.setpgrp
9948
9949
Make the current process the leader of its process group.
9950
[clinic start generated code]*/
9951
9952
static PyObject *
9953
os_setpgrp_impl(PyObject *module)
9954
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9955
0
{
9956
#ifdef SETPGRP_HAVE_ARG
9957
    if (setpgrp(0, 0) < 0)
9958
#else /* SETPGRP_HAVE_ARG */
9959
0
    if (setpgrp() < 0)
9960
0
#endif /* SETPGRP_HAVE_ARG */
9961
0
        return posix_error();
9962
0
    Py_RETURN_NONE;
9963
0
}
9964
#endif /* HAVE_SETPGRP */
9965
9966
#ifdef HAVE_GETPPID
9967
9968
#ifdef MS_WINDOWS
9969
#include <winternl.h>
9970
#include <ProcessSnapshot.h>
9971
9972
#ifdef MS_WINDOWS_DESKTOP
9973
// The structure definition in winternl.h may be incomplete.
9974
// This structure is the full version from the MSDN documentation.
9975
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9976
    NTSTATUS ExitStatus;
9977
    PVOID PebBaseAddress;
9978
    ULONG_PTR AffinityMask;
9979
    LONG BasePriority;
9980
    ULONG_PTR UniqueProcessId;
9981
    ULONG_PTR InheritedFromUniqueProcessId;
9982
} PROCESS_BASIC_INFORMATION_FULL;
9983
9984
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9985
    IN    HANDLE           ProcessHandle,
9986
    IN    PROCESSINFOCLASS ProcessInformationClass,
9987
    OUT   PVOID            ProcessInformation,
9988
    IN    ULONG            ProcessInformationLength,
9989
    OUT   PULONG           ReturnLength OPTIONAL);
9990
9991
// This function returns the process ID of the parent process.
9992
// Returns 0 on failure.
9993
static ULONG
9994
win32_getppid_fast(void)
9995
{
9996
    NTSTATUS status;
9997
    HMODULE ntdll;
9998
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9999
    PROCESS_BASIC_INFORMATION_FULL basic_information;
10000
    static ULONG cached_ppid = 0;
10001
10002
    if (cached_ppid) {
10003
        // No need to query the kernel again.
10004
        return cached_ppid;
10005
    }
10006
10007
    ntdll = GetModuleHandleW(L"ntdll.dll");
10008
    if (!ntdll) {
10009
        return 0;
10010
    }
10011
10012
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
10013
    if (!pNtQueryInformationProcess) {
10014
        return 0;
10015
    }
10016
10017
    status = pNtQueryInformationProcess(GetCurrentProcess(),
10018
                                        ProcessBasicInformation,
10019
                                        &basic_information,
10020
                                        sizeof(basic_information),
10021
                                        NULL);
10022
10023
    if (!NT_SUCCESS(status)) {
10024
        return 0;
10025
    }
10026
10027
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
10028
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
10029
    // zero and (ULONG) -1.
10030
10031
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
10032
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
10033
    {
10034
        return 0;
10035
    }
10036
10037
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
10038
    // structure member contains a ULONG_PTR which represents the process ID of our parent
10039
    // process. This process ID will be correctly returned even if the parent process has
10040
    // exited or been terminated.
10041
10042
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
10043
    return cached_ppid;
10044
}
10045
#endif // MS_WINDOWS_DESKTOP
10046
10047
static PyObject*
10048
win32_getppid(void)
10049
{
10050
    DWORD error;
10051
    PyObject* result = NULL;
10052
    HANDLE process = GetCurrentProcess();
10053
    HPSS snapshot = NULL;
10054
10055
#ifdef MS_WINDOWS_DESKTOP
10056
    ULONG pid = win32_getppid_fast();
10057
    if (pid != 0) {
10058
        return PyLong_FromUnsignedLong(pid);
10059
    }
10060
#endif
10061
10062
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
10063
10064
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
10065
    if (error != ERROR_SUCCESS) {
10066
        return PyErr_SetFromWindowsErr(error);
10067
    }
10068
10069
    PSS_PROCESS_INFORMATION info;
10070
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
10071
                             sizeof(info));
10072
    if (error == ERROR_SUCCESS) {
10073
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
10074
    }
10075
    else {
10076
        result = PyErr_SetFromWindowsErr(error);
10077
    }
10078
10079
    PssFreeSnapshot(process, snapshot);
10080
    return result;
10081
}
10082
#endif /*MS_WINDOWS*/
10083
10084
10085
/*[clinic input]
10086
os.getppid
10087
10088
Return the parent's process id.
10089
10090
If the parent process has already exited, Windows machines will still
10091
return its id; others systems will return the id of the 'init' proces
10092
(1).
10093
[clinic start generated code]*/
10094
10095
static PyObject *
10096
os_getppid_impl(PyObject *module)
10097
/*[clinic end generated code: output=43b2a946a8c603b4 input=e17c1de18f41316b]*/
10098
0
{
10099
#ifdef MS_WINDOWS
10100
    return win32_getppid();
10101
#else
10102
0
    return PyLong_FromPid(getppid());
10103
0
#endif
10104
0
}
10105
#endif /* HAVE_GETPPID */
10106
10107
10108
#ifdef HAVE_GETLOGIN
10109
/*[clinic input]
10110
os.getlogin
10111
10112
Return the actual login name.
10113
[clinic start generated code]*/
10114
10115
static PyObject *
10116
os_getlogin_impl(PyObject *module)
10117
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10118
0
{
10119
0
    PyObject *result = NULL;
10120
#ifdef MS_WINDOWS
10121
    wchar_t user_name[UNLEN + 1];
10122
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10123
10124
    if (GetUserNameW(user_name, &num_chars)) {
10125
        /* num_chars is the number of unicode chars plus null terminator */
10126
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10127
    }
10128
    else
10129
        result = PyErr_SetFromWindowsErr(GetLastError());
10130
#elif defined (HAVE_GETLOGIN_R)
10131
# if defined (HAVE_MAXLOGNAME)
10132
    char name[MAXLOGNAME + 1];
10133
# elif defined (HAVE_UT_NAMESIZE)
10134
    char name[UT_NAMESIZE + 1];
10135
# else
10136
    char name[256];
10137
# endif
10138
0
    int err = getlogin_r(name, sizeof(name));
10139
0
    if (err) {
10140
0
        int old_errno = errno;
10141
0
        errno = err;
10142
0
        posix_error();
10143
0
        errno = old_errno;
10144
0
    }
10145
0
    else {
10146
0
        _Py_MSAN_UNPOISON(name, sizeof(name));
10147
0
        result = PyUnicode_DecodeFSDefault(name);
10148
0
    }
10149
#else
10150
    char *name;
10151
    int old_errno = errno;
10152
10153
    errno = 0;
10154
    name = getlogin();
10155
    if (name == NULL) {
10156
        if (errno)
10157
            posix_error();
10158
        else
10159
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10160
    }
10161
    else
10162
        result = PyUnicode_DecodeFSDefault(name);
10163
    errno = old_errno;
10164
#endif
10165
0
    return result;
10166
0
}
10167
#endif /* HAVE_GETLOGIN */
10168
10169
10170
#ifdef HAVE_GETUID
10171
/*[clinic input]
10172
os.getuid
10173
10174
Return the current process's user id.
10175
[clinic start generated code]*/
10176
10177
static PyObject *
10178
os_getuid_impl(PyObject *module)
10179
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10180
37
{
10181
37
    return _PyLong_FromUid(getuid());
10182
37
}
10183
#endif /* HAVE_GETUID */
10184
10185
10186
#ifdef MS_WINDOWS
10187
#define HAVE_KILL
10188
#endif /* MS_WINDOWS */
10189
10190
#ifdef HAVE_KILL
10191
/*[clinic input]
10192
os.kill
10193
10194
    pid: pid_t
10195
    signal: Py_ssize_t
10196
    /
10197
10198
Kill a process with a signal.
10199
[clinic start generated code]*/
10200
10201
static PyObject *
10202
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10203
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10204
0
{
10205
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10206
0
        return NULL;
10207
0
    }
10208
0
#ifndef MS_WINDOWS
10209
0
    if (kill(pid, (int)signal) == -1) {
10210
0
        return posix_error();
10211
0
    }
10212
10213
    // Check immediately if the signal was sent to the current process.
10214
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10215
    // is cheap.
10216
0
    if (PyErr_CheckSignals()) {
10217
0
        return NULL;
10218
0
    }
10219
10220
0
    Py_RETURN_NONE;
10221
#else /* !MS_WINDOWS */
10222
    DWORD sig = (DWORD)signal;
10223
10224
#ifdef HAVE_WINDOWS_CONSOLE_IO
10225
    /* Console processes which share a common console can be sent CTRL+C or
10226
       CTRL+BREAK events, provided they handle said events. */
10227
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10228
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10229
            return PyErr_SetFromWindowsErr(0);
10230
        }
10231
        Py_RETURN_NONE;
10232
    }
10233
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10234
10235
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10236
       attempt to open and terminate the process. */
10237
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10238
    if (handle == NULL) {
10239
        return PyErr_SetFromWindowsErr(0);
10240
    }
10241
10242
    BOOL res = TerminateProcess(handle, sig);
10243
    CloseHandle(handle);
10244
    if (res == 0) {
10245
        return PyErr_SetFromWindowsErr(0);
10246
    }
10247
10248
    Py_RETURN_NONE;
10249
#endif /* !MS_WINDOWS */
10250
0
}
10251
#endif /* HAVE_KILL */
10252
10253
10254
#ifdef HAVE_KILLPG
10255
/*[clinic input]
10256
os.killpg
10257
10258
    pgid: pid_t
10259
    signal: int
10260
    /
10261
10262
Kill a process group with a signal.
10263
[clinic start generated code]*/
10264
10265
static PyObject *
10266
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10267
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10268
0
{
10269
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10270
0
        return NULL;
10271
0
    }
10272
    /* XXX some man pages make the `pgid` parameter an int, others
10273
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10274
       take the same type. Moreover, pid_t is always at least as wide as
10275
       int (else compilation of this module fails), which is safe. */
10276
0
    if (killpg(pgid, signal) == -1)
10277
0
        return posix_error();
10278
0
    Py_RETURN_NONE;
10279
0
}
10280
#endif /* HAVE_KILLPG */
10281
10282
10283
#ifdef HAVE_PLOCK
10284
#ifdef HAVE_SYS_LOCK_H
10285
#include <sys/lock.h>
10286
#endif
10287
10288
/*[clinic input]
10289
os.plock
10290
    op: int
10291
    /
10292
10293
Lock program segments into memory.");
10294
[clinic start generated code]*/
10295
10296
static PyObject *
10297
os_plock_impl(PyObject *module, int op)
10298
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10299
{
10300
    if (plock(op) == -1)
10301
        return posix_error();
10302
    Py_RETURN_NONE;
10303
}
10304
#endif /* HAVE_PLOCK */
10305
10306
10307
#ifdef HAVE_SETUID
10308
/*[clinic input]
10309
os.setuid
10310
10311
    uid: uid_t
10312
    /
10313
10314
Set the current process's user id.
10315
[clinic start generated code]*/
10316
10317
static PyObject *
10318
os_setuid_impl(PyObject *module, uid_t uid)
10319
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10320
0
{
10321
#ifdef __ANDROID__
10322
    // On Android, calling this function as a non-root user leads to a process crash
10323
    // rather than returning a permission error.
10324
    if (getuid() != 0) {
10325
        errno = EPERM;
10326
        return posix_error();
10327
    }
10328
#endif
10329
0
    if (setuid(uid) < 0)
10330
0
        return posix_error();
10331
0
    Py_RETURN_NONE;
10332
0
}
10333
#endif /* HAVE_SETUID */
10334
10335
10336
#ifdef HAVE_SETEUID
10337
/*[clinic input]
10338
os.seteuid
10339
10340
    euid: uid_t
10341
    /
10342
10343
Set the current process's effective user id.
10344
[clinic start generated code]*/
10345
10346
static PyObject *
10347
os_seteuid_impl(PyObject *module, uid_t euid)
10348
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10349
0
{
10350
#ifdef __ANDROID__
10351
    // On Android, calling this function as a non-root user leads to a process crash
10352
    // rather than returning a permission error.
10353
    if (getuid() != 0) {
10354
        errno = EPERM;
10355
        return posix_error();
10356
    }
10357
#endif
10358
0
    if (seteuid(euid) < 0)
10359
0
        return posix_error();
10360
0
    Py_RETURN_NONE;
10361
0
}
10362
#endif /* HAVE_SETEUID */
10363
10364
10365
#ifdef HAVE_SETEGID
10366
/*[clinic input]
10367
os.setegid
10368
10369
    egid: gid_t
10370
    /
10371
10372
Set the current process's effective group id.
10373
[clinic start generated code]*/
10374
10375
static PyObject *
10376
os_setegid_impl(PyObject *module, gid_t egid)
10377
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10378
0
{
10379
#ifdef __ANDROID__
10380
    // On Android, calling this function as a non-root user leads to a process crash
10381
    // rather than returning a permission error.
10382
    if (getuid() != 0) {
10383
        errno = EPERM;
10384
        return posix_error();
10385
    }
10386
#endif
10387
0
    if (setegid(egid) < 0)
10388
0
        return posix_error();
10389
0
    Py_RETURN_NONE;
10390
0
}
10391
#endif /* HAVE_SETEGID */
10392
10393
10394
#ifdef HAVE_SETREUID
10395
/*[clinic input]
10396
os.setreuid
10397
10398
    ruid: uid_t
10399
    euid: uid_t
10400
    /
10401
10402
Set the current process's real and effective user ids.
10403
[clinic start generated code]*/
10404
10405
static PyObject *
10406
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10407
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10408
0
{
10409
#ifdef __ANDROID__
10410
    // On Android, calling this function as a non-root user leads to a process crash
10411
    // rather than returning a permission error.
10412
    if (getuid() != 0) {
10413
        errno = EPERM;
10414
        return posix_error();
10415
    }
10416
#endif
10417
0
    if (setreuid(ruid, euid) < 0) {
10418
0
        return posix_error();
10419
0
    } else {
10420
0
        Py_RETURN_NONE;
10421
0
    }
10422
0
}
10423
#endif /* HAVE_SETREUID */
10424
10425
10426
#ifdef HAVE_SETREGID
10427
/*[clinic input]
10428
os.setregid
10429
10430
    rgid: gid_t
10431
    egid: gid_t
10432
    /
10433
10434
Set the current process's real and effective group ids.
10435
[clinic start generated code]*/
10436
10437
static PyObject *
10438
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10439
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10440
0
{
10441
#ifdef __ANDROID__
10442
    // On Android, calling this function as a non-root user leads to a process crash
10443
    // rather than returning a permission error.
10444
    if (getuid() != 0) {
10445
        errno = EPERM;
10446
        return posix_error();
10447
    }
10448
#endif
10449
0
    if (setregid(rgid, egid) < 0)
10450
0
        return posix_error();
10451
0
    Py_RETURN_NONE;
10452
0
}
10453
#endif /* HAVE_SETREGID */
10454
10455
10456
#ifdef HAVE_SETGID
10457
/*[clinic input]
10458
os.setgid
10459
    gid: gid_t
10460
    /
10461
10462
Set the current process's group id.
10463
[clinic start generated code]*/
10464
10465
static PyObject *
10466
os_setgid_impl(PyObject *module, gid_t gid)
10467
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10468
0
{
10469
#ifdef __ANDROID__
10470
    // On Android, calling this function as a non-root user leads to a process crash
10471
    // rather than returning a permission error.
10472
    if (getuid() != 0) {
10473
        errno = EPERM;
10474
        return posix_error();
10475
    }
10476
#endif
10477
0
    if (setgid(gid) < 0)
10478
0
        return posix_error();
10479
0
    Py_RETURN_NONE;
10480
0
}
10481
#endif /* HAVE_SETGID */
10482
10483
10484
#ifdef HAVE_SETGROUPS
10485
/*[clinic input]
10486
os.setgroups
10487
10488
    groups: object
10489
    /
10490
10491
Set the groups of the current process to list.
10492
[clinic start generated code]*/
10493
10494
static PyObject *
10495
os_setgroups(PyObject *module, PyObject *groups)
10496
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10497
0
{
10498
0
    if (!PySequence_Check(groups)) {
10499
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10500
0
        return NULL;
10501
0
    }
10502
0
    Py_ssize_t len = PySequence_Size(groups);
10503
0
    if (len < 0) {
10504
0
        return NULL;
10505
0
    }
10506
0
    if (len > MAX_GROUPS) {
10507
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10508
0
        return NULL;
10509
0
    }
10510
10511
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10512
0
    if (grouplist == NULL) {
10513
0
        PyErr_NoMemory();
10514
0
        return NULL;
10515
0
    }
10516
0
    for (Py_ssize_t i = 0; i < len; i++) {
10517
0
        PyObject *elem;
10518
0
        elem = PySequence_GetItem(groups, i);
10519
0
        if (!elem) {
10520
0
            PyMem_Free(grouplist);
10521
0
            return NULL;
10522
0
        }
10523
0
        if (!PyIndex_Check(elem)) {
10524
0
            PyErr_SetString(PyExc_TypeError,
10525
0
                            "groups must be integers");
10526
0
            Py_DECREF(elem);
10527
0
            PyMem_Free(grouplist);
10528
0
            return NULL;
10529
0
        } else {
10530
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10531
0
                Py_DECREF(elem);
10532
0
                PyMem_Free(grouplist);
10533
0
                return NULL;
10534
0
            }
10535
0
        }
10536
0
        Py_DECREF(elem);
10537
0
    }
10538
10539
0
    if (setgroups(len, grouplist) < 0) {
10540
0
        posix_error();
10541
0
        PyMem_Free(grouplist);
10542
0
        return NULL;
10543
0
    }
10544
0
    PyMem_Free(grouplist);
10545
0
    Py_RETURN_NONE;
10546
0
}
10547
#endif /* HAVE_SETGROUPS */
10548
10549
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10550
static PyObject *
10551
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10552
0
{
10553
0
    PyObject *result;
10554
0
    PyObject *struct_rusage;
10555
10556
0
    if (pid == -1)
10557
0
        return posix_error();
10558
10559
    // If wait succeeded but no child was ready to report status, ru will not
10560
    // have been populated.
10561
0
    if (pid == 0) {
10562
0
        memset(ru, 0, sizeof(*ru));
10563
0
    }
10564
10565
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10566
0
    if (struct_rusage == NULL)
10567
0
        return NULL;
10568
10569
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10570
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10571
0
    Py_DECREF(struct_rusage);
10572
0
    if (!result)
10573
0
        return NULL;
10574
10575
0
    int pos = 0;
10576
10577
0
#ifndef doubletime
10578
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10579
0
#endif
10580
10581
0
#define SET_RESULT(CALL)                                     \
10582
0
    do {                                                     \
10583
0
        PyObject *item = (CALL);                             \
10584
0
        if (item == NULL) {                                  \
10585
0
            Py_DECREF(result);                               \
10586
0
            return NULL;                                     \
10587
0
        }                                                    \
10588
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10589
0
    } while(0)
10590
10591
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10592
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10593
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10594
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10595
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10596
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10597
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10598
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10599
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10600
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10601
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10602
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10603
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10604
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10605
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10606
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10607
0
#undef SET_RESULT
10608
10609
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10610
0
}
10611
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10612
10613
10614
#ifdef HAVE_WAIT3
10615
/*[clinic input]
10616
os.wait3
10617
10618
    options: int
10619
Wait for completion of a child process.
10620
10621
Returns a tuple of information about the child process:
10622
  (pid, status, rusage)
10623
[clinic start generated code]*/
10624
10625
static PyObject *
10626
os_wait3_impl(PyObject *module, int options)
10627
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10628
0
{
10629
0
    pid_t pid;
10630
0
    struct rusage ru;
10631
0
    int async_err = 0;
10632
0
    WAIT_TYPE status;
10633
0
    WAIT_STATUS_INT(status) = 0;
10634
10635
0
    do {
10636
0
        Py_BEGIN_ALLOW_THREADS
10637
0
        pid = wait3(&status, options, &ru);
10638
0
        Py_END_ALLOW_THREADS
10639
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10640
0
    if (pid < 0)
10641
0
        return (!async_err) ? posix_error() : NULL;
10642
10643
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10644
0
}
10645
#endif /* HAVE_WAIT3 */
10646
10647
10648
#ifdef HAVE_WAIT4
10649
/*[clinic input]
10650
10651
os.wait4
10652
10653
    pid: pid_t
10654
    options: int
10655
10656
Wait for completion of a specific child process.
10657
10658
Returns a tuple of information about the child process:
10659
  (pid, status, rusage)
10660
[clinic start generated code]*/
10661
10662
static PyObject *
10663
os_wait4_impl(PyObject *module, pid_t pid, int options)
10664
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10665
0
{
10666
0
    pid_t res;
10667
0
    struct rusage ru;
10668
0
    int async_err = 0;
10669
0
    WAIT_TYPE status;
10670
0
    WAIT_STATUS_INT(status) = 0;
10671
10672
0
    do {
10673
0
        Py_BEGIN_ALLOW_THREADS
10674
0
        res = wait4(pid, &status, options, &ru);
10675
0
        Py_END_ALLOW_THREADS
10676
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10677
0
    if (res < 0)
10678
0
        return (!async_err) ? posix_error() : NULL;
10679
10680
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10681
0
}
10682
#endif /* HAVE_WAIT4 */
10683
10684
10685
#if defined(HAVE_WAITID)
10686
/*[clinic input]
10687
os.waitid
10688
10689
    idtype: idtype_t
10690
        Must be one of be P_PID, P_PGID or P_ALL.
10691
    id: id_t
10692
        The id to wait on.
10693
    options: int
10694
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10695
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10696
    /
10697
10698
Returns the result of waiting for a process or processes.
10699
10700
Returns either waitid_result or None if WNOHANG is specified and there
10701
are no children in a waitable state.
10702
[clinic start generated code]*/
10703
10704
static PyObject *
10705
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10706
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=14956bc8d102b5db]*/
10707
0
{
10708
0
    PyObject *result;
10709
0
    int res;
10710
0
    int async_err = 0;
10711
0
    siginfo_t si;
10712
0
    si.si_pid = 0;
10713
10714
0
    do {
10715
0
        Py_BEGIN_ALLOW_THREADS
10716
0
        res = waitid(idtype, id, &si, options);
10717
0
        Py_END_ALLOW_THREADS
10718
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10719
0
    if (res < 0)
10720
0
        return (!async_err) ? posix_error() : NULL;
10721
10722
0
    if (si.si_pid == 0)
10723
0
        Py_RETURN_NONE;
10724
10725
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10726
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10727
0
    if (!result)
10728
0
        return NULL;
10729
10730
0
    int pos = 0;
10731
10732
0
#define SET_RESULT(CALL)                                     \
10733
0
    do {                                                     \
10734
0
        PyObject *item = (CALL);                             \
10735
0
        if (item == NULL) {                                  \
10736
0
            Py_DECREF(result);                               \
10737
0
            return NULL;                                     \
10738
0
        }                                                    \
10739
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10740
0
    } while(0)
10741
10742
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10743
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10744
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10745
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10746
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10747
10748
0
#undef SET_RESULT
10749
10750
0
    return result;
10751
0
}
10752
#endif /* defined(HAVE_WAITID) */
10753
10754
10755
#if defined(HAVE_WAITPID)
10756
/*[clinic input]
10757
os.waitpid
10758
    pid: pid_t
10759
    options: int
10760
    /
10761
10762
Wait for completion of a given child process.
10763
10764
Returns a tuple of information regarding the child process:
10765
    (pid, status)
10766
10767
The options argument is ignored on Windows.
10768
[clinic start generated code]*/
10769
10770
static PyObject *
10771
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10772
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10773
0
{
10774
0
    pid_t res;
10775
0
    int async_err = 0;
10776
0
    WAIT_TYPE status;
10777
0
    WAIT_STATUS_INT(status) = 0;
10778
10779
0
    do {
10780
0
        Py_BEGIN_ALLOW_THREADS
10781
0
        res = waitpid(pid, &status, options);
10782
0
        Py_END_ALLOW_THREADS
10783
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10784
0
    if (res < 0)
10785
0
        return (!async_err) ? posix_error() : NULL;
10786
10787
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10788
0
}
10789
#elif defined(HAVE_CWAIT)
10790
/* MS C has a variant of waitpid() that's usable for most purposes. */
10791
/*[clinic input]
10792
os.waitpid
10793
    pid: intptr_t
10794
    options: int
10795
    /
10796
10797
Wait for completion of a given process.
10798
10799
Returns a tuple of information regarding the process:
10800
    (pid, status << 8)
10801
10802
The options argument is ignored on Windows.
10803
[clinic start generated code]*/
10804
10805
static PyObject *
10806
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10807
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10808
{
10809
    int status;
10810
    intptr_t res;
10811
    int async_err = 0;
10812
10813
    do {
10814
        Py_BEGIN_ALLOW_THREADS
10815
        _Py_BEGIN_SUPPRESS_IPH
10816
        res = _cwait(&status, pid, options);
10817
        _Py_END_SUPPRESS_IPH
10818
        Py_END_ALLOW_THREADS
10819
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10820
    if (res < 0)
10821
        return (!async_err) ? posix_error() : NULL;
10822
10823
    unsigned long long ustatus = (unsigned int)status;
10824
10825
    /* shift the status left a byte so this is more like the POSIX waitpid */
10826
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10827
}
10828
#endif
10829
10830
10831
#ifdef HAVE_WAIT
10832
/*[clinic input]
10833
os.wait
10834
10835
Wait for completion of a child process.
10836
10837
Returns a tuple of information about the child process:
10838
    (pid, status)
10839
[clinic start generated code]*/
10840
10841
static PyObject *
10842
os_wait_impl(PyObject *module)
10843
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10844
0
{
10845
0
    pid_t pid;
10846
0
    int async_err = 0;
10847
0
    WAIT_TYPE status;
10848
0
    WAIT_STATUS_INT(status) = 0;
10849
10850
0
    do {
10851
0
        Py_BEGIN_ALLOW_THREADS
10852
0
        pid = wait(&status);
10853
0
        Py_END_ALLOW_THREADS
10854
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10855
0
    if (pid < 0)
10856
0
        return (!async_err) ? posix_error() : NULL;
10857
10858
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10859
0
}
10860
#endif /* HAVE_WAIT */
10861
10862
10863
// This system call always crashes on older Android versions.
10864
#if defined(HAVE_PIDFD_OPEN) \
10865
    || (defined(__linux__) && defined(__NR_pidfd_open) \
10866
        && !(defined(__ANDROID__) && __ANDROID_API__ < 31))
10867
/*[clinic input]
10868
os.pidfd_open
10869
  pid: pid_t
10870
  flags: unsigned_int = 0
10871
10872
Return a file descriptor referring to the process *pid*.
10873
10874
The descriptor can be used to perform process management without races
10875
and signals.
10876
[clinic start generated code]*/
10877
10878
static PyObject *
10879
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10880
/*[clinic end generated code: output=5c7252698947dc41 input=03058b32c389f874]*/
10881
4
{
10882
#ifdef HAVE_PIDFD_OPEN
10883
    int fd = pidfd_open(pid, flags);
10884
#else
10885
4
    int fd = syscall(__NR_pidfd_open, pid, flags);
10886
4
#endif
10887
4
    if (fd < 0) {
10888
0
        return posix_error();
10889
0
    }
10890
4
    return PyLong_FromLong(fd);
10891
4
}
10892
#endif
10893
10894
10895
#if defined(HAVE_PIDFD_GETFD) \
10896
    || (defined(__linux__) && defined(__NR_pidfd_getfd) \
10897
        && !(defined(__ANDROID__) && __ANDROID_API__ < 31))
10898
/*[clinic input]
10899
os.pidfd_getfd
10900
  pidfd: int
10901
    A process file descriptor.
10902
  targetfd: int
10903
    The file descriptor to duplicate from the target process.
10904
  *
10905
  flags: unsigned_int = 0
10906
    Reserved, must be 0.
10907
10908
Duplicate a file descriptor from the process referred to by *pidfd*.
10909
[clinic start generated code]*/
10910
10911
static PyObject *
10912
os_pidfd_getfd_impl(PyObject *module, int pidfd, int targetfd,
10913
                    unsigned int flags)
10914
/*[clinic end generated code: output=e1a1415a13c7137f input=ef6417fb10deb1cc]*/
10915
{
10916
#ifdef HAVE_PIDFD_GETFD
10917
    int fd = pidfd_getfd(pidfd, targetfd, flags);
10918
#else
10919
    int fd = syscall(__NR_pidfd_getfd, pidfd, targetfd, flags);
10920
#endif
10921
    if (fd < 0) {
10922
        return posix_error();
10923
    }
10924
    return PyLong_FromLong(fd);
10925
}
10926
#endif
10927
10928
10929
#ifdef HAVE_SETNS
10930
/*[clinic input]
10931
os.setns
10932
  fd: fildes
10933
    A file descriptor to a namespace.
10934
  nstype: int = 0
10935
    Type of namespace.
10936
10937
Move the calling thread into different namespaces.
10938
[clinic start generated code]*/
10939
10940
static PyObject *
10941
os_setns_impl(PyObject *module, int fd, int nstype)
10942
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10943
0
{
10944
0
    int res;
10945
10946
0
    Py_BEGIN_ALLOW_THREADS
10947
0
    res = setns(fd, nstype);
10948
0
    Py_END_ALLOW_THREADS
10949
10950
0
    if (res != 0) {
10951
0
        return posix_error();
10952
0
    }
10953
10954
0
    Py_RETURN_NONE;
10955
0
}
10956
#endif
10957
10958
10959
#ifdef HAVE_UNSHARE
10960
/*[clinic input]
10961
os.unshare
10962
  flags: int
10963
    Namespaces to be unshared.
10964
10965
Disassociate parts of a process (or thread) execution context.
10966
[clinic start generated code]*/
10967
10968
static PyObject *
10969
os_unshare_impl(PyObject *module, int flags)
10970
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10971
0
{
10972
0
    int res;
10973
10974
0
    Py_BEGIN_ALLOW_THREADS
10975
0
    res = unshare(flags);
10976
0
    Py_END_ALLOW_THREADS
10977
10978
0
    if (res != 0) {
10979
0
        return posix_error();
10980
0
    }
10981
10982
0
    Py_RETURN_NONE;
10983
0
}
10984
#endif
10985
10986
10987
10988
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10989
10990
#if (defined(__linux__) || defined(__ANDROID__)) && defined(O_PATH)
10991
// readlinkat(fd, "", ...) reads the symlink that fd refers to.
10992
// supported since Linux 2.6.39 (same version that O_PATH was introduced).
10993
#define _Py_READLINKAT_SUPPORTS_EMPTY_PATH
10994
#endif
10995
10996
/*[clinic input]
10997
os.readlink
10998
10999
    path: path_t(allow_fd=True)
11000
    *
11001
    dir_fd: dir_fd(requires='readlinkat') = None
11002
11003
Return a string representing the path to which the symbolic link points.
11004
11005
If dir_fd is not None, it should be a file descriptor open to
11006
a directory, and path should be relative; path will then be relative to
11007
that directory.
11008
11009
dir_fd may not be implemented on your platform.  If it is unavailable,
11010
using it will raise a NotImplementedError.
11011
11012
On Linux, Android, macOS and iOS, path may be a file descriptor
11013
referring to a symlink. If it is, dir_fd must be None.
11014
[clinic start generated code]*/
11015
11016
static PyObject *
11017
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
11018
/*[clinic end generated code: output=d21b732a2e814030 input=d90bddfeee86f673]*/
11019
6
{
11020
6
#if defined(HAVE_READLINK)
11021
6
    char buffer[MAXPATHLEN+1];
11022
6
    ssize_t length;
11023
11024
6
    if (path_and_dir_fd_invalid("readlink", path, dir_fd)) {
11025
0
        return NULL;
11026
0
    }
11027
11028
6
    if (path->is_fd) {
11029
#if defined(_Py_HAVE_FREADLINK)
11030
        if (HAVE_FREADLINK_RUNTIME) {
11031
            Py_BEGIN_ALLOW_THREADS
11032
            length = freadlink(path->fd, buffer, MAXPATHLEN);
11033
            Py_END_ALLOW_THREADS
11034
        } else
11035
#elif defined(HAVE_READLINKAT) && defined(_Py_READLINKAT_SUPPORTS_EMPTY_PATH)
11036
        // linux/android:
11037
        // readlinkat(fd, "", ...) reads the link that fd refers to.
11038
0
        if (HAVE_READLINKAT_RUNTIME) {
11039
0
            Py_BEGIN_ALLOW_THREADS
11040
0
            length = readlinkat(path->fd, "", buffer, MAXPATHLEN);
11041
0
            Py_END_ALLOW_THREADS
11042
0
        } else
11043
0
#endif
11044
0
        {
11045
0
            PyErr_SetString(PyExc_NotImplementedError,
11046
0
                "readlink cannot read file descriptors on this platform");
11047
0
            return NULL;
11048
0
        }
11049
0
    } else
11050
6
#ifdef HAVE_READLINKAT
11051
6
    if (dir_fd != DEFAULT_DIR_FD) {
11052
0
        if (HAVE_READLINKAT_RUNTIME) {
11053
0
            Py_BEGIN_ALLOW_THREADS
11054
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
11055
0
            Py_END_ALLOW_THREADS
11056
0
        } else {
11057
0
            argument_unavailable_error(NULL, "dir_fd");
11058
0
            return NULL;
11059
0
        }
11060
0
    } else
11061
6
#endif
11062
6
    {
11063
6
        Py_BEGIN_ALLOW_THREADS
11064
6
        length = readlink(path->narrow, buffer, MAXPATHLEN);
11065
6
        Py_END_ALLOW_THREADS
11066
6
    }
11067
11068
6
    if (length < 0) {
11069
0
        return path_error(path);
11070
0
    }
11071
6
    buffer[length] = '\0';
11072
11073
6
    if (path->is_fd || PyUnicode_Check(path->object)) {
11074
6
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
11075
6
    }
11076
0
    else {
11077
0
        return PyBytes_FromStringAndSize(buffer, length);
11078
0
    }
11079
#elif defined(MS_WINDOWS)
11080
    DWORD n_bytes_returned;
11081
    DWORD io_result = 0;
11082
    HANDLE reparse_point_handle;
11083
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
11084
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
11085
    PyObject *result = NULL;
11086
11087
    if (path->is_fd) {
11088
        PyErr_SetString(PyExc_NotImplementedError,
11089
            "readlink cannot read file descriptors on this platform");
11090
        return NULL;
11091
    }
11092
11093
    /* First get a handle to the reparse point */
11094
    Py_BEGIN_ALLOW_THREADS
11095
    reparse_point_handle = CreateFileW(
11096
        path->wide,
11097
        0,
11098
        0,
11099
        0,
11100
        OPEN_EXISTING,
11101
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
11102
        0);
11103
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
11104
        /* New call DeviceIoControl to read the reparse point */
11105
        io_result = DeviceIoControl(
11106
            reparse_point_handle,
11107
            FSCTL_GET_REPARSE_POINT,
11108
            0, 0, /* in buffer */
11109
            target_buffer, sizeof(target_buffer),
11110
            &n_bytes_returned,
11111
            0 /* we're not using OVERLAPPED_IO */
11112
            );
11113
        CloseHandle(reparse_point_handle);
11114
    }
11115
    Py_END_ALLOW_THREADS
11116
11117
    if (io_result == 0) {
11118
        return path_error(path);
11119
    }
11120
11121
    wchar_t *name = NULL;
11122
    Py_ssize_t nameLen = 0;
11123
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
11124
    {
11125
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
11126
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
11127
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
11128
    }
11129
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
11130
    {
11131
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
11132
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
11133
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
11134
    }
11135
    else
11136
    {
11137
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
11138
    }
11139
    if (name) {
11140
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
11141
            /* Our buffer is mutable, so this is okay */
11142
            name[1] = L'\\';
11143
        }
11144
        result = PyUnicode_FromWideChar(name, nameLen);
11145
        if (result && PyBytes_Check(path->object)) {
11146
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
11147
        }
11148
    }
11149
    return result;
11150
#endif
11151
6
}
11152
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
11153
11154
#if defined(MS_WINDOWS)
11155
11156
/* Remove the last portion of the path - return 0 on success */
11157
static int
11158
_dirnameW(WCHAR *path)
11159
{
11160
    WCHAR *ptr;
11161
    size_t length = wcsnlen_s(path, MAX_PATH);
11162
    if (length == MAX_PATH) {
11163
        return -1;
11164
    }
11165
11166
    /* walk the path from the end until a backslash is encountered */
11167
    for(ptr = path + length; ptr != path; ptr--) {
11168
        if (*ptr == L'\\' || *ptr == L'/') {
11169
            break;
11170
        }
11171
    }
11172
    *ptr = 0;
11173
    return 0;
11174
}
11175
11176
#endif
11177
11178
#ifdef HAVE_SYMLINK
11179
11180
#if defined(MS_WINDOWS)
11181
11182
/* Is this path absolute? */
11183
static int
11184
_is_absW(const WCHAR *path)
11185
{
11186
    return path[0] == L'\\' || path[0] == L'/' ||
11187
        (path[0] && path[1] == L':');
11188
}
11189
11190
/* join root and rest with a backslash - return 0 on success */
11191
static int
11192
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
11193
{
11194
    if (_is_absW(rest)) {
11195
        return wcscpy_s(dest_path, MAX_PATH, rest);
11196
    }
11197
11198
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
11199
        return -1;
11200
    }
11201
11202
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
11203
        return -1;
11204
    }
11205
11206
    return wcscat_s(dest_path, MAX_PATH, rest);
11207
}
11208
11209
/* Return True if the path at src relative to dest is a directory */
11210
static int
11211
_check_dirW(LPCWSTR src, LPCWSTR dest)
11212
{
11213
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11214
    WCHAR dest_parent[MAX_PATH];
11215
    WCHAR src_resolved[MAX_PATH] = L"";
11216
11217
    /* dest_parent = os.path.dirname(dest) */
11218
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11219
        _dirnameW(dest_parent)) {
11220
        return 0;
11221
    }
11222
    /* src_resolved = os.path.join(dest_parent, src) */
11223
    if (_joinW(src_resolved, dest_parent, src)) {
11224
        return 0;
11225
    }
11226
    return (
11227
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11228
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11229
    );
11230
}
11231
#endif
11232
11233
11234
/*[clinic input]
11235
os.symlink
11236
    src: path_t
11237
    dst: path_t
11238
    target_is_directory: bool = False
11239
    *
11240
    dir_fd: dir_fd(requires='symlinkat')=None
11241
11242
Create a symbolic link pointing to src named dst.
11243
11244
target_is_directory is required on Windows if the target is to be
11245
interpreted as a directory.  (On Windows, symlink requires Windows 6.0
11246
or greater, and raises a NotImplementedError otherwise.)
11247
target_is_directory is ignored on non-Windows platforms.
11248
11249
If dir_fd is not None, it should be a file descriptor open to
11250
a directory, and path should be relative; path will then be relative
11251
to that directory.
11252
dir_fd may not be implemented on your platform.  If it is unavailable,
11253
using it will raise a NotImplementedError.
11254
11255
[clinic start generated code]*/
11256
11257
static PyObject *
11258
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11259
                int target_is_directory, int dir_fd)
11260
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=71b75467b31c45f7]*/
11261
0
{
11262
#ifdef MS_WINDOWS
11263
    DWORD result;
11264
    DWORD flags = 0;
11265
11266
    /* Assumed true, set to false if detected to not be available. */
11267
    static int windows_has_symlink_unprivileged_flag = TRUE;
11268
#else
11269
0
    int result;
11270
0
#ifdef HAVE_SYMLINKAT
11271
0
    int symlinkat_unavailable = 0;
11272
0
#endif
11273
0
#endif
11274
11275
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11276
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11277
0
        return NULL;
11278
0
    }
11279
11280
#ifdef MS_WINDOWS
11281
11282
    if (windows_has_symlink_unprivileged_flag) {
11283
        /* Allow non-admin symlinks if system allows it. */
11284
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11285
    }
11286
11287
    Py_BEGIN_ALLOW_THREADS
11288
    _Py_BEGIN_SUPPRESS_IPH
11289
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11290
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11291
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11292
    }
11293
11294
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11295
    _Py_END_SUPPRESS_IPH
11296
    Py_END_ALLOW_THREADS
11297
11298
    if (windows_has_symlink_unprivileged_flag && !result &&
11299
        ERROR_INVALID_PARAMETER == GetLastError()) {
11300
11301
        Py_BEGIN_ALLOW_THREADS
11302
        _Py_BEGIN_SUPPRESS_IPH
11303
        /* This error might be caused by
11304
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11305
        Try again, and update windows_has_symlink_unprivileged_flag if we
11306
        are successful this time.
11307
11308
        NOTE: There is a risk of a race condition here if there are other
11309
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11310
        another process (or thread) changes that condition in between our
11311
        calls to CreateSymbolicLink.
11312
        */
11313
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11314
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11315
        _Py_END_SUPPRESS_IPH
11316
        Py_END_ALLOW_THREADS
11317
11318
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11319
            windows_has_symlink_unprivileged_flag = FALSE;
11320
        }
11321
    }
11322
11323
    if (!result)
11324
        return path_error2(src, dst);
11325
11326
#else
11327
11328
0
    Py_BEGIN_ALLOW_THREADS
11329
0
#ifdef HAVE_SYMLINKAT
11330
0
    if (dir_fd != DEFAULT_DIR_FD) {
11331
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11332
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11333
0
        } else {
11334
0
            symlinkat_unavailable = 1;
11335
0
        }
11336
0
    } else
11337
0
#endif
11338
0
        result = symlink(src->narrow, dst->narrow);
11339
0
    Py_END_ALLOW_THREADS
11340
11341
0
#ifdef HAVE_SYMLINKAT
11342
0
    if (symlinkat_unavailable) {
11343
0
          argument_unavailable_error(NULL, "dir_fd");
11344
0
          return NULL;
11345
0
    }
11346
0
#endif
11347
11348
0
    if (result)
11349
0
        return path_error2(src, dst);
11350
0
#endif
11351
11352
0
    Py_RETURN_NONE;
11353
0
}
11354
#endif /* HAVE_SYMLINK */
11355
11356
11357
static PyStructSequence_Field times_result_fields[] = {
11358
    {"user",    "user time"},
11359
    {"system",   "system time"},
11360
    {"children_user",    "user time of children"},
11361
    {"children_system",    "system time of children"},
11362
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11363
    {NULL}
11364
};
11365
11366
PyDoc_STRVAR(times_result__doc__,
11367
"times_result: Result from os.times().\n\n\
11368
This object may be accessed either as a tuple of\n\
11369
  (user, system, children_user, children_system, elapsed),\n\
11370
or via the attributes user, system, children_user, children_system,\n\
11371
and elapsed.\n\
11372
\n\
11373
See os.times for more information.");
11374
11375
static PyStructSequence_Desc times_result_desc = {
11376
    MODNAME ".times_result", /* name */
11377
    times_result__doc__, /* doc */
11378
    times_result_fields,
11379
    5
11380
};
11381
11382
static PyObject *
11383
build_times_result(PyObject *module, double user, double system,
11384
    double children_user, double children_system,
11385
    double elapsed)
11386
0
{
11387
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11388
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11389
0
    if (value == NULL)
11390
0
        return NULL;
11391
11392
0
#define SET(i, field) \
11393
0
    { \
11394
0
    PyObject *o = PyFloat_FromDouble(field); \
11395
0
    if (!o) { \
11396
0
        Py_DECREF(value); \
11397
0
        return NULL; \
11398
0
    } \
11399
0
    PyStructSequence_SET_ITEM(value, i, o); \
11400
0
    } \
11401
0
11402
0
    SET(0, user);
11403
0
    SET(1, system);
11404
0
    SET(2, children_user);
11405
0
    SET(3, children_system);
11406
0
    SET(4, elapsed);
11407
11408
0
#undef SET
11409
11410
0
    return value;
11411
0
}
11412
11413
11414
/*[clinic input]
11415
os.times
11416
11417
Return a collection containing process timing information.
11418
11419
The object returned behaves like a named tuple with these fields:
11420
  (utime, stime, cutime, cstime, elapsed_time)
11421
All fields are floating-point numbers.
11422
[clinic start generated code]*/
11423
11424
static PyObject *
11425
os_times_impl(PyObject *module)
11426
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11427
0
{
11428
#ifdef MS_WINDOWS
11429
    FILETIME create, exit, kernel, user;
11430
    HANDLE hProc;
11431
    hProc = GetCurrentProcess();
11432
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11433
    /* The fields of a FILETIME structure are the hi and lo part
11434
       of a 64-bit value expressed in 100 nanosecond units.
11435
       1e7 is one second in such units; 1e-7 the inverse.
11436
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11437
    */
11438
    return build_times_result(module,
11439
        (double)(user.dwHighDateTime*429.4967296 +
11440
                 user.dwLowDateTime*1e-7),
11441
        (double)(kernel.dwHighDateTime*429.4967296 +
11442
                 kernel.dwLowDateTime*1e-7),
11443
        (double)0,
11444
        (double)0,
11445
        (double)0);
11446
#else /* MS_WINDOWS */
11447
0
    _posixstate *state = get_posix_state(module);
11448
0
    long ticks_per_second = state->ticks_per_second;
11449
11450
0
    struct tms process;
11451
0
    clock_t elapsed;
11452
0
    errno = 0;
11453
0
    elapsed = times(&process);
11454
0
    if (elapsed == (clock_t) -1) {
11455
0
        return posix_error();
11456
0
    }
11457
11458
0
    return build_times_result(module,
11459
0
        (double)process.tms_utime / ticks_per_second,
11460
0
        (double)process.tms_stime / ticks_per_second,
11461
0
        (double)process.tms_cutime / ticks_per_second,
11462
0
        (double)process.tms_cstime / ticks_per_second,
11463
0
        (double)elapsed / ticks_per_second);
11464
0
#endif /* MS_WINDOWS */
11465
0
}
11466
11467
11468
#if defined(HAVE_TIMERFD_CREATE)
11469
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11470
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11471
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11472
11473
static PyObject *
11474
build_itimerspec(const struct itimerspec* curr_value)
11475
0
{
11476
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11477
0
                                                          curr_value->it_value.tv_nsec);
11478
0
    PyObject *value = PyFloat_FromDouble(_value);
11479
0
    if (value == NULL) {
11480
0
        return NULL;
11481
0
    }
11482
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11483
0
                                                   curr_value->it_interval.tv_nsec);
11484
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11485
0
    if (interval == NULL) {
11486
0
        Py_DECREF(value);
11487
0
        return NULL;
11488
0
    }
11489
0
    return _PyTuple_FromPairSteal(value, interval);
11490
0
}
11491
11492
static PyObject *
11493
build_itimerspec_ns(const struct itimerspec* curr_value)
11494
0
{
11495
0
    PyTime_t value, interval;
11496
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11497
0
        return NULL;
11498
0
    }
11499
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11500
0
        return NULL;
11501
0
    }
11502
0
    return Py_BuildValue("LL", value, interval);
11503
0
}
11504
11505
/*[clinic input]
11506
os.timerfd_create
11507
11508
    clockid: int
11509
        A valid clock ID constant as timer file descriptor.
11510
11511
        time.CLOCK_REALTIME
11512
        time.CLOCK_MONOTONIC
11513
        time.CLOCK_BOOTTIME
11514
    /
11515
    *
11516
    flags: int = 0
11517
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11518
11519
        os.TFD_NONBLOCK
11520
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11521
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11522
11523
        os.TFD_CLOEXEC
11524
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11525
11526
Create and return a timer file descriptor.
11527
[clinic start generated code]*/
11528
11529
static PyObject *
11530
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11531
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11532
11533
0
{
11534
0
    int fd;
11535
0
    Py_BEGIN_ALLOW_THREADS
11536
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11537
0
    fd = timerfd_create(clockid, flags);
11538
0
    Py_END_ALLOW_THREADS
11539
0
    if (fd == -1) {
11540
0
        return PyErr_SetFromErrno(PyExc_OSError);
11541
0
    }
11542
0
    return PyLong_FromLong(fd);
11543
0
}
11544
11545
/*[clinic input]
11546
os.timerfd_settime
11547
11548
    fd: fildes
11549
        A timer file descriptor.
11550
    /
11551
    *
11552
    flags: int = 0
11553
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11554
    initial as initial_double: double = 0.0
11555
        The initial expiration time, in seconds.
11556
    interval as interval_double: double = 0.0
11557
        The timer's interval, in seconds.
11558
11559
Alter a timer file descriptor's internal timer in seconds.
11560
[clinic start generated code]*/
11561
11562
static PyObject *
11563
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11564
                        double initial_double, double interval_double)
11565
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11566
0
{
11567
0
    PyTime_t initial, interval;
11568
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11569
0
                                  &initial) < 0) {
11570
0
        return NULL;
11571
0
    }
11572
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11573
0
                                  &interval) < 0) {
11574
0
        return NULL;
11575
0
    }
11576
11577
0
    struct itimerspec new_value, old_value;
11578
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11579
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11580
0
        return NULL;
11581
0
    }
11582
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11583
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11584
0
        return NULL;
11585
0
    }
11586
11587
0
    int result;
11588
0
    Py_BEGIN_ALLOW_THREADS
11589
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11590
0
    Py_END_ALLOW_THREADS
11591
0
    if (result == -1) {
11592
0
        return PyErr_SetFromErrno(PyExc_OSError);
11593
0
    }
11594
0
    return build_itimerspec(&old_value);
11595
0
}
11596
11597
11598
/*[clinic input]
11599
os.timerfd_settime_ns
11600
11601
    fd: fildes
11602
        A timer file descriptor.
11603
    /
11604
    *
11605
    flags: int = 0
11606
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11607
    initial: long_long = 0
11608
        initial expiration timing in nanoseconds.
11609
    interval: long_long = 0
11610
        interval for the timer in nanoseconds.
11611
11612
Alter a timer file descriptor's internal timer in nanoseconds.
11613
[clinic start generated code]*/
11614
11615
static PyObject *
11616
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11617
                           long long initial, long long interval)
11618
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=94bdcea7292157eb]*/
11619
0
{
11620
0
    struct itimerspec new_value;
11621
0
    struct itimerspec old_value;
11622
0
    int result;
11623
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11624
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11625
0
        return NULL;
11626
0
    }
11627
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11628
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11629
0
        return NULL;
11630
0
    }
11631
0
    Py_BEGIN_ALLOW_THREADS
11632
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11633
0
    Py_END_ALLOW_THREADS
11634
0
    if (result == -1) {
11635
0
        return PyErr_SetFromErrno(PyExc_OSError);
11636
0
    }
11637
0
    return build_itimerspec_ns(&old_value);
11638
0
}
11639
11640
/*[clinic input]
11641
@permit_long_summary
11642
os.timerfd_gettime
11643
11644
    fd: fildes
11645
        A timer file descriptor.
11646
    /
11647
11648
Return a tuple of a timer file descriptor's (next expiration, interval) in float seconds.
11649
[clinic start generated code]*/
11650
11651
static PyObject *
11652
os_timerfd_gettime_impl(PyObject *module, int fd)
11653
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=7b0a7cc61ea9e31a]*/
11654
0
{
11655
0
    struct itimerspec curr_value;
11656
0
    int result;
11657
0
    Py_BEGIN_ALLOW_THREADS
11658
0
    result = timerfd_gettime(fd, &curr_value);
11659
0
    Py_END_ALLOW_THREADS
11660
0
    if (result == -1) {
11661
0
        return PyErr_SetFromErrno(PyExc_OSError);
11662
0
    }
11663
0
    return build_itimerspec(&curr_value);
11664
0
}
11665
11666
11667
/*[clinic input]
11668
@permit_long_summary
11669
os.timerfd_gettime_ns
11670
11671
    fd: fildes
11672
        A timer file descriptor.
11673
    /
11674
11675
Return a tuple of a timer file descriptor's (next expiration, interval) in nanoseconds.
11676
[clinic start generated code]*/
11677
11678
static PyObject *
11679
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11680
/*[clinic end generated code: output=580633a4465f39fe input=89702268455fa93b]*/
11681
0
{
11682
0
    struct itimerspec curr_value;
11683
0
    int result;
11684
0
    Py_BEGIN_ALLOW_THREADS
11685
0
    result = timerfd_gettime(fd, &curr_value);
11686
0
    Py_END_ALLOW_THREADS
11687
0
    if (result == -1) {
11688
0
        return PyErr_SetFromErrno(PyExc_OSError);
11689
0
    }
11690
0
    return build_itimerspec_ns(&curr_value);
11691
0
}
11692
11693
#undef ONE_SECOND_IN_NS
11694
#undef EXTRACT_NSEC
11695
11696
#endif  /* HAVE_TIMERFD_CREATE */
11697
11698
#ifdef HAVE_GETSID
11699
/*[clinic input]
11700
os.getsid
11701
11702
    pid: pid_t
11703
    /
11704
11705
Call the system call getsid(pid) and return the result.
11706
[clinic start generated code]*/
11707
11708
static PyObject *
11709
os_getsid_impl(PyObject *module, pid_t pid)
11710
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11711
0
{
11712
0
    int sid;
11713
0
    sid = getsid(pid);
11714
0
    if (sid < 0)
11715
0
        return posix_error();
11716
0
    return PyLong_FromLong((long)sid);
11717
0
}
11718
#endif /* HAVE_GETSID */
11719
11720
11721
#ifdef HAVE_SETSID
11722
/*[clinic input]
11723
os.setsid
11724
11725
Call the system call setsid().
11726
[clinic start generated code]*/
11727
11728
static PyObject *
11729
os_setsid_impl(PyObject *module)
11730
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11731
0
{
11732
0
    if (setsid() < 0)
11733
0
        return posix_error();
11734
0
    Py_RETURN_NONE;
11735
0
}
11736
#endif /* HAVE_SETSID */
11737
11738
11739
#ifdef HAVE_SETPGID
11740
/*[clinic input]
11741
os.setpgid
11742
11743
    pid: pid_t
11744
    pgrp: pid_t
11745
    /
11746
11747
Call the system call setpgid(pid, pgrp).
11748
[clinic start generated code]*/
11749
11750
static PyObject *
11751
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11752
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11753
0
{
11754
0
    if (setpgid(pid, pgrp) < 0)
11755
0
        return posix_error();
11756
0
    Py_RETURN_NONE;
11757
0
}
11758
#endif /* HAVE_SETPGID */
11759
11760
11761
#ifdef HAVE_TCGETPGRP
11762
/*[clinic input]
11763
os.tcgetpgrp
11764
11765
    fd: int
11766
    /
11767
11768
Return the process group associated with the terminal specified by fd.
11769
[clinic start generated code]*/
11770
11771
static PyObject *
11772
os_tcgetpgrp_impl(PyObject *module, int fd)
11773
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11774
0
{
11775
0
    pid_t pgid = tcgetpgrp(fd);
11776
0
    if (pgid < 0)
11777
0
        return posix_error();
11778
0
    return PyLong_FromPid(pgid);
11779
0
}
11780
#endif /* HAVE_TCGETPGRP */
11781
11782
11783
#ifdef HAVE_TCSETPGRP
11784
/*[clinic input]
11785
os.tcsetpgrp
11786
11787
    fd: int
11788
    pgid: pid_t
11789
    /
11790
11791
Set the process group associated with the terminal specified by fd.
11792
[clinic start generated code]*/
11793
11794
static PyObject *
11795
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11796
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11797
0
{
11798
0
    if (tcsetpgrp(fd, pgid) < 0)
11799
0
        return posix_error();
11800
0
    Py_RETURN_NONE;
11801
0
}
11802
#endif /* HAVE_TCSETPGRP */
11803
11804
/* Functions acting on file descriptors */
11805
11806
#ifdef O_CLOEXEC
11807
extern int _Py_open_cloexec_works;
11808
#endif
11809
11810
11811
/*[clinic input]
11812
os.open -> int
11813
    path: path_t
11814
    flags: int
11815
    mode: int = 0o777
11816
    *
11817
    dir_fd: dir_fd(requires='openat') = None
11818
11819
Open a file for low level IO.  Returns a file descriptor (integer).
11820
11821
If dir_fd is not None, it should be a file descriptor open to
11822
a directory, and path should be relative; path will then be relative to
11823
that directory.
11824
dir_fd may not be implemented on your platform.  If it is unavailable,
11825
using it will raise a NotImplementedError.
11826
[clinic start generated code]*/
11827
11828
static int
11829
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11830
/*[clinic end generated code: output=abc7227888c8bc73 input=75f7b4eaf92f2225]*/
11831
88.6k
{
11832
88.6k
    int fd;
11833
88.6k
    int async_err = 0;
11834
88.6k
#ifdef HAVE_OPENAT
11835
88.6k
    int openat_unavailable = 0;
11836
88.6k
#endif
11837
11838
88.6k
#ifdef O_CLOEXEC
11839
88.6k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11840
#elif !defined(MS_WINDOWS)
11841
    int *atomic_flag_works = NULL;
11842
#endif
11843
11844
#ifdef MS_WINDOWS
11845
    flags |= O_NOINHERIT;
11846
#elif defined(O_CLOEXEC)
11847
88.6k
    flags |= O_CLOEXEC;
11848
88.6k
#endif
11849
11850
88.6k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11851
0
        return -1;
11852
0
    }
11853
11854
88.6k
    _Py_BEGIN_SUPPRESS_IPH
11855
88.6k
    do {
11856
88.6k
        Py_BEGIN_ALLOW_THREADS
11857
#ifdef MS_WINDOWS
11858
        fd = _wopen(path->wide, flags, mode);
11859
#else
11860
88.6k
#ifdef HAVE_OPENAT
11861
88.6k
        if (dir_fd != DEFAULT_DIR_FD) {
11862
84.3k
            if (HAVE_OPENAT_RUNTIME) {
11863
84.3k
                fd = openat(dir_fd, path->narrow, flags, mode);
11864
11865
84.3k
            } else {
11866
0
                openat_unavailable = 1;
11867
0
                fd = -1;
11868
0
            }
11869
84.3k
        } else
11870
4.24k
#endif /* HAVE_OPENAT */
11871
4.24k
            fd = open(path->narrow, flags, mode);
11872
88.6k
#endif /* !MS_WINDOWS */
11873
88.6k
        Py_END_ALLOW_THREADS
11874
88.6k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11875
88.6k
    _Py_END_SUPPRESS_IPH
11876
11877
88.6k
#ifdef HAVE_OPENAT
11878
88.6k
    if (openat_unavailable) {
11879
0
        argument_unavailable_error(NULL, "dir_fd");
11880
0
        return -1;
11881
0
    }
11882
88.6k
#endif
11883
11884
88.6k
    if (fd < 0) {
11885
0
        if (!async_err)
11886
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11887
0
        return -1;
11888
0
    }
11889
11890
88.6k
#ifndef MS_WINDOWS
11891
88.6k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11892
0
        close(fd);
11893
0
        return -1;
11894
0
    }
11895
88.6k
#endif
11896
11897
88.6k
    return fd;
11898
88.6k
}
11899
11900
11901
/*[clinic input]
11902
os.close
11903
11904
    fd: int
11905
11906
Close a file descriptor.
11907
[clinic start generated code]*/
11908
11909
static PyObject *
11910
os_close_impl(PyObject *module, int fd)
11911
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11912
88.4k
{
11913
88.4k
    int res;
11914
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11915
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11916
     * for more details.
11917
     */
11918
88.4k
    Py_BEGIN_ALLOW_THREADS
11919
88.4k
    _Py_BEGIN_SUPPRESS_IPH
11920
88.4k
    res = close(fd);
11921
88.4k
    _Py_END_SUPPRESS_IPH
11922
88.4k
    Py_END_ALLOW_THREADS
11923
88.4k
    if (res < 0)
11924
0
        return posix_error();
11925
88.4k
    Py_RETURN_NONE;
11926
88.4k
}
11927
11928
/*[clinic input]
11929
os.closerange
11930
11931
    fd_low: int
11932
    fd_high: int
11933
    /
11934
11935
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11936
[clinic start generated code]*/
11937
11938
static PyObject *
11939
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11940
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11941
0
{
11942
0
    Py_BEGIN_ALLOW_THREADS
11943
0
    _Py_closerange(fd_low, fd_high - 1);
11944
0
    Py_END_ALLOW_THREADS
11945
0
    Py_RETURN_NONE;
11946
0
}
11947
11948
11949
/*[clinic input]
11950
os.dup -> int
11951
11952
    fd: int
11953
    /
11954
11955
Return a duplicate of a file descriptor.
11956
[clinic start generated code]*/
11957
11958
static int
11959
os_dup_impl(PyObject *module, int fd)
11960
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11961
0
{
11962
0
    return _Py_dup(fd);
11963
0
}
11964
11965
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11966
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11967
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11968
/*[clinic input]
11969
os.dup2 -> int
11970
    fd: int
11971
    fd2: int
11972
    inheritable: bool=True
11973
11974
Duplicate file descriptor.
11975
[clinic start generated code]*/
11976
11977
static int
11978
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11979
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11980
0
{
11981
0
    int res = 0;
11982
11983
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 and macOS 27.0;
11984
     * it needs runtime detection for the case of running on older kernels.
11985
     * Values: -1: unknown; 0: doesn't work; 1: works
11986
     * For thread safety, use a process-global with one read & one store,
11987
     * both relaxed. (It's fine if two threads race and do the detection
11988
     * simultaneously; they should get the same result.)
11989
     */
11990
0
    static int dup3_works_atomic = -1;
11991
0
    (void) dup3_works_atomic;  // unused on some platforms
11992
11993
    /* dup2() can fail with EINTR if the target FD is already open, because it
11994
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11995
     * upon close(), and therefore below.
11996
     */
11997
#ifdef MS_WINDOWS
11998
    Py_BEGIN_ALLOW_THREADS
11999
    _Py_BEGIN_SUPPRESS_IPH
12000
    res = dup2(fd, fd2);
12001
    _Py_END_SUPPRESS_IPH
12002
    Py_END_ALLOW_THREADS
12003
    if (res < 0) {
12004
        posix_error();
12005
        return -1;
12006
    }
12007
    res = fd2; // msvcrt dup2 returns 0 on success.
12008
12009
    /* Character files like console cannot be make non-inheritable */
12010
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
12011
        close(fd2);
12012
        return -1;
12013
    }
12014
12015
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
12016
    Py_BEGIN_ALLOW_THREADS
12017
    if (!inheritable)
12018
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
12019
    else
12020
        res = dup2(fd, fd2);
12021
    Py_END_ALLOW_THREADS
12022
    if (res < 0) {
12023
        posix_error();
12024
        return -1;
12025
    }
12026
12027
#else
12028
12029
0
#ifdef HAVE_DUP3
12030
0
    int dup3_works = FT_ATOMIC_LOAD_INT_RELAXED(dup3_works_atomic);
12031
0
    if (!inheritable && dup3_works != 0) {
12032
0
        if (HAVE_DUP3_RUNTIME) {
12033
0
            Py_BEGIN_ALLOW_THREADS
12034
0
            res = dup3(fd, fd2, O_CLOEXEC);
12035
0
            Py_END_ALLOW_THREADS
12036
0
            if (res < 0) {
12037
0
                if (dup3_works == -1) {
12038
0
                    dup3_works = (errno != ENOSYS);
12039
0
                    FT_ATOMIC_STORE_INT_RELAXED(dup3_works_atomic, dup3_works);
12040
0
                }
12041
0
                if (dup3_works) {
12042
0
                    posix_error();
12043
0
                    return -1;
12044
0
                }
12045
0
            }
12046
0
        }
12047
0
        else {
12048
0
            dup3_works = 0;
12049
0
            FT_ATOMIC_STORE_INT_RELAXED(dup3_works_atomic, dup3_works);
12050
0
        }
12051
0
    }
12052
12053
0
    if (inheritable || dup3_works == 0)
12054
0
    {
12055
0
#endif
12056
0
        Py_BEGIN_ALLOW_THREADS
12057
0
        res = dup2(fd, fd2);
12058
0
        Py_END_ALLOW_THREADS
12059
0
        if (res < 0) {
12060
0
            posix_error();
12061
0
            return -1;
12062
0
        }
12063
12064
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
12065
0
            close(fd2);
12066
0
            return -1;
12067
0
        }
12068
0
#ifdef HAVE_DUP3
12069
0
    }
12070
0
#endif
12071
12072
0
#endif
12073
12074
0
    return res;
12075
0
}
12076
#endif
12077
12078
12079
#ifdef HAVE_LOCKF
12080
/*[clinic input]
12081
os.lockf
12082
12083
    fd: int
12084
        An open file descriptor.
12085
    command: int
12086
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
12087
    length: Py_off_t
12088
        The number of bytes to lock, starting at the current position.
12089
    /
12090
12091
Apply, test or remove a POSIX lock on an open file descriptor.
12092
12093
[clinic start generated code]*/
12094
12095
static PyObject *
12096
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
12097
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
12098
0
{
12099
0
    int res;
12100
12101
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
12102
0
        return NULL;
12103
0
    }
12104
12105
0
    Py_BEGIN_ALLOW_THREADS
12106
0
    res = lockf(fd, command, length);
12107
0
    Py_END_ALLOW_THREADS
12108
12109
0
    if (res < 0)
12110
0
        return posix_error();
12111
12112
0
    Py_RETURN_NONE;
12113
0
}
12114
#endif /* HAVE_LOCKF */
12115
12116
12117
/*[clinic input]
12118
os.lseek -> Py_off_t
12119
12120
    fd: int
12121
        An open file descriptor, as returned by os.open().
12122
    position: Py_off_t
12123
        Position, interpreted relative to 'whence'.
12124
    whence as how: int
12125
        The relative position to seek from. Valid values are:
12126
        - SEEK_SET: seek from the start of the file.
12127
        - SEEK_CUR: seek from the current file position.
12128
        - SEEK_END: seek from the end of the file.
12129
    /
12130
12131
Set the position of a file descriptor.  Return the new position.
12132
12133
The return value is the number of bytes relative to the beginning of
12134
the file.
12135
[clinic start generated code]*/
12136
12137
static Py_off_t
12138
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
12139
/*[clinic end generated code: output=971e1efb6b30bd2f input=32ea0788da7cb44b]*/
12140
0
{
12141
0
    Py_off_t result = -1;
12142
12143
0
#ifdef SEEK_SET
12144
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
12145
0
    switch (how) {
12146
0
        case 0: how = SEEK_SET; break;
12147
0
        case 1: how = SEEK_CUR; break;
12148
0
        case 2: how = SEEK_END; break;
12149
0
    }
12150
0
#endif /* SEEK_END */
12151
12152
0
    Py_BEGIN_ALLOW_THREADS
12153
0
    _Py_BEGIN_SUPPRESS_IPH
12154
#ifdef MS_WINDOWS
12155
    HANDLE h = (HANDLE)_get_osfhandle(fd);
12156
    if (h != INVALID_HANDLE_VALUE && GetFileType(h) == FILE_TYPE_PIPE) {
12157
        errno = ESPIPE;
12158
    }
12159
    else {
12160
        result = _lseeki64(fd, position, how);
12161
    }
12162
#else
12163
0
    result = lseek(fd, position, how);
12164
0
#endif
12165
0
    _Py_END_SUPPRESS_IPH
12166
0
    Py_END_ALLOW_THREADS
12167
0
    if (result < 0) {
12168
0
        posix_error();
12169
0
    }
12170
12171
0
    return result;
12172
0
}
12173
12174
12175
/*[clinic input]
12176
os.read
12177
    fd: int
12178
    length: Py_ssize_t
12179
    /
12180
12181
Read from a file descriptor.  Returns a bytes object.
12182
[clinic start generated code]*/
12183
12184
static PyObject *
12185
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
12186
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
12187
0
{
12188
0
    if (length < 0) {
12189
0
        errno = EINVAL;
12190
0
        return posix_error();
12191
0
    }
12192
12193
0
    length = Py_MIN(length, _PY_READ_MAX);
12194
12195
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12196
0
    if (writer == NULL) {
12197
0
        return NULL;
12198
0
    }
12199
12200
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
12201
0
    if (n == -1) {
12202
0
        PyBytesWriter_Discard(writer);
12203
0
        return NULL;
12204
0
    }
12205
12206
0
    return PyBytesWriter_FinishWithSize(writer, n);
12207
0
}
12208
12209
/*[clinic input]
12210
os.readinto -> Py_ssize_t
12211
    fd: int
12212
    buffer: Py_buffer(accept={rwbuffer})
12213
    /
12214
12215
Read into a buffer object from a file descriptor.
12216
12217
The buffer should be mutable and bytes-like.  On success, returns the
12218
number of bytes read.  Less bytes may be read than the size of the
12219
buffer.  The underlying system call will be retried when interrupted by
12220
a signal, unless the signal handler raises an exception.  Other errors
12221
will not be retried and an error will be raised.
12222
12223
Returns 0 if *fd* is at end of file or if the provided *buffer* has
12224
length 0 (which can be used to check for errors without reading data).
12225
Never returns negative.
12226
[clinic start generated code]*/
12227
12228
static Py_ssize_t
12229
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12230
/*[clinic end generated code: output=8091a3513c683a80 input=2a5f8b212cb5730c]*/
12231
0
{
12232
0
    assert(buffer->len >= 0);
12233
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12234
    /* Ensure negative is never returned without an error. Simplifies calling
12235
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12236
        error. */
12237
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12238
0
    return result;
12239
0
}
12240
12241
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12242
                                || defined(__APPLE__))) \
12243
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12244
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12245
static int
12246
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12247
0
{
12248
0
    Py_ssize_t i, j;
12249
12250
0
    *iov = PyMem_New(struct iovec, cnt);
12251
0
    if (*iov == NULL) {
12252
0
        PyErr_NoMemory();
12253
0
        return -1;
12254
0
    }
12255
12256
0
    *buf = PyMem_New(Py_buffer, cnt);
12257
0
    if (*buf == NULL) {
12258
0
        PyMem_Free(*iov);
12259
0
        PyErr_NoMemory();
12260
0
        return -1;
12261
0
    }
12262
12263
0
    for (i = 0; i < cnt; i++) {
12264
0
        PyObject *item = PySequence_GetItem(seq, i);
12265
0
        if (item == NULL)
12266
0
            goto fail;
12267
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12268
0
            Py_DECREF(item);
12269
0
            goto fail;
12270
0
        }
12271
0
        Py_DECREF(item);
12272
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12273
0
        (*iov)[i].iov_len = (*buf)[i].len;
12274
0
    }
12275
0
    return 0;
12276
12277
0
fail:
12278
0
    PyMem_Free(*iov);
12279
0
    for (j = 0; j < i; j++) {
12280
0
        PyBuffer_Release(&(*buf)[j]);
12281
0
    }
12282
0
    PyMem_Free(*buf);
12283
0
    return -1;
12284
0
}
12285
12286
static void
12287
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12288
0
{
12289
0
    int i;
12290
0
    PyMem_Free(iov);
12291
0
    for (i = 0; i < cnt; i++) {
12292
0
        PyBuffer_Release(&buf[i]);
12293
0
    }
12294
0
    PyMem_Free(buf);
12295
0
}
12296
#endif
12297
12298
12299
#ifdef HAVE_READV
12300
/*[clinic input]
12301
os.readv -> Py_ssize_t
12302
12303
    fd: int
12304
    buffers: object
12305
    /
12306
12307
Read from a file descriptor fd into an iterable of buffers.
12308
12309
The buffers should be mutable buffers accepting bytes.
12310
readv will transfer data into each buffer until it is full
12311
and then move on to the next buffer in the sequence to hold
12312
the rest of the data.
12313
12314
readv returns the total number of bytes read,
12315
which may be less than the total capacity of all the buffers.
12316
[clinic start generated code]*/
12317
12318
static Py_ssize_t
12319
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12320
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12321
0
{
12322
0
    Py_ssize_t cnt, n;
12323
0
    int async_err = 0;
12324
0
    struct iovec *iov;
12325
0
    Py_buffer *buf;
12326
12327
0
    if (!PySequence_Check(buffers)) {
12328
0
        PyErr_SetString(PyExc_TypeError,
12329
0
            "readv() arg 2 must be a sequence");
12330
0
        return -1;
12331
0
    }
12332
12333
0
    cnt = PySequence_Size(buffers);
12334
0
    if (cnt < 0)
12335
0
        return -1;
12336
12337
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12338
0
        return -1;
12339
12340
0
    do {
12341
0
        Py_BEGIN_ALLOW_THREADS
12342
0
        n = readv(fd, iov, cnt);
12343
0
        Py_END_ALLOW_THREADS
12344
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12345
12346
0
    int saved_errno = errno;
12347
0
    iov_cleanup(iov, buf, cnt);
12348
0
    if (n < 0) {
12349
0
        if (!async_err) {
12350
0
            errno = saved_errno;
12351
0
            posix_error();
12352
0
        }
12353
0
        return -1;
12354
0
    }
12355
12356
0
    return n;
12357
0
}
12358
#endif /* HAVE_READV */
12359
12360
12361
#ifdef HAVE_PREAD
12362
/*[clinic input]
12363
@permit_long_summary
12364
os.pread
12365
12366
    fd: int
12367
    length: Py_ssize_t
12368
    offset: Py_off_t
12369
    /
12370
12371
Read a number of bytes from a file descriptor starting at a particular offset.
12372
12373
Read length bytes from file descriptor fd, starting at offset bytes from
12374
the beginning of the file.  The file offset remains unchanged.
12375
[clinic start generated code]*/
12376
12377
static PyObject *
12378
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12379
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12380
0
{
12381
0
    Py_ssize_t n;
12382
0
    int async_err = 0;
12383
12384
0
    if (length < 0) {
12385
0
        errno = EINVAL;
12386
0
        return posix_error();
12387
0
    }
12388
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12389
0
    if (writer == NULL) {
12390
0
        return NULL;
12391
0
    }
12392
12393
0
    do {
12394
0
        Py_BEGIN_ALLOW_THREADS
12395
0
        _Py_BEGIN_SUPPRESS_IPH
12396
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12397
0
        _Py_END_SUPPRESS_IPH
12398
0
        Py_END_ALLOW_THREADS
12399
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12400
12401
0
    if (n < 0) {
12402
0
        if (!async_err) {
12403
0
            posix_error();
12404
0
        }
12405
0
        PyBytesWriter_Discard(writer);
12406
0
        return NULL;
12407
0
    }
12408
0
    return PyBytesWriter_FinishWithSize(writer, n);
12409
0
}
12410
#endif /* HAVE_PREAD */
12411
12412
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12413
/*[clinic input]
12414
@permit_long_summary
12415
os.preadv -> Py_ssize_t
12416
12417
    fd: int
12418
    buffers: object
12419
    offset: Py_off_t
12420
    flags: int = 0
12421
    /
12422
12423
Reads from a file descriptor into a number of mutable bytes-like objects.
12424
12425
Combines the functionality of readv() and pread().  As readv(), it will
12426
transfer data into each buffer until it is full and then move on to the
12427
next buffer in the sequence to hold the rest of the data.  Its fourth
12428
argument, specifies the file offset at which the input operation is to
12429
be performed.  It will return the total number of bytes read (which can
12430
be less than the total capacity of all the objects).
12431
12432
The flags argument contains a bitwise OR of zero or more of the
12433
following flags:
12434
12435
- RWF_HIPRI
12436
- RWF_NOWAIT
12437
- RWF_DONTCACHE
12438
12439
Using non-zero flags requires Linux 4.6 or newer.
12440
[clinic start generated code]*/
12441
12442
static Py_ssize_t
12443
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12444
               int flags)
12445
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=bbc70c63b4f4e877]*/
12446
0
{
12447
0
    Py_ssize_t cnt, n;
12448
0
    int async_err = 0;
12449
0
    struct iovec *iov;
12450
0
    Py_buffer *buf;
12451
12452
0
    if (!PySequence_Check(buffers)) {
12453
0
        PyErr_SetString(PyExc_TypeError,
12454
0
            "preadv2() arg 2 must be a sequence");
12455
0
        return -1;
12456
0
    }
12457
12458
0
    cnt = PySequence_Size(buffers);
12459
0
    if (cnt < 0) {
12460
0
        return -1;
12461
0
    }
12462
12463
#ifndef HAVE_PREADV2
12464
    if(flags != 0) {
12465
        argument_unavailable_error("preadv2", "flags");
12466
        return -1;
12467
    }
12468
#endif
12469
12470
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12471
0
        return -1;
12472
0
    }
12473
0
#ifdef HAVE_PREADV2
12474
0
    do {
12475
0
        Py_BEGIN_ALLOW_THREADS
12476
0
        _Py_BEGIN_SUPPRESS_IPH
12477
0
        n = preadv2(fd, iov, cnt, offset, flags);
12478
0
        _Py_END_SUPPRESS_IPH
12479
0
        Py_END_ALLOW_THREADS
12480
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12481
#else
12482
    do {
12483
#if defined(__APPLE__) && defined(__clang__)
12484
/* This entire function will be removed from the module dict when the API
12485
 * is not available.
12486
 */
12487
#pragma clang diagnostic push
12488
#pragma clang diagnostic ignored "-Wunguarded-availability"
12489
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12490
#endif
12491
        Py_BEGIN_ALLOW_THREADS
12492
        _Py_BEGIN_SUPPRESS_IPH
12493
        n = preadv(fd, iov, cnt, offset);
12494
        _Py_END_SUPPRESS_IPH
12495
        Py_END_ALLOW_THREADS
12496
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12497
12498
#if defined(__APPLE__) && defined(__clang__)
12499
#pragma clang diagnostic pop
12500
#endif
12501
12502
#endif
12503
12504
0
    int saved_errno = errno;
12505
0
    iov_cleanup(iov, buf, cnt);
12506
0
    if (n < 0) {
12507
0
        if (!async_err) {
12508
0
            errno = saved_errno;
12509
0
            posix_error();
12510
0
        }
12511
0
        return -1;
12512
0
    }
12513
12514
0
    return n;
12515
0
}
12516
#endif /* HAVE_PREADV */
12517
12518
12519
/*[clinic input]
12520
os.write -> Py_ssize_t
12521
12522
    fd: int
12523
    data: Py_buffer
12524
    /
12525
12526
Write a bytes object to a file descriptor.
12527
[clinic start generated code]*/
12528
12529
static Py_ssize_t
12530
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12531
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12532
2
{
12533
2
    return _Py_write(fd, data->buf, data->len);
12534
2
}
12535
12536
#ifdef HAVE_SENDFILE
12537
#ifdef __APPLE__
12538
/*[clinic input]
12539
os.sendfile
12540
12541
    out_fd: int
12542
    in_fd: int
12543
    offset: Py_off_t
12544
    count as sbytes: Py_off_t
12545
    headers: object(c_default="NULL") = ()
12546
    trailers: object(c_default="NULL") = ()
12547
    flags: int = 0
12548
12549
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12550
[clinic start generated code]*/
12551
12552
static PyObject *
12553
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12554
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12555
                 int flags)
12556
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12557
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12558
/*[clinic input]
12559
os.sendfile
12560
12561
    out_fd: int
12562
    in_fd: int
12563
    offset: Py_off_t
12564
    count: Py_ssize_t(allow_negative=False)
12565
    headers: object(c_default="NULL") = ()
12566
    trailers: object(c_default="NULL") = ()
12567
    flags: int = 0
12568
12569
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12570
[clinic start generated code]*/
12571
12572
static PyObject *
12573
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12574
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12575
                 int flags)
12576
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12577
#else
12578
/*[clinic input]
12579
os.sendfile
12580
12581
    out_fd: int
12582
    in_fd: int
12583
    offset as offobj: object
12584
    count: Py_ssize_t(allow_negative=False)
12585
12586
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12587
[clinic start generated code]*/
12588
12589
static PyObject *
12590
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12591
                 Py_ssize_t count)
12592
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12593
#endif
12594
0
{
12595
0
    Py_ssize_t ret;
12596
0
    int async_err = 0;
12597
12598
#ifdef __APPLE__
12599
    if(sbytes < 0) {
12600
        PyErr_SetString(PyExc_ValueError,
12601
                        "count cannot be negative");
12602
        return NULL;
12603
    }
12604
#else
12605
0
    assert(count >= 0);
12606
0
#endif
12607
12608
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12609
#ifndef __APPLE__
12610
    off_t sbytes;
12611
#endif
12612
    Py_buffer *hbuf, *tbuf;
12613
    struct sf_hdtr sf;
12614
12615
    sf.headers = NULL;
12616
    sf.trailers = NULL;
12617
12618
    if (headers != NULL) {
12619
        if (!PySequence_Check(headers)) {
12620
            PyErr_SetString(PyExc_TypeError,
12621
                "sendfile() headers must be a sequence");
12622
            return NULL;
12623
        } else {
12624
            Py_ssize_t i = PySequence_Size(headers);
12625
            if (i < 0)
12626
                return NULL;
12627
            if (i > INT_MAX) {
12628
                PyErr_SetString(PyExc_OverflowError,
12629
                    "sendfile() header is too large");
12630
                return NULL;
12631
            }
12632
            if (i > 0) {
12633
                sf.hdr_cnt = (int)i;
12634
                if (iov_setup(&(sf.headers), &hbuf,
12635
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12636
                    return NULL;
12637
#ifdef __APPLE__
12638
                for (i = 0; i < sf.hdr_cnt; i++) {
12639
                    Py_ssize_t blen = sf.headers[i].iov_len;
12640
# define OFF_T_MAX 0x7fffffffffffffff
12641
                    if (sbytes >= OFF_T_MAX - blen) {
12642
                        PyErr_SetString(PyExc_OverflowError,
12643
                            "sendfile() header is too large");
12644
                        return NULL;
12645
                    }
12646
                    sbytes += blen;
12647
                }
12648
#endif
12649
            }
12650
        }
12651
    }
12652
    if (trailers != NULL) {
12653
        if (!PySequence_Check(trailers)) {
12654
            PyErr_SetString(PyExc_TypeError,
12655
                "sendfile() trailers must be a sequence");
12656
            return NULL;
12657
        } else {
12658
            Py_ssize_t i = PySequence_Size(trailers);
12659
            if (i < 0)
12660
                return NULL;
12661
            if (i > INT_MAX) {
12662
                PyErr_SetString(PyExc_OverflowError,
12663
                    "sendfile() trailer is too large");
12664
                return NULL;
12665
            }
12666
            if (i > 0) {
12667
                sf.trl_cnt = (int)i;
12668
                if (iov_setup(&(sf.trailers), &tbuf,
12669
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12670
                    return NULL;
12671
            }
12672
        }
12673
    }
12674
12675
    _Py_BEGIN_SUPPRESS_IPH
12676
    do {
12677
        Py_BEGIN_ALLOW_THREADS
12678
#ifdef __APPLE__
12679
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12680
#else
12681
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12682
#endif
12683
        Py_END_ALLOW_THREADS
12684
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12685
    _Py_END_SUPPRESS_IPH
12686
12687
    int saved_errno = errno;
12688
    if (sf.headers != NULL)
12689
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12690
    if (sf.trailers != NULL)
12691
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12692
12693
    if (ret < 0) {
12694
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12695
            if (sbytes != 0) {
12696
                // some data has been sent
12697
                goto done;
12698
            }
12699
            // no data has been sent; upper application is supposed
12700
            // to retry on EAGAIN or EBUSY
12701
        }
12702
        if (!async_err) {
12703
            errno = saved_errno;
12704
            posix_error();
12705
        }
12706
        return NULL;
12707
    }
12708
    goto done;
12709
12710
done:
12711
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12712
        return PyLong_FromLong(sbytes);
12713
    #else
12714
        return PyLong_FromLongLong(sbytes);
12715
    #endif
12716
12717
#else
12718
0
#ifdef __linux__
12719
0
    if (offobj == Py_None) {
12720
0
        do {
12721
0
            Py_BEGIN_ALLOW_THREADS
12722
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12723
0
            Py_END_ALLOW_THREADS
12724
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12725
0
        if (ret < 0)
12726
0
            return (!async_err) ? posix_error() : NULL;
12727
0
        return PyLong_FromSsize_t(ret);
12728
0
    }
12729
0
#endif
12730
0
    off_t offset;
12731
0
    if (!_Py_Off_t_Converter(offobj, &offset))
12732
0
        return NULL;
12733
12734
#if defined(__sun) && defined(__SVR4)
12735
    // On Solaris, sendfile raises EINVAL rather than returning 0
12736
    // when the offset is equal or bigger than the in_fd size.
12737
    struct stat st;
12738
12739
    do {
12740
        Py_BEGIN_ALLOW_THREADS
12741
        ret = fstat(in_fd, &st);
12742
        Py_END_ALLOW_THREADS
12743
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12744
    if (ret < 0)
12745
        return (!async_err) ? posix_error() : NULL;
12746
12747
    if (offset >= st.st_size) {
12748
        return PyLong_FromLong(0);
12749
    }
12750
12751
    // sendfile() may perform a partial write and still return -1, so the
12752
    // number of transferred bytes must be taken from the out parameter.
12753
    // sendfile() reports it by adding it to the offset, but does not
12754
    // initialize it when the transfer fails before writing any data, so use
12755
    // sendfilev(), which reports it explicitly.
12756
    sendfilevec_t vec;
12757
    size_t xferred;
12758
12759
    vec.sfv_fd = in_fd;
12760
    vec.sfv_flag = 0;
12761
    vec.sfv_off = offset;
12762
    vec.sfv_len = count;
12763
12764
    do {
12765
        Py_BEGIN_ALLOW_THREADS
12766
        xferred = 0;
12767
        ret = sendfilev(out_fd, &vec, 1, &xferred);
12768
        if (ret < 0 && xferred != 0) {
12769
            ret = (Py_ssize_t)xferred;
12770
        }
12771
        Py_END_ALLOW_THREADS
12772
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12773
#else
12774
0
    do {
12775
0
        Py_BEGIN_ALLOW_THREADS
12776
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12777
0
        Py_END_ALLOW_THREADS
12778
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12779
0
#endif
12780
0
    if (ret < 0)
12781
0
        return (!async_err) ? posix_error() : NULL;
12782
0
    return PyLong_FromSsize_t(ret);
12783
0
#endif
12784
0
}
12785
#endif /* HAVE_SENDFILE */
12786
12787
12788
#if defined(__APPLE__)
12789
/*[clinic input]
12790
@permit_long_summary
12791
os._fcopyfile
12792
12793
    in_fd: int
12794
    out_fd: int
12795
    flags: int
12796
    /
12797
12798
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12799
[clinic start generated code]*/
12800
12801
static PyObject *
12802
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12803
/*[clinic end generated code: output=c9d1a35a992e401b input=80b53ad8863c9101]*/
12804
{
12805
    int ret;
12806
12807
    Py_BEGIN_ALLOW_THREADS
12808
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12809
    Py_END_ALLOW_THREADS
12810
    if (ret < 0)
12811
        return posix_error();
12812
    Py_RETURN_NONE;
12813
}
12814
#endif
12815
12816
12817
/*[clinic input]
12818
os.fstat
12819
12820
    fd : int
12821
12822
Perform a stat system call on the given file descriptor.
12823
12824
Like stat(), but for an open file descriptor.
12825
Equivalent to os.stat(fd).
12826
[clinic start generated code]*/
12827
12828
static PyObject *
12829
os_fstat_impl(PyObject *module, int fd)
12830
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12831
88.4k
{
12832
88.4k
    STRUCT_STAT st;
12833
88.4k
    int res;
12834
88.4k
    int async_err = 0;
12835
12836
88.4k
    do {
12837
88.4k
        Py_BEGIN_ALLOW_THREADS
12838
88.4k
        res = FSTAT(fd, &st);
12839
88.4k
        Py_END_ALLOW_THREADS
12840
88.4k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12841
88.4k
    if (res != 0) {
12842
#ifdef MS_WINDOWS
12843
        return PyErr_SetFromWindowsErr(0);
12844
#else
12845
0
        return (!async_err) ? posix_error() : NULL;
12846
0
#endif
12847
0
    }
12848
12849
88.4k
    return _pystat_fromstructstat(module, &st);
12850
88.4k
}
12851
12852
12853
/*[clinic input]
12854
os.isatty -> bool
12855
    fd: int
12856
    /
12857
12858
Return True if the fd is connected to a terminal.
12859
12860
Return True if the file descriptor is an open file descriptor
12861
connected to the slave end of a terminal.
12862
[clinic start generated code]*/
12863
12864
static int
12865
os_isatty_impl(PyObject *module, int fd)
12866
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12867
0
{
12868
0
    int return_value;
12869
0
    Py_BEGIN_ALLOW_THREADS
12870
0
    _Py_BEGIN_SUPPRESS_IPH
12871
0
    return_value = isatty(fd);
12872
0
    _Py_END_SUPPRESS_IPH
12873
0
    Py_END_ALLOW_THREADS
12874
0
    return return_value;
12875
0
}
12876
12877
12878
#ifdef HAVE_PIPE
12879
/*[clinic input]
12880
os.pipe
12881
12882
Create a pipe.
12883
12884
Returns a tuple of two file descriptors:
12885
  (read_fd, write_fd)
12886
[clinic start generated code]*/
12887
12888
static PyObject *
12889
os_pipe_impl(PyObject *module)
12890
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12891
0
{
12892
0
    int fds[2];
12893
#ifdef MS_WINDOWS
12894
    HANDLE read, write;
12895
    SECURITY_ATTRIBUTES attr;
12896
    BOOL ok;
12897
#else
12898
0
    int res = -1;
12899
12900
    /* pipe2() is available on some newer linux/glibc & macOS;
12901
     * use the same runtime detection as for dup3 above.
12902
     */
12903
0
    static int pipe2_works_atomic = -1;
12904
0
    (void) pipe2_works_atomic;  // unused on some platforms
12905
0
#endif
12906
12907
#ifdef MS_WINDOWS
12908
    attr.nLength = sizeof(attr);
12909
    attr.lpSecurityDescriptor = NULL;
12910
    attr.bInheritHandle = FALSE;
12911
12912
    Py_BEGIN_ALLOW_THREADS
12913
    ok = CreatePipe(&read, &write, &attr, 0);
12914
    if (ok) {
12915
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12916
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12917
        if (fds[0] == -1 || fds[1] == -1) {
12918
            CloseHandle(read);
12919
            CloseHandle(write);
12920
            ok = 0;
12921
        }
12922
    }
12923
    Py_END_ALLOW_THREADS
12924
12925
    if (!ok)
12926
        return PyErr_SetFromWindowsErr(0);
12927
#else
12928
12929
0
#ifdef HAVE_PIPE2
12930
0
    int pipe2_works = FT_ATOMIC_LOAD_INT_RELAXED(pipe2_works_atomic);
12931
0
    if (pipe2_works != 0) {
12932
0
        if (HAVE_PIPE2_RUNTIME) {
12933
0
            Py_BEGIN_ALLOW_THREADS
12934
0
            res = pipe2(fds, O_CLOEXEC);
12935
0
            Py_END_ALLOW_THREADS
12936
0
            if (pipe2_works == -1) {
12937
0
                if (res != 0 && errno == ENOSYS) {
12938
0
                    pipe2_works = 0;
12939
0
                }
12940
0
                else {
12941
                    // pipe2 is present but this call failed
12942
0
                    pipe2_works = 1;
12943
0
                }
12944
0
                FT_ATOMIC_STORE_INT_RELAXED(pipe2_works_atomic, pipe2_works);
12945
0
            }
12946
0
        }
12947
0
        else {
12948
0
            pipe2_works = 0;
12949
0
            FT_ATOMIC_STORE_INT_RELAXED(pipe2_works_atomic, pipe2_works);
12950
0
        }
12951
0
    }
12952
12953
0
    if (pipe2_works == 0)
12954
0
    {
12955
0
#endif
12956
0
        Py_BEGIN_ALLOW_THREADS
12957
0
        res = pipe(fds);
12958
0
        Py_END_ALLOW_THREADS
12959
12960
0
        if (res == 0) {
12961
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12962
0
                close(fds[0]);
12963
0
                close(fds[1]);
12964
0
                return NULL;
12965
0
            }
12966
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12967
0
                close(fds[0]);
12968
0
                close(fds[1]);
12969
0
                return NULL;
12970
0
            }
12971
0
        }
12972
0
#ifdef HAVE_PIPE2
12973
0
    }
12974
0
#endif
12975
12976
0
    if (res != 0) {
12977
0
        return PyErr_SetFromErrno(PyExc_OSError);
12978
0
    }
12979
0
#endif /* !MS_WINDOWS */
12980
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12981
0
}
12982
#endif  /* HAVE_PIPE */
12983
12984
12985
#ifdef HAVE_PIPE2
12986
/*[clinic input]
12987
os.pipe2
12988
12989
    flags: int
12990
    /
12991
12992
Create a pipe with flags set atomically.
12993
12994
Returns a tuple of two file descriptors:
12995
  (read_fd, write_fd)
12996
12997
flags can be constructed by ORing together one or more of these values:
12998
O_NONBLOCK, O_CLOEXEC.
12999
[clinic start generated code]*/
13000
13001
static PyObject *
13002
os_pipe2_impl(PyObject *module, int flags)
13003
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
13004
0
{
13005
0
    int fds[2];
13006
0
    int res;
13007
13008
0
    if (HAVE_PIPE2_RUNTIME) {
13009
0
        res = pipe2(fds, flags);
13010
0
    }
13011
0
    else {
13012
0
        res = -1;
13013
0
        errno = ENOSYS;
13014
0
    }
13015
0
    if (res != 0) {
13016
0
        return posix_error();
13017
0
    }
13018
13019
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
13020
0
}
13021
#endif /* HAVE_PIPE2 */
13022
13023
13024
#ifdef HAVE_WRITEV
13025
/*[clinic input]
13026
@permit_long_summary
13027
os.writev -> Py_ssize_t
13028
    fd: int
13029
    buffers: object
13030
    /
13031
13032
Iterate over buffers, and write the contents of each to a file descriptor.
13033
13034
Returns the total number of bytes written.
13035
buffers must be a sequence of bytes-like objects.
13036
[clinic start generated code]*/
13037
13038
static Py_ssize_t
13039
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
13040
/*[clinic end generated code: output=56565cfac3aac15b input=5771a0f0c2b326f2]*/
13041
0
{
13042
0
    Py_ssize_t cnt;
13043
0
    Py_ssize_t result;
13044
0
    int async_err = 0;
13045
0
    struct iovec *iov;
13046
0
    Py_buffer *buf;
13047
13048
0
    if (!PySequence_Check(buffers)) {
13049
0
        PyErr_SetString(PyExc_TypeError,
13050
0
            "writev() arg 2 must be a sequence");
13051
0
        return -1;
13052
0
    }
13053
0
    cnt = PySequence_Size(buffers);
13054
0
    if (cnt < 0)
13055
0
        return -1;
13056
13057
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
13058
0
        return -1;
13059
0
    }
13060
13061
0
    do {
13062
0
        Py_BEGIN_ALLOW_THREADS
13063
0
        result = writev(fd, iov, cnt);
13064
0
        Py_END_ALLOW_THREADS
13065
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13066
13067
0
    if (result < 0 && !async_err)
13068
0
        posix_error();
13069
13070
0
    iov_cleanup(iov, buf, cnt);
13071
0
    return result;
13072
0
}
13073
#endif /* HAVE_WRITEV */
13074
13075
13076
#ifdef HAVE_PWRITE
13077
/*[clinic input]
13078
os.pwrite -> Py_ssize_t
13079
13080
    fd: int
13081
    buffer: Py_buffer
13082
    offset: Py_off_t
13083
    /
13084
13085
Write bytes to a file descriptor starting at a particular offset.
13086
13087
Write buffer to fd, starting at offset bytes from the beginning of
13088
the file.  Returns the number of bytes written.  Does not change the
13089
current file offset.
13090
[clinic start generated code]*/
13091
13092
static Py_ssize_t
13093
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
13094
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
13095
0
{
13096
0
    Py_ssize_t size;
13097
0
    int async_err = 0;
13098
13099
0
    do {
13100
0
        Py_BEGIN_ALLOW_THREADS
13101
0
        _Py_BEGIN_SUPPRESS_IPH
13102
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
13103
0
        _Py_END_SUPPRESS_IPH
13104
0
        Py_END_ALLOW_THREADS
13105
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13106
13107
0
    if (size < 0 && !async_err)
13108
0
        posix_error();
13109
0
    return size;
13110
0
}
13111
#endif /* HAVE_PWRITE */
13112
13113
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
13114
/*[clinic input]
13115
@permit_long_summary
13116
os.pwritev -> Py_ssize_t
13117
13118
    fd: int
13119
    buffers: object
13120
    offset: Py_off_t
13121
    flags: int = 0
13122
    /
13123
13124
Writes the contents of bytes-like objects to a file descriptor at a given offset.
13125
13126
Combines the functionality of writev() and pwrite(). All buffers must be
13127
a sequence of bytes-like objects.  Buffers are processed in array order.
13128
Entire contents of first buffer is written before proceeding to second,
13129
and so on. The operating system may set a limit (sysconf() value
13130
SC_IOV_MAX) on the number of buffers that can be used.
13131
This function writes the contents of each object to the file descriptor
13132
and returns the total number of bytes written.
13133
13134
The flags argument contains a bitwise OR of zero or more of the
13135
following flags:
13136
13137
- RWF_DSYNC
13138
- RWF_SYNC
13139
- RWF_APPEND
13140
- RWF_DONTCACHE
13141
- RWF_ATOMIC
13142
- RWF_NOSIGNAL
13143
13144
Using non-zero flags requires Linux 4.7 or newer.
13145
[clinic start generated code]*/
13146
13147
static Py_ssize_t
13148
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
13149
                int flags)
13150
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=c202f24f01fa66c9]*/
13151
0
{
13152
0
    Py_ssize_t cnt;
13153
0
    Py_ssize_t result;
13154
0
    int async_err = 0;
13155
0
    struct iovec *iov;
13156
0
    Py_buffer *buf;
13157
13158
0
    if (!PySequence_Check(buffers)) {
13159
0
        PyErr_SetString(PyExc_TypeError,
13160
0
            "pwritev() arg 2 must be a sequence");
13161
0
        return -1;
13162
0
    }
13163
13164
0
    cnt = PySequence_Size(buffers);
13165
0
    if (cnt < 0) {
13166
0
        return -1;
13167
0
    }
13168
13169
#ifndef HAVE_PWRITEV2
13170
    if(flags != 0) {
13171
        argument_unavailable_error("pwritev2", "flags");
13172
        return -1;
13173
    }
13174
#endif
13175
13176
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
13177
0
        return -1;
13178
0
    }
13179
0
#ifdef HAVE_PWRITEV2
13180
0
    do {
13181
0
        Py_BEGIN_ALLOW_THREADS
13182
0
        _Py_BEGIN_SUPPRESS_IPH
13183
0
        result = pwritev2(fd, iov, cnt, offset, flags);
13184
0
        _Py_END_SUPPRESS_IPH
13185
0
        Py_END_ALLOW_THREADS
13186
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13187
#else
13188
13189
#if defined(__APPLE__) && defined(__clang__)
13190
/* This entire function will be removed from the module dict when the API
13191
 * is not available.
13192
 */
13193
#pragma clang diagnostic push
13194
#pragma clang diagnostic ignored "-Wunguarded-availability"
13195
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
13196
#endif
13197
    do {
13198
        Py_BEGIN_ALLOW_THREADS
13199
        _Py_BEGIN_SUPPRESS_IPH
13200
        result = pwritev(fd, iov, cnt, offset);
13201
        _Py_END_SUPPRESS_IPH
13202
        Py_END_ALLOW_THREADS
13203
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13204
13205
#if defined(__APPLE__) && defined(__clang__)
13206
#pragma clang diagnostic pop
13207
#endif
13208
13209
#endif
13210
13211
0
    if (result < 0) {
13212
0
        if (!async_err) {
13213
0
            posix_error();
13214
0
        }
13215
0
        result = -1;
13216
0
    }
13217
0
    iov_cleanup(iov, buf, cnt);
13218
13219
0
    return result;
13220
0
}
13221
#endif /* HAVE_PWRITEV */
13222
13223
#if defined(HAVE_COPY_FILE_RANGE) || \
13224
    (defined(__linux__) && defined(__NR_copy_file_range))
13225
#  define _Py_HAVE_COPY_FILE_RANGE
13226
#endif
13227
13228
#ifdef _Py_HAVE_COPY_FILE_RANGE
13229
/*[clinic input]
13230
13231
os.copy_file_range
13232
    src: int
13233
        Source file descriptor.
13234
    dst: int
13235
        Destination file descriptor.
13236
    count: Py_ssize_t(allow_negative=False)
13237
        Number of bytes to copy.
13238
    offset_src: object = None
13239
        Starting offset in src.
13240
    offset_dst: object = None
13241
        Starting offset in dst.
13242
13243
Copy count bytes from one file descriptor to another.
13244
13245
If offset_src is None, then src is read from the current position;
13246
respectively for offset_dst.
13247
[clinic start generated code]*/
13248
13249
static PyObject *
13250
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13251
                        PyObject *offset_src, PyObject *offset_dst)
13252
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
13253
0
{
13254
0
    off_t offset_src_val, offset_dst_val;
13255
0
    off_t *p_offset_src = NULL;
13256
0
    off_t *p_offset_dst = NULL;
13257
0
    Py_ssize_t ret;
13258
0
    int async_err = 0;
13259
    /* The flags argument is provided to allow
13260
     * for future extensions and currently must be to 0. */
13261
0
    int flags = 0;
13262
13263
13264
0
    if (offset_src != Py_None) {
13265
0
        if (!_Py_Off_t_Converter(offset_src, &offset_src_val)) {
13266
0
            return NULL;
13267
0
        }
13268
0
        p_offset_src = &offset_src_val;
13269
0
    }
13270
13271
0
    if (offset_dst != Py_None) {
13272
0
        if (!_Py_Off_t_Converter(offset_dst, &offset_dst_val)) {
13273
0
            return NULL;
13274
0
        }
13275
0
        p_offset_dst = &offset_dst_val;
13276
0
    }
13277
13278
0
    do {
13279
0
        Py_BEGIN_ALLOW_THREADS
13280
0
#ifdef HAVE_COPY_FILE_RANGE
13281
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13282
#else
13283
        /* Largefile support makes off_t 64-bit, as the kernel expects. */
13284
        ret = syscall(__NR_copy_file_range, src, p_offset_src, dst, p_offset_dst,
13285
                      count, flags);
13286
#endif
13287
0
        Py_END_ALLOW_THREADS
13288
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13289
13290
0
    if (ret < 0) {
13291
0
        return (!async_err) ? posix_error() : NULL;
13292
0
    }
13293
13294
0
    return PyLong_FromSsize_t(ret);
13295
0
}
13296
#endif /* _Py_HAVE_COPY_FILE_RANGE */
13297
13298
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13299
/*[clinic input]
13300
13301
os.splice
13302
    src: int
13303
        Source file descriptor.
13304
    dst: int
13305
        Destination file descriptor.
13306
    count: Py_ssize_t(allow_negative=False)
13307
        Number of bytes to copy.
13308
    offset_src: object = None
13309
        Starting offset in src.
13310
    offset_dst: object = None
13311
        Starting offset in dst.
13312
    flags: unsigned_int = 0
13313
        Flags to modify the semantics of the call.
13314
13315
Transfer count bytes from one pipe to a descriptor or vice versa.
13316
13317
If offset_src is None, then src is read from the current position;
13318
respectively for offset_dst. The offset associated to the file
13319
descriptor that refers to a pipe must be None.
13320
[clinic start generated code]*/
13321
13322
static PyObject *
13323
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13324
               PyObject *offset_src, PyObject *offset_dst,
13325
               unsigned int flags)
13326
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13327
0
{
13328
0
    off_t offset_src_val, offset_dst_val;
13329
0
    off_t *p_offset_src = NULL;
13330
0
    off_t *p_offset_dst = NULL;
13331
0
    Py_ssize_t ret;
13332
0
    int async_err = 0;
13333
13334
13335
0
    if (offset_src != Py_None) {
13336
0
        if (!_Py_Off_t_Converter(offset_src, &offset_src_val)) {
13337
0
            return NULL;
13338
0
        }
13339
0
        p_offset_src = &offset_src_val;
13340
0
    }
13341
13342
0
    if (offset_dst != Py_None) {
13343
0
        if (!_Py_Off_t_Converter(offset_dst, &offset_dst_val)) {
13344
0
            return NULL;
13345
0
        }
13346
0
        p_offset_dst = &offset_dst_val;
13347
0
    }
13348
13349
0
    do {
13350
0
        Py_BEGIN_ALLOW_THREADS
13351
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13352
0
        Py_END_ALLOW_THREADS
13353
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13354
13355
0
    if (ret < 0) {
13356
0
        return (!async_err) ? posix_error() : NULL;
13357
0
    }
13358
13359
0
    return PyLong_FromSsize_t(ret);
13360
0
}
13361
#endif /* HAVE_SPLICE*/
13362
13363
#ifdef HAVE_MKFIFO
13364
/*[clinic input]
13365
os.mkfifo
13366
13367
    path: path_t
13368
    mode: int=0o666
13369
    *
13370
    dir_fd: dir_fd(requires='mkfifoat')=None
13371
13372
Create a "fifo" (a POSIX named pipe).
13373
13374
If dir_fd is not None, it should be a file descriptor open to
13375
a directory, and path should be relative; path will then be relative to
13376
that directory.
13377
dir_fd may not be implemented on your platform.  If it is unavailable,
13378
using it will raise a NotImplementedError.
13379
[clinic start generated code]*/
13380
13381
static PyObject *
13382
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13383
/*[clinic end generated code: output=ce41cfad0e68c940 input=d2fb917c01e888d6]*/
13384
0
{
13385
0
    int result;
13386
0
    int async_err = 0;
13387
0
#ifdef HAVE_MKFIFOAT
13388
0
    int mkfifoat_unavailable = 0;
13389
0
#endif
13390
13391
0
    do {
13392
0
        Py_BEGIN_ALLOW_THREADS
13393
0
#ifdef HAVE_MKFIFOAT
13394
0
        if (dir_fd != DEFAULT_DIR_FD) {
13395
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13396
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13397
13398
0
            } else {
13399
0
                mkfifoat_unavailable = 1;
13400
0
                result = 0;
13401
0
            }
13402
0
        } else
13403
0
#endif
13404
0
            result = mkfifo(path->narrow, mode);
13405
0
        Py_END_ALLOW_THREADS
13406
0
    } while (result != 0 && errno == EINTR &&
13407
0
             !(async_err = PyErr_CheckSignals()));
13408
13409
0
#ifdef HAVE_MKFIFOAT
13410
0
    if (mkfifoat_unavailable) {
13411
0
        argument_unavailable_error(NULL, "dir_fd");
13412
0
        return NULL;
13413
0
    }
13414
0
#endif
13415
13416
0
    if (result != 0)
13417
0
        return (!async_err) ? posix_error() : NULL;
13418
13419
0
    Py_RETURN_NONE;
13420
0
}
13421
#endif /* HAVE_MKFIFO */
13422
13423
13424
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13425
/*[clinic input]
13426
os.mknod
13427
13428
    path: path_t
13429
    mode: int=0o600
13430
    device: dev_t=0
13431
    *
13432
    dir_fd: dir_fd(requires='mknodat')=None
13433
13434
Create a node in the file system.
13435
13436
Create a node in the file system (file, device special file or named
13437
pipe) at path.  mode specifies both the permissions to use and the
13438
type of node to be created, being combined (bitwise OR) with one of
13439
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set
13440
on mode, device defines the newly created device special file (probably
13441
using os.makedev()).  Otherwise device is ignored.
13442
13443
If dir_fd is not None, it should be a file descriptor open to
13444
a directory, and path should be relative; path will then be relative
13445
to that directory.
13446
dir_fd may not be implemented on your platform.  If it is unavailable,
13447
using it will raise a NotImplementedError.
13448
[clinic start generated code]*/
13449
13450
static PyObject *
13451
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13452
              int dir_fd)
13453
/*[clinic end generated code: output=92e55d3ca8917461 input=7d0099e85c6b4cba]*/
13454
0
{
13455
0
    int result;
13456
0
    int async_err = 0;
13457
0
#ifdef HAVE_MKNODAT
13458
0
    int mknodat_unavailable = 0;
13459
0
#endif
13460
13461
0
    do {
13462
0
        Py_BEGIN_ALLOW_THREADS
13463
0
#ifdef HAVE_MKNODAT
13464
0
        if (dir_fd != DEFAULT_DIR_FD) {
13465
0
            if (HAVE_MKNODAT_RUNTIME) {
13466
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13467
13468
0
            } else {
13469
0
                mknodat_unavailable = 1;
13470
0
                result = 0;
13471
0
            }
13472
0
        } else
13473
0
#endif
13474
0
            result = mknod(path->narrow, mode, device);
13475
0
        Py_END_ALLOW_THREADS
13476
0
    } while (result != 0 && errno == EINTR &&
13477
0
             !(async_err = PyErr_CheckSignals()));
13478
0
#ifdef HAVE_MKNODAT
13479
0
    if (mknodat_unavailable) {
13480
0
        argument_unavailable_error(NULL, "dir_fd");
13481
0
        return NULL;
13482
0
    }
13483
0
#endif
13484
0
    if (result != 0)
13485
0
        return (!async_err) ? posix_error() : NULL;
13486
13487
0
    Py_RETURN_NONE;
13488
0
}
13489
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13490
13491
13492
#ifdef HAVE_DEVICE_MACROS
13493
static PyObject *
13494
major_minor_conv(unsigned int value)
13495
0
{
13496
0
#ifdef NODEV
13497
0
    if (value == (unsigned int)NODEV) {
13498
0
        return PyLong_FromLong((int)NODEV);
13499
0
    }
13500
0
#endif
13501
0
    return PyLong_FromUnsignedLong(value);
13502
0
}
13503
13504
static int
13505
major_minor_check(dev_t value)
13506
0
{
13507
0
#ifdef NODEV
13508
0
    if (value == NODEV) {
13509
0
        return 1;
13510
0
    }
13511
0
#endif
13512
0
    return (dev_t)(unsigned int)value == value;
13513
0
}
13514
13515
/*[clinic input]
13516
os.major
13517
13518
    device: dev_t
13519
    /
13520
13521
Extracts a device major number from a raw device number.
13522
[clinic start generated code]*/
13523
13524
static PyObject *
13525
os_major_impl(PyObject *module, dev_t device)
13526
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13527
0
{
13528
0
    return major_minor_conv(major(device));
13529
0
}
13530
13531
13532
/*[clinic input]
13533
os.minor
13534
13535
    device: dev_t
13536
    /
13537
13538
Extracts a device minor number from a raw device number.
13539
[clinic start generated code]*/
13540
13541
static PyObject *
13542
os_minor_impl(PyObject *module, dev_t device)
13543
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13544
0
{
13545
0
    return major_minor_conv(minor(device));
13546
0
}
13547
13548
13549
/*[clinic input]
13550
os.makedev -> dev_t
13551
13552
    major: dev_t
13553
    minor: dev_t
13554
    /
13555
13556
Composes a raw device number from the major and minor device numbers.
13557
[clinic start generated code]*/
13558
13559
static dev_t
13560
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13561
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13562
0
{
13563
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13564
0
        PyErr_SetString(PyExc_OverflowError,
13565
0
                        "Python int too large to convert to C unsigned int");
13566
0
        return (dev_t)-1;
13567
0
    }
13568
0
    return makedev(major, minor);
13569
0
}
13570
#endif /* HAVE_DEVICE_MACROS */
13571
13572
13573
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13574
/*[clinic input]
13575
os.ftruncate
13576
13577
    fd: int
13578
    length: Py_off_t
13579
    /
13580
13581
Truncate a file, specified by file descriptor, to a specific length.
13582
[clinic start generated code]*/
13583
13584
static PyObject *
13585
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13586
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13587
0
{
13588
0
    int result;
13589
0
    int async_err = 0;
13590
13591
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13592
0
        return NULL;
13593
0
    }
13594
13595
0
    do {
13596
0
        Py_BEGIN_ALLOW_THREADS
13597
0
        _Py_BEGIN_SUPPRESS_IPH
13598
#ifdef MS_WINDOWS
13599
        result = _chsize_s(fd, length);
13600
#else
13601
0
        result = ftruncate(fd, length);
13602
0
#endif
13603
0
        _Py_END_SUPPRESS_IPH
13604
0
        Py_END_ALLOW_THREADS
13605
0
    } while (result != 0 && errno == EINTR &&
13606
0
             !(async_err = PyErr_CheckSignals()));
13607
0
    if (result != 0)
13608
0
        return (!async_err) ? posix_error() : NULL;
13609
0
    Py_RETURN_NONE;
13610
0
}
13611
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13612
13613
13614
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13615
/*[clinic input]
13616
os.truncate
13617
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13618
    length: Py_off_t
13619
13620
Truncate a file, specified by path, to a specific length.
13621
13622
On some platforms, path may also be specified as an open file
13623
descriptor.  If this functionality is unavailable, using it raises
13624
an exception.
13625
[clinic start generated code]*/
13626
13627
static PyObject *
13628
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13629
/*[clinic end generated code: output=43009c8df5c0a12b input=ce33fd7808a511c4]*/
13630
0
{
13631
0
    int result;
13632
#ifdef MS_WINDOWS
13633
    int fd;
13634
#endif
13635
13636
0
    if (path->is_fd)
13637
0
        return os_ftruncate_impl(module, path->fd, length);
13638
13639
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13640
0
        return NULL;
13641
0
    }
13642
13643
0
    Py_BEGIN_ALLOW_THREADS
13644
0
    _Py_BEGIN_SUPPRESS_IPH
13645
#ifdef MS_WINDOWS
13646
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13647
    if (fd < 0)
13648
        result = -1;
13649
    else {
13650
        result = _chsize_s(fd, length);
13651
        close(fd);
13652
        if (result < 0)
13653
            errno = result;
13654
    }
13655
#else
13656
0
    result = truncate(path->narrow, length);
13657
0
#endif
13658
0
    _Py_END_SUPPRESS_IPH
13659
0
    Py_END_ALLOW_THREADS
13660
0
    if (result < 0)
13661
0
        return posix_path_error(path);
13662
13663
0
    Py_RETURN_NONE;
13664
0
}
13665
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13666
13667
13668
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13669
   OSs, support was dropped in WASI preview2. */
13670
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13671
/*[clinic input]
13672
@permit_long_summary
13673
os.posix_fallocate
13674
13675
    fd: int
13676
    offset: Py_off_t
13677
    length: Py_off_t
13678
    /
13679
13680
Ensure a file has allocated at least a particular number of bytes on disk.
13681
13682
Ensure that the file specified by fd encompasses a range of bytes
13683
starting at offset bytes from the beginning and continuing for length
13684
bytes.
13685
[clinic start generated code]*/
13686
13687
static PyObject *
13688
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13689
                        Py_off_t length)
13690
/*[clinic end generated code: output=73f107139564aa9d input=c718971d18b96896]*/
13691
0
{
13692
0
    int result;
13693
0
    int async_err = 0;
13694
13695
0
    do {
13696
0
        Py_BEGIN_ALLOW_THREADS
13697
0
        result = posix_fallocate(fd, offset, length);
13698
0
        Py_END_ALLOW_THREADS
13699
        // DragonFly BSD returns -1 and sets errno.
13700
0
        if (result == -1) {
13701
0
            result = errno;
13702
0
        }
13703
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13704
13705
0
    if (result == 0)
13706
0
        Py_RETURN_NONE;
13707
13708
0
    if (async_err)
13709
0
        return NULL;
13710
13711
0
    errno = result;
13712
0
    return posix_error();
13713
0
}
13714
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13715
13716
13717
#if defined(HAVE_POSIX_FADVISE)
13718
/*[clinic input]
13719
os.posix_fadvise
13720
13721
    fd: int
13722
    offset: Py_off_t
13723
    length: Py_off_t
13724
    advice: int
13725
    /
13726
13727
Announce an intention to access data in a specific pattern.
13728
13729
Announce an intention to access data in a specific pattern, thus
13730
allowing the kernel to make optimizations.
13731
The advice applies to the region of the file specified by fd starting at
13732
offset and continuing for length bytes.
13733
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13734
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13735
POSIX_FADV_DONTNEED.
13736
[clinic start generated code]*/
13737
13738
static PyObject *
13739
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13740
                      Py_off_t length, int advice)
13741
/*[clinic end generated code: output=412ef4aa70c98642 input=961b01a4518ef727]*/
13742
0
{
13743
0
    int result;
13744
0
    int async_err = 0;
13745
13746
0
    do {
13747
0
        Py_BEGIN_ALLOW_THREADS
13748
0
        result = posix_fadvise(fd, offset, length, advice);
13749
0
        Py_END_ALLOW_THREADS
13750
        // DragonFly BSD returns -1 and sets errno.
13751
0
        if (result == -1) {
13752
0
            result = errno;
13753
0
        }
13754
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13755
13756
0
    if (result == 0)
13757
0
        Py_RETURN_NONE;
13758
13759
0
    if (async_err)
13760
0
        return NULL;
13761
13762
0
    errno = result;
13763
0
    return posix_error();
13764
0
}
13765
#endif /* HAVE_POSIX_FADVISE */
13766
13767
13768
#ifdef MS_WINDOWS
13769
static PyObject*
13770
win32_putenv(PyObject *name, PyObject *value)
13771
{
13772
    /* Search from index 1 because on Windows starting '=' is allowed for
13773
       defining hidden environment variables. */
13774
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13775
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13776
    {
13777
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13778
        return NULL;
13779
    }
13780
    PyObject *unicode;
13781
    if (value != NULL) {
13782
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13783
    }
13784
    else {
13785
        unicode = PyUnicode_FromFormat("%U=", name);
13786
    }
13787
    if (unicode == NULL) {
13788
        return NULL;
13789
    }
13790
13791
    Py_ssize_t size;
13792
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13793
    Py_DECREF(unicode);
13794
13795
    if (env == NULL) {
13796
        return NULL;
13797
    }
13798
    if (size > _MAX_ENV) {
13799
        PyErr_Format(PyExc_ValueError,
13800
                     "the environment variable is longer than %u characters",
13801
                     _MAX_ENV);
13802
        PyMem_Free(env);
13803
        return NULL;
13804
    }
13805
    if (wcslen(env) != (size_t)size) {
13806
        PyErr_SetString(PyExc_ValueError,
13807
                        "embedded null character");
13808
        PyMem_Free(env);
13809
        return NULL;
13810
    }
13811
13812
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13813
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13814
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13815
13816
       Prefer _wputenv() to be compatible with C libraries using CRT
13817
       variables and CRT functions using these variables (ex: getenv()). */
13818
    int err = _wputenv(env);
13819
13820
    if (err) {
13821
        posix_error();
13822
        PyMem_Free(env);
13823
        return NULL;
13824
    }
13825
    PyMem_Free(env);
13826
13827
    Py_RETURN_NONE;
13828
}
13829
#endif
13830
13831
13832
#ifdef MS_WINDOWS
13833
/*[clinic input]
13834
os.putenv
13835
13836
    name: unicode
13837
    value: unicode
13838
    /
13839
13840
Change or add an environment variable.
13841
[clinic start generated code]*/
13842
13843
static PyObject *
13844
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13845
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13846
{
13847
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13848
        return NULL;
13849
    }
13850
    return win32_putenv(name, value);
13851
}
13852
#else
13853
/*[clinic input]
13854
os.putenv
13855
13856
    name: unicode_fs_encoded
13857
    value: unicode_fs_encoded
13858
    /
13859
13860
Change or add an environment variable.
13861
[clinic start generated code]*/
13862
13863
static PyObject *
13864
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13865
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13866
0
{
13867
0
    const char *name_string = PyBytes_AS_STRING(name);
13868
0
    const char *value_string = PyBytes_AS_STRING(value);
13869
13870
0
    if (strchr(name_string, '=') != NULL) {
13871
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13872
0
        return NULL;
13873
0
    }
13874
13875
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13876
0
        return NULL;
13877
0
    }
13878
13879
0
    if (setenv(name_string, value_string, 1)) {
13880
0
        return posix_error();
13881
0
    }
13882
0
    Py_RETURN_NONE;
13883
0
}
13884
#endif  /* !defined(MS_WINDOWS) */
13885
13886
13887
#ifdef MS_WINDOWS
13888
/*[clinic input]
13889
os.unsetenv
13890
    name: unicode
13891
    /
13892
13893
Delete an environment variable.
13894
[clinic start generated code]*/
13895
13896
static PyObject *
13897
os_unsetenv_impl(PyObject *module, PyObject *name)
13898
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13899
{
13900
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13901
        return NULL;
13902
    }
13903
    return win32_putenv(name, NULL);
13904
}
13905
#else
13906
/*[clinic input]
13907
os.unsetenv
13908
    name: unicode_fs_encoded
13909
    /
13910
13911
Delete an environment variable.
13912
[clinic start generated code]*/
13913
13914
static PyObject *
13915
os_unsetenv_impl(PyObject *module, PyObject *name)
13916
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13917
0
{
13918
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13919
0
        return NULL;
13920
0
    }
13921
#ifdef HAVE_BROKEN_UNSETENV
13922
    unsetenv(PyBytes_AS_STRING(name));
13923
#else
13924
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13925
0
    if (err) {
13926
0
        return posix_error();
13927
0
    }
13928
0
#endif
13929
13930
0
    Py_RETURN_NONE;
13931
0
}
13932
#endif /* !MS_WINDOWS */
13933
13934
13935
#ifdef HAVE_CLEARENV
13936
/*[clinic input]
13937
os._clearenv
13938
[clinic start generated code]*/
13939
13940
static PyObject *
13941
os__clearenv_impl(PyObject *module)
13942
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13943
0
{
13944
0
    if (PySys_Audit("os._clearenv", NULL) < 0) {
13945
0
        return NULL;
13946
0
    }
13947
13948
0
    errno = 0;
13949
0
    int err = clearenv();
13950
0
    if (err) {
13951
0
        return posix_error();
13952
0
    }
13953
0
    Py_RETURN_NONE;
13954
0
}
13955
#endif
13956
13957
13958
/*[clinic input]
13959
os.strerror
13960
13961
    code: int
13962
    /
13963
13964
Translate an error code to a message string.
13965
[clinic start generated code]*/
13966
13967
static PyObject *
13968
os_strerror_impl(PyObject *module, int code)
13969
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13970
0
{
13971
0
    return _Py_strerror(code);
13972
0
}
13973
13974
13975
#ifdef HAVE_SYS_WAIT_H
13976
#ifdef WCOREDUMP
13977
/*[clinic input]
13978
os.WCOREDUMP -> bool
13979
13980
    status: int
13981
    /
13982
13983
Return True if the process returning status was dumped to a core file.
13984
[clinic start generated code]*/
13985
13986
static int
13987
os_WCOREDUMP_impl(PyObject *module, int status)
13988
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13989
0
{
13990
0
    WAIT_TYPE wait_status;
13991
0
    WAIT_STATUS_INT(wait_status) = status;
13992
0
    return WCOREDUMP(wait_status);
13993
0
}
13994
#endif /* WCOREDUMP */
13995
13996
13997
#ifdef WIFCONTINUED
13998
/*[clinic input]
13999
@permit_long_summary
14000
os.WIFCONTINUED -> bool
14001
14002
    status: int
14003
14004
Return True if a particular process was continued from a job control stop.
14005
14006
Return True if the process returning status was continued from a
14007
job control stop.
14008
[clinic start generated code]*/
14009
14010
static int
14011
os_WIFCONTINUED_impl(PyObject *module, int status)
14012
/*[clinic end generated code: output=1e35295d844364bd input=7b577845a0f8b12f]*/
14013
0
{
14014
0
    WAIT_TYPE wait_status;
14015
0
    WAIT_STATUS_INT(wait_status) = status;
14016
0
    return WIFCONTINUED(wait_status);
14017
0
}
14018
#endif /* WIFCONTINUED */
14019
14020
14021
#ifdef WIFSTOPPED
14022
/*[clinic input]
14023
os.WIFSTOPPED -> bool
14024
14025
    status: int
14026
14027
Return True if the process returning status was stopped.
14028
[clinic start generated code]*/
14029
14030
static int
14031
os_WIFSTOPPED_impl(PyObject *module, int status)
14032
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
14033
0
{
14034
0
    WAIT_TYPE wait_status;
14035
0
    WAIT_STATUS_INT(wait_status) = status;
14036
0
    return WIFSTOPPED(wait_status);
14037
0
}
14038
#endif /* WIFSTOPPED */
14039
14040
14041
#ifdef WIFSIGNALED
14042
/*[clinic input]
14043
os.WIFSIGNALED -> bool
14044
14045
    status: int
14046
14047
Return True if the process returning status was terminated by a signal.
14048
[clinic start generated code]*/
14049
14050
static int
14051
os_WIFSIGNALED_impl(PyObject *module, int status)
14052
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
14053
0
{
14054
0
    WAIT_TYPE wait_status;
14055
0
    WAIT_STATUS_INT(wait_status) = status;
14056
0
    return WIFSIGNALED(wait_status);
14057
0
}
14058
#endif /* WIFSIGNALED */
14059
14060
14061
#ifdef WIFEXITED
14062
/*[clinic input]
14063
@permit_long_summary
14064
os.WIFEXITED -> bool
14065
14066
    status: int
14067
14068
Return True if the process returning status exited via the exit() system call.
14069
[clinic start generated code]*/
14070
14071
static int
14072
os_WIFEXITED_impl(PyObject *module, int status)
14073
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
14074
0
{
14075
0
    WAIT_TYPE wait_status;
14076
0
    WAIT_STATUS_INT(wait_status) = status;
14077
0
    return WIFEXITED(wait_status);
14078
0
}
14079
#endif /* WIFEXITED */
14080
14081
14082
#ifdef WEXITSTATUS
14083
/*[clinic input]
14084
os.WEXITSTATUS -> int
14085
14086
    status: int
14087
14088
Return the process return code from status.
14089
[clinic start generated code]*/
14090
14091
static int
14092
os_WEXITSTATUS_impl(PyObject *module, int status)
14093
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
14094
0
{
14095
0
    WAIT_TYPE wait_status;
14096
0
    WAIT_STATUS_INT(wait_status) = status;
14097
0
    return WEXITSTATUS(wait_status);
14098
0
}
14099
#endif /* WEXITSTATUS */
14100
14101
14102
#ifdef WTERMSIG
14103
/*[clinic input]
14104
@permit_long_summary
14105
os.WTERMSIG -> int
14106
14107
    status: int
14108
14109
Return the signal that terminated the process that provided the status value.
14110
[clinic start generated code]*/
14111
14112
static int
14113
os_WTERMSIG_impl(PyObject *module, int status)
14114
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
14115
0
{
14116
0
    WAIT_TYPE wait_status;
14117
0
    WAIT_STATUS_INT(wait_status) = status;
14118
0
    return WTERMSIG(wait_status);
14119
0
}
14120
#endif /* WTERMSIG */
14121
14122
14123
#ifdef WSTOPSIG
14124
/*[clinic input]
14125
@permit_long_summary
14126
os.WSTOPSIG -> int
14127
14128
    status: int
14129
14130
Return the signal that stopped the process that provided the status value.
14131
[clinic start generated code]*/
14132
14133
static int
14134
os_WSTOPSIG_impl(PyObject *module, int status)
14135
/*[clinic end generated code: output=0ab7586396f5d82b input=4698db1a6a320433]*/
14136
0
{
14137
0
    WAIT_TYPE wait_status;
14138
0
    WAIT_STATUS_INT(wait_status) = status;
14139
0
    return WSTOPSIG(wait_status);
14140
0
}
14141
#endif /* WSTOPSIG */
14142
#endif /* HAVE_SYS_WAIT_H */
14143
14144
14145
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
14146
#ifdef _SCO_DS
14147
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
14148
   needed definitions in sys/statvfs.h */
14149
#define _SVID3
14150
#endif
14151
#include <sys/statvfs.h>
14152
14153
#ifdef __APPLE__
14154
/* On macOS struct statvfs uses 32-bit integers for block counts,
14155
 * resulting in overflow when filesystems are larger than 4TB. Therefore
14156
 * os.statvfs is implemented in terms of statfs(2).
14157
 */
14158
14159
static PyObject*
14160
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
14161
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
14162
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
14163
    if (v == NULL) {
14164
        return NULL;
14165
    }
14166
14167
    long flags = 0;
14168
    if (st.f_flags & MNT_RDONLY) {
14169
        flags |= ST_RDONLY;
14170
    }
14171
    if (st.f_flags & MNT_NOSUID) {
14172
        flags |= ST_NOSUID;
14173
    }
14174
14175
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
14176
14177
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
14178
    do {                                                 \
14179
        PyObject *obj = (EXPR);                          \
14180
        if (obj == NULL) {                               \
14181
            Py_DECREF((SEQ));                            \
14182
            return NULL;                                 \
14183
        }                                                \
14184
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
14185
    } while (0)
14186
14187
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
14188
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
14189
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
14190
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
14191
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
14192
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
14193
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
14194
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
14195
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
14196
14197
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
14198
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
14199
14200
#undef SET_ITEM
14201
14202
    return v;
14203
}
14204
14205
#else
14206
14207
14208
14209
static PyObject*
14210
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
14211
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
14212
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
14213
0
    if (v == NULL)
14214
0
        return NULL;
14215
14216
0
    int pos = 0;
14217
14218
0
#define SET_RESULT(CALL)                                     \
14219
0
    do {                                                     \
14220
0
        PyObject *item = (CALL);                             \
14221
0
        if (item == NULL) {                                  \
14222
0
            Py_DECREF(v);                                    \
14223
0
            return NULL;                                     \
14224
0
        }                                                    \
14225
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
14226
0
    } while(0)
14227
14228
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
14229
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
14230
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
14231
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
14232
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
14233
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
14234
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
14235
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
14236
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
14237
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
14238
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
14239
#else
14240
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
14241
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
14242
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
14243
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
14244
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
14245
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
14246
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
14247
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
14248
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
14249
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
14250
#endif
14251
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
14252
 * (issue #32390). */
14253
#if defined(_AIX) && defined(_ALL_SOURCE)
14254
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
14255
#else
14256
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
14257
0
#endif
14258
14259
0
#undef SET_RESULT
14260
14261
0
    return v;
14262
0
}
14263
14264
#endif
14265
14266
14267
/*[clinic input]
14268
os.fstatvfs
14269
    fd: int
14270
    /
14271
14272
Perform an fstatvfs system call on the given fd.
14273
14274
Equivalent to statvfs(fd).
14275
[clinic start generated code]*/
14276
14277
static PyObject *
14278
os_fstatvfs_impl(PyObject *module, int fd)
14279
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
14280
0
{
14281
0
    int result;
14282
0
    int async_err = 0;
14283
#ifdef __APPLE__
14284
    struct statfs st;
14285
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
14286
     * the former uses 32-bit values for block counts.
14287
     */
14288
    do {
14289
        Py_BEGIN_ALLOW_THREADS
14290
        result = fstatfs(fd, &st);
14291
        Py_END_ALLOW_THREADS
14292
    } while (result != 0 && errno == EINTR &&
14293
             !(async_err = PyErr_CheckSignals()));
14294
    if (result != 0)
14295
        return (!async_err) ? posix_error() : NULL;
14296
14297
    return _pystatvfs_fromstructstatfs(module, st);
14298
#else
14299
0
    struct statvfs st;
14300
14301
0
    do {
14302
0
        Py_BEGIN_ALLOW_THREADS
14303
0
        result = fstatvfs(fd, &st);
14304
0
        Py_END_ALLOW_THREADS
14305
0
    } while (result != 0 && errno == EINTR &&
14306
0
             !(async_err = PyErr_CheckSignals()));
14307
0
    if (result != 0)
14308
0
        return (!async_err) ? posix_error() : NULL;
14309
14310
0
    return _pystatvfs_fromstructstatvfs(module, st);
14311
0
#endif
14312
0
}
14313
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14314
14315
14316
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14317
#include <sys/statvfs.h>
14318
/*[clinic input]
14319
os.statvfs
14320
14321
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14322
14323
Perform a statvfs system call on the given path.
14324
14325
path may always be specified as a string.
14326
On some platforms, path may also be specified as an open file
14327
descriptor.  If this functionality is unavailable, using it raises
14328
an exception.
14329
[clinic start generated code]*/
14330
14331
static PyObject *
14332
os_statvfs_impl(PyObject *module, path_t *path)
14333
/*[clinic end generated code: output=87106dd1beb8556e input=1cfd9a4fd36f7425]*/
14334
0
{
14335
0
    int result;
14336
14337
#ifdef __APPLE__
14338
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14339
     * the former uses 32-bit values for block counts.
14340
     */
14341
    struct statfs st;
14342
14343
    Py_BEGIN_ALLOW_THREADS
14344
    if (path->is_fd) {
14345
        result = fstatfs(path->fd, &st);
14346
    }
14347
    else
14348
        result = statfs(path->narrow, &st);
14349
    Py_END_ALLOW_THREADS
14350
14351
    if (result) {
14352
        return path_error(path);
14353
    }
14354
14355
    return _pystatvfs_fromstructstatfs(module, st);
14356
14357
#else
14358
0
    struct statvfs st;
14359
14360
0
    Py_BEGIN_ALLOW_THREADS
14361
0
#ifdef HAVE_FSTATVFS
14362
0
    if (path->is_fd) {
14363
0
        result = fstatvfs(path->fd, &st);
14364
0
    }
14365
0
    else
14366
0
#endif
14367
0
        result = statvfs(path->narrow, &st);
14368
0
    Py_END_ALLOW_THREADS
14369
14370
0
    if (result) {
14371
0
        return path_error(path);
14372
0
    }
14373
14374
0
    return _pystatvfs_fromstructstatvfs(module, st);
14375
0
#endif
14376
0
}
14377
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14378
14379
14380
#ifdef MS_WINDOWS
14381
/*[clinic input]
14382
@permit_long_summary
14383
os._getdiskusage
14384
14385
    path: path_t
14386
14387
Return disk usage statistics about the given path as a (total, free) tuple.
14388
[clinic start generated code]*/
14389
14390
static PyObject *
14391
os__getdiskusage_impl(PyObject *module, path_t *path)
14392
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=aee7e38bc3e7fb08]*/
14393
{
14394
    BOOL retval;
14395
    ULARGE_INTEGER _, total, free;
14396
    DWORD err = 0;
14397
14398
    Py_BEGIN_ALLOW_THREADS
14399
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14400
    Py_END_ALLOW_THREADS
14401
    if (retval == 0) {
14402
        if (GetLastError() == ERROR_DIRECTORY) {
14403
            wchar_t *dir_path = NULL;
14404
14405
            dir_path = PyMem_New(wchar_t, path->length + 1);
14406
            if (dir_path == NULL) {
14407
                return PyErr_NoMemory();
14408
            }
14409
14410
            wcscpy_s(dir_path, path->length + 1, path->wide);
14411
14412
            if (_dirnameW(dir_path) != -1) {
14413
                Py_BEGIN_ALLOW_THREADS
14414
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14415
                Py_END_ALLOW_THREADS
14416
            }
14417
            /* Record the last error in case it's modified by PyMem_Free. */
14418
            err = GetLastError();
14419
            PyMem_Free(dir_path);
14420
            if (retval) {
14421
                goto success;
14422
            }
14423
        }
14424
        return PyErr_SetFromWindowsErr(err);
14425
    }
14426
14427
success:
14428
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14429
}
14430
#endif /* MS_WINDOWS */
14431
14432
14433
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14434
 * It maps strings representing configuration variable names to
14435
 * integer values, allowing those functions to be called with the
14436
 * magic names instead of polluting the module's namespace with tons of
14437
 * rarely-used constants.  There are three separate tables that use
14438
 * these definitions.
14439
 *
14440
 * This code is always included, even if none of the interfaces that
14441
 * need it are included.  The #if hackery needed to avoid it would be
14442
 * sufficiently pervasive that it's not worth the loss of readability.
14443
 */
14444
struct constdef {
14445
    const char *name;
14446
    int value;
14447
};
14448
14449
static int
14450
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14451
4
{
14452
4
    if (PyUnicode_Check(arg)) {
14453
4
        PyObject *table = PyObject_GetAttrString(module, tablename);
14454
4
        if (table == NULL) {
14455
0
            return 0;
14456
0
        }
14457
14458
4
        arg = PyObject_GetItem(table, arg);
14459
4
        Py_DECREF(table);
14460
4
        if (arg == NULL) {
14461
0
            PyErr_SetString(
14462
0
                PyExc_ValueError, "unrecognized configuration name");
14463
0
            return 0;
14464
0
        }
14465
4
    } else {
14466
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14467
0
    }
14468
14469
4
    int success = 0;
14470
4
    if (!PyIndex_Check(arg)) {
14471
0
        PyErr_SetString(PyExc_TypeError,
14472
0
            "configuration names must be strings or integers");
14473
4
    } else {
14474
4
        int value = PyLong_AsInt(arg);
14475
4
        if (!(value == -1 && PyErr_Occurred())) {
14476
4
            *valuep = value;
14477
4
            success = 1;
14478
4
        }
14479
4
    }
14480
4
    Py_DECREF(arg);
14481
4
    return success;
14482
4
}
14483
14484
14485
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14486
static struct constdef  posix_constants_pathconf[] = {
14487
#ifdef _PC_ABI_AIO_XFER_MAX
14488
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14489
#endif
14490
#ifdef _PC_ABI_ASYNC_IO
14491
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14492
#endif
14493
#ifdef _PC_ASYNC_IO
14494
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14495
#endif
14496
#ifdef _PC_CHOWN_RESTRICTED
14497
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14498
#endif
14499
#ifdef _PC_FILESIZEBITS
14500
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14501
#endif
14502
#ifdef _PC_LAST
14503
    {"PC_LAST", _PC_LAST},
14504
#endif
14505
#ifdef _PC_LINK_MAX
14506
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14507
#endif
14508
#ifdef _PC_MAX_CANON
14509
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14510
#endif
14511
#ifdef _PC_MAX_INPUT
14512
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14513
#endif
14514
#ifdef _PC_NAME_MAX
14515
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14516
#endif
14517
#ifdef _PC_NO_TRUNC
14518
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14519
#endif
14520
#ifdef _PC_PATH_MAX
14521
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14522
#endif
14523
#ifdef _PC_PIPE_BUF
14524
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14525
#endif
14526
#ifdef _PC_PRIO_IO
14527
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14528
#endif
14529
#ifdef _PC_SOCK_MAXBUF
14530
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14531
#endif
14532
#ifdef _PC_SYNC_IO
14533
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14534
#endif
14535
#ifdef _PC_VDISABLE
14536
    {"PC_VDISABLE",     _PC_VDISABLE},
14537
#endif
14538
#ifdef _PC_ACL_ENABLED
14539
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14540
#endif
14541
#ifdef _PC_MIN_HOLE_SIZE
14542
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14543
#endif
14544
#ifdef _PC_ALLOC_SIZE_MIN
14545
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14546
#endif
14547
#ifdef _PC_REC_INCR_XFER_SIZE
14548
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14549
#endif
14550
#ifdef _PC_REC_MAX_XFER_SIZE
14551
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14552
#endif
14553
#ifdef _PC_REC_MIN_XFER_SIZE
14554
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14555
#endif
14556
#ifdef _PC_REC_XFER_ALIGN
14557
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14558
#endif
14559
#ifdef _PC_SYMLINK_MAX
14560
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14561
#endif
14562
#ifdef _PC_XATTR_ENABLED
14563
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14564
#endif
14565
#ifdef _PC_XATTR_EXISTS
14566
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14567
#endif
14568
#ifdef _PC_TIMESTAMP_RESOLUTION
14569
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14570
#endif
14571
};
14572
#endif
14573
14574
14575
#ifdef HAVE_FPATHCONF
14576
/*[clinic input]
14577
os.fpathconf -> long
14578
14579
    fd: fildes
14580
    name: confname(table="pathconf_names")
14581
    /
14582
14583
Return the configuration limit name for the file descriptor fd.
14584
14585
If there is no limit, return -1.
14586
[clinic start generated code]*/
14587
14588
static long
14589
os_fpathconf_impl(PyObject *module, int fd, int name)
14590
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14591
0
{
14592
0
    long limit;
14593
14594
0
    errno = 0;
14595
0
    limit = fpathconf(fd, name);
14596
0
    if (limit == -1 && errno != 0)
14597
0
        posix_error();
14598
14599
0
    return limit;
14600
0
}
14601
#endif /* HAVE_FPATHCONF */
14602
14603
14604
#ifdef HAVE_PATHCONF
14605
/*[clinic input]
14606
os.pathconf -> long
14607
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14608
    name: confname(table="pathconf_names")
14609
14610
Return the configuration limit name for the file or directory path.
14611
14612
If there is no limit, return -1.
14613
On some platforms, path may also be specified as an open file
14614
descriptor.  If this functionality is unavailable, using it raises
14615
an exception.
14616
[clinic start generated code]*/
14617
14618
static long
14619
os_pathconf_impl(PyObject *module, path_t *path, int name)
14620
/*[clinic end generated code: output=5bedee35b293a089 input=e86f6eacfa006426]*/
14621
0
{
14622
0
    long limit;
14623
14624
0
    errno = 0;
14625
0
#ifdef HAVE_FPATHCONF
14626
0
    if (path->is_fd) {
14627
0
        limit = fpathconf(path->fd, name);
14628
0
    }
14629
0
    else
14630
0
#endif
14631
0
        limit = pathconf(path->narrow, name);
14632
0
    if (limit == -1 && errno != 0) {
14633
0
        if (errno == EINVAL)
14634
            /* could be a path or name problem */
14635
0
            posix_error();
14636
0
        else
14637
0
            path_error(path);
14638
0
    }
14639
14640
0
    return limit;
14641
0
}
14642
#endif /* HAVE_PATHCONF */
14643
14644
#ifdef HAVE_CONFSTR
14645
static struct constdef posix_constants_confstr[] = {
14646
#ifdef _CS_ARCHITECTURE
14647
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14648
#endif
14649
#ifdef _CS_GNU_LIBC_VERSION
14650
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14651
#endif
14652
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14653
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14654
#endif
14655
#ifdef _CS_HOSTNAME
14656
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14657
#endif
14658
#ifdef _CS_HW_PROVIDER
14659
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14660
#endif
14661
#ifdef _CS_HW_SERIAL
14662
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14663
#endif
14664
#ifdef _CS_INITTAB_NAME
14665
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14666
#endif
14667
#ifdef _CS_LFS64_CFLAGS
14668
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14669
#endif
14670
#ifdef _CS_LFS64_LDFLAGS
14671
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14672
#endif
14673
#ifdef _CS_LFS64_LIBS
14674
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14675
#endif
14676
#ifdef _CS_LFS64_LINTFLAGS
14677
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14678
#endif
14679
#ifdef _CS_LFS_CFLAGS
14680
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14681
#endif
14682
#ifdef _CS_LFS_LDFLAGS
14683
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14684
#endif
14685
#ifdef _CS_LFS_LIBS
14686
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14687
#endif
14688
#ifdef _CS_LFS_LINTFLAGS
14689
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14690
#endif
14691
#ifdef _CS_MACHINE
14692
    {"CS_MACHINE",      _CS_MACHINE},
14693
#endif
14694
#ifdef _CS_PATH
14695
    {"CS_PATH", _CS_PATH},
14696
#endif
14697
#ifdef _CS_RELEASE
14698
    {"CS_RELEASE",      _CS_RELEASE},
14699
#endif
14700
#ifdef _CS_SRPC_DOMAIN
14701
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14702
#endif
14703
#ifdef _CS_SYSNAME
14704
    {"CS_SYSNAME",      _CS_SYSNAME},
14705
#endif
14706
#ifdef _CS_VERSION
14707
    {"CS_VERSION",      _CS_VERSION},
14708
#endif
14709
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14710
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14711
#endif
14712
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14713
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14714
#endif
14715
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14716
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14717
#endif
14718
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14719
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14720
#endif
14721
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14722
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14723
#endif
14724
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14725
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14726
#endif
14727
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14728
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14729
#endif
14730
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14731
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14732
#endif
14733
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14734
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14735
#endif
14736
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14737
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14738
#endif
14739
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14740
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14741
#endif
14742
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14743
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14744
#endif
14745
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14746
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14747
#endif
14748
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14749
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14750
#endif
14751
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14752
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14753
#endif
14754
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14755
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14756
#endif
14757
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14758
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14759
#endif
14760
#ifdef _MIPS_CS_BASE
14761
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14762
#endif
14763
#ifdef _MIPS_CS_HOSTID
14764
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14765
#endif
14766
#ifdef _MIPS_CS_HW_NAME
14767
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14768
#endif
14769
#ifdef _MIPS_CS_NUM_PROCESSORS
14770
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14771
#endif
14772
#ifdef _MIPS_CS_OSREL_MAJ
14773
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14774
#endif
14775
#ifdef _MIPS_CS_OSREL_MIN
14776
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14777
#endif
14778
#ifdef _MIPS_CS_OSREL_PATCH
14779
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14780
#endif
14781
#ifdef _MIPS_CS_OS_NAME
14782
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14783
#endif
14784
#ifdef _MIPS_CS_OS_PROVIDER
14785
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14786
#endif
14787
#ifdef _MIPS_CS_PROCESSORS
14788
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14789
#endif
14790
#ifdef _MIPS_CS_SERIAL
14791
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14792
#endif
14793
#ifdef _MIPS_CS_VENDOR
14794
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14795
#endif
14796
};
14797
14798
14799
/*[clinic input]
14800
os.confstr
14801
14802
    name: confname(table="confstr_names")
14803
    /
14804
14805
Return a string-valued system configuration variable.
14806
[clinic start generated code]*/
14807
14808
static PyObject *
14809
os_confstr_impl(PyObject *module, int name)
14810
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14811
4
{
14812
4
    PyObject *result = NULL;
14813
4
    char buffer[255];
14814
4
    size_t len;
14815
14816
4
    errno = 0;
14817
4
    len = confstr(name, buffer, sizeof(buffer));
14818
4
    if (len == 0) {
14819
0
        if (errno) {
14820
0
            posix_error();
14821
0
            return NULL;
14822
0
        }
14823
0
        else {
14824
0
            Py_RETURN_NONE;
14825
0
        }
14826
0
    }
14827
14828
4
    if (len >= sizeof(buffer)) {
14829
0
        size_t len2;
14830
0
        char *buf = PyMem_Malloc(len);
14831
0
        if (buf == NULL)
14832
0
            return PyErr_NoMemory();
14833
0
        len2 = confstr(name, buf, len);
14834
0
        assert(len == len2);
14835
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14836
0
        PyMem_Free(buf);
14837
0
    }
14838
4
    else
14839
4
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14840
4
    return result;
14841
4
}
14842
#endif /* HAVE_CONFSTR */
14843
14844
14845
#ifdef HAVE_SYSCONF
14846
static struct constdef posix_constants_sysconf[] = {
14847
#ifdef _SC_2_CHAR_TERM
14848
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14849
#endif
14850
#ifdef _SC_2_C_BIND
14851
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14852
#endif
14853
#ifdef _SC_2_C_DEV
14854
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14855
#endif
14856
#ifdef _SC_2_C_VERSION
14857
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14858
#endif
14859
#ifdef _SC_2_FORT_DEV
14860
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14861
#endif
14862
#ifdef _SC_2_FORT_RUN
14863
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14864
#endif
14865
#ifdef _SC_2_LOCALEDEF
14866
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14867
#endif
14868
#ifdef _SC_2_SW_DEV
14869
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14870
#endif
14871
#ifdef _SC_2_UPE
14872
    {"SC_2_UPE",        _SC_2_UPE},
14873
#endif
14874
#ifdef _SC_2_VERSION
14875
    {"SC_2_VERSION",    _SC_2_VERSION},
14876
#endif
14877
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14878
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14879
#endif
14880
#ifdef _SC_ACL
14881
    {"SC_ACL",  _SC_ACL},
14882
#endif
14883
#ifdef _SC_AIO_LISTIO_MAX
14884
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14885
#endif
14886
#ifdef _SC_AIO_MAX
14887
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14888
#endif
14889
#ifdef _SC_AIO_PRIO_DELTA_MAX
14890
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14891
#endif
14892
#ifdef _SC_ARG_MAX
14893
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14894
#endif
14895
#ifdef _SC_ASYNCHRONOUS_IO
14896
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14897
#endif
14898
#ifdef _SC_ATEXIT_MAX
14899
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14900
#endif
14901
#ifdef _SC_AUDIT
14902
    {"SC_AUDIT",        _SC_AUDIT},
14903
#endif
14904
#ifdef _SC_AVPHYS_PAGES
14905
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14906
#endif
14907
#ifdef _SC_BC_BASE_MAX
14908
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14909
#endif
14910
#ifdef _SC_BC_DIM_MAX
14911
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14912
#endif
14913
#ifdef _SC_BC_SCALE_MAX
14914
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14915
#endif
14916
#ifdef _SC_BC_STRING_MAX
14917
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14918
#endif
14919
#ifdef _SC_CAP
14920
    {"SC_CAP",  _SC_CAP},
14921
#endif
14922
#ifdef _SC_CHARCLASS_NAME_MAX
14923
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14924
#endif
14925
#ifdef _SC_CHAR_BIT
14926
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14927
#endif
14928
#ifdef _SC_CHAR_MAX
14929
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14930
#endif
14931
#ifdef _SC_CHAR_MIN
14932
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14933
#endif
14934
#ifdef _SC_CHILD_MAX
14935
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14936
#endif
14937
#ifdef _SC_CLK_TCK
14938
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14939
#endif
14940
#ifdef _SC_COHER_BLKSZ
14941
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14942
#endif
14943
#ifdef _SC_COLL_WEIGHTS_MAX
14944
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14945
#endif
14946
#ifdef _SC_DCACHE_ASSOC
14947
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14948
#endif
14949
#ifdef _SC_DCACHE_BLKSZ
14950
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14951
#endif
14952
#ifdef _SC_DCACHE_LINESZ
14953
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14954
#endif
14955
#ifdef _SC_DCACHE_SZ
14956
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14957
#endif
14958
#ifdef _SC_DCACHE_TBLKSZ
14959
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14960
#endif
14961
#ifdef _SC_DELAYTIMER_MAX
14962
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14963
#endif
14964
#ifdef _SC_EQUIV_CLASS_MAX
14965
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14966
#endif
14967
#ifdef _SC_EXPR_NEST_MAX
14968
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14969
#endif
14970
#ifdef _SC_FSYNC
14971
    {"SC_FSYNC",        _SC_FSYNC},
14972
#endif
14973
#ifdef _SC_GETGR_R_SIZE_MAX
14974
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14975
#endif
14976
#ifdef _SC_GETPW_R_SIZE_MAX
14977
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14978
#endif
14979
#ifdef _SC_ICACHE_ASSOC
14980
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14981
#endif
14982
#ifdef _SC_ICACHE_BLKSZ
14983
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14984
#endif
14985
#ifdef _SC_ICACHE_LINESZ
14986
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14987
#endif
14988
#ifdef _SC_ICACHE_SZ
14989
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14990
#endif
14991
#ifdef _SC_INF
14992
    {"SC_INF",  _SC_INF},
14993
#endif
14994
#ifdef _SC_INT_MAX
14995
    {"SC_INT_MAX",      _SC_INT_MAX},
14996
#endif
14997
#ifdef _SC_INT_MIN
14998
    {"SC_INT_MIN",      _SC_INT_MIN},
14999
#endif
15000
#ifdef _SC_IOV_MAX
15001
    {"SC_IOV_MAX",      _SC_IOV_MAX},
15002
#endif
15003
#ifdef _SC_IP_SECOPTS
15004
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
15005
#endif
15006
#ifdef _SC_JOB_CONTROL
15007
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
15008
#endif
15009
#ifdef _SC_KERN_POINTERS
15010
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
15011
#endif
15012
#ifdef _SC_KERN_SIM
15013
    {"SC_KERN_SIM",     _SC_KERN_SIM},
15014
#endif
15015
#ifdef _SC_LINE_MAX
15016
    {"SC_LINE_MAX",     _SC_LINE_MAX},
15017
#endif
15018
#ifdef _SC_LOGIN_NAME_MAX
15019
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
15020
#endif
15021
#ifdef _SC_LOGNAME_MAX
15022
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
15023
#endif
15024
#ifdef _SC_LONG_BIT
15025
    {"SC_LONG_BIT",     _SC_LONG_BIT},
15026
#endif
15027
#ifdef _SC_MAC
15028
    {"SC_MAC",  _SC_MAC},
15029
#endif
15030
#ifdef _SC_MAPPED_FILES
15031
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
15032
#endif
15033
#ifdef _SC_MAXPID
15034
    {"SC_MAXPID",       _SC_MAXPID},
15035
#endif
15036
#ifdef _SC_MB_LEN_MAX
15037
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
15038
#endif
15039
#ifdef _SC_MEMLOCK
15040
    {"SC_MEMLOCK",      _SC_MEMLOCK},
15041
#endif
15042
#ifdef _SC_MEMLOCK_RANGE
15043
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
15044
#endif
15045
#ifdef _SC_MEMORY_PROTECTION
15046
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
15047
#endif
15048
#ifdef _SC_MESSAGE_PASSING
15049
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
15050
#endif
15051
#ifdef _SC_MMAP_FIXED_ALIGNMENT
15052
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
15053
#endif
15054
#ifdef _SC_MQ_OPEN_MAX
15055
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
15056
#endif
15057
#ifdef _SC_MQ_PRIO_MAX
15058
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
15059
#endif
15060
#ifdef _SC_NACLS_MAX
15061
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
15062
#endif
15063
#ifdef _SC_NGROUPS_MAX
15064
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
15065
#endif
15066
#ifdef _SC_NL_ARGMAX
15067
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
15068
#endif
15069
#ifdef _SC_NL_LANGMAX
15070
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
15071
#endif
15072
#ifdef _SC_NL_MSGMAX
15073
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
15074
#endif
15075
#ifdef _SC_NL_NMAX
15076
    {"SC_NL_NMAX",      _SC_NL_NMAX},
15077
#endif
15078
#ifdef _SC_NL_SETMAX
15079
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
15080
#endif
15081
#ifdef _SC_NL_TEXTMAX
15082
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
15083
#endif
15084
#ifdef _SC_NPROCESSORS_CONF
15085
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
15086
#endif
15087
#ifdef _SC_NPROCESSORS_ONLN
15088
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
15089
#endif
15090
#ifdef _SC_NPROC_CONF
15091
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
15092
#endif
15093
#ifdef _SC_NPROC_ONLN
15094
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
15095
#endif
15096
#ifdef _SC_NZERO
15097
    {"SC_NZERO",        _SC_NZERO},
15098
#endif
15099
#ifdef _SC_OPEN_MAX
15100
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
15101
#endif
15102
#ifdef _SC_PAGESIZE
15103
    {"SC_PAGESIZE",     _SC_PAGESIZE},
15104
#endif
15105
#ifdef _SC_PAGE_SIZE
15106
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
15107
#endif
15108
#ifdef _SC_AIX_REALMEM
15109
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
15110
#endif
15111
#ifdef _SC_PASS_MAX
15112
    {"SC_PASS_MAX",     _SC_PASS_MAX},
15113
#endif
15114
#ifdef _SC_PHYS_PAGES
15115
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
15116
#endif
15117
#ifdef _SC_PII
15118
    {"SC_PII",  _SC_PII},
15119
#endif
15120
#ifdef _SC_PII_INTERNET
15121
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
15122
#endif
15123
#ifdef _SC_PII_INTERNET_DGRAM
15124
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
15125
#endif
15126
#ifdef _SC_PII_INTERNET_STREAM
15127
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
15128
#endif
15129
#ifdef _SC_PII_OSI
15130
    {"SC_PII_OSI",      _SC_PII_OSI},
15131
#endif
15132
#ifdef _SC_PII_OSI_CLTS
15133
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
15134
#endif
15135
#ifdef _SC_PII_OSI_COTS
15136
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
15137
#endif
15138
#ifdef _SC_PII_OSI_M
15139
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
15140
#endif
15141
#ifdef _SC_PII_SOCKET
15142
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
15143
#endif
15144
#ifdef _SC_PII_XTI
15145
    {"SC_PII_XTI",      _SC_PII_XTI},
15146
#endif
15147
#ifdef _SC_POLL
15148
    {"SC_POLL", _SC_POLL},
15149
#endif
15150
#ifdef _SC_PRIORITIZED_IO
15151
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
15152
#endif
15153
#ifdef _SC_PRIORITY_SCHEDULING
15154
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
15155
#endif
15156
#ifdef _SC_REALTIME_SIGNALS
15157
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
15158
#endif
15159
#ifdef _SC_RE_DUP_MAX
15160
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
15161
#endif
15162
#ifdef _SC_RTSIG_MAX
15163
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
15164
#endif
15165
#ifdef _SC_SAVED_IDS
15166
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
15167
#endif
15168
#ifdef _SC_SCHAR_MAX
15169
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
15170
#endif
15171
#ifdef _SC_SCHAR_MIN
15172
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
15173
#endif
15174
#ifdef _SC_SELECT
15175
    {"SC_SELECT",       _SC_SELECT},
15176
#endif
15177
#ifdef _SC_SEMAPHORES
15178
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
15179
#endif
15180
#ifdef _SC_SEM_NSEMS_MAX
15181
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
15182
#endif
15183
#ifdef _SC_SEM_VALUE_MAX
15184
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
15185
#endif
15186
#ifdef _SC_SHARED_MEMORY_OBJECTS
15187
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
15188
#endif
15189
#ifdef _SC_SHRT_MAX
15190
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
15191
#endif
15192
#ifdef _SC_SHRT_MIN
15193
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
15194
#endif
15195
#ifdef _SC_SIGQUEUE_MAX
15196
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
15197
#endif
15198
#ifdef _SC_SIGRT_MAX
15199
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
15200
#endif
15201
#ifdef _SC_SIGRT_MIN
15202
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
15203
#endif
15204
#ifdef _SC_SOFTPOWER
15205
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
15206
#endif
15207
#ifdef _SC_SPLIT_CACHE
15208
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
15209
#endif
15210
#ifdef _SC_SSIZE_MAX
15211
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
15212
#endif
15213
#ifdef _SC_STACK_PROT
15214
    {"SC_STACK_PROT",   _SC_STACK_PROT},
15215
#endif
15216
#ifdef _SC_STREAM_MAX
15217
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
15218
#endif
15219
#ifdef _SC_SYNCHRONIZED_IO
15220
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
15221
#endif
15222
#ifdef _SC_THREADS
15223
    {"SC_THREADS",      _SC_THREADS},
15224
#endif
15225
#ifdef _SC_THREAD_ATTR_STACKADDR
15226
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
15227
#endif
15228
#ifdef _SC_THREAD_ATTR_STACKSIZE
15229
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
15230
#endif
15231
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
15232
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
15233
#endif
15234
#ifdef _SC_THREAD_KEYS_MAX
15235
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
15236
#endif
15237
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
15238
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
15239
#endif
15240
#ifdef _SC_THREAD_PRIO_INHERIT
15241
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
15242
#endif
15243
#ifdef _SC_THREAD_PRIO_PROTECT
15244
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
15245
#endif
15246
#ifdef _SC_THREAD_PROCESS_SHARED
15247
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
15248
#endif
15249
#ifdef _SC_THREAD_SAFE_FUNCTIONS
15250
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
15251
#endif
15252
#ifdef _SC_THREAD_STACK_MIN
15253
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
15254
#endif
15255
#ifdef _SC_THREAD_THREADS_MAX
15256
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
15257
#endif
15258
#ifdef _SC_TIMERS
15259
    {"SC_TIMERS",       _SC_TIMERS},
15260
#endif
15261
#ifdef _SC_TIMER_MAX
15262
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
15263
#endif
15264
#ifdef _SC_TTY_NAME_MAX
15265
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
15266
#endif
15267
#ifdef _SC_TZNAME_MAX
15268
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
15269
#endif
15270
#ifdef _SC_T_IOV_MAX
15271
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
15272
#endif
15273
#ifdef _SC_UCHAR_MAX
15274
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
15275
#endif
15276
#ifdef _SC_UINT_MAX
15277
    {"SC_UINT_MAX",     _SC_UINT_MAX},
15278
#endif
15279
#ifdef _SC_UIO_MAXIOV
15280
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
15281
#endif
15282
#ifdef _SC_ULONG_MAX
15283
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
15284
#endif
15285
#ifdef _SC_USHRT_MAX
15286
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
15287
#endif
15288
#ifdef _SC_VERSION
15289
    {"SC_VERSION",      _SC_VERSION},
15290
#endif
15291
#ifdef _SC_WORD_BIT
15292
    {"SC_WORD_BIT",     _SC_WORD_BIT},
15293
#endif
15294
#ifdef _SC_XBS5_ILP32_OFF32
15295
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15296
#endif
15297
#ifdef _SC_XBS5_ILP32_OFFBIG
15298
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15299
#endif
15300
#ifdef _SC_XBS5_LP64_OFF64
15301
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15302
#endif
15303
#ifdef _SC_XBS5_LPBIG_OFFBIG
15304
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15305
#endif
15306
#ifdef _SC_XOPEN_CRYPT
15307
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15308
#endif
15309
#ifdef _SC_XOPEN_ENH_I18N
15310
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15311
#endif
15312
#ifdef _SC_XOPEN_LEGACY
15313
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15314
#endif
15315
#ifdef _SC_XOPEN_REALTIME
15316
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15317
#endif
15318
#ifdef _SC_XOPEN_REALTIME_THREADS
15319
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15320
#endif
15321
#ifdef _SC_XOPEN_SHM
15322
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15323
#endif
15324
#ifdef _SC_XOPEN_UNIX
15325
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15326
#endif
15327
#ifdef _SC_XOPEN_VERSION
15328
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15329
#endif
15330
#ifdef _SC_XOPEN_XCU_VERSION
15331
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15332
#endif
15333
#ifdef _SC_XOPEN_XPG2
15334
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15335
#endif
15336
#ifdef _SC_XOPEN_XPG3
15337
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15338
#endif
15339
#ifdef _SC_XOPEN_XPG4
15340
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15341
#endif
15342
#ifdef _SC_MINSIGSTKSZ
15343
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15344
#endif
15345
};
15346
15347
15348
/*[clinic input]
15349
os.sysconf -> long
15350
    name: confname(table="sysconf_names")
15351
    /
15352
15353
Return an integer-valued system configuration variable.
15354
[clinic start generated code]*/
15355
15356
static long
15357
os_sysconf_impl(PyObject *module, int name)
15358
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15359
0
{
15360
0
    long value;
15361
15362
0
    errno = 0;
15363
0
    value = sysconf(name);
15364
0
    if (value == -1 && errno != 0)
15365
0
        posix_error();
15366
0
    return value;
15367
0
}
15368
#endif /* HAVE_SYSCONF */
15369
15370
15371
static int
15372
setup_confname_table(struct constdef *table, size_t tablesize,
15373
                     const char *tablename, PyObject *module)
15374
111
{
15375
111
    PyObject *d = PyDict_New();
15376
111
    if (d == NULL)
15377
0
        return -1;
15378
15379
6.80k
    for (size_t i=0; i < tablesize; ++i) {
15380
6.69k
        PyObject *o = PyLong_FromLong(table[i].value);
15381
6.69k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15382
0
            Py_XDECREF(o);
15383
0
            Py_DECREF(d);
15384
0
            return -1;
15385
0
        }
15386
6.69k
        Py_DECREF(o);
15387
6.69k
    }
15388
111
    return PyModule_Add(module, tablename, d);
15389
111
}
15390
15391
/* Return -1 on failure, 0 on success. */
15392
static int
15393
setup_confname_tables(PyObject *module)
15394
37
{
15395
37
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15396
37
    if (setup_confname_table(posix_constants_pathconf,
15397
37
                             sizeof(posix_constants_pathconf)
15398
37
                               / sizeof(struct constdef),
15399
37
                             "pathconf_names", module))
15400
0
        return -1;
15401
37
#endif
15402
37
#ifdef HAVE_CONFSTR
15403
37
    if (setup_confname_table(posix_constants_confstr,
15404
37
                             sizeof(posix_constants_confstr)
15405
37
                               / sizeof(struct constdef),
15406
37
                             "confstr_names", module))
15407
0
        return -1;
15408
37
#endif
15409
37
#ifdef HAVE_SYSCONF
15410
37
    if (setup_confname_table(posix_constants_sysconf,
15411
37
                             sizeof(posix_constants_sysconf)
15412
37
                               / sizeof(struct constdef),
15413
37
                             "sysconf_names", module))
15414
0
        return -1;
15415
37
#endif
15416
37
    return 0;
15417
37
}
15418
15419
15420
/*[clinic input]
15421
os.abort
15422
15423
Abort the interpreter immediately.
15424
15425
This function 'dumps core' or otherwise fails in the hardest way
15426
possible on the hosting operating system.  This function never returns.
15427
[clinic start generated code]*/
15428
15429
static PyObject *
15430
os_abort_impl(PyObject *module)
15431
/*[clinic end generated code: output=dcf52586dad2467c input=ee8bd0ed690440ab]*/
15432
0
{
15433
0
    abort();
15434
    /*NOTREACHED*/
15435
#ifndef __clang__
15436
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15437
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15438
       is smarter and emits a warning on the return. */
15439
    Py_FatalError("abort() called from Python code didn't abort!");
15440
    return NULL;
15441
#endif
15442
0
}
15443
15444
#ifdef MS_WINDOWS
15445
/* Grab ShellExecute dynamically from shell32 */
15446
static int has_ShellExecute = -1;
15447
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15448
                                              LPCWSTR, INT);
15449
static int
15450
check_ShellExecute(void)
15451
{
15452
    HINSTANCE hShell32;
15453
15454
    /* only recheck */
15455
    if (-1 == has_ShellExecute) {
15456
        Py_BEGIN_ALLOW_THREADS
15457
        /* Security note: this call is not vulnerable to "DLL hijacking".
15458
           SHELL32 is part of "KnownDLLs" and so Windows always load
15459
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15460
           in the DLL search path. */
15461
        hShell32 = LoadLibraryW(L"SHELL32");
15462
        if (hShell32) {
15463
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15464
                                            "ShellExecuteW");
15465
            has_ShellExecute = Py_ShellExecuteW != NULL;
15466
        } else {
15467
            has_ShellExecute = 0;
15468
        }
15469
        Py_END_ALLOW_THREADS
15470
    }
15471
    return has_ShellExecute;
15472
}
15473
15474
15475
/*[clinic input]
15476
os.startfile
15477
    filepath: path_t
15478
    operation: Py_UNICODE = NULL
15479
    arguments: Py_UNICODE = NULL
15480
    cwd: path_t(nullable=True) = None
15481
    show_cmd: int = 1
15482
15483
Start a file with its associated application.
15484
15485
When "operation" is not specified or "open", this acts like
15486
double-clicking the file in Explorer, or giving the file name as an
15487
argument to the DOS "start" command: the file is opened with whatever
15488
application (if any) its extension is associated.
15489
When another "operation" is given, it specifies what should be done with
15490
the file.  A typical operation is "print".
15491
15492
"arguments" is passed to the application, but should be omitted if the
15493
file is a document.
15494
15495
"cwd" is the working directory for the operation. If "filepath" is
15496
relative, it will be resolved against this directory. This argument
15497
should usually be an absolute path.
15498
15499
"show_cmd" can be used to override the recommended visibility option.
15500
See the Windows ShellExecute documentation for values.
15501
15502
startfile returns as soon as the associated application is launched.
15503
There is no option to wait for the application to close, and no way
15504
to retrieve the application's exit status.
15505
15506
The filepath is relative to the current directory.  If you want to use
15507
an absolute path, make sure the first character is not a slash ("/");
15508
the underlying Win32 ShellExecute function doesn't work if it is.
15509
[clinic start generated code]*/
15510
15511
static PyObject *
15512
os_startfile_impl(PyObject *module, path_t *filepath,
15513
                  const wchar_t *operation, const wchar_t *arguments,
15514
                  path_t *cwd, int show_cmd)
15515
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15516
{
15517
    HINSTANCE rc;
15518
15519
    if(!check_ShellExecute()) {
15520
        /* If the OS doesn't have ShellExecute, return a
15521
           NotImplementedError. */
15522
        return PyErr_Format(PyExc_NotImplementedError,
15523
            "startfile not available on this platform");
15524
    }
15525
15526
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15527
        return NULL;
15528
    }
15529
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15530
                    arguments, cwd->object ? cwd->object : Py_None,
15531
                    show_cmd) < 0) {
15532
        return NULL;
15533
    }
15534
15535
    Py_BEGIN_ALLOW_THREADS
15536
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15537
                          arguments, cwd->wide, show_cmd);
15538
    Py_END_ALLOW_THREADS
15539
15540
    if (rc <= (HINSTANCE)32) {
15541
        win32_error_object("startfile", filepath->object);
15542
        return NULL;
15543
    }
15544
    Py_RETURN_NONE;
15545
}
15546
#endif /* MS_WINDOWS */
15547
15548
15549
#ifdef HAVE_GETLOADAVG
15550
/*[clinic input]
15551
os.getloadavg
15552
15553
Return average recent system load information.
15554
15555
Return the number of processes in the system run queue averaged over
15556
the last 1, 5, and 15 minutes as a tuple of three floats.
15557
Raises OSError if the load average was unobtainable.
15558
[clinic start generated code]*/
15559
15560
static PyObject *
15561
os_getloadavg_impl(PyObject *module)
15562
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15563
0
{
15564
0
    double loadavg[3];
15565
0
    if (getloadavg(loadavg, 3)!=3) {
15566
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15567
0
        return NULL;
15568
0
    } else
15569
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15570
0
}
15571
#endif /* HAVE_GETLOADAVG */
15572
15573
15574
/*[clinic input]
15575
os.device_encoding
15576
    fd: int
15577
15578
Return a string describing the encoding of a terminal's file descriptor.
15579
15580
The file descriptor must be attached to a terminal.
15581
If the device is not a terminal, return None.
15582
[clinic start generated code]*/
15583
15584
static PyObject *
15585
os_device_encoding_impl(PyObject *module, int fd)
15586
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15587
0
{
15588
0
    return _Py_device_encoding(fd);
15589
0
}
15590
15591
15592
#ifdef HAVE_SETRESUID
15593
/*[clinic input]
15594
os.setresuid
15595
15596
    ruid: uid_t
15597
    euid: uid_t
15598
    suid: uid_t
15599
    /
15600
15601
Set the current process's real, effective, and saved user ids.
15602
[clinic start generated code]*/
15603
15604
static PyObject *
15605
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15606
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15607
0
{
15608
#ifdef __ANDROID__
15609
    // On Android, calling this function as a non-root user leads to a process crash
15610
    // rather than returning a permission error.
15611
    if (getuid() != 0) {
15612
        errno = EPERM;
15613
        return posix_error();
15614
    }
15615
#endif
15616
0
    if (setresuid(ruid, euid, suid) < 0)
15617
0
        return posix_error();
15618
0
    Py_RETURN_NONE;
15619
0
}
15620
#endif /* HAVE_SETRESUID */
15621
15622
15623
#ifdef HAVE_SETRESGID
15624
/*[clinic input]
15625
os.setresgid
15626
15627
    rgid: gid_t
15628
    egid: gid_t
15629
    sgid: gid_t
15630
    /
15631
15632
Set the current process's real, effective, and saved group ids.
15633
[clinic start generated code]*/
15634
15635
static PyObject *
15636
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15637
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15638
0
{
15639
#ifdef __ANDROID__
15640
    // On Android, calling this function as a non-root user leads to a process crash
15641
    // rather than returning a permission error.
15642
    if (getuid() != 0) {
15643
        errno = EPERM;
15644
        return posix_error();
15645
    }
15646
#endif
15647
0
    if (setresgid(rgid, egid, sgid) < 0)
15648
0
        return posix_error();
15649
0
    Py_RETURN_NONE;
15650
0
}
15651
#endif /* HAVE_SETRESGID */
15652
15653
15654
#ifdef HAVE_GETRESUID
15655
/*[clinic input]
15656
@permit_long_summary
15657
os.getresuid
15658
15659
Return a tuple of the current process's real, effective, and saved user ids.
15660
[clinic start generated code]*/
15661
15662
static PyObject *
15663
os_getresuid_impl(PyObject *module)
15664
/*[clinic end generated code: output=8e0becff5dece5bf input=ddf95881f492cb97]*/
15665
0
{
15666
0
    uid_t ruid, euid, suid;
15667
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15668
0
        return posix_error();
15669
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15670
0
                                  _PyLong_FromUid(euid),
15671
0
                                  _PyLong_FromUid(suid));
15672
0
}
15673
#endif /* HAVE_GETRESUID */
15674
15675
15676
#ifdef HAVE_GETRESGID
15677
/*[clinic input]
15678
@permit_long_summary
15679
os.getresgid
15680
15681
Return a tuple of the current process's real, effective, and saved group ids.
15682
[clinic start generated code]*/
15683
15684
static PyObject *
15685
os_getresgid_impl(PyObject *module)
15686
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15687
0
{
15688
0
    gid_t rgid, egid, sgid;
15689
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15690
0
        return posix_error();
15691
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15692
0
                                  _PyLong_FromGid(egid),
15693
0
                                  _PyLong_FromGid(sgid));
15694
0
}
15695
#endif /* HAVE_GETRESGID */
15696
15697
15698
#ifdef USE_XATTRS
15699
/*[clinic input]
15700
os.getxattr
15701
15702
    path: path_t(allow_fd=True)
15703
    attribute: path_t
15704
    *
15705
    follow_symlinks: bool = True
15706
15707
Return the value of extended attribute attribute on path.
15708
15709
path may be either a string, a path-like object, or an open file
15710
descriptor.
15711
If follow_symlinks is False, and the last element of the path is
15712
a symbolic link, getxattr will examine the symbolic link itself
15713
instead of the file the link points to.
15714
15715
[clinic start generated code]*/
15716
15717
static PyObject *
15718
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15719
                 int follow_symlinks)
15720
/*[clinic end generated code: output=5f2f44200a43cff2 input=db1021ed738d9754]*/
15721
0
{
15722
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
15723
0
        return NULL;
15724
15725
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15726
0
        return NULL;
15727
0
    }
15728
15729
0
    for (Py_ssize_t i = 0; ; i++) {
15730
0
        ssize_t result;
15731
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15732
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15733
0
        if (!buffer_size) {
15734
0
            path_error(path);
15735
0
            return NULL;
15736
0
        }
15737
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15738
0
        if (writer == NULL) {
15739
0
            return NULL;
15740
0
        }
15741
0
        void *ptr = PyBytesWriter_GetData(writer);
15742
15743
0
        Py_BEGIN_ALLOW_THREADS;
15744
0
        if (path->is_fd)
15745
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15746
0
        else if (follow_symlinks)
15747
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15748
0
        else
15749
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15750
0
        Py_END_ALLOW_THREADS;
15751
15752
0
        if (result < 0) {
15753
0
            PyBytesWriter_Discard(writer);
15754
0
            if (errno == ERANGE) {
15755
0
                continue;
15756
0
            }
15757
0
            path_error(path);
15758
0
            return NULL;
15759
0
        }
15760
15761
0
        return PyBytesWriter_FinishWithSize(writer, result);
15762
0
    }
15763
0
}
15764
15765
15766
/*[clinic input]
15767
os.setxattr
15768
15769
    path: path_t(allow_fd=True)
15770
    attribute: path_t
15771
    value: Py_buffer
15772
    flags: int = 0
15773
    *
15774
    follow_symlinks: bool = True
15775
15776
Set extended attribute attribute on path to value.
15777
15778
path may be either a string, a path-like object,  or an open file
15779
descriptor.
15780
If follow_symlinks is False, and the last element of the path is
15781
a symbolic link, setxattr will modify the symbolic link itself instead
15782
of the file the link points to.
15783
15784
[clinic start generated code]*/
15785
15786
static PyObject *
15787
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15788
                 Py_buffer *value, int flags, int follow_symlinks)
15789
/*[clinic end generated code: output=98b83f63fdde26bb input=6c4ee6724e8947a4]*/
15790
0
{
15791
0
    ssize_t result;
15792
15793
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
15794
0
        return NULL;
15795
15796
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15797
0
                    value->buf, value->len, flags) < 0) {
15798
0
        return NULL;
15799
0
    }
15800
15801
0
    Py_BEGIN_ALLOW_THREADS;
15802
0
    if (path->is_fd)
15803
0
        result = fsetxattr(path->fd, attribute->narrow,
15804
0
                           value->buf, value->len, flags);
15805
0
    else if (follow_symlinks)
15806
0
        result = setxattr(path->narrow, attribute->narrow,
15807
0
                           value->buf, value->len, flags);
15808
0
    else
15809
0
        result = lsetxattr(path->narrow, attribute->narrow,
15810
0
                           value->buf, value->len, flags);
15811
0
    Py_END_ALLOW_THREADS;
15812
15813
0
    if (result) {
15814
0
        path_error(path);
15815
0
        return NULL;
15816
0
    }
15817
15818
0
    Py_RETURN_NONE;
15819
0
}
15820
15821
15822
/*[clinic input]
15823
os.removexattr
15824
15825
    path: path_t(allow_fd=True)
15826
    attribute: path_t
15827
    *
15828
    follow_symlinks: bool = True
15829
15830
Remove extended attribute attribute on path.
15831
15832
path may be either a string, a path-like object, or an open file
15833
descriptor.
15834
If follow_symlinks is False, and the last element of the path is
15835
a symbolic link, removexattr will modify the symbolic link itself
15836
instead of the file the link points to.
15837
15838
[clinic start generated code]*/
15839
15840
static PyObject *
15841
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15842
                    int follow_symlinks)
15843
/*[clinic end generated code: output=521a51817980cda6 input=a7ec62a86aa83f01]*/
15844
0
{
15845
0
    ssize_t result;
15846
15847
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
15848
0
        return NULL;
15849
15850
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15851
0
        return NULL;
15852
0
    }
15853
15854
0
    Py_BEGIN_ALLOW_THREADS;
15855
0
    if (path->is_fd)
15856
0
        result = fremovexattr(path->fd, attribute->narrow);
15857
0
    else if (follow_symlinks)
15858
0
        result = removexattr(path->narrow, attribute->narrow);
15859
0
    else
15860
0
        result = lremovexattr(path->narrow, attribute->narrow);
15861
0
    Py_END_ALLOW_THREADS;
15862
15863
0
    if (result) {
15864
0
        return path_error(path);
15865
0
    }
15866
15867
0
    Py_RETURN_NONE;
15868
0
}
15869
15870
15871
/*[clinic input]
15872
os.listxattr
15873
15874
    path: path_t(allow_fd=True, nullable=True) = None
15875
    *
15876
    follow_symlinks: bool = True
15877
15878
Return a list of extended attributes on path.
15879
15880
path may be either None, a string, a path-like object, or an open file
15881
descriptor.  If path is None, listxattr will examine the current
15882
directory.
15883
If follow_symlinks is False, and the last element of the path is
15884
a symbolic link, listxattr will examine the symbolic link itself instead
15885
of the file the link points to.
15886
[clinic start generated code]*/
15887
15888
static PyObject *
15889
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15890
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=cb4a6414afaa99bd]*/
15891
0
{
15892
0
    Py_ssize_t i;
15893
0
    PyObject *result = NULL;
15894
0
    const char *name;
15895
0
    char *buffer = NULL;
15896
15897
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
15898
0
        goto exit;
15899
15900
0
    if (PySys_Audit("os.listxattr", "(O)",
15901
0
                    path->object ? path->object : Py_None) < 0) {
15902
0
        return NULL;
15903
0
    }
15904
15905
0
    name = path->narrow ? path->narrow : ".";
15906
15907
0
    for (i = 0; ; i++) {
15908
0
        const char *start, *trace, *end;
15909
0
        ssize_t length;
15910
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15911
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15912
0
        if (!buffer_size) {
15913
            /* ERANGE */
15914
0
            path_error(path);
15915
0
            break;
15916
0
        }
15917
0
        buffer = PyMem_Malloc(buffer_size);
15918
0
        if (!buffer) {
15919
0
            PyErr_NoMemory();
15920
0
            break;
15921
0
        }
15922
15923
0
        Py_BEGIN_ALLOW_THREADS;
15924
0
        if (path->is_fd)
15925
0
            length = flistxattr(path->fd, buffer, buffer_size);
15926
0
        else if (follow_symlinks)
15927
0
            length = listxattr(name, buffer, buffer_size);
15928
0
        else
15929
0
            length = llistxattr(name, buffer, buffer_size);
15930
0
        Py_END_ALLOW_THREADS;
15931
15932
0
        if (length < 0) {
15933
0
            if (errno == ERANGE) {
15934
0
                PyMem_Free(buffer);
15935
0
                buffer = NULL;
15936
0
                continue;
15937
0
            }
15938
0
            path_error(path);
15939
0
            break;
15940
0
        }
15941
15942
0
        result = PyList_New(0);
15943
0
        if (!result) {
15944
0
            goto exit;
15945
0
        }
15946
15947
0
        end = buffer + length;
15948
0
        for (trace = start = buffer; trace != end; trace++) {
15949
0
            if (!*trace) {
15950
0
                int error;
15951
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15952
0
                                                                 trace - start);
15953
0
                if (!attribute) {
15954
0
                    Py_SETREF(result, NULL);
15955
0
                    goto exit;
15956
0
                }
15957
0
                error = PyList_Append(result, attribute);
15958
0
                Py_DECREF(attribute);
15959
0
                if (error) {
15960
0
                    Py_SETREF(result, NULL);
15961
0
                    goto exit;
15962
0
                }
15963
0
                start = trace + 1;
15964
0
            }
15965
0
        }
15966
0
    break;
15967
0
    }
15968
0
exit:
15969
0
    if (buffer)
15970
0
        PyMem_Free(buffer);
15971
0
    return result;
15972
0
}
15973
#endif /* USE_XATTRS */
15974
15975
15976
/*[clinic input]
15977
@permit_long_summary
15978
os.urandom
15979
15980
    size: Py_ssize_t(allow_negative=False)
15981
    /
15982
15983
Return a bytes object containing random bytes suitable for cryptographic use.
15984
[clinic start generated code]*/
15985
15986
static PyObject *
15987
os_urandom_impl(PyObject *module, Py_ssize_t size)
15988
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15989
0
{
15990
0
    if (size < 0) {
15991
0
        return PyErr_Format(PyExc_ValueError,
15992
0
                            "negative argument not allowed");
15993
0
    }
15994
15995
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15996
0
    if (writer == NULL) {
15997
0
        return NULL;
15998
0
    }
15999
16000
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
16001
0
    if (result == -1) {
16002
0
        PyBytesWriter_Discard(writer);
16003
0
        return NULL;
16004
0
    }
16005
0
    return PyBytesWriter_Finish(writer);
16006
0
}
16007
16008
#if defined(HAVE_MEMFD_CREATE) || \
16009
    (defined(__linux__) && defined(__NR_memfd_create) && defined(MFD_CLOEXEC))
16010
#  define _Py_HAVE_MEMFD_CREATE
16011
#endif
16012
16013
#ifdef _Py_HAVE_MEMFD_CREATE
16014
/*[clinic input]
16015
os.memfd_create
16016
16017
    name: unicode_fs_encoded
16018
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
16019
16020
[clinic start generated code]*/
16021
16022
static PyObject *
16023
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
16024
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
16025
0
{
16026
0
    int fd;
16027
0
    const char *bytes = PyBytes_AS_STRING(name);
16028
0
    Py_BEGIN_ALLOW_THREADS
16029
0
#ifdef HAVE_MEMFD_CREATE
16030
0
    fd = memfd_create(bytes, flags);
16031
#else
16032
    fd = syscall(__NR_memfd_create, bytes, flags);
16033
#endif
16034
0
    Py_END_ALLOW_THREADS
16035
0
    if (fd == -1) {
16036
0
        return PyErr_SetFromErrno(PyExc_OSError);
16037
0
    }
16038
0
    return PyLong_FromLong(fd);
16039
0
}
16040
#endif
16041
16042
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
16043
/*[clinic input]
16044
os.eventfd
16045
16046
    initval: unsigned_int
16047
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
16048
16049
Creates and returns an event notification file descriptor.
16050
[clinic start generated code]*/
16051
16052
static PyObject *
16053
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
16054
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
16055
16056
0
{
16057
    /* initval is limited to uint32_t, internal counter is uint64_t */
16058
0
    int fd;
16059
0
    Py_BEGIN_ALLOW_THREADS
16060
0
    fd = eventfd(initval, flags);
16061
0
    Py_END_ALLOW_THREADS
16062
0
    if (fd == -1) {
16063
0
        return PyErr_SetFromErrno(PyExc_OSError);
16064
0
    }
16065
0
    return PyLong_FromLong(fd);
16066
0
}
16067
16068
/*[clinic input]
16069
os.eventfd_read
16070
16071
    fd: fildes
16072
16073
Read eventfd value
16074
[clinic start generated code]*/
16075
16076
static PyObject *
16077
os_eventfd_read_impl(PyObject *module, int fd)
16078
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
16079
0
{
16080
0
    eventfd_t value;
16081
0
    int result;
16082
0
    Py_BEGIN_ALLOW_THREADS
16083
0
    result = eventfd_read(fd, &value);
16084
0
    Py_END_ALLOW_THREADS
16085
0
    if (result == -1) {
16086
0
        return PyErr_SetFromErrno(PyExc_OSError);
16087
0
    }
16088
0
    return PyLong_FromUnsignedLongLong(value);
16089
0
}
16090
16091
/*[clinic input]
16092
os.eventfd_write
16093
16094
    fd: fildes
16095
    value: unsigned_long_long
16096
16097
Write eventfd value.
16098
[clinic start generated code]*/
16099
16100
static PyObject *
16101
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
16102
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
16103
0
{
16104
0
    int result;
16105
0
    Py_BEGIN_ALLOW_THREADS
16106
0
    result = eventfd_write(fd, value);
16107
0
    Py_END_ALLOW_THREADS
16108
0
    if (result == -1) {
16109
0
        return PyErr_SetFromErrno(PyExc_OSError);
16110
0
    }
16111
0
    Py_RETURN_NONE;
16112
0
}
16113
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
16114
16115
/* Terminal size querying */
16116
16117
PyDoc_STRVAR(TerminalSize_docstring,
16118
    "A tuple of (columns, lines) for holding terminal window size");
16119
16120
static PyStructSequence_Field TerminalSize_fields[] = {
16121
    {"columns", "width of the terminal window in characters"},
16122
    {"lines", "height of the terminal window in characters"},
16123
    {NULL, NULL}
16124
};
16125
16126
static PyStructSequence_Desc TerminalSize_desc = {
16127
    "os.terminal_size",
16128
    TerminalSize_docstring,
16129
    TerminalSize_fields,
16130
    2,
16131
};
16132
16133
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
16134
/*[clinic input]
16135
os.get_terminal_size
16136
16137
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
16138
    /
16139
16140
Return the size of the terminal window as (columns, lines).
16141
16142
The optional argument fd (default standard output) specifies
16143
which file descriptor should be queried.
16144
16145
If the file descriptor is not connected to a terminal, an OSError
16146
is thrown.
16147
16148
This function will only be defined if an implementation is
16149
available for this system.
16150
16151
shutil.get_terminal_size is the high-level function which should
16152
normally be used, os.get_terminal_size is the low-level implementation.
16153
[clinic start generated code]*/
16154
16155
static PyObject *
16156
os_get_terminal_size_impl(PyObject *module, int fd)
16157
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
16158
0
{
16159
0
    int columns, lines;
16160
0
    PyObject *termsize;
16161
16162
    /* Under some conditions stdout may not be connected and
16163
     * fileno(stdout) may point to an invalid file descriptor. For example
16164
     * GUI apps don't have valid standard streams by default.
16165
     *
16166
     * If this happens, and the optional fd argument is not present,
16167
     * the ioctl below will fail returning EBADF. This is what we want.
16168
     */
16169
16170
0
#ifdef TERMSIZE_USE_IOCTL
16171
0
    {
16172
        // On Android, stdout is probably not connected, and calling TIOCGWINSZ
16173
        // on an invalid file descriptor causes a log message "avc:  denied  {
16174
        // ioctl }". Some common tools such as pytest call get_terminal_size
16175
        // very often, so check it's a TTY first to avoid cluttering the log.
16176
0
        if (!isatty(fd))
16177
0
            return PyErr_SetFromErrno(PyExc_OSError);
16178
16179
0
        struct winsize w;
16180
0
        if (ioctl(fd, TIOCGWINSZ, &w))
16181
0
            return PyErr_SetFromErrno(PyExc_OSError);
16182
0
        columns = w.ws_col;
16183
0
        lines = w.ws_row;
16184
0
    }
16185
0
#endif /* TERMSIZE_USE_IOCTL */
16186
16187
#ifdef TERMSIZE_USE_CONIO
16188
    {
16189
        HANDLE handle;
16190
        CONSOLE_SCREEN_BUFFER_INFO csbi;
16191
        handle = _Py_get_osfhandle(fd);
16192
        if (handle == INVALID_HANDLE_VALUE)
16193
            return NULL;
16194
16195
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
16196
            return PyErr_SetFromWindowsErr(0);
16197
16198
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
16199
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
16200
    }
16201
#endif /* TERMSIZE_USE_CONIO */
16202
16203
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
16204
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
16205
0
    if (termsize == NULL)
16206
0
        return NULL;
16207
16208
0
    int pos = 0;
16209
16210
0
#define SET_TERMSIZE(CALL)                                   \
16211
0
    do {                                                     \
16212
0
        PyObject *item = (CALL);                             \
16213
0
        if (item == NULL) {                                  \
16214
0
            Py_DECREF(termsize);                             \
16215
0
            return NULL;                                     \
16216
0
        }                                                    \
16217
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
16218
0
    } while(0)
16219
16220
0
    SET_TERMSIZE(PyLong_FromLong(columns));
16221
0
    SET_TERMSIZE(PyLong_FromLong(lines));
16222
0
#undef SET_TERMSIZE
16223
16224
0
    return termsize;
16225
0
}
16226
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
16227
16228
/*[clinic input]
16229
os.cpu_count
16230
16231
Return the number of logical CPUs in the system.
16232
16233
Return None if indeterminable.
16234
[clinic start generated code]*/
16235
16236
static PyObject *
16237
os_cpu_count_impl(PyObject *module)
16238
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
16239
0
{
16240
0
    const PyConfig *config = _Py_GetConfig();
16241
0
    if (config->cpu_count > 0) {
16242
0
        return PyLong_FromLong(config->cpu_count);
16243
0
    }
16244
16245
0
    int ncpu = 0;
16246
#ifdef MS_WINDOWS
16247
# ifdef MS_WINDOWS_DESKTOP
16248
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
16249
# else
16250
    SYSTEM_INFO sysinfo;
16251
    GetSystemInfo(&sysinfo);
16252
    ncpu = sysinfo.dwNumberOfProcessors;
16253
# endif
16254
16255
#elif defined(__hpux)
16256
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
16257
16258
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
16259
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
16260
16261
#elif defined(__VXWORKS__)
16262
    ncpu = _Py_popcount32(vxCpuEnabledGet());
16263
16264
#elif defined(__DragonFly__) || \
16265
      defined(__OpenBSD__)   || \
16266
      defined(__FreeBSD__)   || \
16267
      defined(__NetBSD__)    || \
16268
      defined(__APPLE__)
16269
    ncpu = 0;
16270
    size_t len = sizeof(ncpu);
16271
    int mib[2] = {CTL_HW, HW_NCPU};
16272
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
16273
        ncpu = 0;
16274
    }
16275
#endif
16276
16277
0
    if (ncpu < 1) {
16278
0
        Py_RETURN_NONE;
16279
0
    }
16280
0
    return PyLong_FromLong(ncpu);
16281
0
}
16282
16283
16284
/*[clinic input]
16285
os.get_inheritable -> bool
16286
16287
    fd: int
16288
    /
16289
16290
Get the close-on-exe flag of the specified file descriptor.
16291
[clinic start generated code]*/
16292
16293
static int
16294
os_get_inheritable_impl(PyObject *module, int fd)
16295
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
16296
0
{
16297
0
    int return_value;
16298
0
    _Py_BEGIN_SUPPRESS_IPH
16299
0
    return_value = _Py_get_inheritable(fd);
16300
0
    _Py_END_SUPPRESS_IPH
16301
0
    return return_value;
16302
0
}
16303
16304
16305
/*[clinic input]
16306
os.set_inheritable
16307
    fd: int
16308
    inheritable: int
16309
    /
16310
16311
Set the inheritable flag of the specified file descriptor.
16312
[clinic start generated code]*/
16313
16314
static PyObject *
16315
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
16316
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
16317
0
{
16318
0
    int result;
16319
16320
0
    _Py_BEGIN_SUPPRESS_IPH
16321
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
16322
0
    _Py_END_SUPPRESS_IPH
16323
0
    if (result < 0)
16324
0
        return NULL;
16325
0
    Py_RETURN_NONE;
16326
0
}
16327
16328
16329
#ifdef MS_WINDOWS
16330
#ifndef HANDLE_FLAG_INHERIT
16331
#define HANDLE_FLAG_INHERIT 0x00000001
16332
#endif
16333
16334
/*[clinic input]
16335
os.get_handle_inheritable -> bool
16336
    handle: intptr_t
16337
    /
16338
16339
Get the close-on-exe flag of the specified file descriptor.
16340
[clinic start generated code]*/
16341
16342
static int
16343
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16344
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16345
{
16346
    DWORD flags;
16347
16348
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16349
        PyErr_SetFromWindowsErr(0);
16350
        return -1;
16351
    }
16352
16353
    return flags & HANDLE_FLAG_INHERIT;
16354
}
16355
16356
16357
/*[clinic input]
16358
os.set_handle_inheritable
16359
    handle: intptr_t
16360
    inheritable: bool
16361
    /
16362
16363
Set the inheritable flag of the specified handle.
16364
[clinic start generated code]*/
16365
16366
static PyObject *
16367
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16368
                               int inheritable)
16369
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16370
{
16371
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16372
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16373
        PyErr_SetFromWindowsErr(0);
16374
        return NULL;
16375
    }
16376
    Py_RETURN_NONE;
16377
}
16378
#endif /* MS_WINDOWS */
16379
16380
/*[clinic input]
16381
os.get_blocking -> bool
16382
    fd: int
16383
    /
16384
16385
Get the blocking mode of the file descriptor.
16386
16387
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16388
[clinic start generated code]*/
16389
16390
static int
16391
os_get_blocking_impl(PyObject *module, int fd)
16392
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16393
0
{
16394
0
    int blocking;
16395
16396
0
    _Py_BEGIN_SUPPRESS_IPH
16397
0
    blocking = _Py_get_blocking(fd);
16398
0
    _Py_END_SUPPRESS_IPH
16399
0
    return blocking;
16400
0
}
16401
16402
/*[clinic input]
16403
os.set_blocking
16404
    fd: int
16405
    blocking: bool
16406
    /
16407
16408
Set the blocking mode of the specified file descriptor.
16409
16410
Set the O_NONBLOCK flag if blocking is False,
16411
clear the O_NONBLOCK flag otherwise.
16412
[clinic start generated code]*/
16413
16414
static PyObject *
16415
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16416
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16417
0
{
16418
0
    int result;
16419
16420
0
    _Py_BEGIN_SUPPRESS_IPH
16421
0
    result = _Py_set_blocking(fd, blocking);
16422
0
    _Py_END_SUPPRESS_IPH
16423
0
    if (result < 0)
16424
0
        return NULL;
16425
0
    Py_RETURN_NONE;
16426
0
}
16427
16428
16429
/*[clinic input]
16430
class os.DirEntry "DirEntry *" "DirEntryType"
16431
class os.ScandirIterator "PyObject *" "ScandirIteratorType"
16432
[clinic start generated code]*/
16433
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b845e502eb4a0406]*/
16434
16435
typedef struct {
16436
    PyObject_HEAD
16437
    PyObject *name;
16438
    PyObject *path;
16439
    PyObject *stat;
16440
    PyObject *lstat;
16441
#ifdef MS_WINDOWS
16442
    struct _Py_stat_struct win32_lstat;
16443
    uint64_t win32_file_index;
16444
    uint64_t win32_file_index_high;
16445
    int got_file_index;
16446
#else /* POSIX */
16447
#ifdef HAVE_DIRENT_D_TYPE
16448
    unsigned char d_type;
16449
#endif
16450
    ino_t d_ino;
16451
    int dir_fd;
16452
#endif
16453
} DirEntry;
16454
16455
101k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16456
16457
static void
16458
DirEntry_dealloc(PyObject *op)
16459
101k
{
16460
101k
    DirEntry *entry = DirEntry_CAST(op);
16461
101k
    PyTypeObject *tp = Py_TYPE(entry);
16462
101k
    Py_XDECREF(entry->name);
16463
101k
    Py_XDECREF(entry->path);
16464
101k
    Py_XDECREF(entry->stat);
16465
101k
    Py_XDECREF(entry->lstat);
16466
101k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16467
101k
    free_func(entry);
16468
101k
    Py_DECREF(tp);
16469
101k
}
16470
16471
/* Forward reference */
16472
static int
16473
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16474
                   int follow_symlinks, unsigned short mode_bits);
16475
16476
/*[clinic input]
16477
os.DirEntry.is_symlink -> bool
16478
    defining_class: defining_class
16479
    /
16480
16481
Return True if the entry is a symbolic link; cached per entry.
16482
[clinic start generated code]*/
16483
16484
static int
16485
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16486
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16487
0
{
16488
#ifdef MS_WINDOWS
16489
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16490
#elif defined(HAVE_DIRENT_D_TYPE)
16491
    /* POSIX */
16492
0
    if (self->d_type != DT_UNKNOWN)
16493
0
        return self->d_type == DT_LNK;
16494
0
    else
16495
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16496
#else
16497
    /* POSIX without d_type */
16498
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16499
#endif
16500
0
}
16501
16502
/*[clinic input]
16503
os.DirEntry.is_junction -> bool
16504
16505
Return True if the entry is a junction; cached per entry.
16506
[clinic start generated code]*/
16507
16508
static int
16509
os_DirEntry_is_junction_impl(DirEntry *self)
16510
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16511
0
{
16512
#ifdef MS_WINDOWS
16513
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16514
#else
16515
0
    return 0;
16516
0
#endif
16517
0
}
16518
16519
static PyObject *
16520
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16521
84.3k
{
16522
84.3k
    int result;
16523
84.3k
    STRUCT_STAT st;
16524
84.3k
    PyObject *ub;
16525
16526
#ifdef MS_WINDOWS
16527
    if (!PyUnicode_FSDecoder(self->path, &ub))
16528
        return NULL;
16529
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16530
    Py_DECREF(ub);
16531
#else /* POSIX */
16532
84.3k
    if (!PyUnicode_FSConverter(self->path, &ub))
16533
0
        return NULL;
16534
84.3k
    const char *path = PyBytes_AS_STRING(ub);
16535
84.3k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16536
84.3k
#ifdef HAVE_FSTATAT
16537
84.3k
      if (HAVE_FSTATAT_RUNTIME) {
16538
84.3k
        Py_BEGIN_ALLOW_THREADS
16539
84.3k
        result = fstatat(self->dir_fd, path, &st,
16540
84.3k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16541
84.3k
        Py_END_ALLOW_THREADS
16542
84.3k
      } else
16543
16544
0
#endif /* HAVE_FSTATAT */
16545
0
      {
16546
0
        Py_DECREF(ub);
16547
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16548
0
        return NULL;
16549
0
      }
16550
84.3k
    }
16551
0
    else
16552
0
#endif
16553
0
    {
16554
0
        Py_BEGIN_ALLOW_THREADS
16555
0
        if (follow_symlinks) {
16556
0
            result = STAT(path, &st);
16557
0
        }
16558
0
        else {
16559
0
            result = LSTAT(path, &st);
16560
0
        }
16561
0
        Py_END_ALLOW_THREADS
16562
0
    }
16563
16564
84.3k
    int saved_errno = errno;
16565
#if defined(MS_WINDOWS)
16566
    PyMem_Free(path);
16567
#else
16568
84.3k
    Py_DECREF(ub);
16569
84.3k
#endif
16570
16571
84.3k
    if (result != 0) {
16572
0
        errno = saved_errno;
16573
0
        path_object_error(self->path);
16574
0
        return NULL;
16575
0
    }
16576
16577
84.3k
    return _pystat_fromstructstat(module, &st);
16578
84.3k
}
16579
16580
static PyObject *
16581
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16582
84.3k
{
16583
84.3k
    if (!self->lstat) {
16584
84.3k
        PyObject *module = PyType_GetModule(defining_class);
16585
#ifdef MS_WINDOWS
16586
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16587
#else /* POSIX */
16588
84.3k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16589
84.3k
#endif
16590
84.3k
    }
16591
84.3k
    return Py_XNewRef(self->lstat);
16592
84.3k
}
16593
16594
/*[clinic input]
16595
os.DirEntry.stat
16596
    defining_class: defining_class
16597
    /
16598
    *
16599
    follow_symlinks: bool = True
16600
16601
Return stat_result object for the entry; cached per entry.
16602
[clinic start generated code]*/
16603
16604
static PyObject *
16605
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16606
                      int follow_symlinks)
16607
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16608
84.3k
{
16609
84.3k
    if (!follow_symlinks) {
16610
84.3k
        return DirEntry_get_lstat(defining_class, self);
16611
84.3k
    }
16612
16613
0
    if (!self->stat) {
16614
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16615
0
        if (result == -1) {
16616
0
            return NULL;
16617
0
        }
16618
0
        if (result) {
16619
0
            PyObject *module = PyType_GetModule(defining_class);
16620
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16621
0
        }
16622
0
        else {
16623
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16624
0
        }
16625
0
    }
16626
16627
0
    return Py_XNewRef(self->stat);
16628
0
}
16629
16630
/* Set exception and return -1 on error, 0 for False, 1 for True */
16631
static int
16632
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16633
                   int follow_symlinks, unsigned short mode_bits)
16634
101k
{
16635
101k
    PyObject *stat = NULL;
16636
101k
    PyObject *st_mode = NULL;
16637
101k
    long mode;
16638
101k
    int result;
16639
101k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16640
101k
    int is_symlink;
16641
101k
    int need_stat;
16642
101k
#endif
16643
#ifdef MS_WINDOWS
16644
    unsigned long dir_bits;
16645
#endif
16646
16647
#ifdef MS_WINDOWS
16648
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16649
    need_stat = follow_symlinks && is_symlink;
16650
#elif defined(HAVE_DIRENT_D_TYPE)
16651
101k
    is_symlink = self->d_type == DT_LNK;
16652
101k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16653
101k
#endif
16654
16655
101k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16656
101k
    if (need_stat) {
16657
0
#endif
16658
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16659
0
        if (!stat) {
16660
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16661
                /* If file doesn't exist (anymore), then return False
16662
                   (i.e., say it's not a file/directory) */
16663
0
                PyErr_Clear();
16664
0
                return 0;
16665
0
            }
16666
0
            goto error;
16667
0
        }
16668
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16669
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16670
0
        if (!st_mode)
16671
0
            goto error;
16672
16673
0
        mode = PyLong_AsLong(st_mode);
16674
0
        if (mode == -1 && PyErr_Occurred())
16675
0
            goto error;
16676
0
        Py_CLEAR(st_mode);
16677
0
        Py_CLEAR(stat);
16678
0
        result = (mode & S_IFMT) == mode_bits;
16679
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16680
0
    }
16681
101k
    else if (is_symlink) {
16682
0
        assert(mode_bits != S_IFLNK);
16683
0
        result = 0;
16684
0
    }
16685
101k
    else {
16686
101k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16687
#ifdef MS_WINDOWS
16688
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16689
        if (mode_bits == S_IFDIR)
16690
            result = dir_bits != 0;
16691
        else
16692
            result = dir_bits == 0;
16693
#else /* POSIX */
16694
101k
        if (mode_bits == S_IFDIR)
16695
101k
            result = self->d_type == DT_DIR;
16696
0
        else
16697
0
            result = self->d_type == DT_REG;
16698
101k
#endif
16699
101k
    }
16700
101k
#endif
16701
16702
101k
    return result;
16703
16704
0
error:
16705
0
    Py_XDECREF(st_mode);
16706
0
    Py_XDECREF(stat);
16707
0
    return -1;
16708
101k
}
16709
16710
/*[clinic input]
16711
os.DirEntry.is_dir -> bool
16712
    defining_class: defining_class
16713
    /
16714
    *
16715
    follow_symlinks: bool = True
16716
16717
Return True if the entry is a directory; cached per entry.
16718
[clinic start generated code]*/
16719
16720
static int
16721
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16722
                        int follow_symlinks)
16723
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16724
101k
{
16725
101k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16726
101k
}
16727
16728
/*[clinic input]
16729
os.DirEntry.is_file -> bool
16730
    defining_class: defining_class
16731
    /
16732
    *
16733
    follow_symlinks: bool = True
16734
16735
Return True if the entry is a file; cached per entry.
16736
[clinic start generated code]*/
16737
16738
static int
16739
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16740
                         int follow_symlinks)
16741
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16742
0
{
16743
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16744
0
}
16745
16746
/*[clinic input]
16747
os.DirEntry.inode
16748
16749
Return inode of the entry; cached per entry.
16750
[clinic start generated code]*/
16751
16752
static PyObject *
16753
os_DirEntry_inode_impl(DirEntry *self)
16754
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16755
0
{
16756
#ifdef MS_WINDOWS
16757
    if (!self->got_file_index) {
16758
        PyObject *unicode;
16759
        STRUCT_STAT stat;
16760
        int result;
16761
16762
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16763
            return NULL;
16764
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16765
        Py_DECREF(unicode);
16766
        result = LSTAT(path, &stat);
16767
16768
        int saved_errno = errno;
16769
        PyMem_Free(path);
16770
16771
        if (result != 0) {
16772
            errno = saved_errno;
16773
            return path_object_error(self->path);
16774
        }
16775
16776
        self->win32_file_index = stat.st_ino;
16777
        self->win32_file_index_high = stat.st_ino_high;
16778
        self->got_file_index = 1;
16779
    }
16780
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16781
#else /* POSIX */
16782
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16783
0
                  "DirEntry.d_ino is larger than unsigned long long");
16784
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16785
0
#endif
16786
0
}
16787
16788
static PyObject *
16789
DirEntry_repr(PyObject *op)
16790
0
{
16791
0
    DirEntry *self = DirEntry_CAST(op);
16792
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16793
0
}
16794
16795
/*[clinic input]
16796
os.DirEntry.__fspath__
16797
16798
Returns the path for the entry.
16799
[clinic start generated code]*/
16800
16801
static PyObject *
16802
os_DirEntry___fspath___impl(DirEntry *self)
16803
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16804
0
{
16805
0
    return Py_NewRef(self->path);
16806
0
}
16807
16808
static PyMemberDef DirEntry_members[] = {
16809
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16810
     "the entry's base filename, relative to scandir() \"path\" argument"},
16811
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16812
     "the entry's full path name; equivalent to\nos.path.join(scandir_path, entry.name)"},
16813
    {NULL}
16814
};
16815
16816
#include "clinic/posixmodule.c.h"
16817
16818
static PyMethodDef DirEntry_methods[] = {
16819
    OS_DIRENTRY_IS_DIR_METHODDEF
16820
    OS_DIRENTRY_IS_FILE_METHODDEF
16821
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16822
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16823
    OS_DIRENTRY_STAT_METHODDEF
16824
    OS_DIRENTRY_INODE_METHODDEF
16825
    OS_DIRENTRY___FSPATH___METHODDEF
16826
    {"__class_getitem__",       Py_GenericAlias,
16827
    METH_O|METH_CLASS,          PyDoc_STR("DirEntry is generic over the type of the path (str or bytes)")},
16828
    {NULL}
16829
};
16830
16831
static PyType_Slot DirEntryType_slots[] = {
16832
    {Py_tp_dealloc, DirEntry_dealloc},
16833
    {Py_tp_repr, DirEntry_repr},
16834
    {Py_tp_methods, DirEntry_methods},
16835
    {Py_tp_members, DirEntry_members},
16836
    {0, 0},
16837
};
16838
16839
static PyType_Spec DirEntryType_spec = {
16840
    .name = MODNAME ".DirEntry",
16841
    .basicsize = sizeof(DirEntry),
16842
    .flags = (
16843
        Py_TPFLAGS_DEFAULT
16844
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16845
        | Py_TPFLAGS_IMMUTABLETYPE
16846
    ),
16847
    .slots = DirEntryType_slots
16848
};
16849
16850
16851
#ifdef MS_WINDOWS
16852
16853
static wchar_t *
16854
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,
16855
                    int normalize)
16856
{
16857
    Py_ssize_t path_len;
16858
    wchar_t *result;
16859
    wchar_t *path_allocated = NULL;
16860
16861
    if (!path_wide) { /* Default arg: "." */
16862
        path_wide = L".";
16863
        path_len = 1;
16864
    }
16865
    else {
16866
        path_len = wcslen(path_wide);
16867
    }
16868
16869
    if (path_len == 0) {
16870
        result = PyMem_New(wchar_t, 1);
16871
        if (result == NULL) {
16872
            PyErr_NoMemory();
16873
            return NULL;
16874
        }
16875
        result[0] = L'\0';
16876
        return result;
16877
    }
16878
16879
    if (normalize && !is_extended_path(path_wide)) {
16880
        int err = _PyOS_getfullpathname(path_wide, &path_allocated);
16881
        if (err < 0) {
16882
            PyErr_SetFromWindowsErr(0);
16883
            return NULL;
16884
        }
16885
        if (path_allocated == NULL) {
16886
            PyErr_NoMemory();
16887
            return NULL;
16888
        }
16889
        path_wide = path_allocated;
16890
        path_len = wcslen(path_wide);
16891
    }
16892
16893
    size_t size = (size_t)path_len + 1 + wcslen(filename) + 1;
16894
    result = PyMem_New(wchar_t, size);
16895
    if (result == NULL) {
16896
        PyMem_RawFree(path_allocated);
16897
        PyErr_NoMemory();
16898
        return NULL;
16899
    }
16900
    wcscpy(result, path_wide);
16901
    wchar_t ch = result[path_len - 1];
16902
    if (ch != SEP && ch != ALTSEP && ch != L':') {
16903
        result[path_len++] = SEP;
16904
    }
16905
    wcscpy(result + path_len, filename);
16906
    PyMem_RawFree(path_allocated);
16907
    return result;
16908
}
16909
16910
static PyObject *
16911
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16912
{
16913
    DirEntry *entry;
16914
    FILE_BASIC_INFO basic_info;
16915
    FILE_STANDARD_INFO standard_info;
16916
    ULONG reparse_tag;
16917
    wchar_t *joined_path;
16918
16919
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16920
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16921
    if (!entry)
16922
        return NULL;
16923
    entry->name = NULL;
16924
    entry->path = NULL;
16925
    entry->stat = NULL;
16926
    entry->lstat = NULL;
16927
    entry->got_file_index = 0;
16928
16929
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16930
    if (!entry->name)
16931
        goto error;
16932
    int return_bytes = path->wide && PyBytes_Check(path->object);
16933
    if (return_bytes) {
16934
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16935
        if (!entry->name)
16936
            goto error;
16937
    }
16938
16939
    joined_path = join_path_filenameW(path->wide, dataW->cFileName, 0);
16940
    if (!joined_path)
16941
        goto error;
16942
16943
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16944
    PyMem_Free(joined_path);
16945
    if (!entry->path)
16946
        goto error;
16947
    if (return_bytes) {
16948
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16949
        if (!entry->path)
16950
            goto error;
16951
    }
16952
16953
    find_data_to_file_info(dataW, &basic_info, &standard_info, &reparse_tag);
16954
    _Py_attribute_data_to_stat(&standard_info, reparse_tag, &basic_info, NULL, &entry->win32_lstat);
16955
16956
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16957
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16958
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16959
16960
    return (PyObject *)entry;
16961
16962
error:
16963
    Py_DECREF(entry);
16964
    return NULL;
16965
}
16966
16967
#else /* POSIX */
16968
16969
static char *
16970
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16971
0
{
16972
0
    Py_ssize_t path_len;
16973
0
    Py_ssize_t size;
16974
0
    char *result;
16975
16976
0
    if (!path_narrow) { /* Default arg: "." */
16977
0
        path_narrow = ".";
16978
0
        path_len = 1;
16979
0
    }
16980
0
    else {
16981
0
        path_len = strlen(path_narrow);
16982
0
    }
16983
16984
0
    if (filename_len == -1)
16985
0
        filename_len = strlen(filename);
16986
16987
    /* The +1's are for the path separator and the NUL */
16988
0
    size = path_len + 1 + filename_len + 1;
16989
0
    result = PyMem_New(char, size);
16990
0
    if (!result) {
16991
0
        PyErr_NoMemory();
16992
0
        return NULL;
16993
0
    }
16994
0
    strcpy(result, path_narrow);
16995
0
    if (path_len > 0 && result[path_len - 1] != '/')
16996
0
        result[path_len++] = '/';
16997
0
    strcpy(result + path_len, filename);
16998
0
    return result;
16999
0
}
17000
17001
static PyObject *
17002
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
17003
                         Py_ssize_t name_len, ino_t d_ino
17004
#ifdef HAVE_DIRENT_D_TYPE
17005
                         , unsigned char d_type
17006
#endif
17007
                         )
17008
101k
{
17009
101k
    DirEntry *entry;
17010
101k
    char *joined_path;
17011
17012
101k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
17013
101k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
17014
101k
    if (!entry)
17015
0
        return NULL;
17016
101k
    entry->name = NULL;
17017
101k
    entry->path = NULL;
17018
101k
    entry->stat = NULL;
17019
101k
    entry->lstat = NULL;
17020
17021
101k
    if (path->is_fd) {
17022
101k
        entry->dir_fd = path->fd;
17023
101k
        joined_path = NULL;
17024
101k
    }
17025
0
    else {
17026
0
        entry->dir_fd = DEFAULT_DIR_FD;
17027
0
        joined_path = join_path_filename(path->narrow, name, name_len);
17028
0
        if (!joined_path)
17029
0
            goto error;
17030
0
    }
17031
17032
101k
    if (!path->narrow || !PyBytes_Check(path->object)) {
17033
101k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
17034
101k
        if (joined_path)
17035
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
17036
101k
    }
17037
0
    else {
17038
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
17039
0
        if (joined_path)
17040
0
            entry->path = PyBytes_FromString(joined_path);
17041
0
    }
17042
101k
    PyMem_Free(joined_path);
17043
101k
    if (!entry->name)
17044
0
        goto error;
17045
17046
101k
    if (path->is_fd) {
17047
101k
        entry->path = Py_NewRef(entry->name);
17048
101k
    }
17049
0
    else if (!entry->path)
17050
0
        goto error;
17051
17052
101k
#ifdef HAVE_DIRENT_D_TYPE
17053
101k
    entry->d_type = d_type;
17054
101k
#endif
17055
101k
    entry->d_ino = d_ino;
17056
17057
101k
    return (PyObject *)entry;
17058
17059
0
error:
17060
0
    Py_XDECREF(entry);
17061
0
    return NULL;
17062
101k
}
17063
17064
#endif
17065
17066
17067
typedef struct {
17068
    PyObject_HEAD
17069
    path_t path;
17070
#ifdef MS_WINDOWS
17071
    HANDLE handle;
17072
    WIN32_FIND_DATAW file_data;
17073
    int first_time;
17074
#else /* POSIX */
17075
    DIR *dirp;
17076
#endif
17077
#ifdef HAVE_FDOPENDIR
17078
    int fd;
17079
#endif
17080
    // Sharing the iterator between threads is subject to race conditions:
17081
    // which entries each thread receives is unspecified.  It must not
17082
    // corrupt the iterator or crash.  Since we don't want close() to be
17083
    // held up by a blocking directory read, we set the 'closed' flag if
17084
    // there are reads in progress.
17085
    PyMutex read_mutex;
17086
    uint8_t closed;
17087
} ScandirIterator;
17088
17089
366k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
17090
17091
#ifdef MS_WINDOWS
17092
17093
static int
17094
ScandirIterator_is_closed(ScandirIterator *iterator)
17095
{
17096
    return _Py_atomic_load_uint8(&iterator->closed);
17097
}
17098
17099
static void
17100
ScandirIterator_closedir(ScandirIterator *iterator)
17101
{
17102
    HANDLE handle = INVALID_HANDLE_VALUE;
17103
17104
    _Py_atomic_store_uint8(&iterator->closed, 1);
17105
    if (PyMutex_LockFast(&iterator->read_mutex)) {
17106
        // no reads in progress, we can close the handle
17107
        handle = iterator->handle;
17108
        iterator->handle = INVALID_HANDLE_VALUE;
17109
        PyMutex_Unlock(&iterator->read_mutex);
17110
    }
17111
17112
    if (handle != INVALID_HANDLE_VALUE) {
17113
        Py_BEGIN_ALLOW_THREADS
17114
        FindClose(handle);
17115
        Py_END_ALLOW_THREADS
17116
    }
17117
}
17118
17119
static PyObject *
17120
ScandirIterator_iternext(PyObject *op)
17121
{
17122
    ScandirIterator *iterator = ScandirIterator_CAST(op);
17123
    WIN32_FIND_DATAW file_data;
17124
    BOOL success;
17125
    DWORD error = ERROR_SUCCESS;
17126
    int found = 0;
17127
17128
    PyMutex_Lock(&iterator->read_mutex);
17129
    /* Happens if the iterator is iterated twice, or closed explicitly */
17130
    while (iterator->handle != INVALID_HANDLE_VALUE &&
17131
           !_Py_atomic_load_uint8_relaxed(&iterator->closed))
17132
    {
17133
        if (!iterator->first_time) {
17134
            Py_BEGIN_ALLOW_THREADS
17135
            success = FindNextFileW(iterator->handle, &iterator->file_data);
17136
            if (!success) {
17137
                error = GetLastError();
17138
            }
17139
            Py_END_ALLOW_THREADS
17140
            if (!success) {
17141
                break;
17142
            }
17143
        }
17144
        iterator->first_time = 0;
17145
17146
        /* Skip over . and .. */
17147
        if (wcscmp(iterator->file_data.cFileName, L".") != 0 &&
17148
            wcscmp(iterator->file_data.cFileName, L"..") != 0)
17149
        {
17150
            file_data = iterator->file_data;
17151
            found = 1;
17152
            break;
17153
        }
17154
17155
        /* Loop till we get a non-dot directory or finish iterating */
17156
    }
17157
    PyMutex_Unlock(&iterator->read_mutex);
17158
17159
    if (found && ScandirIterator_is_closed(iterator)) {
17160
        ScandirIterator_closedir(iterator); // deferred close
17161
    }
17162
17163
    if (found) {
17164
        PyObject *module = PyType_GetModule(Py_TYPE(iterator));
17165
        PyObject *entry = DirEntry_from_find_data(module, &iterator->path, &file_data);
17166
        if (entry != NULL) {
17167
            return entry;
17168
        }
17169
    }
17170
    else if (error != ERROR_SUCCESS && error != ERROR_NO_MORE_FILES) {
17171
        SetLastError(error);
17172
        path_error(&iterator->path);
17173
    }
17174
17175
    /* Error or no more files */
17176
    ScandirIterator_closedir(iterator);
17177
    return NULL;
17178
}
17179
17180
#else /* POSIX */
17181
17182
static int
17183
ScandirIterator_is_closed(ScandirIterator *iterator)
17184
189k
{
17185
189k
    return _Py_atomic_load_uint8(&iterator->closed);
17186
189k
}
17187
17188
static void
17189
ScandirIterator_closedir(ScandirIterator *iterator)
17190
265k
{
17191
265k
    DIR *dirp = NULL;
17192
17193
265k
    _Py_atomic_store_uint8(&iterator->closed, 1);
17194
265k
    if (PyMutex_LockFast(&iterator->read_mutex)) {
17195
        // no reads in progress, we can close dirp
17196
265k
        dirp = iterator->dirp;
17197
265k
        iterator->dirp = NULL;
17198
265k
        PyMutex_Unlock(&iterator->read_mutex);
17199
265k
    }
17200
17201
265k
    if (dirp != NULL) {
17202
88.4k
        Py_BEGIN_ALLOW_THREADS
17203
88.4k
#ifdef HAVE_FDOPENDIR
17204
88.4k
        if (iterator->path.is_fd) {
17205
88.4k
            rewinddir(dirp);
17206
88.4k
        }
17207
88.4k
#endif
17208
88.4k
        closedir(dirp);
17209
88.4k
        Py_END_ALLOW_THREADS
17210
88.4k
    }
17211
265k
}
17212
17213
static PyObject *
17214
ScandirIterator_iternext(PyObject *op)
17215
189k
{
17216
189k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
17217
189k
    struct dirent *direntp;
17218
189k
    Py_ssize_t name_len = 0;
17219
189k
    int is_dot;
17220
189k
    int found = 0;
17221
189k
    int error = 0;
17222
189k
    int no_memory = 0;
17223
189k
    char namebuf[256];
17224
189k
    char *name = namebuf;
17225
189k
    ino_t d_ino = 0;
17226
189k
#ifdef HAVE_DIRENT_D_TYPE
17227
189k
    unsigned char d_type = 0;
17228
189k
#endif
17229
17230
189k
    PyMutex_Lock(&iterator->read_mutex);
17231
    /* Happens if the iterator is iterated twice, or closed explicitly */
17232
366k
    while (iterator->dirp != NULL &&
17233
366k
           !_Py_atomic_load_uint8_relaxed(&iterator->closed))
17234
366k
    {
17235
366k
        Py_BEGIN_ALLOW_THREADS
17236
366k
        errno = 0;
17237
366k
        direntp = readdir(iterator->dirp);
17238
366k
        if (direntp == NULL) {
17239
88.4k
            error = errno;
17240
88.4k
        }
17241
366k
        Py_END_ALLOW_THREADS
17242
17243
366k
        if (!direntp) {
17244
88.4k
            break;
17245
88.4k
        }
17246
17247
        /* Skip over . and .. */
17248
278k
        name_len = NAMLEN(direntp);
17249
278k
        is_dot = direntp->d_name[0] == '.' &&
17250
177k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
17251
278k
        if (!is_dot) {
17252
101k
            if ((size_t)name_len >= sizeof(namebuf)) {
17253
0
                name = PyMem_RawMalloc(name_len + 1);
17254
0
                if (name == NULL) {
17255
0
                    no_memory = 1;
17256
0
                    break;
17257
0
                }
17258
0
            }
17259
101k
            memcpy(name, direntp->d_name, name_len);
17260
101k
            name[name_len] = '\0';
17261
101k
            d_ino = direntp->d_ino;
17262
101k
#ifdef HAVE_DIRENT_D_TYPE
17263
101k
            d_type = direntp->d_type;
17264
101k
#endif
17265
101k
            found = 1;
17266
101k
            break;
17267
101k
        }
17268
17269
        /* Loop till we get a non-dot directory or finish iterating */
17270
278k
    }
17271
189k
    PyMutex_Unlock(&iterator->read_mutex);
17272
17273
189k
    if (found && ScandirIterator_is_closed(iterator)) {
17274
0
        ScandirIterator_closedir(iterator); // deferred close
17275
0
    }
17276
17277
189k
    if (found) {
17278
101k
        PyObject *module = PyType_GetModule(Py_TYPE(iterator));
17279
101k
        PyObject *entry = DirEntry_from_posix_info(module,
17280
101k
                                                   &iterator->path, name,
17281
101k
                                                   name_len, d_ino
17282
101k
#ifdef HAVE_DIRENT_D_TYPE
17283
101k
                                                   , d_type
17284
101k
#endif
17285
101k
                                                  );
17286
101k
        if (name != namebuf) {
17287
0
            PyMem_RawFree(name);
17288
0
        }
17289
101k
        if (entry != NULL) {
17290
101k
            return entry;
17291
101k
        }
17292
101k
    }
17293
88.4k
    else if (no_memory) {
17294
0
        PyErr_NoMemory();
17295
0
    }
17296
88.4k
    else if (error != 0) {
17297
0
        errno = error;
17298
0
        path_error(&iterator->path);
17299
0
    }
17300
17301
    /* Error or no more files */
17302
88.4k
    ScandirIterator_closedir(iterator);
17303
88.4k
    return NULL;
17304
189k
}
17305
17306
#endif
17307
17308
static PyObject *
17309
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
17310
0
{
17311
0
    ScandirIterator *self = ScandirIterator_CAST(op);
17312
0
    ScandirIterator_closedir(self);
17313
0
    Py_RETURN_NONE;
17314
0
}
17315
17316
static PyObject *
17317
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
17318
88.4k
{
17319
88.4k
    return Py_NewRef(self);
17320
88.4k
}
17321
17322
/*[clinic input]
17323
os.ScandirIterator.__exit__
17324
17325
    *exc_info: array
17326
17327
Close the scandir iterator.
17328
[clinic start generated code]*/
17329
17330
static PyObject *
17331
os_ScandirIterator___exit___impl(PyObject *self, PyObject * const *exc_info,
17332
                                 Py_ssize_t exc_info_length)
17333
/*[clinic end generated code: output=5d3941725a7c97c7 input=ff3ffe83ae605a36]*/
17334
88.4k
{
17335
88.4k
    ScandirIterator_closedir(ScandirIterator_CAST(self));
17336
88.4k
    Py_RETURN_NONE;
17337
88.4k
}
17338
17339
static void
17340
ScandirIterator_finalize(PyObject *op)
17341
88.4k
{
17342
88.4k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
17343
    /* Save the current exception, if any. */
17344
88.4k
    PyObject *exc = PyErr_GetRaisedException();
17345
17346
88.4k
    int was_closed = ScandirIterator_is_closed(iterator);
17347
17348
88.4k
    ScandirIterator_closedir(iterator);
17349
17350
88.4k
    if (!was_closed) {
17351
0
        if (PyErr_ResourceWarning(op, 1,
17352
0
                                  "unclosed scandir iterator %R", iterator))
17353
0
        {
17354
            /* Spurious errors can appear at shutdown */
17355
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
17356
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
17357
0
                                       "scandir iterator %R", iterator);
17358
0
            }
17359
0
        }
17360
0
    }
17361
17362
88.4k
    path_cleanup(&iterator->path);
17363
17364
    /* Restore the saved exception. */
17365
88.4k
    PyErr_SetRaisedException(exc);
17366
88.4k
}
17367
17368
static void
17369
ScandirIterator_dealloc(PyObject *op)
17370
88.4k
{
17371
88.4k
    PyTypeObject *tp = Py_TYPE(op);
17372
88.4k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
17373
0
        return;
17374
17375
88.4k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
17376
88.4k
    free_func(op);
17377
88.4k
    Py_DECREF(tp);
17378
88.4k
}
17379
17380
static PyMethodDef ScandirIterator_methods[] = {
17381
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
17382
    OS_SCANDIRITERATOR___EXIT___METHODDEF
17383
    {"close", ScandirIterator_close, METH_NOARGS},
17384
    {NULL}
17385
};
17386
17387
static PyType_Slot ScandirIteratorType_slots[] = {
17388
    {Py_tp_dealloc, ScandirIterator_dealloc},
17389
    {Py_tp_finalize, ScandirIterator_finalize},
17390
    {Py_tp_iter, PyObject_SelfIter},
17391
    {Py_tp_iternext, ScandirIterator_iternext},
17392
    {Py_tp_methods, ScandirIterator_methods},
17393
    {0, 0},
17394
};
17395
17396
static PyType_Spec ScandirIteratorType_spec = {
17397
    .name = MODNAME ".ScandirIterator",
17398
    .basicsize = sizeof(ScandirIterator),
17399
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
17400
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
17401
    .flags = (
17402
        Py_TPFLAGS_DEFAULT
17403
        | Py_TPFLAGS_HAVE_FINALIZE
17404
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
17405
        | Py_TPFLAGS_IMMUTABLETYPE
17406
    ),
17407
    .slots = ScandirIteratorType_slots
17408
};
17409
17410
/*[clinic input]
17411
os.scandir
17412
17413
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
17414
17415
Return an iterator of DirEntry objects for given path.
17416
17417
path can be specified as either str, bytes, or a path-like object.  If
17418
path is bytes, the names of yielded DirEntry objects will also be bytes;
17419
in all other circumstances they will be str.
17420
17421
If path is None, uses the path='.'.
17422
[clinic start generated code]*/
17423
17424
static PyObject *
17425
os_scandir_impl(PyObject *module, path_t *path)
17426
/*[clinic end generated code: output=6eb2668b675ca89e input=6ab9600993f51577]*/
17427
88.4k
{
17428
88.4k
    ScandirIterator *iterator;
17429
#ifdef MS_WINDOWS
17430
    wchar_t *path_strW;
17431
#else
17432
88.4k
    const char *path_str;
17433
88.4k
#ifdef HAVE_FDOPENDIR
17434
88.4k
    int fd = -1;
17435
88.4k
#endif
17436
88.4k
#endif
17437
17438
88.4k
    if (PySys_Audit("os.scandir", "O",
17439
88.4k
                    path->object ? path->object : Py_None) < 0) {
17440
0
        return NULL;
17441
0
    }
17442
17443
88.4k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
17444
88.4k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
17445
88.4k
    if (!iterator)
17446
0
        return NULL;
17447
17448
88.4k
    iterator->read_mutex = (PyMutex){0};
17449
88.4k
    iterator->closed = 1;
17450
#ifdef MS_WINDOWS
17451
    iterator->handle = INVALID_HANDLE_VALUE;
17452
#else
17453
88.4k
    iterator->dirp = NULL;
17454
88.4k
#endif
17455
17456
    /* Move the ownership to iterator->path */
17457
88.4k
    memcpy(&iterator->path, path, sizeof(path_t));
17458
88.4k
    memset(path, 0, sizeof(path_t));
17459
17460
#ifdef MS_WINDOWS
17461
    iterator->first_time = 1;
17462
17463
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*", 1);
17464
    if (!path_strW)
17465
        goto error;
17466
17467
    Py_BEGIN_ALLOW_THREADS
17468
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17469
    Py_END_ALLOW_THREADS
17470
17471
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17472
        path_error(&iterator->path);
17473
        PyMem_Free(path_strW);
17474
        goto error;
17475
    }
17476
    PyMem_Free(path_strW);
17477
#else /* POSIX */
17478
88.4k
    errno = 0;
17479
88.4k
#ifdef HAVE_FDOPENDIR
17480
88.4k
    if (iterator->path.is_fd) {
17481
88.4k
      if (HAVE_FDOPENDIR_RUNTIME) {
17482
        /* closedir() closes the FD, so we duplicate it */
17483
88.4k
        fd = _Py_dup(iterator->path.fd);
17484
88.4k
        if (fd == -1)
17485
0
            goto error;
17486
17487
88.4k
        Py_BEGIN_ALLOW_THREADS
17488
88.4k
        iterator->dirp = fdopendir(fd);
17489
88.4k
        Py_END_ALLOW_THREADS
17490
88.4k
      } else {
17491
0
        PyErr_SetString(PyExc_TypeError,
17492
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17493
0
        return NULL;
17494
0
      }
17495
88.4k
    }
17496
0
    else
17497
0
#endif
17498
0
    {
17499
0
        if (iterator->path.narrow)
17500
0
            path_str = iterator->path.narrow;
17501
0
        else
17502
0
            path_str = ".";
17503
17504
0
        Py_BEGIN_ALLOW_THREADS
17505
0
        iterator->dirp = opendir(path_str);
17506
0
        Py_END_ALLOW_THREADS
17507
0
    }
17508
17509
88.4k
    if (!iterator->dirp) {
17510
0
        path_error(&iterator->path);
17511
0
#ifdef HAVE_FDOPENDIR
17512
0
        if (fd != -1) {
17513
0
            Py_BEGIN_ALLOW_THREADS
17514
0
            close(fd);
17515
0
            Py_END_ALLOW_THREADS
17516
0
        }
17517
0
#endif
17518
0
        goto error;
17519
0
    }
17520
88.4k
#endif
17521
17522
88.4k
    iterator->closed = 0;
17523
88.4k
    return (PyObject *)iterator;
17524
17525
0
error:
17526
0
    Py_DECREF(iterator);
17527
0
    return NULL;
17528
88.4k
}
17529
17530
/*
17531
    Return the file system path representation of the object.
17532
17533
    If the object is str or bytes, then allow it to pass through with
17534
    an incremented refcount. If the object defines __fspath__(), then
17535
    return the result of that method. All other types raise a TypeError.
17536
*/
17537
PyObject *
17538
PyOS_FSPath(PyObject *path)
17539
915k
{
17540
    /* For error message reasons, this function is manually inlined in
17541
       path_converter(). */
17542
915k
    PyObject *func = NULL;
17543
915k
    PyObject *path_repr = NULL;
17544
17545
915k
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17546
915k
        return Py_NewRef(path);
17547
915k
    }
17548
17549
216
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17550
216
    if ((NULL == func) || (func == Py_None)) {
17551
0
        return PyErr_Format(PyExc_TypeError,
17552
0
                            "expected str, bytes or os.PathLike object, "
17553
0
                            "not %.200s",
17554
0
                            _PyType_Name(Py_TYPE(path)));
17555
0
    }
17556
17557
216
    path_repr = _PyObject_CallNoArgs(func);
17558
216
    Py_DECREF(func);
17559
216
    if (NULL == path_repr) {
17560
0
        return NULL;
17561
0
    }
17562
17563
216
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17564
0
        PyErr_Format(PyExc_TypeError,
17565
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17566
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17567
0
                     _PyType_Name(Py_TYPE(path_repr)));
17568
0
        Py_DECREF(path_repr);
17569
0
        return NULL;
17570
0
    }
17571
17572
216
    return path_repr;
17573
216
}
17574
17575
/*[clinic input]
17576
os.fspath
17577
17578
    path: object
17579
17580
Return the file system path representation of the object.
17581
17582
If the object is str or bytes, then allow it to pass through as-is.  If
17583
the object defines __fspath__(), then return the result of that method.
17584
All other types raise a TypeError.
17585
[clinic start generated code]*/
17586
17587
static PyObject *
17588
os_fspath_impl(PyObject *module, PyObject *path)
17589
/*[clinic end generated code: output=c3c3b78ecff2914f input=d3c54404240d5da0]*/
17590
646k
{
17591
646k
    return PyOS_FSPath(path);
17592
646k
}
17593
17594
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
17595
/*[clinic input]
17596
os.getrandom
17597
17598
    size: Py_ssize_t
17599
    flags: unsigned_int(bitwise=True) = 0
17600
17601
Obtain a series of random bytes.
17602
[clinic start generated code]*/
17603
17604
static PyObject *
17605
os_getrandom_impl(PyObject *module, Py_ssize_t size, unsigned int flags)
17606
/*[clinic end generated code: output=c2163c05f0e1d0a1 input=e0174983f5703f82]*/
17607
0
{
17608
0
    if (size < 0) {
17609
0
        errno = EINVAL;
17610
0
        return posix_error();
17611
0
    }
17612
17613
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17614
0
    if (writer == NULL) {
17615
0
        return NULL;
17616
0
    }
17617
0
    void *data = PyBytesWriter_GetData(writer);
17618
17619
0
    Py_ssize_t n;
17620
0
    while (1) {
17621
0
#ifdef HAVE_GETRANDOM
17622
0
        n = getrandom(data, size, flags);
17623
#else
17624
        n = syscall(SYS_getrandom, data, size, flags);
17625
#endif
17626
0
        if (n < 0 && errno == EINTR) {
17627
0
            if (PyErr_CheckSignals() < 0) {
17628
0
                goto error;
17629
0
            }
17630
17631
            /* getrandom() was interrupted by a signal: retry */
17632
0
            continue;
17633
0
        }
17634
0
        break;
17635
0
    }
17636
17637
0
    if (n < 0) {
17638
0
        PyErr_SetFromErrno(PyExc_OSError);
17639
0
        goto error;
17640
0
    }
17641
17642
0
    _Py_MSAN_UNPOISON(data, size);
17643
17644
0
    return PyBytesWriter_FinishWithSize(writer, n);
17645
17646
0
error:
17647
0
    PyBytesWriter_Discard(writer);
17648
0
    return NULL;
17649
0
}
17650
#endif   /* HAVE_GETRANDOM_SYSCALL */
17651
17652
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17653
17654
/* bpo-36085: Helper functions for managing DLL search directories
17655
 * on win32
17656
 */
17657
17658
/*[clinic input]
17659
os._add_dll_directory
17660
17661
    path: path_t
17662
17663
Add a path to the DLL search path.
17664
17665
This search path is used when resolving dependencies for imported
17666
extension modules (the module itself is resolved through sys.path),
17667
and also by ctypes.
17668
17669
Returns an opaque value that may be passed to os.remove_dll_directory
17670
to remove this directory from the search path.
17671
[clinic start generated code]*/
17672
17673
static PyObject *
17674
os__add_dll_directory_impl(PyObject *module, path_t *path)
17675
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17676
{
17677
    DLL_DIRECTORY_COOKIE cookie = 0;
17678
    DWORD err = 0;
17679
17680
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17681
        return NULL;
17682
    }
17683
17684
    Py_BEGIN_ALLOW_THREADS
17685
    if (!(cookie = AddDllDirectory(path->wide))) {
17686
        err = GetLastError();
17687
    }
17688
    Py_END_ALLOW_THREADS
17689
17690
    if (err) {
17691
        return win32_error_object_err("add_dll_directory",
17692
                                      path->object, err);
17693
    }
17694
17695
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17696
}
17697
17698
/*[clinic input]
17699
os._remove_dll_directory
17700
17701
    cookie: object
17702
17703
Removes a path from the DLL search path.
17704
17705
The parameter is an opaque value that was returned from
17706
os.add_dll_directory. You can only remove directories that you added
17707
yourself.
17708
[clinic start generated code]*/
17709
17710
static PyObject *
17711
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17712
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17713
{
17714
    DLL_DIRECTORY_COOKIE cookieValue;
17715
    DWORD err = 0;
17716
17717
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17718
        PyErr_SetString(PyExc_TypeError,
17719
            "Provided cookie was not returned from os.add_dll_directory");
17720
        return NULL;
17721
    }
17722
17723
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17724
        cookie, "DLL directory cookie");
17725
17726
    Py_BEGIN_ALLOW_THREADS
17727
    if (!RemoveDllDirectory(cookieValue)) {
17728
        err = GetLastError();
17729
    }
17730
    Py_END_ALLOW_THREADS
17731
17732
    if (err) {
17733
        return win32_error_object_err("remove_dll_directory",
17734
                                      NULL, err);
17735
    }
17736
17737
    if (PyCapsule_SetName(cookie, NULL)) {
17738
        return NULL;
17739
    }
17740
17741
    Py_RETURN_NONE;
17742
}
17743
17744
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17745
17746
17747
/* Only check if WIFEXITED is available: expect that it comes
17748
   with WEXITSTATUS, WIFSIGNALED, etc.
17749
17750
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17751
   subprocess can safely call it during late Python finalization without
17752
   risking that used os attributes were set to None by finalize_modules(). */
17753
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17754
/*[clinic input]
17755
os.waitstatus_to_exitcode
17756
17757
    status as status_obj: object
17758
17759
Convert a wait status to an exit code.
17760
17761
On Unix:
17762
17763
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17764
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17765
* Otherwise, raise a ValueError.
17766
17767
On Windows, return status shifted right by 8 bits.
17768
17769
On Unix, if the process is being traced or if waitpid() was called with
17770
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is
17771
true.  This function must not be called if WIFSTOPPED(status) is true.
17772
[clinic start generated code]*/
17773
17774
static PyObject *
17775
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17776
/*[clinic end generated code: output=db50b1b0ba3c7153 input=3b44a23f5090006c]*/
17777
0
{
17778
0
#ifndef MS_WINDOWS
17779
0
    int status = PyLong_AsInt(status_obj);
17780
0
    if (status == -1 && PyErr_Occurred()) {
17781
0
        return NULL;
17782
0
    }
17783
17784
0
    WAIT_TYPE wait_status;
17785
0
    WAIT_STATUS_INT(wait_status) = status;
17786
0
    int exitcode;
17787
0
    if (WIFEXITED(wait_status)) {
17788
0
        exitcode = WEXITSTATUS(wait_status);
17789
        /* Sanity check to provide warranty on the function behavior.
17790
           It should not occur in practice */
17791
0
        if (exitcode < 0) {
17792
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17793
0
            return NULL;
17794
0
        }
17795
0
    }
17796
0
    else if (WIFSIGNALED(wait_status)) {
17797
0
        int signum = WTERMSIG(wait_status);
17798
        /* Sanity check to provide warranty on the function behavior.
17799
           It should not occurs in practice */
17800
0
        if (signum <= 0) {
17801
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17802
0
            return NULL;
17803
0
        }
17804
0
        exitcode = -signum;
17805
0
    } else if (WIFSTOPPED(wait_status)) {
17806
        /* Status only received if the process is being traced
17807
           or if waitpid() was called with WUNTRACED option. */
17808
0
        int signum = WSTOPSIG(wait_status);
17809
0
        PyErr_Format(PyExc_ValueError,
17810
0
                     "process stopped by delivery of signal %i",
17811
0
                     signum);
17812
0
        return NULL;
17813
0
    }
17814
0
    else {
17815
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17816
0
        return NULL;
17817
0
    }
17818
0
    return PyLong_FromLong(exitcode);
17819
#else
17820
    /* Windows implementation: see os.waitpid() implementation
17821
       which uses _cwait(). */
17822
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17823
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17824
        return NULL;
17825
    }
17826
17827
    unsigned long long exitcode = (status >> 8);
17828
    /* ExitProcess() accepts an UINT type:
17829
       reject exit code which doesn't fit in an UINT */
17830
    if (exitcode > UINT_MAX) {
17831
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17832
        return NULL;
17833
    }
17834
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17835
#endif
17836
0
}
17837
#endif
17838
17839
#if defined(MS_WINDOWS)
17840
/*[clinic input]
17841
os._supports_virtual_terminal
17842
17843
Checks if virtual terminal is supported in windows
17844
[clinic start generated code]*/
17845
17846
static PyObject *
17847
os__supports_virtual_terminal_impl(PyObject *module)
17848
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17849
{
17850
#ifdef HAVE_WINDOWS_CONSOLE_IO
17851
    DWORD mode = 0;
17852
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17853
    if (!GetConsoleMode(handle, &mode)) {
17854
        Py_RETURN_FALSE;
17855
    }
17856
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17857
#else
17858
    Py_RETURN_FALSE;
17859
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17860
}
17861
#endif
17862
17863
/*[clinic input]
17864
os._inputhook
17865
17866
Calls PyOS_InputHook dropping the GIL first
17867
[clinic start generated code]*/
17868
17869
static PyObject *
17870
os__inputhook_impl(PyObject *module)
17871
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17872
0
{
17873
0
     int result = 0;
17874
0
     if (PyOS_InputHook) {
17875
0
         Py_BEGIN_ALLOW_THREADS;
17876
0
         result = PyOS_InputHook();
17877
0
         Py_END_ALLOW_THREADS;
17878
0
     }
17879
0
     return PyLong_FromLong(result);
17880
0
}
17881
17882
/*[clinic input]
17883
os._is_inputhook_installed
17884
17885
Checks if PyOS_InputHook is set
17886
[clinic start generated code]*/
17887
17888
static PyObject *
17889
os__is_inputhook_installed_impl(PyObject *module)
17890
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17891
0
{
17892
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17893
0
}
17894
17895
/*[clinic input]
17896
os._create_environ
17897
17898
Create the environment dictionary.
17899
[clinic start generated code]*/
17900
17901
static PyObject *
17902
os__create_environ_impl(PyObject *module)
17903
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17904
0
{
17905
0
    return convertenviron();
17906
0
}
17907
17908
17909
#ifdef __EMSCRIPTEN__
17910
/*[clinic input]
17911
os._emscripten_debugger
17912
17913
Create a breakpoint for the JavaScript debugger. Emscripten only.
17914
[clinic start generated code]*/
17915
17916
static PyObject *
17917
os__emscripten_debugger_impl(PyObject *module)
17918
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17919
{
17920
    emscripten_debugger();
17921
    Py_RETURN_NONE;
17922
}
17923
17924
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17925
    console.warn(UTF8ToString(arg));
17926
});
17927
17928
/*[clinic input]
17929
os._emscripten_log
17930
   arg: str
17931
17932
Log something to the JS console. Emscripten only.
17933
[clinic start generated code]*/
17934
17935
static PyObject *
17936
os__emscripten_log_impl(PyObject *module, const char *arg)
17937
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17938
{
17939
    emscripten_log_impl_js(arg);
17940
    Py_RETURN_NONE;
17941
}
17942
#endif /* __EMSCRIPTEN__ */
17943
17944
17945
static PyMethodDef posix_methods[] = {
17946
    OS_STAT_METHODDEF
17947
    OS_STATX_METHODDEF
17948
    OS_ACCESS_METHODDEF
17949
    OS_TTYNAME_METHODDEF
17950
    OS_CHDIR_METHODDEF
17951
    OS_CHFLAGS_METHODDEF
17952
    OS_CHMOD_METHODDEF
17953
    OS_FCHMOD_METHODDEF
17954
    OS_LCHMOD_METHODDEF
17955
    OS_CHOWN_METHODDEF
17956
    OS_FCHOWN_METHODDEF
17957
    OS_LCHOWN_METHODDEF
17958
    OS_LCHFLAGS_METHODDEF
17959
    OS_CHROOT_METHODDEF
17960
    OS_CTERMID_METHODDEF
17961
    OS_GETCWD_METHODDEF
17962
    OS_GETCWDB_METHODDEF
17963
    OS_LINK_METHODDEF
17964
    OS_LISTDIR_METHODDEF
17965
    OS_LISTDRIVES_METHODDEF
17966
    OS_LISTMOUNTS_METHODDEF
17967
    OS_LISTVOLUMES_METHODDEF
17968
    OS_LSTAT_METHODDEF
17969
    OS_MKDIR_METHODDEF
17970
    OS_NICE_METHODDEF
17971
    OS_GETPRIORITY_METHODDEF
17972
    OS_SETPRIORITY_METHODDEF
17973
    OS_POSIX_SPAWN_METHODDEF
17974
    OS_POSIX_SPAWNP_METHODDEF
17975
    OS_READLINK_METHODDEF
17976
    OS_COPY_FILE_RANGE_METHODDEF
17977
    OS_SPLICE_METHODDEF
17978
    OS_RENAME_METHODDEF
17979
    OS_REPLACE_METHODDEF
17980
    OS_RMDIR_METHODDEF
17981
    OS_SYMLINK_METHODDEF
17982
    OS_SYSTEM_METHODDEF
17983
    OS_UMASK_METHODDEF
17984
    OS_UNAME_METHODDEF
17985
    OS_UNLINK_METHODDEF
17986
    OS_REMOVE_METHODDEF
17987
    OS_UTIME_METHODDEF
17988
    OS_TIMES_METHODDEF
17989
    OS__EXIT_METHODDEF
17990
    OS__FCOPYFILE_METHODDEF
17991
    OS_EXECV_METHODDEF
17992
    OS_EXECVE_METHODDEF
17993
    OS_SPAWNV_METHODDEF
17994
    OS_SPAWNVE_METHODDEF
17995
    OS_FORK1_METHODDEF
17996
    OS_FORK_METHODDEF
17997
    OS_REGISTER_AT_FORK_METHODDEF
17998
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17999
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
18000
    OS_SCHED_GETPARAM_METHODDEF
18001
    OS_SCHED_GETSCHEDULER_METHODDEF
18002
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
18003
    OS_SCHED_SETPARAM_METHODDEF
18004
    OS_SCHED_SETSCHEDULER_METHODDEF
18005
    OS_SCHED_YIELD_METHODDEF
18006
    OS_SCHED_SETAFFINITY_METHODDEF
18007
    OS_SCHED_GETAFFINITY_METHODDEF
18008
    OS_POSIX_OPENPT_METHODDEF
18009
    OS_GRANTPT_METHODDEF
18010
    OS_UNLOCKPT_METHODDEF
18011
    OS_PTSNAME_METHODDEF
18012
    OS_OPENPTY_METHODDEF
18013
    OS_LOGIN_TTY_METHODDEF
18014
    OS_FORKPTY_METHODDEF
18015
    OS_GETEGID_METHODDEF
18016
    OS_GETEUID_METHODDEF
18017
    OS_GETGID_METHODDEF
18018
    OS_GETGROUPLIST_METHODDEF
18019
    OS_GETGROUPS_METHODDEF
18020
    OS_GETPID_METHODDEF
18021
    OS_GETPGRP_METHODDEF
18022
    OS_GETPPID_METHODDEF
18023
    OS_GETUID_METHODDEF
18024
    OS_GETLOGIN_METHODDEF
18025
    OS_KILL_METHODDEF
18026
    OS_KILLPG_METHODDEF
18027
    OS_PLOCK_METHODDEF
18028
    OS_STARTFILE_METHODDEF
18029
    OS_SETUID_METHODDEF
18030
    OS_SETEUID_METHODDEF
18031
    OS_SETREUID_METHODDEF
18032
    OS_SETGID_METHODDEF
18033
    OS_SETEGID_METHODDEF
18034
    OS_SETREGID_METHODDEF
18035
    OS_SETGROUPS_METHODDEF
18036
    OS_INITGROUPS_METHODDEF
18037
    OS_GETPGID_METHODDEF
18038
    OS_SETPGRP_METHODDEF
18039
    OS_WAIT_METHODDEF
18040
    OS_WAIT3_METHODDEF
18041
    OS_WAIT4_METHODDEF
18042
    OS_WAITID_METHODDEF
18043
    OS_WAITPID_METHODDEF
18044
    OS_PIDFD_OPEN_METHODDEF
18045
    OS_PIDFD_GETFD_METHODDEF
18046
    OS_GETSID_METHODDEF
18047
    OS_SETSID_METHODDEF
18048
    OS_SETPGID_METHODDEF
18049
    OS_TCGETPGRP_METHODDEF
18050
    OS_TCSETPGRP_METHODDEF
18051
    OS_OPEN_METHODDEF
18052
    OS_CLOSE_METHODDEF
18053
    OS_CLOSERANGE_METHODDEF
18054
    OS_DEVICE_ENCODING_METHODDEF
18055
    OS_DUP_METHODDEF
18056
    OS_DUP2_METHODDEF
18057
    OS_LOCKF_METHODDEF
18058
    OS_LSEEK_METHODDEF
18059
    OS_READ_METHODDEF
18060
    OS_READINTO_METHODDEF
18061
    OS_READV_METHODDEF
18062
    OS_PREAD_METHODDEF
18063
    OS_PREADV_METHODDEF
18064
    OS_WRITE_METHODDEF
18065
    OS_WRITEV_METHODDEF
18066
    OS_PWRITE_METHODDEF
18067
    OS_PWRITEV_METHODDEF
18068
    OS_SENDFILE_METHODDEF
18069
    OS_FSTAT_METHODDEF
18070
    OS_ISATTY_METHODDEF
18071
    OS_PIPE_METHODDEF
18072
    OS_PIPE2_METHODDEF
18073
    OS_MKFIFO_METHODDEF
18074
    OS_MKNOD_METHODDEF
18075
    OS_MAJOR_METHODDEF
18076
    OS_MINOR_METHODDEF
18077
    OS_MAKEDEV_METHODDEF
18078
    OS_FTRUNCATE_METHODDEF
18079
    OS_TRUNCATE_METHODDEF
18080
    OS_POSIX_FALLOCATE_METHODDEF
18081
    OS_POSIX_FADVISE_METHODDEF
18082
    OS_PUTENV_METHODDEF
18083
    OS_UNSETENV_METHODDEF
18084
    OS__CLEARENV_METHODDEF
18085
    OS_STRERROR_METHODDEF
18086
    OS_FCHDIR_METHODDEF
18087
    OS_FSYNC_METHODDEF
18088
    OS_SYNC_METHODDEF
18089
    OS_FDATASYNC_METHODDEF
18090
    OS_WCOREDUMP_METHODDEF
18091
    OS_WIFCONTINUED_METHODDEF
18092
    OS_WIFSTOPPED_METHODDEF
18093
    OS_WIFSIGNALED_METHODDEF
18094
    OS_WIFEXITED_METHODDEF
18095
    OS_WEXITSTATUS_METHODDEF
18096
    OS_WTERMSIG_METHODDEF
18097
    OS_WSTOPSIG_METHODDEF
18098
    OS_FSTATVFS_METHODDEF
18099
    OS_STATVFS_METHODDEF
18100
    OS_CONFSTR_METHODDEF
18101
    OS_SYSCONF_METHODDEF
18102
    OS_FPATHCONF_METHODDEF
18103
    OS_PATHCONF_METHODDEF
18104
    OS_ABORT_METHODDEF
18105
    OS__GETFULLPATHNAME_METHODDEF
18106
    OS__GETDISKUSAGE_METHODDEF
18107
    OS__GETFINALPATHNAME_METHODDEF
18108
    OS__FINDFIRSTFILE_METHODDEF
18109
    OS__GETVOLUMEPATHNAME_METHODDEF
18110
    OS__PATH_SPLITROOT_METHODDEF
18111
    OS__PATH_SPLITROOT_EX_METHODDEF
18112
    OS__PATH_NORMPATH_METHODDEF
18113
    OS_GETLOADAVG_METHODDEF
18114
    OS_URANDOM_METHODDEF
18115
    OS_SETRESUID_METHODDEF
18116
    OS_SETRESGID_METHODDEF
18117
    OS_GETRESUID_METHODDEF
18118
    OS_GETRESGID_METHODDEF
18119
18120
    OS_GETXATTR_METHODDEF
18121
    OS_SETXATTR_METHODDEF
18122
    OS_REMOVEXATTR_METHODDEF
18123
    OS_LISTXATTR_METHODDEF
18124
18125
    OS_GET_TERMINAL_SIZE_METHODDEF
18126
    OS_CPU_COUNT_METHODDEF
18127
    OS_GET_INHERITABLE_METHODDEF
18128
    OS_SET_INHERITABLE_METHODDEF
18129
    OS_GET_HANDLE_INHERITABLE_METHODDEF
18130
    OS_SET_HANDLE_INHERITABLE_METHODDEF
18131
    OS_GET_BLOCKING_METHODDEF
18132
    OS_SET_BLOCKING_METHODDEF
18133
    OS_SCANDIR_METHODDEF
18134
    OS_FSPATH_METHODDEF
18135
    OS_GETRANDOM_METHODDEF
18136
    OS_MEMFD_CREATE_METHODDEF
18137
    OS_EVENTFD_METHODDEF
18138
    OS_EVENTFD_READ_METHODDEF
18139
    OS_EVENTFD_WRITE_METHODDEF
18140
    OS__ADD_DLL_DIRECTORY_METHODDEF
18141
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
18142
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
18143
    OS_SETNS_METHODDEF
18144
    OS_UNSHARE_METHODDEF
18145
    OS_TIMERFD_CREATE_METHODDEF
18146
    OS_TIMERFD_SETTIME_METHODDEF
18147
    OS_TIMERFD_SETTIME_NS_METHODDEF
18148
    OS_TIMERFD_GETTIME_METHODDEF
18149
    OS_TIMERFD_GETTIME_NS_METHODDEF
18150
18151
    OS__PATH_ISDEVDRIVE_METHODDEF
18152
    OS__PATH_ISDIR_METHODDEF
18153
    OS__PATH_ISFILE_METHODDEF
18154
    OS__PATH_ISLINK_METHODDEF
18155
    OS__PATH_ISJUNCTION_METHODDEF
18156
    OS__PATH_EXISTS_METHODDEF
18157
    OS__PATH_LEXISTS_METHODDEF
18158
18159
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
18160
    OS__INPUTHOOK_METHODDEF
18161
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
18162
    OS__CREATE_ENVIRON_METHODDEF
18163
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
18164
    OS__EMSCRIPTEN_LOG_METHODDEF
18165
    {NULL,              NULL}            /* Sentinel */
18166
};
18167
18168
static int
18169
all_ins(PyObject *m)
18170
37
{
18171
37
#ifdef F_OK
18172
37
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
18173
37
#endif
18174
37
#ifdef R_OK
18175
37
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
18176
37
#endif
18177
37
#ifdef W_OK
18178
37
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
18179
37
#endif
18180
37
#ifdef X_OK
18181
37
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
18182
37
#endif
18183
37
#ifdef NGROUPS_MAX
18184
37
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
18185
37
#endif
18186
37
#ifdef TMP_MAX
18187
37
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
18188
37
#endif
18189
37
#ifdef WCONTINUED
18190
37
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
18191
37
#endif
18192
37
#ifdef WNOHANG
18193
37
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
18194
37
#endif
18195
37
#ifdef WUNTRACED
18196
37
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
18197
37
#endif
18198
37
#ifdef O_RDONLY
18199
37
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
18200
37
#endif
18201
37
#ifdef O_WRONLY
18202
37
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
18203
37
#endif
18204
37
#ifdef O_RDWR
18205
37
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
18206
37
#endif
18207
37
#ifdef O_NDELAY
18208
37
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
18209
37
#endif
18210
37
#ifdef O_NONBLOCK
18211
37
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
18212
37
#endif
18213
37
#ifdef O_APPEND
18214
37
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
18215
37
#endif
18216
37
#ifdef O_DSYNC
18217
37
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
18218
37
#endif
18219
37
#ifdef O_RSYNC
18220
37
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
18221
37
#endif
18222
37
#ifdef O_SYNC
18223
37
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
18224
37
#endif
18225
37
#ifdef O_NOCTTY
18226
37
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
18227
37
#endif
18228
37
#ifdef O_CREAT
18229
37
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
18230
37
#endif
18231
37
#ifdef O_EXCL
18232
37
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
18233
37
#endif
18234
37
#ifdef O_TRUNC
18235
37
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
18236
37
#endif
18237
#ifdef O_BINARY
18238
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
18239
#endif
18240
#ifdef O_TEXT
18241
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
18242
#endif
18243
#ifdef O_XATTR
18244
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
18245
#endif
18246
37
#ifdef O_LARGEFILE
18247
37
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
18248
37
#endif
18249
37
#ifndef __GNU__
18250
#ifdef O_SHLOCK
18251
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
18252
#endif
18253
#ifdef O_EXLOCK
18254
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
18255
#endif
18256
37
#endif
18257
#ifdef O_EXEC
18258
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
18259
#endif
18260
#ifdef O_SEARCH
18261
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
18262
#endif
18263
37
#ifdef O_PATH
18264
37
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
18265
37
#endif
18266
#ifdef O_TTY_INIT
18267
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
18268
#endif
18269
37
#ifdef O_TMPFILE
18270
37
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
18271
37
#endif
18272
37
#ifdef PRIO_PROCESS
18273
37
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
18274
37
#endif
18275
37
#ifdef PRIO_PGRP
18276
37
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
18277
37
#endif
18278
37
#ifdef PRIO_USER
18279
37
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
18280
37
#endif
18281
#ifdef PRIO_DARWIN_THREAD
18282
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
18283
#endif
18284
#ifdef PRIO_DARWIN_PROCESS
18285
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
18286
#endif
18287
#ifdef PRIO_DARWIN_BG
18288
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
18289
#endif
18290
#ifdef PRIO_DARWIN_NONUI
18291
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
18292
#endif
18293
37
#ifdef O_CLOEXEC
18294
37
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
18295
37
#endif
18296
37
#ifdef O_ACCMODE
18297
37
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
18298
37
#endif
18299
#ifdef O_EVTONLY
18300
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
18301
#endif
18302
37
#ifdef O_FSYNC
18303
37
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
18304
37
#endif
18305
#ifdef O_SYMLINK
18306
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
18307
#endif
18308
18309
37
#ifdef SEEK_HOLE
18310
37
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
18311
37
#endif
18312
37
#ifdef SEEK_DATA
18313
37
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
18314
37
#endif
18315
18316
/* MS Windows */
18317
#ifdef O_NOINHERIT
18318
    /* Don't inherit in child processes. */
18319
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
18320
#endif
18321
#ifdef _O_SHORT_LIVED
18322
    /* Optimize for short life (keep in memory). */
18323
    /* MS forgot to define this one with a non-underscore form too. */
18324
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
18325
#endif
18326
#ifdef O_TEMPORARY
18327
    /* Automatically delete when last handle is closed. */
18328
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
18329
#endif
18330
#ifdef O_RANDOM
18331
    /* Optimize for random access. */
18332
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
18333
#endif
18334
#ifdef O_SEQUENTIAL
18335
    /* Optimize for sequential access. */
18336
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
18337
#endif
18338
18339
/* GNU extensions. */
18340
37
#ifdef O_ASYNC
18341
    /* Send a SIGIO signal whenever input or output
18342
       becomes available on file descriptor */
18343
37
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
18344
37
#endif
18345
37
#ifdef O_DIRECT
18346
    /* Direct disk access. */
18347
37
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
18348
37
#endif
18349
37
#ifdef O_DIRECTORY
18350
    /* Must be a directory.      */
18351
37
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
18352
37
#endif
18353
37
#ifdef O_NOFOLLOW
18354
    /* Do not follow links.      */
18355
37
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
18356
37
#endif
18357
#ifdef O_NOFOLLOW_ANY
18358
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
18359
#endif
18360
#ifdef O_NOLINKS
18361
    /* Fails if link count of the named file is greater than 1 */
18362
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
18363
#endif
18364
37
#ifdef O_NOATIME
18365
    /* Do not update the access time. */
18366
37
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
18367
37
#endif
18368
18369
    /* These come from sysexits.h */
18370
37
#ifdef EX_OK
18371
37
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
18372
37
#endif /* EX_OK */
18373
37
#ifdef EX_USAGE
18374
37
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
18375
37
#endif /* EX_USAGE */
18376
37
#ifdef EX_DATAERR
18377
37
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
18378
37
#endif /* EX_DATAERR */
18379
37
#ifdef EX_NOINPUT
18380
37
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
18381
37
#endif /* EX_NOINPUT */
18382
37
#ifdef EX_NOUSER
18383
37
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
18384
37
#endif /* EX_NOUSER */
18385
37
#ifdef EX_NOHOST
18386
37
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
18387
37
#endif /* EX_NOHOST */
18388
37
#ifdef EX_UNAVAILABLE
18389
37
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
18390
37
#endif /* EX_UNAVAILABLE */
18391
37
#ifdef EX_SOFTWARE
18392
37
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
18393
37
#endif /* EX_SOFTWARE */
18394
37
#ifdef EX_OSERR
18395
37
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
18396
37
#endif /* EX_OSERR */
18397
37
#ifdef EX_OSFILE
18398
37
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
18399
37
#endif /* EX_OSFILE */
18400
37
#ifdef EX_CANTCREAT
18401
37
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
18402
37
#endif /* EX_CANTCREAT */
18403
37
#ifdef EX_IOERR
18404
37
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
18405
37
#endif /* EX_IOERR */
18406
37
#ifdef EX_TEMPFAIL
18407
37
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
18408
37
#endif /* EX_TEMPFAIL */
18409
37
#ifdef EX_PROTOCOL
18410
37
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
18411
37
#endif /* EX_PROTOCOL */
18412
37
#ifdef EX_NOPERM
18413
37
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
18414
37
#endif /* EX_NOPERM */
18415
37
#ifdef EX_CONFIG
18416
37
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
18417
37
#endif /* EX_CONFIG */
18418
#ifdef EX_NOTFOUND
18419
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
18420
#endif /* EX_NOTFOUND */
18421
18422
    /* statvfs */
18423
37
#ifdef ST_RDONLY
18424
37
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
18425
37
#endif /* ST_RDONLY */
18426
37
#ifdef ST_NOSUID
18427
37
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
18428
37
#endif /* ST_NOSUID */
18429
18430
       /* GNU extensions */
18431
37
#ifdef ST_NODEV
18432
37
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
18433
37
#endif /* ST_NODEV */
18434
37
#ifdef ST_NOEXEC
18435
37
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
18436
37
#endif /* ST_NOEXEC */
18437
37
#ifdef ST_SYNCHRONOUS
18438
37
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
18439
37
#endif /* ST_SYNCHRONOUS */
18440
37
#ifdef ST_MANDLOCK
18441
37
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
18442
37
#endif /* ST_MANDLOCK */
18443
37
#ifdef ST_WRITE
18444
37
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
18445
37
#endif /* ST_WRITE */
18446
37
#ifdef ST_APPEND
18447
37
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
18448
37
#endif /* ST_APPEND */
18449
37
#ifdef ST_NOATIME
18450
37
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
18451
37
#endif /* ST_NOATIME */
18452
37
#ifdef ST_NODIRATIME
18453
37
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
18454
37
#endif /* ST_NODIRATIME */
18455
37
#ifdef ST_RELATIME
18456
37
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18457
37
#endif /* ST_RELATIME */
18458
18459
    /* FreeBSD sendfile() constants */
18460
#ifdef SF_NODISKIO
18461
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18462
#endif
18463
    /* is obsolete since the 11.x release */
18464
#ifdef SF_MNOWAIT
18465
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18466
#endif
18467
#ifdef SF_SYNC
18468
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18469
#endif
18470
#ifdef SF_NOCACHE
18471
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18472
#endif
18473
18474
37
#ifdef TFD_NONBLOCK
18475
37
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18476
37
#endif
18477
37
#ifdef TFD_CLOEXEC
18478
37
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18479
37
#endif
18480
37
#ifdef TFD_TIMER_ABSTIME
18481
37
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18482
37
#endif
18483
37
#ifdef TFD_TIMER_CANCEL_ON_SET
18484
37
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18485
37
#endif
18486
18487
    /* constants for posix_fadvise */
18488
37
#ifdef POSIX_FADV_NORMAL
18489
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18490
37
#endif
18491
37
#ifdef POSIX_FADV_SEQUENTIAL
18492
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18493
37
#endif
18494
37
#ifdef POSIX_FADV_RANDOM
18495
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18496
37
#endif
18497
37
#ifdef POSIX_FADV_NOREUSE
18498
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18499
37
#endif
18500
37
#ifdef POSIX_FADV_WILLNEED
18501
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18502
37
#endif
18503
37
#ifdef POSIX_FADV_DONTNEED
18504
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18505
37
#endif
18506
18507
    /* constants for waitid */
18508
37
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18509
37
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18510
37
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18511
37
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18512
37
#ifdef P_PIDFD
18513
37
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18514
37
#endif
18515
#ifdef PIDFD_NONBLOCK
18516
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18517
#endif
18518
37
#endif
18519
37
#ifdef WEXITED
18520
37
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18521
37
#endif
18522
37
#ifdef WNOWAIT
18523
37
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18524
37
#endif
18525
37
#ifdef WSTOPPED
18526
37
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18527
37
#endif
18528
37
#ifdef CLD_EXITED
18529
37
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18530
37
#endif
18531
37
#ifdef CLD_KILLED
18532
37
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18533
37
#endif
18534
37
#ifdef CLD_DUMPED
18535
37
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18536
37
#endif
18537
37
#ifdef CLD_TRAPPED
18538
37
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18539
37
#endif
18540
37
#ifdef CLD_STOPPED
18541
37
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18542
37
#endif
18543
37
#ifdef CLD_CONTINUED
18544
37
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18545
37
#endif
18546
18547
    /* constants for lockf */
18548
37
#ifdef F_LOCK
18549
37
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18550
37
#endif
18551
37
#ifdef F_TLOCK
18552
37
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18553
37
#endif
18554
37
#ifdef F_ULOCK
18555
37
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18556
37
#endif
18557
37
#ifdef F_TEST
18558
37
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18559
37
#endif
18560
18561
37
#ifdef RWF_DSYNC
18562
37
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18563
37
#endif
18564
37
#ifdef RWF_HIPRI
18565
37
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18566
37
#endif
18567
37
#ifdef RWF_SYNC
18568
37
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18569
37
#endif
18570
37
#ifdef RWF_NOWAIT
18571
37
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18572
37
#endif
18573
#ifdef RWF_DONTCACHE
18574
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18575
#endif
18576
#ifdef RWF_ATOMIC
18577
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18578
#endif
18579
37
#ifdef RWF_APPEND
18580
37
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18581
37
#endif
18582
#ifdef RWF_NOSIGNAL
18583
    if (PyModule_AddIntConstant(m, "RWF_NOSIGNAL", RWF_NOSIGNAL)) return -1;
18584
#endif
18585
18586
/* constants for splice */
18587
37
#if defined(HAVE_SPLICE) && defined(__linux__)
18588
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18589
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18590
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18591
37
#endif
18592
18593
/* constants for posix_spawn */
18594
37
#ifdef HAVE_POSIX_SPAWN
18595
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18596
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18597
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18598
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18599
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18600
#endif
18601
37
#endif
18602
18603
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18604
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18605
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18606
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18607
#endif
18608
#ifdef HAVE_SPAWNV
18609
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18610
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18611
#endif
18612
18613
37
#ifdef HAVE_SCHED_H
18614
37
#ifdef SCHED_OTHER
18615
37
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18616
37
#endif
18617
37
#ifdef SCHED_DEADLINE
18618
37
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18619
37
#endif
18620
37
#ifdef SCHED_FIFO
18621
37
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18622
37
#endif
18623
37
#ifdef SCHED_NORMAL
18624
37
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18625
37
#endif
18626
37
#ifdef SCHED_RR
18627
37
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18628
37
#endif
18629
#ifdef SCHED_SPORADIC
18630
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18631
#endif
18632
37
#ifdef SCHED_BATCH
18633
37
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18634
37
#endif
18635
37
#ifdef SCHED_IDLE
18636
37
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18637
37
#endif
18638
37
#ifdef SCHED_RESET_ON_FORK
18639
37
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18640
37
#endif
18641
#ifdef SCHED_SYS
18642
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18643
#endif
18644
#ifdef SCHED_IA
18645
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18646
#endif
18647
#ifdef SCHED_FSS
18648
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18649
#endif
18650
#ifdef SCHED_FX
18651
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18652
#endif
18653
18654
/* constants for namespaces */
18655
37
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18656
37
#ifdef CLONE_FS
18657
37
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18658
37
#endif
18659
37
#ifdef CLONE_FILES
18660
37
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18661
37
#endif
18662
37
#ifdef CLONE_NEWNS
18663
37
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18664
37
#endif
18665
37
#ifdef CLONE_NEWCGROUP
18666
37
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18667
37
#endif
18668
37
#ifdef CLONE_NEWUTS
18669
37
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18670
37
#endif
18671
37
#ifdef CLONE_NEWIPC
18672
37
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18673
37
#endif
18674
37
#ifdef CLONE_NEWUSER
18675
37
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18676
37
#endif
18677
37
#ifdef CLONE_NEWPID
18678
37
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18679
37
#endif
18680
37
#ifdef CLONE_NEWNET
18681
37
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18682
37
#endif
18683
#ifdef CLONE_NEWTIME
18684
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18685
#endif
18686
37
#ifdef CLONE_SYSVSEM
18687
37
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18688
37
#endif
18689
37
#ifdef CLONE_THREAD
18690
37
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18691
37
#endif
18692
37
#ifdef CLONE_SIGHAND
18693
37
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18694
37
#endif
18695
37
#ifdef CLONE_VM
18696
37
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18697
37
#endif
18698
37
#endif
18699
18700
37
#endif
18701
18702
37
#ifdef USE_XATTRS
18703
37
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18704
37
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18705
37
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18706
37
#endif
18707
18708
37
#if HAVE_DECL_RTLD_LAZY
18709
37
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18710
37
#endif
18711
37
#if HAVE_DECL_RTLD_NOW
18712
37
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18713
37
#endif
18714
37
#if HAVE_DECL_RTLD_GLOBAL
18715
37
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18716
37
#endif
18717
37
#if HAVE_DECL_RTLD_LOCAL
18718
37
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18719
37
#endif
18720
37
#if HAVE_DECL_RTLD_NODELETE
18721
37
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18722
37
#endif
18723
37
#if HAVE_DECL_RTLD_NOLOAD
18724
37
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18725
37
#endif
18726
37
#if HAVE_DECL_RTLD_DEEPBIND
18727
37
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18728
37
#endif
18729
#if HAVE_DECL_RTLD_MEMBER
18730
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18731
#endif
18732
18733
37
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
18734
37
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18735
37
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18736
37
#endif
18737
37
#ifdef _Py_HAVE_MEMFD_CREATE
18738
37
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18739
37
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18740
37
#ifdef MFD_HUGETLB
18741
37
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18742
37
#endif
18743
37
#ifdef MFD_HUGE_SHIFT
18744
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18745
37
#endif
18746
37
#ifdef MFD_HUGE_MASK
18747
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18748
37
#endif
18749
37
#ifdef MFD_HUGE_64KB
18750
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18751
37
#endif
18752
37
#ifdef MFD_HUGE_512KB
18753
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18754
37
#endif
18755
37
#ifdef MFD_HUGE_1MB
18756
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18757
37
#endif
18758
37
#ifdef MFD_HUGE_2MB
18759
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18760
37
#endif
18761
37
#ifdef MFD_HUGE_8MB
18762
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18763
37
#endif
18764
37
#ifdef MFD_HUGE_16MB
18765
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18766
37
#endif
18767
37
#ifdef MFD_HUGE_32MB
18768
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18769
37
#endif
18770
37
#ifdef MFD_HUGE_256MB
18771
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18772
37
#endif
18773
37
#ifdef MFD_HUGE_512MB
18774
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18775
37
#endif
18776
37
#ifdef MFD_HUGE_1GB
18777
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18778
37
#endif
18779
37
#ifdef MFD_HUGE_2GB
18780
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18781
37
#endif
18782
37
#ifdef MFD_HUGE_16GB
18783
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18784
37
#endif
18785
37
#endif /* _Py_HAVE_MEMFD_CREATE */
18786
18787
37
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18788
37
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18789
37
#ifdef EFD_NONBLOCK
18790
37
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18791
37
#endif
18792
37
#ifdef EFD_SEMAPHORE
18793
37
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18794
37
#endif
18795
37
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18796
18797
37
#ifdef NODEV
18798
37
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18799
37
#endif
18800
18801
37
#ifdef AT_NO_AUTOMOUNT
18802
37
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18803
37
#endif
18804
18805
37
#ifdef HAVE_STATX
18806
37
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18807
37
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18808
37
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18809
37
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18810
37
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18811
37
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18812
37
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18813
37
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18814
37
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18815
37
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18816
37
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18817
37
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18818
37
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18819
#ifdef STATX_MNT_ID
18820
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18821
#endif
18822
#ifdef STATX_DIOALIGN
18823
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18824
#endif
18825
#ifdef STATX_MNT_ID_UNIQUE
18826
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18827
#endif
18828
#ifdef STATX_SUBVOL
18829
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18830
#endif
18831
#ifdef STATX_WRITE_ATOMIC
18832
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18833
#endif
18834
#ifdef STATX_DIO_READ_ALIGN
18835
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18836
#endif
18837
    /* STATX_ALL intentionally omitted because it is deprecated */
18838
37
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18839
37
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18840
37
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18841
    /* STATX_ATTR_* constants are in the stat module */
18842
37
#endif /* HAVE_STATX */
18843
18844
#if defined(__APPLE__)
18845
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18846
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18847
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18848
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18849
#endif
18850
18851
#ifdef MS_WINDOWS
18852
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18853
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18854
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18855
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18856
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18857
#endif
18858
18859
37
    return 0;
18860
37
}
18861
18862
18863
18864
#define PROBE(name, test) \
18865
   static int name(void)  \
18866
629
   {                      \
18867
629
      if (test) {        \
18868
629
          return 1;       \
18869
629
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
629
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_futimens
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_linkat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_openat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_renameat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18866
37
   {                      \
18867
37
      if (test) {        \
18868
37
          return 1;       \
18869
37
      } else {            \
18870
0
          return 0;       \
18871
0
      }                   \
18872
37
   }
18873
18874
#ifdef HAVE_FSTATAT
18875
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18876
#endif
18877
18878
#ifdef HAVE_FACCESSAT
18879
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18880
#endif
18881
18882
#ifdef HAVE_FCHMODAT
18883
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18884
#endif
18885
18886
#ifdef HAVE_FCHOWNAT
18887
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18888
#endif
18889
18890
#ifdef HAVE_LINKAT
18891
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18892
#endif
18893
18894
#ifdef HAVE_FDOPENDIR
18895
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18896
#endif
18897
18898
#ifdef HAVE_MKDIRAT
18899
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18900
#endif
18901
18902
#ifdef HAVE_MKFIFOAT
18903
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18904
#endif
18905
18906
#ifdef HAVE_MKNODAT
18907
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18908
#endif
18909
18910
#ifdef HAVE_RENAMEAT
18911
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18912
#endif
18913
18914
#ifdef HAVE_UNLINKAT
18915
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18916
#endif
18917
18918
#ifdef HAVE_OPENAT
18919
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18920
#endif
18921
18922
#ifdef HAVE_READLINKAT
18923
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18924
#endif
18925
18926
#ifdef _Py_HAVE_FREADLINK
18927
PROBE(probe_freadlink, HAVE_FREADLINK_RUNTIME)
18928
#endif
18929
18930
#ifdef HAVE_SYMLINKAT
18931
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18932
#endif
18933
18934
#ifdef HAVE_FUTIMENS
18935
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18936
#endif
18937
18938
#ifdef HAVE_UTIMENSAT
18939
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18940
#endif
18941
18942
#ifdef HAVE_PTSNAME_R
18943
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18944
#endif
18945
18946
18947
18948
static const struct have_function {
18949
    const char * const label;
18950
    int (*probe)(void);
18951
} have_functions[] = {
18952
18953
#ifdef HAVE_EVENTFD
18954
    {"HAVE_EVENTFD", NULL},
18955
#endif
18956
18957
#ifdef HAVE_TIMERFD_CREATE
18958
    {"HAVE_TIMERFD_CREATE", NULL},
18959
#endif
18960
18961
#ifdef HAVE_FACCESSAT
18962
    { "HAVE_FACCESSAT", probe_faccessat },
18963
#endif
18964
18965
#ifdef HAVE_FCHDIR
18966
    { "HAVE_FCHDIR", NULL },
18967
#endif
18968
18969
#ifdef HAVE_FCHMOD
18970
    { "HAVE_FCHMOD", NULL },
18971
#endif
18972
18973
#ifdef HAVE_FCHMODAT
18974
    { "HAVE_FCHMODAT", probe_fchmodat },
18975
#endif
18976
18977
#ifdef HAVE_FCHOWN
18978
    { "HAVE_FCHOWN", NULL },
18979
#endif
18980
18981
#ifdef HAVE_FCHOWNAT
18982
    { "HAVE_FCHOWNAT", probe_fchownat },
18983
#endif
18984
18985
#ifdef HAVE_FEXECVE
18986
    { "HAVE_FEXECVE", NULL },
18987
#endif
18988
18989
#ifdef HAVE_FDOPENDIR
18990
    { "HAVE_FDOPENDIR", probe_fdopendir },
18991
#endif
18992
18993
#ifdef HAVE_FPATHCONF
18994
    { "HAVE_FPATHCONF", NULL },
18995
#endif
18996
18997
#ifdef _Py_HAVE_FREADLINK
18998
    { "HAVE_FREADLINK", probe_freadlink },
18999
#endif
19000
19001
#ifdef HAVE_FSTATAT
19002
    { "HAVE_FSTATAT", probe_fstatat },
19003
#endif
19004
19005
#ifdef HAVE_FSTATVFS
19006
    { "HAVE_FSTATVFS", NULL },
19007
#endif
19008
19009
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
19010
    { "HAVE_FTRUNCATE", NULL },
19011
#endif
19012
19013
#ifdef HAVE_FUTIMENS
19014
    { "HAVE_FUTIMENS", probe_futimens },
19015
#endif
19016
19017
#ifdef HAVE_FUTIMES
19018
    { "HAVE_FUTIMES", NULL },
19019
#endif
19020
19021
#ifdef HAVE_FUTIMESAT
19022
    { "HAVE_FUTIMESAT", NULL },
19023
#endif
19024
19025
#ifdef HAVE_LINKAT
19026
    { "HAVE_LINKAT", probe_linkat },
19027
#endif
19028
19029
#ifdef HAVE_LCHFLAGS
19030
    { "HAVE_LCHFLAGS", NULL },
19031
#endif
19032
19033
#ifdef HAVE_LCHMOD
19034
    { "HAVE_LCHMOD", NULL },
19035
#endif
19036
19037
#ifdef HAVE_LCHOWN
19038
    { "HAVE_LCHOWN", NULL },
19039
#endif
19040
19041
#ifdef HAVE_LSTAT
19042
    { "HAVE_LSTAT", NULL },
19043
#endif
19044
19045
#ifdef HAVE_LUTIMES
19046
    { "HAVE_LUTIMES", NULL },
19047
#endif
19048
19049
#ifdef _Py_HAVE_MEMFD_CREATE
19050
    { "HAVE_MEMFD_CREATE", NULL },
19051
#endif
19052
19053
#ifdef HAVE_MKDIRAT
19054
    { "HAVE_MKDIRAT", probe_mkdirat },
19055
#endif
19056
19057
#ifdef HAVE_MKFIFOAT
19058
    { "HAVE_MKFIFOAT", probe_mkfifoat },
19059
#endif
19060
19061
#ifdef HAVE_MKNODAT
19062
    { "HAVE_MKNODAT", probe_mknodat },
19063
#endif
19064
19065
#ifdef HAVE_OPENAT
19066
    { "HAVE_OPENAT", probe_openat },
19067
#endif
19068
19069
#ifdef HAVE_READLINKAT
19070
    { "HAVE_READLINKAT", probe_readlinkat },
19071
#endif
19072
19073
#ifdef HAVE_RENAMEAT
19074
    { "HAVE_RENAMEAT", probe_renameat },
19075
#endif
19076
19077
#ifdef HAVE_SYMLINKAT
19078
    { "HAVE_SYMLINKAT", probe_symlinkat },
19079
#endif
19080
19081
#ifdef HAVE_UNLINKAT
19082
    { "HAVE_UNLINKAT", probe_unlinkat },
19083
#endif
19084
19085
#ifdef HAVE_UTIMENSAT
19086
    { "HAVE_UTIMENSAT", probe_utimensat },
19087
#endif
19088
19089
#ifdef HAVE_PTSNAME_R
19090
    { "HAVE_PTSNAME_R", probe_ptsname_r },
19091
#endif
19092
19093
#ifdef MS_WINDOWS
19094
    { "MS_WINDOWS", NULL },
19095
#endif
19096
19097
    { NULL, NULL }
19098
};
19099
19100
19101
static int
19102
posixmodule_exec(PyObject *m)
19103
37
{
19104
37
    _posixstate *state = get_posix_state(m);
19105
19106
37
#if defined(HAVE_PWRITEV)
19107
37
    if (HAVE_PWRITEV_RUNTIME) {} else {
19108
0
        PyObject* dct = PyModule_GetDict(m);
19109
19110
0
        if (dct == NULL) {
19111
0
            return -1;
19112
0
        }
19113
19114
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
19115
0
            return -1;
19116
0
        }
19117
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
19118
0
            return -1;
19119
0
        }
19120
0
    }
19121
37
#endif
19122
19123
37
#ifdef HAVE_STATX
19124
37
    if (statx == NULL) {
19125
0
        PyObject* dct = PyModule_GetDict(m);
19126
0
        if (dct == NULL) {
19127
0
            return -1;
19128
0
        }
19129
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
19130
0
            return -1;
19131
0
        }
19132
0
    }
19133
37
    else {
19134
37
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
19135
37
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
19136
0
            return -1;
19137
0
        }
19138
37
    }
19139
37
#endif
19140
19141
37
#if HAVE_PIPE2
19142
37
    if (HAVE_PIPE2_RUNTIME) {
19143
        // Do nothing. (`__builtin_available` doesn't allow `!`; see
19144
        // "using negations" in a comment above.)
19145
37
    }
19146
0
    else {
19147
0
        PyObject* dct = PyModule_GetDict(m);
19148
0
        if (dct == NULL) {
19149
0
            return -1;
19150
0
        }
19151
0
        if (PyDict_PopString(dct, "pipe2", NULL) < 0) {
19152
0
            return -1;
19153
0
        }
19154
0
    }
19155
37
#endif
19156
19157
    /* Initialize environ dictionary */
19158
37
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
19159
0
        return -1;
19160
0
    }
19161
19162
37
    if (all_ins(m))
19163
0
        return -1;
19164
19165
37
    if (setup_confname_tables(m))
19166
0
        return -1;
19167
19168
37
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
19169
0
        return -1;
19170
0
    }
19171
19172
37
#if defined(HAVE_WAITID)
19173
37
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
19174
37
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
19175
0
        return -1;
19176
0
    }
19177
37
#endif
19178
19179
37
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
19180
37
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
19181
37
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
19182
37
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
19183
37
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
19184
0
        return -1;
19185
0
    }
19186
37
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
19187
37
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
19188
19189
37
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
19190
37
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
19191
0
        return -1;
19192
0
    }
19193
19194
37
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
19195
37
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
19196
37
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
19197
0
        return -1;
19198
0
    }
19199
37
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
19200
37
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
19201
37
                          &os_sched_param_reduce_method) < 0)
19202
0
    {
19203
0
        return -1;
19204
0
    }
19205
37
    PyType_Modified((PyTypeObject *)state->SchedParamType);
19206
37
#endif
19207
19208
    /* initialize TerminalSize_info */
19209
37
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
19210
37
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
19211
0
        return -1;
19212
0
    }
19213
19214
    /* initialize scandir types */
19215
37
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
19216
37
    if (ScandirIteratorType == NULL) {
19217
0
        return -1;
19218
0
    }
19219
37
    state->ScandirIteratorType = ScandirIteratorType;
19220
19221
37
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
19222
37
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
19223
0
        return -1;
19224
0
    }
19225
19226
37
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
19227
37
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
19228
0
        return -1;
19229
0
    }
19230
19231
37
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
19232
37
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
19233
0
        return -1;
19234
0
    }
19235
19236
37
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
19237
0
        return -1;
19238
37
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
19239
37
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
19240
37
    if (state->struct_rusage == NULL)
19241
0
        return -1;
19242
37
#endif
19243
37
    state->st_mode = PyUnicode_InternFromString("st_mode");
19244
37
    if (state->st_mode == NULL)
19245
0
        return -1;
19246
19247
    /* suppress "function not used" warnings */
19248
37
    {
19249
37
    int ignored;
19250
37
    fd_specified("", -1);
19251
37
    follow_symlinks_specified("", 1);
19252
37
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
19253
37
    dir_fd_converter(Py_None, &ignored);
19254
37
    dir_fd_unavailable(Py_None, &ignored);
19255
37
    }
19256
19257
    /*
19258
     * provide list of locally available functions
19259
     * so os.py can populate support_* lists
19260
     */
19261
37
    PyObject *list = PyList_New(0);
19262
37
    if (!list) {
19263
0
        return -1;
19264
0
    }
19265
1.22k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
19266
1.18k
        PyObject *unicode;
19267
1.18k
        if (trace->probe && !trace->probe()) continue;
19268
1.18k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
19269
1.18k
        if (!unicode)
19270
0
            return -1;
19271
1.18k
        if (PyList_Append(list, unicode))
19272
0
            return -1;
19273
1.18k
        Py_DECREF(unicode);
19274
1.18k
    }
19275
19276
37
#ifndef MS_WINDOWS
19277
37
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
19278
0
        PyErr_SetString(PyExc_RuntimeError,
19279
0
                        "cannot read ticks_per_second");
19280
0
        return -1;
19281
0
    }
19282
37
    assert(state->ticks_per_second >= 1);
19283
37
#endif
19284
19285
37
    return PyModule_Add(m, "_have_functions", list);
19286
37
}
19287
19288
19289
static PyModuleDef_Slot posixmodile_slots[] = {
19290
    _Py_ABI_SLOT,
19291
    {Py_mod_exec, posixmodule_exec},
19292
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
19293
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
19294
    {0, NULL}
19295
};
19296
19297
static struct PyModuleDef posixmodule = {
19298
    PyModuleDef_HEAD_INIT,
19299
    .m_name = MODNAME,
19300
    .m_doc = posix__doc__,
19301
    .m_size = sizeof(_posixstate),
19302
    .m_methods = posix_methods,
19303
    .m_slots = posixmodile_slots,
19304
    .m_traverse = _posix_traverse,
19305
    .m_clear = _posix_clear,
19306
    .m_free = _posix_free,
19307
};
19308
19309
PyMODINIT_FUNC
19310
INITFUNC(void)
19311
37
{
19312
37
    return PyModuleDef_Init(&posixmodule);
19313
37
}