Coverage Report

Created: 2026-07-14 06:16

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_long.h"          // _PyLong_IsNegative()
25
#include "pycore_moduleobject.h"  // _PyModule_GetState()
26
#include "pycore_object.h"        // _PyObject_LookupSpecial()
27
#include "pycore_pylifecycle.h"   // _PyOS_URandom()
28
#include "pycore_pystate.h"       // _PyInterpreterState_GET()
29
#include "pycore_signal.h"        // Py_NSIG
30
#include "pycore_time.h"          // _PyLong_FromTime_t()
31
#include "pycore_tuple.h"         // _PyTuple_FromPairSteal
32
#include "pycore_typeobject.h"    // _PyType_AddMethod()
33
34
#ifndef MS_WINDOWS
35
#  include "posixmodule.h"        // _PyLong_FromUid()
36
#else
37
#  include "pycore_fileutils_windows.h" // _Py_GetFileInformationByName()
38
#  include "osdefs.h"             // SEP
39
#  include "winreparse.h"         // _Py_REPARSE_DATA_BUFFER
40
#endif
41
42
43
// --- System includes ------------------------------------------------------
44
45
#include <stddef.h>               // offsetof()
46
#include <stdio.h>                // ctermid()
47
#include <stdlib.h>               // system()
48
49
#ifdef HAVE_UNISTD_H
50
#  include <unistd.h>             // symlink()
51
#endif
52
53
#ifdef __APPLE__
54
   /* Needed for the implementation of os.statvfs */
55
#  include <sys/param.h>
56
#  include <sys/mount.h>
57
#endif
58
59
#ifdef HAVE_SYS_TIME_H
60
#  include <sys/time.h>           // futimes()
61
#endif
62
63
#ifdef HAVE_SYS_PIDFD_H
64
#  include <sys/pidfd.h>          // PIDFD_NONBLOCK
65
#endif
66
67
#ifdef __EMSCRIPTEN__
68
#  include "emscripten.h"         // emscripten_debugger()
69
#endif
70
71
#ifdef HAVE_SYS_UIO_H
72
#  include <sys/uio.h>
73
#endif
74
75
#ifdef HAVE_SYS_TYPES_H
76
   /* Should be included before <sys/sysmacros.h> on HP-UX v3 */
77
#  include <sys/types.h>
78
#endif
79
#ifdef HAVE_SYS_SYSMACROS_H
80
   /* GNU C Library: major(), minor(), makedev() */
81
#  include <sys/sysmacros.h>
82
#endif
83
84
#ifdef HAVE_SYS_STAT_H
85
#  include <sys/stat.h>
86
#endif
87
88
#ifdef HAVE_SYS_WAIT_H
89
#  include <sys/wait.h>           // WNOHANG
90
#endif
91
92
#ifdef HAVE_LINUX_WAIT_H
93
#  include <linux/wait.h>         // P_PIDFD
94
#endif
95
96
#ifdef HAVE_SIGNAL_H
97
#  include <signal.h>
98
#endif
99
100
#ifdef HAVE_FCNTL_H
101
#  include <fcntl.h>              // fcntl()
102
#endif
103
104
#ifdef HAVE_GRP_H
105
#  include <grp.h>                // setgroups()
106
#endif
107
108
#ifdef HAVE_SYSEXITS_H
109
#  include <sysexits.h>           // EX_OK
110
#endif
111
112
#ifdef HAVE_SYS_LOADAVG_H
113
#  include <sys/loadavg.h>        // getloadavg()
114
#endif
115
116
#ifdef HAVE_SYS_SENDFILE_H
117
#  include <sys/sendfile.h>       // sendfile()
118
#endif
119
120
#if defined(__APPLE__)
121
#  include <copyfile.h>           // fcopyfile()
122
#endif
123
124
#ifdef HAVE_SCHED_H
125
#  include <sched.h>              // sched_setscheduler()
126
#endif
127
#ifdef HAVE_LINUX_SCHED_H
128
#  include <linux/sched.h>        // SCHED_IDLE, SCHED_RR
129
#endif
130
131
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
132
#  ifdef HAVE_SYS_SOCKET_H
133
#    include <sys/socket.h>
134
#  endif
135
#endif
136
137
#ifdef HAVE_DLFCN_H
138
#  include <dlfcn.h>
139
#endif
140
141
#ifdef __hpux
142
#  include <sys/mpctl.h>
143
#endif
144
145
#if defined(__DragonFly__) || \
146
    defined(__OpenBSD__)   || \
147
    defined(__FreeBSD__)   || \
148
    defined(__NetBSD__)    || \
149
    defined(__APPLE__)
150
#  include <sys/sysctl.h>
151
#endif
152
153
#ifdef HAVE_LINUX_RANDOM_H
154
#  include <linux/random.h>       // GRND_RANDOM
155
#endif
156
#ifdef HAVE_GETRANDOM_SYSCALL
157
#  include <sys/syscall.h>        // syscall()
158
#endif
159
160
#ifdef HAVE_POSIX_SPAWN
161
#  include <spawn.h>              // posix_spawn()
162
#endif
163
164
#ifdef HAVE_UTIME_H
165
#  include <utime.h>              // utime()
166
#endif
167
168
#ifdef HAVE_SYS_UTIME_H
169
#  include <sys/utime.h>
170
#  define HAVE_UTIME_H /* pretend we do for the rest of this file */
171
#endif
172
173
#ifdef HAVE_SYS_TIMES_H
174
#  include <sys/times.h>          // times()
175
#endif
176
177
#ifdef HAVE_SYS_PARAM_H
178
#  include <sys/param.h>
179
#endif
180
181
#ifdef HAVE_SYS_UTSNAME_H
182
#  include <sys/utsname.h>        // uname()
183
#endif
184
185
/* memfd_create is either defined in sys/mman.h or sys/memfd.h
186
 * linux/memfd.h defines additional flags
187
 */
188
#ifdef HAVE_SYS_MMAN_H
189
#  include <sys/mman.h>           // memfd_create()
190
#endif
191
#ifdef HAVE_SYS_MEMFD_H
192
#  include <sys/memfd.h>          // memfd_create()
193
#endif
194
#ifdef HAVE_LINUX_MEMFD_H
195
#  include <linux/memfd.h>        // memfd_create(), MFD_CLOEXEC
196
#endif
197
198
#ifdef HAVE_SYS_EVENTFD_H
199
#  include <sys/eventfd.h>        // eventfd()
200
#endif
201
202
#ifdef HAVE_SYS_TIMERFD_H
203
#  include <sys/timerfd.h>        // timerfd_create()
204
#endif
205
206
#ifdef _Py_MEMORY_SANITIZER
207
#  include <sanitizer/msan_interface.h> // __msan_unpoison()
208
#endif
209
210
211
// --- More complex system includes -----------------------------------------
212
213
#ifdef MS_WINDOWS
214
#  include <windows.h>
215
#  if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP)
216
#    include <pathcch.h>          // PathCchSkipRoot()
217
#  endif
218
#  include <aclapi.h>             // SetEntriesInAcl
219
#  include <lmcons.h>             // UNLEN
220
#  include <sddl.h>               // SDDL_REVISION_1
221
#  include <winioctl.h>           // FSCTL_GET_REPARSE_POINT
222
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
223
#    define HAVE_SYMLINK
224
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
225
#endif
226
227
228
#ifdef _MSC_VER
229
#  ifdef HAVE_DIRECT_H
230
#    include <direct.h>
231
#  endif
232
#  ifdef HAVE_IO_H
233
#    include <io.h>
234
#  endif
235
#  ifdef HAVE_PROCESS_H
236
#    include <process.h>          // getpid(), _cwait()
237
#  endif
238
#  include <malloc.h>
239
#endif /* _MSC_VER */
240
241
242
#ifdef HAVE__GETPTY
243
#  include <sys/types.h>          // mode_t
244
   // SGI apparently needs this forward declaration
245
   extern char * _getpty(int *, int, mode_t, int);
246
#endif
247
248
249
#if defined(HAVE_SYS_XATTR_H)
250
#  if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
251
#    define USE_XATTRS
252
#    include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
253
#  endif
254
#  if defined(__CYGWIN__)
255
#    define USE_XATTRS
256
#    include <cygwin/limits.h>  // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX.
257
#  endif
258
#endif
259
#ifdef USE_XATTRS
260
#  include <sys/xattr.h>          // fgetxattr()
261
#endif
262
263
264
#ifdef HAVE_WINDOWS_CONSOLE_IO
265
#  define TERMSIZE_USE_CONIO
266
#elif defined(HAVE_SYS_IOCTL_H)
267
#  include <sys/ioctl.h>          // ioctl(), TIOCGWINSZ
268
#  if defined(HAVE_TERMIOS_H)
269
#    include <termios.h>
270
#  endif
271
#  if defined(TIOCGWINSZ)
272
#    define TERMSIZE_USE_IOCTL
273
#  endif
274
#endif
275
276
277
/* Various compilers have only certain posix functions */
278
/* XXX Gosh I wish these were all moved into pyconfig.h */
279
#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
280
#  define HAVE_OPENDIR    1
281
#  define HAVE_SYSTEM     1
282
#  include <process.h>
283
#elif defined( _MSC_VER)
284
  /* Microsoft compiler */
285
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
286
#    define HAVE_GETPPID    1
287
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */
288
#  if defined(MS_WINDOWS_DESKTOP)
289
#    define HAVE_GETLOGIN   1
290
#  endif /* MS_WINDOWS_DESKTOP */
291
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
292
#    define HAVE_SPAWNV     1
293
#    define HAVE_EXECV      1
294
#    define HAVE_WSPAWNV    1
295
#    define HAVE_WEXECV     1
296
#    define HAVE_SYSTEM     1
297
#    define HAVE_CWAIT      1
298
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
299
#  define HAVE_PIPE       1
300
#  define HAVE_FSYNC      1
301
#  define fsync _commit
302
#endif
303
304
305
#if !defined(_MSC_VER) && defined(__sgi) && _COMPILER_VERSION>=700
306
/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
307
   (default) */
308
extern char *ctermid_r(char *);
309
#endif
310
311
312
#if defined(__VXWORKS__)
313
#  include <vxCpuLib.h>
314
#  include <rtpLib.h>
315
#  include <wait.h>
316
#  include <taskLib.h>
317
#  ifndef _P_WAIT
318
#    define _P_WAIT          0
319
#    define _P_NOWAIT        1
320
#    define _P_NOWAITO       1
321
#  endif
322
#endif /* __VXWORKS__ */
323
324
325
#ifdef HAVE_DIRENT_H
326
#  include <dirent.h>             // opendir()
327
307k
#  define NAMLEN(dirent) strlen((dirent)->d_name)
328
#else
329
#  if defined(__WATCOMC__) && !defined(__QNX__)
330
#    include <direct.h>
331
#    define NAMLEN(dirent) strlen((dirent)->d_name)
332
#  else
333
#    define dirent direct
334
#    define NAMLEN(dirent) (dirent)->d_namlen
335
#  endif
336
#  ifdef HAVE_SYS_NDIR_H
337
#    include <sys/ndir.h>
338
#  endif
339
#  ifdef HAVE_SYS_DIR_H
340
#    include <sys/dir.h>
341
#  endif
342
#  ifdef HAVE_NDIR_H
343
#    include <ndir.h>
344
#  endif
345
#endif
346
347
348
#if defined(MAJOR_IN_MKDEV)
349
#  include <sys/mkdev.h>
350
#else
351
#  if defined(MAJOR_IN_SYSMACROS)
352
#    include <sys/sysmacros.h>
353
#  endif
354
#  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
355
#    include <sys/mkdev.h>
356
#  endif
357
#endif
358
359
360
// --- Macros ---------------------------------------------------------------
361
362
#ifndef MAXPATHLEN
363
#  if defined(PATH_MAX) && PATH_MAX > 1024
364
#    define MAXPATHLEN PATH_MAX
365
#  else
366
#    define MAXPATHLEN 1024
367
#  endif
368
#endif /* MAXPATHLEN */
369
370
371
#ifdef UNION_WAIT
372
   /* Emulate some macros on systems that have a union instead of macros */
373
#  ifndef WIFEXITED
374
#    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
375
#  endif
376
#  ifndef WEXITSTATUS
377
#    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
378
#  endif
379
#  ifndef WTERMSIG
380
#    define WTERMSIG(u_wait) ((u_wait).w_termsig)
381
#  endif
382
#  define WAIT_TYPE union wait
383
#  define WAIT_STATUS_INT(s) (s.w_status)
384
#else
385
   /* !UNION_WAIT */
386
0
#  define WAIT_TYPE int
387
0
#  define WAIT_STATUS_INT(s) (s)
388
#endif /* UNION_WAIT */
389
390
391
/* Don't use the "_r" form if we don't need it (also, won't have a
392
   prototype for it, at least on Solaris -- maybe others as well?). */
393
#if defined(HAVE_CTERMID_R)
394
#  define USE_CTERMID_R
395
#endif
396
397
398
/* choose the appropriate stat and fstat functions and return structs */
399
#undef STAT
400
#undef FSTAT
401
#undef STRUCT_STAT
402
#ifdef MS_WINDOWS
403
#  define STAT win32_stat
404
#  define LSTAT win32_lstat
405
#  define FSTAT _Py_fstat_noraise
406
#  define STRUCT_STAT struct _Py_stat_struct
407
#else
408
240k
#  define STAT stat
409
11.5k
#  define LSTAT lstat
410
91.1k
#  define FSTAT fstat
411
430k
#  define STRUCT_STAT struct stat
412
#endif
413
414
#ifdef HAVE_STATX
415
/* until we can assume glibc 2.28 at runtime, we must weakly link */
416
#  pragma weak statx
417
static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
418
#ifdef STATX_MNT_ID
419
                                             | STATX_MNT_ID
420
#endif
421
#ifdef STATX_DIOALIGN
422
                                             | STATX_DIOALIGN
423
#endif
424
#ifdef STATX_MNT_ID_UNIQUE
425
                                             | STATX_MNT_ID_UNIQUE
426
#endif
427
#ifdef STATX_SUBVOL
428
                                             | STATX_SUBVOL
429
#endif
430
#ifdef STATX_WRITE_ATOMIC
431
                                             | STATX_WRITE_ATOMIC
432
#endif
433
#ifdef STATX_DIO_READ_ALIGN
434
                                             | STATX_DIO_READ_ALIGN
435
#endif
436
                                            );
437
#endif /* HAVE_STATX */
438
439
440
#if !defined(EX_OK) && defined(EXIT_SUCCESS)
441
#  define EX_OK EXIT_SUCCESS
442
#endif
443
444
#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
445
#  undef HAVE_SCHED_SETAFFINITY
446
#endif
447
448
/* On android API level 21, 'AT_EACCESS' is not declared although
449
 * HAVE_FACCESSAT is defined. */
450
#ifdef __ANDROID__
451
#  undef HAVE_FACCESSAT
452
#endif
453
454
#if defined(__sun)
455
/* Something to implement in autoconf, not present in autoconf 2.69 */
456
#  define HAVE_STRUCT_STAT_ST_FSTYPE 1
457
#endif
458
459
460
// --- Apple __builtin_available() macros -----------------------------------
461
462
/*
463
 * A number of APIs are available on macOS from a certain macOS version.
464
 * To support building with a new SDK while deploying to older versions
465
 * the availability test is split into two:
466
 *   - HAVE_<FUNCTION>:  The configure check for compile time availability
467
 *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
468
 *
469
 * The latter is always true when not on macOS, or when using a compiler
470
 * that does not support __has_builtin (older versions of Xcode).
471
 *
472
 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
473
 *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
474
 *
475
 * In mixing the test with other tests or using negations will result in compile
476
 * errors.
477
 */
478
#if defined(__APPLE__)
479
480
#include <mach/mach.h>
481
482
#if defined(__has_builtin)
483
#if __has_builtin(__builtin_available)
484
#define HAVE_BUILTIN_AVAILABLE 1
485
#endif
486
#endif
487
488
#ifdef HAVE_BUILTIN_AVAILABLE
489
#  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
490
#  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
491
#  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
492
#  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
493
#  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
494
#  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
495
#  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
496
#  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
497
#  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
498
#  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
499
#  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
500
#  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
501
#  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
502
#  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
503
#  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
504
#  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
505
#  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
506
#  define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
507
508
#  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
509
510
#else /* Xcode 8 or earlier */
511
512
   /* __builtin_available is not present in these compilers, but
513
    * some of the symbols might be weak linked (10.10 SDK or later
514
    * deploying on 10.9.
515
    *
516
    * Fall back to the older style of availability checking for
517
    * symbols introduced in macOS 10.10.
518
    */
519
520
#  ifdef HAVE_FSTATAT
521
#    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
522
#  endif
523
524
#  ifdef HAVE_FACCESSAT
525
#    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
526
#  endif
527
528
#  ifdef HAVE_FCHMODAT
529
#    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
530
#  endif
531
532
#  ifdef HAVE_FCHOWNAT
533
#    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
534
#  endif
535
536
#  ifdef HAVE_LINKAT
537
#    define HAVE_LINKAT_RUNTIME (linkat != NULL)
538
#  endif
539
540
#  ifdef HAVE_FDOPENDIR
541
#    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
542
#  endif
543
544
#  ifdef HAVE_MKDIRAT
545
#    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
546
#  endif
547
548
#  ifdef HAVE_RENAMEAT
549
#    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
550
#  endif
551
552
#  ifdef HAVE_UNLINKAT
553
#    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
554
#  endif
555
556
#  ifdef HAVE_OPENAT
557
#    define HAVE_OPENAT_RUNTIME (openat != NULL)
558
#  endif
559
560
#  ifdef HAVE_READLINKAT
561
#    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
562
#  endif
563
564
#  ifdef HAVE_SYMLINKAT
565
#    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
566
#  endif
567
568
#  ifdef HAVE_UTIMENSAT
569
#    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
570
#  endif
571
572
#  ifdef HAVE_FUTIMENS
573
#    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
574
#  endif
575
576
#  ifdef HAVE_PWRITEV
577
#    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
578
#  endif
579
580
#  ifdef HAVE_MKFIFOAT
581
#    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
582
#  endif
583
584
#  ifdef HAVE_MKNODAT
585
#    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
586
#  endif
587
588
#  ifdef HAVE_PTSNAME_R
589
#    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
590
#  endif
591
592
#endif
593
594
#ifdef HAVE_FUTIMESAT
595
/* Some of the logic for weak linking depends on this assertion */
596
# error "HAVE_FUTIMESAT unexpectedly defined"
597
#endif
598
599
#else
600
86.8k
#  define HAVE_FSTATAT_RUNTIME 1
601
0
#  define HAVE_FACCESSAT_RUNTIME 1
602
0
#  define HAVE_FCHMODAT_RUNTIME 1
603
0
#  define HAVE_FCHOWNAT_RUNTIME 1
604
#ifdef __wasi__
605
#  define HAVE_LINKAT_RUNTIME 0
606
# else
607
0
#  define HAVE_LINKAT_RUNTIME 1
608
# endif
609
91.1k
#  define HAVE_FDOPENDIR_RUNTIME 1
610
0
#  define HAVE_MKDIRAT_RUNTIME 1
611
0
#  define HAVE_RENAMEAT_RUNTIME 1
612
104k
#  define HAVE_UNLINKAT_RUNTIME 1
613
86.8k
#  define HAVE_OPENAT_RUNTIME 1
614
0
#  define HAVE_READLINKAT_RUNTIME 1
615
0
#  define HAVE_SYMLINKAT_RUNTIME 1
616
0
#  define HAVE_FUTIMENS_RUNTIME 1
617
0
#  define HAVE_UTIMENSAT_RUNTIME 1
618
36
#  define HAVE_PWRITEV_RUNTIME 1
619
0
#  define HAVE_MKFIFOAT_RUNTIME 1
620
0
#  define HAVE_MKNODAT_RUNTIME 1
621
0
#  define HAVE_PTSNAME_R_RUNTIME 1
622
#endif
623
624
625
// --- os module ------------------------------------------------------------
626
627
#ifdef MS_WINDOWS
628
#  define INITFUNC PyInit_nt
629
#  define MODNAME "nt"
630
#  define MODNAME_OBJ &_Py_ID(nt)
631
#else
632
#  define INITFUNC PyInit_posix
633
#  define MODNAME "posix"
634
0
#  define MODNAME_OBJ &_Py_ID(posix)
635
#endif
636
637
/*[clinic input]
638
# one of the few times we lie about this name!
639
module os
640
[clinic start generated code]*/
641
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
642
643
PyDoc_STRVAR(posix__doc__,
644
"This module provides access to operating system functionality that is\n\
645
standardized by the C Standard and the POSIX standard (a thinly\n\
646
disguised Unix interface).  Refer to the library manual and\n\
647
corresponding Unix manual entries for more information on calls.");
648
649
650
// --- Functions ------------------------------------------------------------
651
652
#ifdef HAVE_FORK
653
static void
654
run_at_forkers(PyObject *lst, int reverse)
655
0
{
656
0
    Py_ssize_t i;
657
0
    PyObject *cpy;
658
659
0
    if (lst != NULL) {
660
0
        assert(PyList_CheckExact(lst));
661
662
        /* Use a list copy in case register_at_fork() is called from
663
         * one of the callbacks.
664
         */
665
0
        cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
666
0
        if (cpy == NULL) {
667
0
            PyErr_FormatUnraisable("Exception ignored in atfork callback "
668
0
                                   "while copying list %R", lst);
669
0
        }
670
0
        else {
671
0
            if (reverse)
672
0
                PyList_Reverse(cpy);
673
0
            for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
674
0
                PyObject *func, *res;
675
0
                func = PyList_GET_ITEM(cpy, i);
676
0
                res = _PyObject_CallNoArgs(func);
677
0
                if (res == NULL) {
678
0
                    PyErr_FormatUnraisable("Exception ignored "
679
0
                                           "in atfork callback %R", func);
680
0
                }
681
0
                else {
682
0
                    Py_DECREF(res);
683
0
                }
684
0
            }
685
0
            Py_DECREF(cpy);
686
0
        }
687
0
    }
688
0
}
689
690
void
691
PyOS_BeforeFork(void)
692
0
{
693
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
694
0
    run_at_forkers(interp->before_forkers, 1);
695
696
0
    _PyImport_AcquireLock(interp);
697
0
    _PyEval_StopTheWorldAll(&_PyRuntime);
698
0
    HEAD_LOCK(&_PyRuntime);
699
0
}
700
701
void
702
PyOS_AfterFork_Parent(void)
703
0
{
704
0
    HEAD_UNLOCK(&_PyRuntime);
705
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
706
707
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
708
0
    _PyImport_ReleaseLock(interp);
709
0
    run_at_forkers(interp->after_forkers_parent, 0);
710
0
}
711
712
static void
713
reset_remotedebug_data(PyThreadState *tstate)
714
0
{
715
0
    tstate->remote_debugger_support.debugger_pending_call = 0;
716
0
    memset(tstate->remote_debugger_support.debugger_script_path, 0,
717
0
           _Py_MAX_SCRIPT_PATH_SIZE);
718
0
}
719
720
static void
721
reset_asyncio_state(_PyThreadStateImpl *tstate)
722
0
{
723
0
    llist_init(&tstate->asyncio_tasks_head);
724
0
    tstate->asyncio_running_loop = NULL;
725
0
    tstate->asyncio_running_task = NULL;
726
0
}
727
728
729
void
730
PyOS_AfterFork_Child(void)
731
0
{
732
0
    PyStatus status;
733
0
    _PyRuntimeState *runtime = &_PyRuntime;
734
735
    // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
736
0
    status = _PyRuntimeState_ReInitThreads(runtime);
737
0
    if (_PyStatus_EXCEPTION(status)) {
738
0
        goto fatal_error;
739
0
    }
740
741
0
    PyThreadState *tstate = _PyThreadState_GET();
742
0
    _Py_EnsureTstateNotNULL(tstate);
743
744
0
    assert(tstate->thread_id == PyThread_get_thread_ident());
745
0
#ifdef PY_HAVE_THREAD_NATIVE_ID
746
0
    tstate->native_thread_id = PyThread_get_thread_native_id();
747
0
#endif
748
749
#ifdef Py_GIL_DISABLED
750
    _Py_brc_after_fork(tstate->interp);
751
    _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
752
#endif
753
754
    // Ideally we could guarantee tstate is running main.
755
0
    _PyInterpreterState_ReinitRunningMain(tstate);
756
757
0
    status = _PyEval_ReInitThreads(tstate);
758
0
    if (_PyStatus_EXCEPTION(status)) {
759
0
        goto fatal_error;
760
0
    }
761
762
#if defined(PY_HAVE_JIT_GDB_UNWIND)
763
    // The child can inherit this mutex locked if another thread held it at
764
    // fork(), but the child itself cannot be inside gdb_jit_register_code().
765
    // Reinitialize it before any executor cleanup can unregister JIT code.
766
    _Py_jit_debug_mutex = (PyMutex){0};
767
#endif
768
769
0
    reset_remotedebug_data(tstate);
770
771
0
    reset_asyncio_state((_PyThreadStateImpl *)tstate);
772
773
    // Remove the dead thread states. We "start the world" once we are the only
774
    // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
775
    // That needs to happen before `_PyThreadState_DeleteList`, because that
776
    // may call destructors.
777
0
    PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
778
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
779
0
    _PyThreadState_DeleteList(list, /*is_after_fork=*/1);
780
781
0
    _PyImport_ReInitLock(tstate->interp);
782
0
    _PyImport_ReleaseLock(tstate->interp);
783
784
0
    _PySignal_AfterFork();
785
786
0
    status = _PyInterpreterState_DeleteExceptMain(runtime);
787
0
    if (_PyStatus_EXCEPTION(status)) {
788
0
        goto fatal_error;
789
0
    }
790
0
    assert(_PyThreadState_GET() == tstate);
791
792
0
    status = _PyPerfTrampoline_AfterFork_Child();
793
0
    if (_PyStatus_EXCEPTION(status)) {
794
0
        goto fatal_error;
795
0
    }
796
797
0
    run_at_forkers(tstate->interp->after_forkers_child, 0);
798
0
    return;
799
800
0
fatal_error:
801
0
    Py_ExitStatusException(status);
802
0
}
803
804
static int
805
register_at_forker(PyObject **lst, PyObject *func)
806
60
{
807
60
    if (func == NULL)  /* nothing to register? do nothing. */
808
40
        return 0;
809
20
    if (*lst == NULL) {
810
10
        *lst = PyList_New(0);
811
10
        if (*lst == NULL)
812
0
            return -1;
813
10
    }
814
20
    return PyList_Append(*lst, func);
815
20
}
816
#endif  /* HAVE_FORK */
817
818
819
/* Legacy wrapper */
820
void
821
PyOS_AfterFork(void)
822
0
{
823
0
#ifdef HAVE_FORK
824
0
    PyOS_AfterFork_Child();
825
0
#endif
826
0
}
827
828
829
#ifdef MS_WINDOWS
830
/* defined in fileutils.c */
831
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
832
void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
833
                                FILE_BASIC_INFO *, FILE_ID_INFO *,
834
                                struct _Py_stat_struct *);
835
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
836
                                 struct _Py_stat_struct *);
837
#endif
838
839
840
#ifndef MS_WINDOWS
841
PyObject *
842
_PyLong_FromUid(uid_t uid)
843
245k
{
844
245k
    if (uid == (uid_t)-1)
845
0
        return PyLong_FromLong(-1);
846
245k
    return PyLong_FromUnsignedLong(uid);
847
245k
}
848
849
PyObject *
850
_PyLong_FromGid(gid_t gid)
851
245k
{
852
245k
    if (gid == (gid_t)-1)
853
0
        return PyLong_FromLong(-1);
854
245k
    return PyLong_FromUnsignedLong(gid);
855
245k
}
856
857
int
858
_Py_Uid_Converter(PyObject *obj, uid_t *p)
859
0
{
860
0
    uid_t uid;
861
0
    PyObject *index;
862
0
    int overflow;
863
0
    long result;
864
0
    unsigned long uresult;
865
866
0
    index = _PyNumber_Index(obj);
867
0
    if (index == NULL) {
868
0
        PyErr_Format(PyExc_TypeError,
869
0
                     "uid should be integer, not %.200s",
870
0
                     _PyType_Name(Py_TYPE(obj)));
871
0
        return 0;
872
0
    }
873
874
    /*
875
     * Handling uid_t is complicated for two reasons:
876
     *  * Although uid_t is (always?) unsigned, it still
877
     *    accepts -1.
878
     *  * We don't know its size in advance--it may be
879
     *    bigger than an int, or it may be smaller than
880
     *    a long.
881
     *
882
     * So a bit of defensive programming is in order.
883
     * Start with interpreting the value passed
884
     * in as a signed long and see if it works.
885
     */
886
887
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
888
889
0
    if (!overflow) {
890
0
        uid = (uid_t)result;
891
892
0
        if (result == -1) {
893
0
            if (PyErr_Occurred())
894
0
                goto fail;
895
            /* It's a legitimate -1, we're done. */
896
0
            goto success;
897
0
        }
898
899
        /* Any other negative number is disallowed. */
900
0
        if (result < 0)
901
0
            goto underflow;
902
903
        /* Ensure the value wasn't truncated. */
904
0
        if (sizeof(uid_t) < sizeof(long) &&
905
0
            (long)uid != result)
906
0
            goto underflow;
907
0
        goto success;
908
0
    }
909
910
0
    if (overflow < 0)
911
0
        goto underflow;
912
913
    /*
914
     * Okay, the value overflowed a signed long.  If it
915
     * fits in an *unsigned* long, it may still be okay,
916
     * as uid_t may be unsigned long on this platform.
917
     */
918
0
    uresult = PyLong_AsUnsignedLong(index);
919
0
    if (PyErr_Occurred()) {
920
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
921
0
            goto overflow;
922
0
        goto fail;
923
0
    }
924
925
0
    uid = (uid_t)uresult;
926
927
    /*
928
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
929
     * but this value would get interpreted as (uid_t)-1  by chown
930
     * and its siblings.   That's not what the user meant!  So we
931
     * throw an overflow exception instead.   (We already
932
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
933
     */
934
0
    if (uid == (uid_t)-1)
935
0
        goto overflow;
936
937
    /* Ensure the value wasn't truncated. */
938
0
    if (sizeof(uid_t) < sizeof(long) &&
939
0
        (unsigned long)uid != uresult)
940
0
        goto overflow;
941
    /* fallthrough */
942
943
0
success:
944
0
    Py_DECREF(index);
945
0
    *p = uid;
946
0
    return 1;
947
948
0
underflow:
949
0
    PyErr_SetString(PyExc_OverflowError,
950
0
                    "uid is less than minimum");
951
0
    goto fail;
952
953
0
overflow:
954
0
    PyErr_SetString(PyExc_OverflowError,
955
0
                    "uid is greater than maximum");
956
    /* fallthrough */
957
958
0
fail:
959
0
    Py_DECREF(index);
960
0
    return 0;
961
0
}
962
963
int
964
_Py_Gid_Converter(PyObject *obj, gid_t *p)
965
0
{
966
0
    gid_t gid;
967
0
    PyObject *index;
968
0
    int overflow;
969
0
    long result;
970
0
    unsigned long uresult;
971
972
0
    index = _PyNumber_Index(obj);
973
0
    if (index == NULL) {
974
0
        PyErr_Format(PyExc_TypeError,
975
0
                     "gid should be integer, not %.200s",
976
0
                     _PyType_Name(Py_TYPE(obj)));
977
0
        return 0;
978
0
    }
979
980
    /*
981
     * Handling gid_t is complicated for two reasons:
982
     *  * Although gid_t is (always?) unsigned, it still
983
     *    accepts -1.
984
     *  * We don't know its size in advance--it may be
985
     *    bigger than an int, or it may be smaller than
986
     *    a long.
987
     *
988
     * So a bit of defensive programming is in order.
989
     * Start with interpreting the value passed
990
     * in as a signed long and see if it works.
991
     */
992
993
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
994
995
0
    if (!overflow) {
996
0
        gid = (gid_t)result;
997
998
0
        if (result == -1) {
999
0
            if (PyErr_Occurred())
1000
0
                goto fail;
1001
            /* It's a legitimate -1, we're done. */
1002
0
            goto success;
1003
0
        }
1004
1005
        /* Any other negative number is disallowed. */
1006
0
        if (result < 0) {
1007
0
            goto underflow;
1008
0
        }
1009
1010
        /* Ensure the value wasn't truncated. */
1011
0
        if (sizeof(gid_t) < sizeof(long) &&
1012
0
            (long)gid != result)
1013
0
            goto underflow;
1014
0
        goto success;
1015
0
    }
1016
1017
0
    if (overflow < 0)
1018
0
        goto underflow;
1019
1020
    /*
1021
     * Okay, the value overflowed a signed long.  If it
1022
     * fits in an *unsigned* long, it may still be okay,
1023
     * as gid_t may be unsigned long on this platform.
1024
     */
1025
0
    uresult = PyLong_AsUnsignedLong(index);
1026
0
    if (PyErr_Occurred()) {
1027
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1028
0
            goto overflow;
1029
0
        goto fail;
1030
0
    }
1031
1032
0
    gid = (gid_t)uresult;
1033
1034
    /*
1035
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
1036
     * but this value would get interpreted as (gid_t)-1  by chown
1037
     * and its siblings.   That's not what the user meant!  So we
1038
     * throw an overflow exception instead.   (We already
1039
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
1040
     */
1041
0
    if (gid == (gid_t)-1)
1042
0
        goto overflow;
1043
1044
    /* Ensure the value wasn't truncated. */
1045
0
    if (sizeof(gid_t) < sizeof(long) &&
1046
0
        (unsigned long)gid != uresult)
1047
0
        goto overflow;
1048
    /* fallthrough */
1049
1050
0
success:
1051
0
    Py_DECREF(index);
1052
0
    *p = gid;
1053
0
    return 1;
1054
1055
0
underflow:
1056
0
    PyErr_SetString(PyExc_OverflowError,
1057
0
                    "gid is less than minimum");
1058
0
    goto fail;
1059
1060
0
overflow:
1061
0
    PyErr_SetString(PyExc_OverflowError,
1062
0
                    "gid is greater than maximum");
1063
    /* fallthrough */
1064
1065
0
fail:
1066
0
    Py_DECREF(index);
1067
0
    return 0;
1068
0
}
1069
#endif /* MS_WINDOWS */
1070
1071
1072
static PyObject *
1073
_PyLong_FromDev(dev_t dev)
1074
491k
{
1075
491k
#ifdef NODEV
1076
491k
    if (dev == NODEV) {
1077
36
        return PyLong_FromLongLong((long long)dev);
1078
36
    }
1079
491k
#endif
1080
491k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1081
491k
}
1082
1083
1084
#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
1085
static int
1086
_Py_Dev_Converter(PyObject *obj, void *p)
1087
0
{
1088
0
    if (!PyLong_Check(obj)) {
1089
0
        obj = _PyNumber_Index(obj);
1090
0
        if (obj == NULL) {
1091
0
            return 0;
1092
0
        }
1093
0
    }
1094
0
    else {
1095
0
        Py_INCREF(obj);
1096
0
    }
1097
0
    assert(PyLong_Check(obj));
1098
0
#ifdef NODEV
1099
0
    if (_PyLong_IsNegative((PyLongObject *)obj)) {
1100
0
        int overflow;
1101
0
        long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
1102
0
        if (result == -1 && PyErr_Occurred()) {
1103
0
            Py_DECREF(obj);
1104
0
            return 0;
1105
0
        }
1106
0
        if (!overflow && result == (long long)NODEV) {
1107
0
            *((dev_t *)p) = NODEV;
1108
0
            Py_DECREF(obj);
1109
0
            return 1;
1110
0
        }
1111
0
    }
1112
0
#endif
1113
1114
0
    unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1115
0
    Py_DECREF(obj);
1116
0
    if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1117
0
        return 0;
1118
0
    }
1119
0
    if ((unsigned long long)(dev_t)result != result) {
1120
0
        PyErr_SetString(PyExc_OverflowError,
1121
0
                        "Python int too large to convert to C dev_t");
1122
0
        return 0;
1123
0
    }
1124
0
    *((dev_t *)p) = (dev_t)result;
1125
0
    return 1;
1126
0
}
1127
#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1128
1129
1130
#ifdef AT_FDCWD
1131
/*
1132
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1133
 * without the int cast, the value gets interpreted as uint (4291925331),
1134
 * which doesn't play nicely with all the initializer lines in this file that
1135
 * look like this:
1136
 *      int dir_fd = DEFAULT_DIR_FD;
1137
 */
1138
1.89M
#define DEFAULT_DIR_FD (int)AT_FDCWD
1139
#else
1140
#define DEFAULT_DIR_FD (-100)
1141
#endif
1142
1143
static int
1144
_fd_converter(PyObject *o, int *p)
1145
282k
{
1146
282k
    int overflow;
1147
282k
    long long_value;
1148
1149
282k
    if (PyBool_Check(o)) {
1150
0
        if (PyErr_WarnEx(PyExc_RuntimeWarning,
1151
0
                "bool is used as a file descriptor", 1))
1152
0
        {
1153
0
            return 0;
1154
0
        }
1155
0
    }
1156
282k
    PyObject *index = _PyNumber_Index(o);
1157
282k
    if (index == NULL) {
1158
0
        return 0;
1159
0
    }
1160
1161
282k
    assert(PyLong_Check(index));
1162
282k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1163
282k
    Py_DECREF(index);
1164
282k
    assert(!PyErr_Occurred());
1165
282k
    if (overflow > 0 || long_value > INT_MAX) {
1166
0
        PyErr_SetString(PyExc_OverflowError,
1167
0
                        "fd is greater than maximum");
1168
0
        return 0;
1169
0
    }
1170
282k
    if (overflow < 0 || long_value < INT_MIN) {
1171
0
        PyErr_SetString(PyExc_OverflowError,
1172
0
                        "fd is less than minimum");
1173
0
        return 0;
1174
0
    }
1175
1176
282k
    *p = (int)long_value;
1177
282k
    return 1;
1178
282k
}
1179
1180
static int
1181
dir_fd_converter(PyObject *o, void *p)
1182
208k
{
1183
208k
    if (o == Py_None) {
1184
17.2k
        *(int *)p = DEFAULT_DIR_FD;
1185
17.2k
        return 1;
1186
17.2k
    }
1187
191k
    else if (PyIndex_Check(o)) {
1188
191k
        return _fd_converter(o, (int *)p);
1189
191k
    }
1190
0
    else {
1191
0
        PyErr_Format(PyExc_TypeError,
1192
0
                     "argument should be integer or None, not %.200s",
1193
0
                     _PyType_Name(Py_TYPE(o)));
1194
0
        return 0;
1195
0
    }
1196
208k
}
1197
1198
typedef struct {
1199
    PyObject *billion;
1200
    PyObject *DirEntryType;
1201
    PyObject *ScandirIteratorType;
1202
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1203
    PyObject *SchedParamType;
1204
#endif
1205
    newfunc statresult_new_orig;
1206
    PyObject *StatResultType;
1207
#ifdef HAVE_STATX
1208
    PyObject *StatxResultType;
1209
#endif
1210
    PyObject *StatVFSResultType;
1211
    PyObject *TerminalSizeType;
1212
    PyObject *TimesResultType;
1213
    PyObject *UnameResultType;
1214
#if defined(HAVE_WAITID)
1215
    PyObject *WaitidResultType;
1216
#endif
1217
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1218
    PyObject *struct_rusage;
1219
#endif
1220
    PyObject *st_mode;
1221
#ifndef MS_WINDOWS
1222
    // times() clock frequency in hertz; used by os.times()
1223
    long ticks_per_second;
1224
#endif
1225
} _posixstate;
1226
1227
1228
static inline _posixstate*
1229
get_posix_state(PyObject *module)
1230
443k
{
1231
443k
    void *state = _PyModule_GetState(module);
1232
443k
    assert(state != NULL);
1233
443k
    return (_posixstate *)state;
1234
443k
}
1235
1236
/*
1237
 * A PyArg_ParseTuple "converter" function
1238
 * that handles filesystem paths in the manner
1239
 * preferred by the os module.
1240
 *
1241
 * path_converter accepts (Unicode) strings and their
1242
 * subclasses, and bytes and their subclasses.  What
1243
 * it does with the argument depends on path.make_wide:
1244
 *
1245
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1246
 *     string we extract the wchar_t * and return it; if we
1247
 *     get bytes we decode to wchar_t * and return that.
1248
 *
1249
 *   * If path.make_wide is zero, if we get bytes we extract
1250
 *     the char_t * and return it; if we get a (Unicode)
1251
 *     string we encode to char_t * and return that.
1252
 *
1253
 * path_converter also optionally accepts signed
1254
 * integers (representing open file descriptors) instead
1255
 * of path strings.
1256
 *
1257
 * Input fields:
1258
 *   path.nullable
1259
 *     If nonzero, the path is permitted to be None.
1260
 *   path.nonstrict
1261
 *     If nonzero, the path is permitted to contain
1262
 *     embedded null characters and have any length.
1263
 *   path.make_wide
1264
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1265
 *     it always uses narrow, encoding if necessary. The default value is
1266
 *     nonzero on Windows, else zero.
1267
 *   path.suppress_value_error
1268
 *     If nonzero, raising ValueError is suppressed.
1269
 *   path.allow_fd
1270
 *     If nonzero, the path is permitted to be a file handle
1271
 *     (a signed int) instead of a string.
1272
 *   path.function_name
1273
 *     If non-NULL, path_converter will use that as the name
1274
 *     of the function in error messages.
1275
 *     (If path.function_name is NULL it omits the function name.)
1276
 *   path.argument_name
1277
 *     If non-NULL, path_converter will use that as the name
1278
 *     of the parameter in error messages.
1279
 *     (If path.argument_name is NULL it uses "path".)
1280
 *
1281
 * Output fields:
1282
 *   path.wide
1283
 *     Points to the path if it was expressed as Unicode
1284
 *     or if it was bytes and decoded to Unicode.
1285
 *   path.narrow
1286
 *     Points to the path if it was expressed as bytes,
1287
 *     or if it was Unicode and encoded to bytes.
1288
 *   path.fd
1289
 *     Contains a file descriptor if path.accept_fd was true
1290
 *     and the caller provided a signed integer instead of any
1291
 *     sort of string.
1292
 *   path.is_fd
1293
 *     True if path was provided as a file descriptor.
1294
 *
1295
 *     WARNING: if your "path" parameter is optional, and is
1296
 *     unspecified, path_converter will never get called.
1297
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1298
 *     yourself!
1299
 *   path.value_error
1300
 *     If nonzero, then suppress_value_error was specified and a ValueError
1301
 *     occurred.
1302
 *   path.length
1303
 *     The length of the path in characters, if specified as
1304
 *     a string.
1305
 *   path.object
1306
 *     The original object passed in (if get a PathLike object,
1307
 *     the result of PyOS_FSPath() is treated as the original object).
1308
 *     Own a reference to the object.
1309
 *   path.cleanup
1310
 *     For internal use only.  May point to a temporary object.
1311
 *     (Pay no attention to the man behind the curtain.)
1312
 *
1313
 *   At most one of path.wide or path.narrow will be non-NULL.
1314
 *   If path was None and path.nullable was set,
1315
 *     or if path was an integer and path.allow_fd was set,
1316
 *     both path.wide and path.narrow will be NULL
1317
 *     and path.length will be 0.
1318
 *
1319
 *   path_converter takes care to not write to the path_t
1320
 *   unless it's successful.  However it must reset the
1321
 *   "cleanup" field each time it's called.
1322
 *
1323
 * Use as follows:
1324
 *      path_t path;
1325
 *      memset(&path, 0, sizeof(path));
1326
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1327
 *      // ... use values from path ...
1328
 *      path_cleanup(&path);
1329
 *
1330
 * (Note that if PyArg_Parse fails you don't need to call
1331
 * path_cleanup().  However it is safe to do so.)
1332
 */
1333
typedef struct {
1334
    // Input fields
1335
    const char *function_name;
1336
    const char *argument_name;
1337
    int nullable;
1338
    int nonstrict;
1339
    int make_wide;
1340
    int suppress_value_error;
1341
    int allow_fd;
1342
    // Output fields
1343
    const wchar_t *wide;
1344
    const char *narrow;
1345
    int fd;
1346
    bool is_fd;
1347
    int value_error;
1348
    Py_ssize_t length;
1349
    PyObject *object;
1350
    PyObject *cleanup;
1351
} path_t;
1352
1353
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1354
                          make_wide, suppress_value_error, allow_fd) \
1355
795k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1356
795k
     suppress_value_error, allow_fd, NULL, NULL, -1, false, 0, 0, NULL, NULL}
1357
#ifdef MS_WINDOWS
1358
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1359
                            nonstrict, suppress_value_error, allow_fd) \
1360
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1361
                      suppress_value_error, allow_fd)
1362
#else
1363
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1364
                            nonstrict, suppress_value_error, allow_fd) \
1365
636k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1366
636k
                      suppress_value_error, allow_fd)
1367
#endif
1368
1369
static void
1370
path_cleanup(path_t *path)
1371
886k
{
1372
886k
    wchar_t *wide = (wchar_t *)path->wide;
1373
886k
    path->wide = NULL;
1374
886k
    PyMem_Free(wide);
1375
886k
    Py_CLEAR(path->object);
1376
886k
    Py_CLEAR(path->cleanup);
1377
886k
}
1378
1379
static int
1380
path_converter(PyObject *o, void *p)
1381
795k
{
1382
795k
    path_t *path = (path_t *)p;
1383
795k
    PyObject *bytes = NULL;
1384
795k
    Py_ssize_t length = 0;
1385
795k
    int is_index, is_bytes, is_unicode;
1386
795k
    const char *narrow;
1387
795k
    PyObject *wo = NULL;
1388
795k
    wchar_t *wide = NULL;
1389
1390
795k
#define FORMAT_EXCEPTION(exc, fmt) \
1391
795k
    PyErr_Format(exc, "%s%s" fmt, \
1392
0
        path->function_name ? path->function_name : "", \
1393
0
        path->function_name ? ": "                : "", \
1394
0
        path->argument_name ? path->argument_name : "path")
1395
1396
    /* Py_CLEANUP_SUPPORTED support */
1397
795k
    if (o == NULL) {
1398
0
        path_cleanup(path);
1399
0
        return 1;
1400
0
    }
1401
1402
    /* Ensure it's always safe to call path_cleanup(). */
1403
795k
    path->object = path->cleanup = NULL;
1404
    /* path->object owns a reference to the original object */
1405
795k
    Py_INCREF(o);
1406
1407
795k
    if ((o == Py_None) && path->nullable) {
1408
0
        path->wide = NULL;
1409
0
        path->narrow = NULL;
1410
0
        path->fd = -1;
1411
0
        goto success_exit;
1412
0
    }
1413
1414
    /* Only call this here so that we don't treat the return value of
1415
       os.fspath() as an fd or buffer. */
1416
795k
    is_index = path->allow_fd && PyIndex_Check(o);
1417
795k
    is_bytes = PyBytes_Check(o);
1418
795k
    is_unicode = PyUnicode_Check(o);
1419
1420
795k
    if (!is_index && !is_unicode && !is_bytes) {
1421
        /* Inline PyOS_FSPath() for better error messages. */
1422
17
        PyObject *func, *res;
1423
1424
17
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1425
17
        if ((NULL == func) || (func == Py_None)) {
1426
0
            goto error_format;
1427
0
        }
1428
17
        res = _PyObject_CallNoArgs(func);
1429
17
        Py_DECREF(func);
1430
17
        if (NULL == res) {
1431
0
            goto error_exit;
1432
0
        }
1433
17
        else if (PyUnicode_Check(res)) {
1434
17
            is_unicode = 1;
1435
17
        }
1436
0
        else if (PyBytes_Check(res)) {
1437
0
            is_bytes = 1;
1438
0
        }
1439
0
        else {
1440
0
            PyErr_Format(PyExc_TypeError,
1441
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1442
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1443
0
                 _PyType_Name(Py_TYPE(res)));
1444
0
            Py_DECREF(res);
1445
0
            goto error_exit;
1446
0
        }
1447
1448
        /* still owns a reference to the original object */
1449
17
        Py_SETREF(o, res);
1450
17
    }
1451
1452
795k
    if (is_unicode) {
1453
704k
        if (path->make_wide) {
1454
159k
            wide = PyUnicode_AsWideCharString(o, &length);
1455
159k
            if (!wide) {
1456
0
                goto error_exit;
1457
0
            }
1458
#ifdef MS_WINDOWS
1459
            if (!path->nonstrict && length > 32767) {
1460
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1461
                goto error_exit;
1462
            }
1463
#endif
1464
159k
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1465
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1466
0
                                 "embedded null character in %s");
1467
0
                goto error_exit;
1468
0
            }
1469
1470
159k
            path->wide = wide;
1471
159k
            path->narrow = NULL;
1472
159k
            path->fd = -1;
1473
159k
            wide = NULL;
1474
159k
            goto success_exit;
1475
159k
        }
1476
545k
        bytes = PyUnicode_EncodeFSDefault(o);
1477
545k
        if (!bytes) {
1478
0
            goto error_exit;
1479
0
        }
1480
545k
    }
1481
91.1k
    else if (is_bytes) {
1482
0
        bytes = Py_NewRef(o);
1483
0
    }
1484
91.1k
    else if (is_index) {
1485
91.1k
        if (!_fd_converter(o, &path->fd)) {
1486
0
            goto error_exit;
1487
0
        }
1488
91.1k
        path->wide = NULL;
1489
91.1k
        path->narrow = NULL;
1490
91.1k
        path->is_fd = true;
1491
91.1k
        goto success_exit;
1492
91.1k
    }
1493
0
    else {
1494
0
 error_format:
1495
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1496
0
            path->function_name ? path->function_name : "",
1497
0
            path->function_name ? ": "                : "",
1498
0
            path->argument_name ? path->argument_name : "path",
1499
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1500
0
                                               "integer or None" :
1501
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1502
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1503
0
                             "string, bytes or os.PathLike",
1504
0
            _PyType_Name(Py_TYPE(o)));
1505
0
        goto error_exit;
1506
0
    }
1507
1508
545k
    length = PyBytes_GET_SIZE(bytes);
1509
545k
    narrow = PyBytes_AS_STRING(bytes);
1510
545k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1511
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1512
0
        goto error_exit;
1513
0
    }
1514
1515
545k
    if (path->make_wide) {
1516
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1517
0
        if (!wo) {
1518
0
            goto error_exit;
1519
0
        }
1520
1521
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1522
0
        Py_DECREF(wo);
1523
0
        if (!wide) {
1524
0
            goto error_exit;
1525
0
        }
1526
#ifdef MS_WINDOWS
1527
        if (!path->nonstrict && length > 32767) {
1528
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1529
            goto error_exit;
1530
        }
1531
#endif
1532
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1533
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1534
0
                             "embedded null character in %s");
1535
0
            goto error_exit;
1536
0
        }
1537
0
        path->wide = wide;
1538
0
        path->narrow = NULL;
1539
0
        Py_DECREF(bytes);
1540
0
        wide = NULL;
1541
0
    }
1542
545k
    else {
1543
545k
        path->wide = NULL;
1544
545k
        path->narrow = narrow;
1545
545k
        if (bytes == o) {
1546
            /* Still a reference owned by path->object, don't have to
1547
            worry about path->narrow is used after free. */
1548
0
            Py_DECREF(bytes);
1549
0
        }
1550
545k
        else {
1551
545k
            path->cleanup = bytes;
1552
545k
        }
1553
545k
    }
1554
545k
    path->fd = -1;
1555
1556
795k
 success_exit:
1557
795k
    path->value_error = 0;
1558
795k
    path->length = length;
1559
795k
    path->object = o;
1560
795k
    return Py_CLEANUP_SUPPORTED;
1561
1562
0
 error_exit:
1563
0
    Py_XDECREF(o);
1564
0
    Py_XDECREF(bytes);
1565
0
    PyMem_Free(wide);
1566
0
    if (!path->suppress_value_error ||
1567
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1568
0
    {
1569
0
        return 0;
1570
0
    }
1571
0
    PyErr_Clear();
1572
0
    path->wide = NULL;
1573
0
    path->narrow = NULL;
1574
0
    path->fd = -1;
1575
0
    path->value_error = 1;
1576
0
    path->length = 0;
1577
0
    path->object = NULL;
1578
0
    return Py_CLEANUP_SUPPORTED;
1579
0
}
1580
1581
static void
1582
argument_unavailable_error(const char *function_name, const char *argument_name)
1583
0
{
1584
0
    PyErr_Format(PyExc_NotImplementedError,
1585
0
        "%s%s%s unavailable on this platform",
1586
0
        (function_name != NULL) ? function_name : "",
1587
0
        (function_name != NULL) ? ": ": "",
1588
0
        argument_name);
1589
0
}
1590
1591
static int
1592
dir_fd_unavailable(PyObject *o, void *p)
1593
36
{
1594
36
    int dir_fd;
1595
36
    if (!dir_fd_converter(o, &dir_fd))
1596
0
        return 0;
1597
36
    if (dir_fd != DEFAULT_DIR_FD) {
1598
0
        argument_unavailable_error(NULL, "dir_fd");
1599
0
        return 0;
1600
0
    }
1601
36
    *(int *)p = dir_fd;
1602
36
    return 1;
1603
36
}
1604
1605
static int
1606
fd_specified(const char *function_name, int fd)
1607
36
{
1608
36
    if (fd == -1)
1609
36
        return 0;
1610
1611
0
    argument_unavailable_error(function_name, "fd");
1612
0
    return 1;
1613
36
}
1614
1615
static int
1616
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1617
36
{
1618
36
    if (follow_symlinks)
1619
36
        return 0;
1620
1621
0
    argument_unavailable_error(function_name, "follow_symlinks");
1622
0
    return 1;
1623
36
}
1624
1625
static int
1626
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1627
252k
{
1628
252k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1629
0
        PyErr_Format(PyExc_ValueError,
1630
0
                     "%s: can't specify dir_fd without matching path",
1631
0
                     function_name);
1632
0
        return 1;
1633
0
    }
1634
252k
    return 0;
1635
252k
}
1636
1637
static int
1638
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1639
252k
{
1640
252k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1641
0
        PyErr_Format(PyExc_ValueError,
1642
0
                     "%s: can't specify both dir_fd and fd",
1643
0
                     function_name);
1644
0
        return 1;
1645
0
    }
1646
252k
    return 0;
1647
252k
}
1648
1649
static int
1650
fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
1651
                               int follow_symlinks)
1652
252k
{
1653
252k
    if (is_fd && (!follow_symlinks)) {
1654
0
        PyErr_Format(PyExc_ValueError,
1655
0
                     "%s: cannot use fd and follow_symlinks together",
1656
0
                     function_name);
1657
0
        return 1;
1658
0
    }
1659
252k
    return 0;
1660
252k
}
1661
1662
static int
1663
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1664
                                   int follow_symlinks)
1665
36
{
1666
36
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1667
0
        PyErr_Format(PyExc_ValueError,
1668
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1669
0
                     function_name);
1670
0
        return 1;
1671
0
    }
1672
36
    return 0;
1673
36
}
1674
1675
#if defined(HAVE_WAITID)
1676
static int
1677
idtype_t_converter(PyObject *arg, void *addr)
1678
0
{
1679
0
    int value = PyLong_AsInt(arg);
1680
0
    if (value == -1 && PyErr_Occurred()) {
1681
0
        return 0;
1682
0
    }
1683
0
    *((idtype_t *)addr) = (idtype_t)(value);
1684
0
    return 1;
1685
0
}
1686
#endif
1687
1688
#ifdef MS_WINDOWS
1689
    typedef long long Py_off_t;
1690
#else
1691
    typedef off_t Py_off_t;
1692
#endif
1693
1694
static int
1695
Py_off_t_converter(PyObject *arg, void *addr)
1696
0
{
1697
#ifdef HAVE_LARGEFILE_SUPPORT
1698
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1699
#else
1700
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1701
0
#endif
1702
0
    if (PyErr_Occurred())
1703
0
        return 0;
1704
0
    return 1;
1705
0
}
1706
1707
static PyObject *
1708
PyLong_FromPy_off_t(Py_off_t offset)
1709
0
{
1710
#ifdef HAVE_LARGEFILE_SUPPORT
1711
    return PyLong_FromLongLong(offset);
1712
#else
1713
0
    return PyLong_FromLong(offset);
1714
0
#endif
1715
0
}
1716
1717
#ifdef HAVE_SIGSET_T
1718
/* Convert an iterable of integers to a sigset.
1719
   Return 1 on success, return 0 and raise an exception on error. */
1720
int
1721
_Py_Sigset_Converter(PyObject *obj, void *addr)
1722
0
{
1723
0
    sigset_t *mask = (sigset_t *)addr;
1724
0
    PyObject *iterator, *item;
1725
0
    long signum;
1726
0
    int overflow;
1727
1728
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1729
0
    if (sigemptyset(mask) < (0)) {
1730
        /* Probably only if mask == NULL. */
1731
0
        PyErr_SetFromErrno(PyExc_OSError);
1732
0
        return 0;
1733
0
    }
1734
1735
0
    iterator = PyObject_GetIter(obj);
1736
0
    if (iterator == NULL) {
1737
0
        return 0;
1738
0
    }
1739
1740
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1741
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1742
0
        Py_DECREF(item);
1743
0
        if (signum <= 0 || signum >= Py_NSIG) {
1744
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1745
0
                PyErr_Format(PyExc_ValueError,
1746
0
                             "signal number %ld out of range [1; %i]",
1747
0
                             signum, Py_NSIG - 1);
1748
0
            }
1749
0
            goto error;
1750
0
        }
1751
0
        if (sigaddset(mask, (int)signum)) {
1752
0
            if (errno != EINVAL) {
1753
                /* Probably impossible */
1754
0
                PyErr_SetFromErrno(PyExc_OSError);
1755
0
                goto error;
1756
0
            }
1757
            /* For backwards compatibility, allow idioms such as
1758
             * `range(1, NSIG)` but warn about invalid signal numbers
1759
             */
1760
0
            const char msg[] =
1761
0
                "invalid signal number %ld, please use valid_signals()";
1762
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1763
0
                goto error;
1764
0
            }
1765
0
        }
1766
0
    }
1767
0
    if (!PyErr_Occurred()) {
1768
0
        Py_DECREF(iterator);
1769
0
        return 1;
1770
0
    }
1771
1772
0
error:
1773
0
    Py_DECREF(iterator);
1774
0
    return 0;
1775
0
}
1776
#endif /* HAVE_SIGSET_T */
1777
1778
/* Return a dictionary corresponding to the POSIX environment table */
1779
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1780
/* On Darwin/MacOSX a shared library or framework has no access to
1781
** environ directly, we must obtain it with _NSGetEnviron(). See also
1782
** man environ(7).
1783
*/
1784
#include <crt_externs.h>
1785
#define USE_DARWIN_NS_GET_ENVIRON 1
1786
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1787
extern char **environ;
1788
#endif /* !_MSC_VER */
1789
1790
static PyObject *
1791
convertenviron(void)
1792
36
{
1793
36
    PyObject *d;
1794
#ifdef MS_WINDOWS
1795
    wchar_t **e;
1796
#else
1797
36
    char **e;
1798
36
#endif
1799
1800
36
    d = PyDict_New();
1801
36
    if (d == NULL)
1802
0
        return NULL;
1803
#ifdef MS_WINDOWS
1804
    /* _wenviron must be initialized in this way if the program is started
1805
       through main() instead of wmain(). */
1806
    (void)_wgetenv(L"");
1807
    e = _wenviron;
1808
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1809
    /* environ is not accessible as an extern in a shared object on OSX; use
1810
       _NSGetEnviron to resolve it. The value changes if you add environment
1811
       variables between calls to Py_Initialize, so don't cache the value. */
1812
    e = *_NSGetEnviron();
1813
#else
1814
36
    e = environ;
1815
36
#endif
1816
36
    if (e == NULL)
1817
0
        return d;
1818
1.26k
    for (; *e != NULL; e++) {
1819
1.22k
        PyObject *k;
1820
1.22k
        PyObject *v;
1821
#ifdef MS_WINDOWS
1822
        const wchar_t *p = wcschr(*e, L'=');
1823
#else
1824
1.22k
        const char *p = strchr(*e, '=');
1825
1.22k
#endif
1826
1.22k
        if (p == NULL)
1827
0
            continue;
1828
#ifdef MS_WINDOWS
1829
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1830
#else
1831
1.22k
        k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
1832
1.22k
#endif
1833
1.22k
        if (k == NULL) {
1834
0
            Py_DECREF(d);
1835
0
            return NULL;
1836
0
        }
1837
#ifdef MS_WINDOWS
1838
        v = PyUnicode_FromWideChar(p+1, -1);
1839
#else
1840
1.22k
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1841
1.22k
#endif
1842
1.22k
        if (v == NULL) {
1843
0
            Py_DECREF(k);
1844
0
            Py_DECREF(d);
1845
0
            return NULL;
1846
0
        }
1847
1.22k
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1848
0
            Py_DECREF(v);
1849
0
            Py_DECREF(k);
1850
0
            Py_DECREF(d);
1851
0
            return NULL;
1852
0
        }
1853
1.22k
        Py_DECREF(k);
1854
1.22k
        Py_DECREF(v);
1855
1.22k
    }
1856
36
    return d;
1857
36
}
1858
1859
/* Set a POSIX-specific error from errno, and return NULL */
1860
1861
static PyObject *
1862
posix_error(void)
1863
0
{
1864
0
    return PyErr_SetFromErrno(PyExc_OSError);
1865
0
}
1866
1867
#ifdef MS_WINDOWS
1868
static PyObject *
1869
win32_error(const char* function, const char* filename)
1870
{
1871
    /* XXX We should pass the function name along in the future.
1872
       (winreg.c also wants to pass the function name.)
1873
       This would however require an additional param to the
1874
       Windows error object, which is non-trivial.
1875
    */
1876
    errno = GetLastError();
1877
    if (filename)
1878
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1879
    else
1880
        return PyErr_SetFromWindowsErr(errno);
1881
}
1882
1883
static PyObject *
1884
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1885
{
1886
    /* XXX - see win32_error for comments on 'function' */
1887
    if (filename)
1888
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1889
                    PyExc_OSError,
1890
                    err,
1891
                    filename);
1892
    else
1893
        return PyErr_SetFromWindowsErr(err);
1894
}
1895
1896
static PyObject *
1897
win32_error_object(const char* function, PyObject* filename)
1898
{
1899
    errno = GetLastError();
1900
    return win32_error_object_err(function, filename, errno);
1901
}
1902
1903
#endif /* MS_WINDOWS */
1904
1905
static PyObject *
1906
posix_path_object_error(PyObject *path)
1907
185k
{
1908
185k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1909
185k
}
1910
1911
static PyObject *
1912
path_object_error(PyObject *path)
1913
185k
{
1914
#ifdef MS_WINDOWS
1915
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1916
                PyExc_OSError, 0, path);
1917
#else
1918
185k
    return posix_path_object_error(path);
1919
185k
#endif
1920
185k
}
1921
1922
static PyObject *
1923
path_object_error2(PyObject *path, PyObject *path2)
1924
0
{
1925
#ifdef MS_WINDOWS
1926
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1927
                PyExc_OSError, 0, path, path2);
1928
#else
1929
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1930
0
#endif
1931
0
}
1932
1933
static PyObject *
1934
path_error(path_t *path)
1935
185k
{
1936
185k
    return path_object_error(path->object);
1937
185k
}
1938
1939
static PyObject *
1940
posix_path_error(path_t *path)
1941
0
{
1942
0
    return posix_path_object_error(path->object);
1943
0
}
1944
1945
static PyObject *
1946
path_error2(path_t *path, path_t *path2)
1947
0
{
1948
0
    return path_object_error2(path->object, path2->object);
1949
0
}
1950
1951
1952
/* POSIX generic methods */
1953
1954
static PyObject *
1955
posix_fildes_fd(int fd, int (*func)(int))
1956
0
{
1957
0
    int res;
1958
0
    int async_err = 0;
1959
1960
0
    do {
1961
0
        Py_BEGIN_ALLOW_THREADS
1962
0
        _Py_BEGIN_SUPPRESS_IPH
1963
0
        res = (*func)(fd);
1964
0
        _Py_END_SUPPRESS_IPH
1965
0
        Py_END_ALLOW_THREADS
1966
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1967
0
    if (res != 0)
1968
0
        return (!async_err) ? posix_error() : NULL;
1969
0
    Py_RETURN_NONE;
1970
0
}
1971
1972
1973
#ifdef MS_WINDOWS
1974
/* This is a reimplementation of the C library's chdir function,
1975
   but one that produces Win32 errors instead of DOS error codes.
1976
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1977
   it also needs to set "magic" environment variables indicating
1978
   the per-drive current directory, which are of the form =<drive>: */
1979
static BOOL __stdcall
1980
win32_wchdir(LPCWSTR path)
1981
{
1982
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1983
    int result;
1984
    wchar_t env[4] = L"=x:";
1985
1986
    if(!SetCurrentDirectoryW(path))
1987
        return FALSE;
1988
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1989
    if (!result)
1990
        return FALSE;
1991
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1992
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1993
        if (!new_path) {
1994
            SetLastError(ERROR_OUTOFMEMORY);
1995
            return FALSE;
1996
        }
1997
        result = GetCurrentDirectoryW(result, new_path);
1998
        if (!result) {
1999
            PyMem_RawFree(new_path);
2000
            return FALSE;
2001
        }
2002
    }
2003
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
2004
                            wcsncmp(new_path, L"//", 2) == 0);
2005
    if (!is_unc_like_path) {
2006
        env[1] = new_path[0];
2007
        result = SetEnvironmentVariableW(env, new_path);
2008
    }
2009
    if (new_path != path_buf)
2010
        PyMem_RawFree(new_path);
2011
    return result ? TRUE : FALSE;
2012
}
2013
#endif
2014
2015
#ifdef MS_WINDOWS
2016
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2017
   - time stamps are restricted to second resolution
2018
   - file modification times suffer from forth-and-back conversions between
2019
     UTC and local time
2020
   Therefore, we implement our own stat, based on the Win32 API directly.
2021
*/
2022
#define HAVE_STAT_NSEC 1
2023
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2024
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2025
2026
static void
2027
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2028
                       BY_HANDLE_FILE_INFORMATION *info,
2029
                       ULONG *reparse_tag)
2030
{
2031
    memset(info, 0, sizeof(*info));
2032
    info->dwFileAttributes = pFileData->dwFileAttributes;
2033
    info->ftCreationTime   = pFileData->ftCreationTime;
2034
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
2035
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
2036
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
2037
    info->nFileSizeLow     = pFileData->nFileSizeLow;
2038
/*  info->nNumberOfLinks   = 1; */
2039
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2040
        *reparse_tag = pFileData->dwReserved0;
2041
    else
2042
        *reparse_tag = 0;
2043
}
2044
2045
static BOOL
2046
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
2047
{
2048
    HANDLE hFindFile;
2049
    WIN32_FIND_DATAW FileData;
2050
    LPCWSTR filename = pszFile;
2051
    size_t n = wcslen(pszFile);
2052
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2053
        // cannot use PyMem_Malloc here because we do not hold the GIL
2054
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2055
        if(!filename) {
2056
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2057
            return FALSE;
2058
        }
2059
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2060
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2061
            ((LPWSTR)filename)[n] = L'\0';
2062
        }
2063
        if (!n || (n == 1 && filename[1] == L':')) {
2064
            // Nothing left to query
2065
            free((void *)filename);
2066
            return FALSE;
2067
        }
2068
    }
2069
    hFindFile = FindFirstFileW(filename, &FileData);
2070
    if (pszFile != filename) {
2071
        free((void *)filename);
2072
    }
2073
    if (hFindFile == INVALID_HANDLE_VALUE) {
2074
        return FALSE;
2075
    }
2076
    FindClose(hFindFile);
2077
    find_data_to_file_info(&FileData, info, reparse_tag);
2078
    return TRUE;
2079
}
2080
2081
2082
static void
2083
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2084
                         struct _Py_stat_struct *result)
2085
{
2086
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2087
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2088
           the filename has an extension that is commonly used by files
2089
           that CreateProcessW can execute. A real implementation calls
2090
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2091
           AccessCheck to check for generic read, write, and execute
2092
           access. */
2093
        const wchar_t *fileExtension = wcsrchr(path, '.');
2094
        if (fileExtension) {
2095
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2096
                _wcsicmp(fileExtension, L".bat") == 0 ||
2097
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2098
                _wcsicmp(fileExtension, L".com") == 0) {
2099
                result->st_mode |= 0111;
2100
            }
2101
        }
2102
    }
2103
}
2104
2105
2106
static int
2107
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2108
                      BOOL traverse)
2109
{
2110
    HANDLE hFile;
2111
    BY_HANDLE_FILE_INFORMATION fileInfo;
2112
    FILE_BASIC_INFO basicInfo;
2113
    FILE_BASIC_INFO *pBasicInfo = NULL;
2114
    FILE_ID_INFO idInfo;
2115
    FILE_ID_INFO *pIdInfo = NULL;
2116
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2117
    DWORD fileType, error;
2118
    BOOL isUnhandledTag = FALSE;
2119
    int retval = 0;
2120
2121
    DWORD access = FILE_READ_ATTRIBUTES;
2122
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2123
    if (!traverse) {
2124
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2125
    }
2126
2127
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2128
    if (hFile == INVALID_HANDLE_VALUE) {
2129
        /* Either the path doesn't exist, or the caller lacks access. */
2130
        error = GetLastError();
2131
        switch (error) {
2132
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2133
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2134
            /* Try reading the parent directory. */
2135
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2136
                /* Cannot read the parent directory. */
2137
                switch (GetLastError()) {
2138
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2139
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2140
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2141
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2142
                    break;
2143
                /* Restore the error from CreateFileW(). */
2144
                default:
2145
                    SetLastError(error);
2146
                }
2147
2148
                return -1;
2149
            }
2150
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2151
                if (traverse ||
2152
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2153
                    /* The stat call has to traverse but cannot, so fail. */
2154
                    SetLastError(error);
2155
                    return -1;
2156
                }
2157
            }
2158
            break;
2159
2160
        case ERROR_INVALID_PARAMETER:
2161
            /* \\.\con requires read or write access. */
2162
            hFile = CreateFileW(path, access | GENERIC_READ,
2163
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2164
                        OPEN_EXISTING, flags, NULL);
2165
            if (hFile == INVALID_HANDLE_VALUE) {
2166
                SetLastError(error);
2167
                return -1;
2168
            }
2169
            break;
2170
2171
        case ERROR_CANT_ACCESS_FILE:
2172
            /* bpo37834: open unhandled reparse points if traverse fails. */
2173
            if (traverse) {
2174
                traverse = FALSE;
2175
                isUnhandledTag = TRUE;
2176
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2177
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2178
            }
2179
            if (hFile == INVALID_HANDLE_VALUE) {
2180
                SetLastError(error);
2181
                return -1;
2182
            }
2183
            break;
2184
2185
        default:
2186
            return -1;
2187
        }
2188
    }
2189
2190
    if (hFile != INVALID_HANDLE_VALUE) {
2191
        /* Handle types other than files on disk. */
2192
        fileType = GetFileType(hFile);
2193
        if (fileType != FILE_TYPE_DISK) {
2194
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2195
                retval = -1;
2196
                goto cleanup;
2197
            }
2198
            DWORD fileAttributes = GetFileAttributesW(path);
2199
            memset(result, 0, sizeof(*result));
2200
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2201
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2202
                /* \\.\pipe\ or \\.\mailslot\ */
2203
                result->st_mode = _S_IFDIR;
2204
            } else if (fileType == FILE_TYPE_CHAR) {
2205
                /* \\.\nul */
2206
                result->st_mode = _S_IFCHR;
2207
            } else if (fileType == FILE_TYPE_PIPE) {
2208
                /* \\.\pipe\spam */
2209
                result->st_mode = _S_IFIFO;
2210
            }
2211
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2212
            goto cleanup;
2213
        }
2214
2215
        /* Query the reparse tag, and traverse a non-link. */
2216
        if (!traverse) {
2217
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2218
                    &tagInfo, sizeof(tagInfo))) {
2219
                /* Allow devices that do not support FileAttributeTagInfo. */
2220
                switch (GetLastError()) {
2221
                case ERROR_INVALID_PARAMETER:
2222
                case ERROR_INVALID_FUNCTION:
2223
                case ERROR_NOT_SUPPORTED:
2224
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2225
                    tagInfo.ReparseTag = 0;
2226
                    break;
2227
                default:
2228
                    retval = -1;
2229
                    goto cleanup;
2230
                }
2231
            } else if (tagInfo.FileAttributes &
2232
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2233
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2234
                    if (isUnhandledTag) {
2235
                        /* Traversing previously failed for either this link
2236
                           or its target. */
2237
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2238
                        retval = -1;
2239
                        goto cleanup;
2240
                    }
2241
                /* Traverse a non-link, but not if traversing already failed
2242
                   for an unhandled tag. */
2243
                } else if (!isUnhandledTag) {
2244
                    CloseHandle(hFile);
2245
                    return win32_xstat_slow_impl(path, result, TRUE);
2246
                }
2247
            }
2248
        }
2249
2250
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2251
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2252
                                          &basicInfo, sizeof(basicInfo))) {
2253
            switch (GetLastError()) {
2254
            case ERROR_INVALID_PARAMETER:
2255
            case ERROR_INVALID_FUNCTION:
2256
            case ERROR_NOT_SUPPORTED:
2257
                /* Volumes and physical disks are block devices, e.g.
2258
                   \\.\C: and \\.\PhysicalDrive0. */
2259
                memset(result, 0, sizeof(*result));
2260
                result->st_mode = 0x6000; /* S_IFBLK */
2261
                goto cleanup;
2262
            }
2263
            retval = -1;
2264
            goto cleanup;
2265
        }
2266
2267
        /* Successfully got FileBasicInfo, so we'll pass it along */
2268
        pBasicInfo = &basicInfo;
2269
2270
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2271
            /* Successfully got FileIdInfo, so pass it along */
2272
            pIdInfo = &idInfo;
2273
        }
2274
    }
2275
2276
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2277
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2278
2279
cleanup:
2280
    if (hFile != INVALID_HANDLE_VALUE) {
2281
        /* Preserve last error if we are failing */
2282
        error = retval ? GetLastError() : 0;
2283
        if (!CloseHandle(hFile)) {
2284
            retval = -1;
2285
        } else if (retval) {
2286
            /* Restore last error */
2287
            SetLastError(error);
2288
        }
2289
    }
2290
2291
    return retval;
2292
}
2293
2294
static int
2295
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2296
                 BOOL traverse)
2297
{
2298
    FILE_STAT_BASIC_INFORMATION statInfo;
2299
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2300
                                     &statInfo, sizeof(statInfo))) {
2301
        if (// Cannot use fast path for reparse points ...
2302
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2303
            // ... unless it's a name surrogate (symlink) and we're not following
2304
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2305
        ) {
2306
            _Py_stat_basic_info_to_stat(&statInfo, result);
2307
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2308
            return 0;
2309
        }
2310
    } else {
2311
        switch(GetLastError()) {
2312
        case ERROR_FILE_NOT_FOUND:
2313
        case ERROR_PATH_NOT_FOUND:
2314
        case ERROR_NOT_READY:
2315
        case ERROR_BAD_NET_NAME:
2316
            /* These errors aren't worth retrying with the slow path */
2317
            return -1;
2318
        case ERROR_NOT_SUPPORTED:
2319
            /* indicates the API couldn't be loaded */
2320
            break;
2321
        }
2322
    }
2323
2324
    return win32_xstat_slow_impl(path, result, traverse);
2325
}
2326
2327
static int
2328
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2329
{
2330
    /* Protocol violation: we explicitly clear errno, instead of
2331
       setting it to a POSIX error. Callers should use GetLastError. */
2332
    int code = win32_xstat_impl(path, result, traverse);
2333
    errno = 0;
2334
2335
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2336
    result->st_ctime = result->st_birthtime;
2337
    result->st_ctime_nsec = result->st_birthtime_nsec;
2338
    return code;
2339
}
2340
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2341
2342
   In Posix, stat automatically traverses symlinks and returns the stat
2343
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2344
   default does not traverse symlinks and instead returns attributes for
2345
   the symlink.
2346
2347
   Instead, we will open the file (which *does* traverse symlinks by default)
2348
   and GetFileInformationByHandle(). */
2349
2350
static int
2351
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2352
{
2353
    return win32_xstat(path, result, FALSE);
2354
}
2355
2356
static int
2357
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2358
{
2359
    return win32_xstat(path, result, TRUE);
2360
}
2361
2362
#endif /* MS_WINDOWS */
2363
2364
PyDoc_STRVAR(stat_result__doc__,
2365
"stat_result: Result from stat, fstat, or lstat.\n\n\
2366
This object may be accessed either as a tuple of\n\
2367
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2368
or via the attributes st_mode, st_ino, st_dev, st_nlink, and so on.\n\
2369
\n\
2370
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2371
or st_flags, they are available as attributes only.\n\
2372
\n\
2373
See os.stat for more information.");
2374
2375
static PyStructSequence_Field stat_result_fields[] = {
2376
    {"st_mode",    "protection bits"},
2377
    {"st_ino",     "inode"},
2378
    {"st_dev",     "device"},
2379
    {"st_nlink",   "number of hard links"},
2380
    {"st_uid",     "user ID of owner"},
2381
    {"st_gid",     "group ID of owner"},
2382
    {"st_size",    "total size, in bytes"},
2383
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2384
    {NULL,   "integer time of last access"},
2385
    {NULL,   "integer time of last modification"},
2386
    {NULL,   "integer time of last change"},
2387
    {"st_atime",   "time of last access"},
2388
    {"st_mtime",   "time of last modification"},
2389
    {"st_ctime",   "time of last change"},
2390
    {"st_atime_ns",   "time of last access in nanoseconds"},
2391
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2392
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2393
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2394
    {"st_blksize", "blocksize for filesystem I/O"},
2395
#endif
2396
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2397
    {"st_blocks",  "number of blocks allocated"},
2398
#endif
2399
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2400
    {"st_rdev",    "device type (if inode device)"},
2401
#endif
2402
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2403
    {"st_flags",   "user defined flags for file"},
2404
#endif
2405
#ifdef HAVE_STRUCT_STAT_ST_GEN
2406
    {"st_gen",    "generation number"},
2407
#endif
2408
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2409
    {"st_birthtime",   "time of creation"},
2410
#endif
2411
#ifdef MS_WINDOWS
2412
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2413
#endif
2414
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2415
    {"st_file_attributes", "Windows file attribute bits"},
2416
#endif
2417
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2418
    {"st_fstype",  "Type of filesystem"},
2419
#endif
2420
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2421
    {"st_reparse_tag", "Windows reparse tag"},
2422
#endif
2423
    {0}
2424
};
2425
2426
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2427
#define ST_BLKSIZE_IDX 16
2428
#else
2429
#define ST_BLKSIZE_IDX 15
2430
#endif
2431
2432
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2433
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2434
#else
2435
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2436
#endif
2437
2438
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2439
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2440
#else
2441
#define ST_RDEV_IDX ST_BLOCKS_IDX
2442
#endif
2443
2444
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2445
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2446
#else
2447
#define ST_FLAGS_IDX ST_RDEV_IDX
2448
#endif
2449
2450
#ifdef HAVE_STRUCT_STAT_ST_GEN
2451
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2452
#else
2453
#define ST_GEN_IDX ST_FLAGS_IDX
2454
#endif
2455
2456
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2457
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2458
#else
2459
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2460
#endif
2461
2462
#ifdef MS_WINDOWS
2463
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2464
#else
2465
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2466
#endif
2467
2468
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2469
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2470
#else
2471
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2472
#endif
2473
2474
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2475
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2476
#else
2477
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2478
#endif
2479
2480
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2481
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2482
#else
2483
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2484
#endif
2485
2486
static PyStructSequence_Desc stat_result_desc = {
2487
    "os.stat_result", /* name; see issue gh-63408 */
2488
    stat_result__doc__, /* doc */
2489
    stat_result_fields,
2490
    10
2491
};
2492
2493
PyDoc_STRVAR(statvfs_result__doc__,
2494
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2495
This object may be accessed either as a tuple of\n\
2496
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2497
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2498
\n\
2499
See os.statvfs for more information.");
2500
2501
static PyStructSequence_Field statvfs_result_fields[] = {
2502
    {"f_bsize",  },
2503
    {"f_frsize", },
2504
    {"f_blocks", },
2505
    {"f_bfree",  },
2506
    {"f_bavail", },
2507
    {"f_files",  },
2508
    {"f_ffree",  },
2509
    {"f_favail", },
2510
    {"f_flag",   },
2511
    {"f_namemax",},
2512
    {"f_fsid",   },
2513
    {0}
2514
};
2515
2516
static PyStructSequence_Desc statvfs_result_desc = {
2517
    "os.statvfs_result", /* name; see issue gh-63408 */
2518
    statvfs_result__doc__, /* doc */
2519
    statvfs_result_fields,
2520
    10
2521
};
2522
2523
#if defined(HAVE_WAITID)
2524
PyDoc_STRVAR(waitid_result__doc__,
2525
"waitid_result: Result from waitid.\n\n\
2526
This object may be accessed either as a tuple of\n\
2527
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2528
or via the attributes si_pid, si_uid, and so on.\n\
2529
\n\
2530
See os.waitid for more information.");
2531
2532
static PyStructSequence_Field waitid_result_fields[] = {
2533
    {"si_pid",  },
2534
    {"si_uid", },
2535
    {"si_signo", },
2536
    {"si_status",  },
2537
    {"si_code", },
2538
    {0}
2539
};
2540
2541
static PyStructSequence_Desc waitid_result_desc = {
2542
    MODNAME ".waitid_result", /* name */
2543
    waitid_result__doc__, /* doc */
2544
    waitid_result_fields,
2545
    5
2546
};
2547
#endif
2548
2549
static PyObject *
2550
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2551
0
{
2552
0
    PyStructSequence *result;
2553
0
    int i;
2554
2555
    // ht_module doesn't get set in PyStructSequence_NewType(),
2556
    // so we can't use PyType_GetModule().
2557
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2558
0
    if (mod == NULL) {
2559
0
        return NULL;
2560
0
    }
2561
0
    _posixstate *state = get_posix_state(mod);
2562
0
    Py_DECREF(mod);
2563
0
    if (state == NULL) {
2564
0
        return NULL;
2565
0
    }
2566
0
#define structseq_new state->statresult_new_orig
2567
2568
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2569
0
    if (!result)
2570
0
        return NULL;
2571
    /* If we have been initialized from a tuple,
2572
       st_?time might be set to None. Initialize it
2573
       from the int slots.  */
2574
0
    for (i = 7; i <= 9; i++) {
2575
0
        if (result->ob_item[i+3] == Py_None) {
2576
0
            Py_DECREF(Py_None);
2577
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2578
0
        }
2579
0
    }
2580
0
    return (PyObject*)result;
2581
0
}
2582
2583
static int
2584
_posix_clear(PyObject *module)
2585
0
{
2586
0
    _posixstate *state = get_posix_state(module);
2587
0
    Py_CLEAR(state->billion);
2588
0
    Py_CLEAR(state->DirEntryType);
2589
0
    Py_CLEAR(state->ScandirIteratorType);
2590
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2591
0
    Py_CLEAR(state->SchedParamType);
2592
0
#endif
2593
0
    Py_CLEAR(state->StatResultType);
2594
0
#ifdef HAVE_STATX
2595
0
    Py_CLEAR(state->StatxResultType);
2596
0
#endif
2597
0
    Py_CLEAR(state->StatVFSResultType);
2598
0
    Py_CLEAR(state->TerminalSizeType);
2599
0
    Py_CLEAR(state->TimesResultType);
2600
0
    Py_CLEAR(state->UnameResultType);
2601
0
#if defined(HAVE_WAITID)
2602
0
    Py_CLEAR(state->WaitidResultType);
2603
0
#endif
2604
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2605
0
    Py_CLEAR(state->struct_rusage);
2606
0
#endif
2607
0
    Py_CLEAR(state->st_mode);
2608
0
    return 0;
2609
0
}
2610
2611
static int
2612
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2613
1.39k
{
2614
1.39k
    _posixstate *state = get_posix_state(module);
2615
1.39k
    Py_VISIT(state->billion);
2616
1.39k
    Py_VISIT(state->DirEntryType);
2617
1.39k
    Py_VISIT(state->ScandirIteratorType);
2618
1.39k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2619
1.39k
    Py_VISIT(state->SchedParamType);
2620
1.39k
#endif
2621
1.39k
    Py_VISIT(state->StatResultType);
2622
1.39k
#ifdef HAVE_STATX
2623
1.39k
    Py_VISIT(state->StatxResultType);
2624
1.39k
#endif
2625
1.39k
    Py_VISIT(state->StatVFSResultType);
2626
1.39k
    Py_VISIT(state->TerminalSizeType);
2627
1.39k
    Py_VISIT(state->TimesResultType);
2628
1.39k
    Py_VISIT(state->UnameResultType);
2629
1.39k
#if defined(HAVE_WAITID)
2630
1.39k
    Py_VISIT(state->WaitidResultType);
2631
1.39k
#endif
2632
1.39k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2633
1.39k
    Py_VISIT(state->struct_rusage);
2634
1.39k
#endif
2635
1.39k
    Py_VISIT(state->st_mode);
2636
1.39k
    return 0;
2637
1.39k
}
2638
2639
static void
2640
_posix_free(void *module)
2641
0
{
2642
0
   _posix_clear((PyObject *)module);
2643
0
}
2644
2645
2646
2.21M
#define SEC_TO_NS (1000000000LL)
2647
static PyObject *
2648
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2649
737k
{
2650
#if SIZEOF_TIME_T == 4
2651
    return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2652
#else
2653
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2654
737k
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2655
737k
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2656
737k
    }
2657
0
    else
2658
0
    {
2659
0
        PyObject *ns_total = NULL;
2660
0
        PyObject *s_in_ns = NULL;
2661
0
        PyObject *s = _PyLong_FromTime_t(sec);
2662
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2663
0
        if (s == NULL || ns_fractional == NULL) {
2664
0
            goto exit;
2665
0
        }
2666
2667
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2668
0
        if (s_in_ns == NULL) {
2669
0
            goto exit;
2670
0
        }
2671
2672
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2673
2674
0
    exit:
2675
0
        Py_XDECREF(s);
2676
0
        Py_XDECREF(ns_fractional);
2677
0
        Py_XDECREF(s_in_ns);
2678
0
        return ns_total;
2679
0
    }
2680
737k
#endif
2681
737k
}
2682
2683
static int
2684
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2685
          int ns_index, time_t sec, unsigned long nsec)
2686
737k
{
2687
737k
    assert(!PyErr_Occurred());
2688
737k
    assert(nsec < SEC_TO_NS);
2689
2690
737k
    if (s_index >= 0) {
2691
737k
        PyObject *s = _PyLong_FromTime_t(sec);
2692
737k
        if (s == NULL) {
2693
0
            return -1;
2694
0
        }
2695
737k
        PyStructSequence_SET_ITEM(v, s_index, s);
2696
737k
    }
2697
2698
737k
    if (f_index >= 0) {
2699
737k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2700
737k
        if (float_s == NULL) {
2701
0
            return -1;
2702
0
        }
2703
737k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2704
737k
    }
2705
2706
737k
    if (ns_index >= 0) {
2707
737k
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2708
737k
        if (ns_total == NULL) {
2709
0
            return -1;
2710
0
        }
2711
737k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2712
737k
    }
2713
2714
737k
    assert(!PyErr_Occurred());
2715
737k
    return 0;
2716
737k
}
2717
#undef SEC_TO_NS
2718
2719
#ifdef MS_WINDOWS
2720
static PyObject*
2721
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2722
{
2723
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2724
    if (!o_low || !high) {
2725
        return o_low;
2726
    }
2727
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2728
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2729
    if (!l64) {
2730
        Py_XDECREF(o_high);
2731
        Py_DECREF(o_low);
2732
        return NULL;
2733
    }
2734
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2735
    Py_DECREF(l64);
2736
    if (!o_high) {
2737
        Py_DECREF(o_low);
2738
        return NULL;
2739
    }
2740
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2741
    Py_DECREF(o_high);
2742
    return o_low;
2743
}
2744
#endif
2745
2746
/* pack a system stat C structure into the Python stat tuple
2747
   (used by posix_stat() and posix_fstat()) */
2748
static PyObject*
2749
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2750
245k
{
2751
245k
    assert(!PyErr_Occurred());
2752
2753
245k
    _posixstate *state = get_posix_state(module);
2754
245k
    PyObject *StatResultType = state->StatResultType;
2755
245k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2756
245k
    if (v == NULL) {
2757
0
        return NULL;
2758
0
    }
2759
2760
245k
#define SET_ITEM(pos, expr) \
2761
2.45M
    do { \
2762
2.45M
        PyObject *obj = (expr); \
2763
2.45M
        if (obj == NULL) { \
2764
0
            goto error; \
2765
0
        } \
2766
2.45M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2767
2.45M
    } while (0)
2768
2769
245k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2770
#ifdef MS_WINDOWS
2771
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2772
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2773
#else
2774
245k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2775
245k
                  "stat.st_ino is larger than unsigned long long");
2776
245k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2777
245k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2778
245k
#endif
2779
245k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2780
#if defined(MS_WINDOWS)
2781
    SET_ITEM(4, PyLong_FromLong(0));
2782
    SET_ITEM(5, PyLong_FromLong(0));
2783
#else
2784
245k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2785
245k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2786
245k
#endif
2787
245k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2788
245k
                  "stat.st_size is larger than long long");
2789
245k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2790
2791
    // Set st_atime, st_mtime and st_ctime
2792
245k
    unsigned long ansec, mnsec, cnsec;
2793
245k
#if defined(HAVE_STAT_TV_NSEC)
2794
245k
    ansec = st->st_atim.tv_nsec;
2795
245k
    mnsec = st->st_mtim.tv_nsec;
2796
245k
    cnsec = st->st_ctim.tv_nsec;
2797
#elif defined(HAVE_STAT_TV_NSEC2)
2798
    ansec = st->st_atimespec.tv_nsec;
2799
    mnsec = st->st_mtimespec.tv_nsec;
2800
    cnsec = st->st_ctimespec.tv_nsec;
2801
#elif defined(HAVE_STAT_NSEC)
2802
    ansec = st->st_atime_nsec;
2803
    mnsec = st->st_mtime_nsec;
2804
    cnsec = st->st_ctime_nsec;
2805
#else
2806
    ansec = mnsec = cnsec = 0;
2807
#endif
2808
245k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2809
0
        goto error;
2810
0
    }
2811
245k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2812
0
        goto error;
2813
0
    }
2814
245k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2815
0
        goto error;
2816
0
    }
2817
2818
245k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2819
245k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2820
245k
#endif
2821
245k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2822
245k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2823
245k
#endif
2824
245k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2825
245k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2826
245k
#endif
2827
#ifdef HAVE_STRUCT_STAT_ST_GEN
2828
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2829
#endif
2830
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2831
    {
2832
      unsigned long bsec, bnsec;
2833
      bsec = (long)st->st_birthtime;
2834
#ifdef HAVE_STAT_TV_NSEC2
2835
      bnsec = st->st_birthtimespec.tv_nsec;
2836
#else
2837
      bnsec = 0;
2838
#endif
2839
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2840
    }
2841
#elif defined(MS_WINDOWS)
2842
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2843
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2844
        goto error;
2845
    }
2846
#endif
2847
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2848
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2849
#endif
2850
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2851
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2852
             PyLong_FromUnsignedLong(st->st_file_attributes));
2853
#endif
2854
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2855
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2856
#endif
2857
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2858
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2859
#endif
2860
2861
245k
    assert(!PyErr_Occurred());
2862
245k
    return v;
2863
2864
0
error:
2865
0
    Py_DECREF(v);
2866
0
    return NULL;
2867
2868
245k
#undef SET_ITEM
2869
245k
}
2870
2871
/* POSIX methods */
2872
2873
2874
static PyObject *
2875
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2876
              int dir_fd, int follow_symlinks)
2877
252k
{
2878
252k
    STRUCT_STAT st;
2879
252k
    int result;
2880
2881
252k
#ifdef HAVE_FSTATAT
2882
252k
    int fstatat_unavailable = 0;
2883
252k
#endif
2884
2885
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2886
    if (follow_symlinks_specified(function_name, follow_symlinks))
2887
        return NULL;
2888
#endif
2889
2890
252k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2891
252k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2892
252k
        fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
2893
0
        return NULL;
2894
2895
252k
    Py_BEGIN_ALLOW_THREADS
2896
252k
    if (path->is_fd) {
2897
0
        result = FSTAT(path->fd, &st);
2898
0
    }
2899
#ifdef MS_WINDOWS
2900
    else if (follow_symlinks)
2901
        result = win32_stat(path->wide, &st);
2902
    else
2903
        result = win32_lstat(path->wide, &st);
2904
#else
2905
252k
    else
2906
252k
#if defined(HAVE_LSTAT)
2907
252k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2908
11.5k
        result = LSTAT(path->narrow, &st);
2909
240k
    else
2910
240k
#endif /* HAVE_LSTAT */
2911
240k
#ifdef HAVE_FSTATAT
2912
240k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2913
0
        if (HAVE_FSTATAT_RUNTIME) {
2914
0
            result = fstatat(dir_fd, path->narrow, &st,
2915
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2916
2917
0
        } else {
2918
0
            fstatat_unavailable = 1;
2919
0
        }
2920
0
    } else
2921
240k
#endif /* HAVE_FSTATAT */
2922
240k
        result = STAT(path->narrow, &st);
2923
252k
#endif /* MS_WINDOWS */
2924
252k
    Py_END_ALLOW_THREADS
2925
2926
252k
#ifdef HAVE_FSTATAT
2927
252k
    if (fstatat_unavailable) {
2928
0
        argument_unavailable_error("stat", "dir_fd");
2929
0
        return NULL;
2930
0
    }
2931
252k
#endif
2932
2933
252k
    if (result != 0) {
2934
184k
        return path_error(path);
2935
184k
    }
2936
2937
67.7k
    return _pystat_fromstructstat(module, &st);
2938
252k
}
2939
2940
/*[python input]
2941
2942
for s in """
2943
2944
FACCESSAT
2945
FCHMODAT
2946
FCHOWNAT
2947
FSTATAT
2948
LINKAT
2949
MKDIRAT
2950
MKFIFOAT
2951
MKNODAT
2952
OPENAT
2953
READLINKAT
2954
SYMLINKAT
2955
UNLINKAT
2956
2957
""".strip().split():
2958
    s = s.strip()
2959
    print("""
2960
#ifdef HAVE_{s}
2961
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2962
#else
2963
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2964
#endif
2965
""".rstrip().format(s=s))
2966
2967
for s in """
2968
2969
FCHDIR
2970
FCHMOD
2971
FCHOWN
2972
FDOPENDIR
2973
FEXECVE
2974
FPATHCONF
2975
FSTATVFS
2976
FTRUNCATE
2977
2978
""".strip().split():
2979
    s = s.strip()
2980
    print("""
2981
#ifdef HAVE_{s}
2982
    #define PATH_HAVE_{s} 1
2983
#else
2984
    #define PATH_HAVE_{s} 0
2985
#endif
2986
2987
""".rstrip().format(s=s))
2988
[python start generated code]*/
2989
2990
#ifdef HAVE_FACCESSAT
2991
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2992
#else
2993
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2994
#endif
2995
2996
#ifdef HAVE_FCHMODAT
2997
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2998
#else
2999
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
3000
#endif
3001
3002
#ifdef HAVE_FCHOWNAT
3003
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
3004
#else
3005
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
3006
#endif
3007
3008
#ifdef HAVE_FSTATAT
3009
8.59k
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
3010
#else
3011
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
3012
#endif
3013
3014
#ifdef HAVE_LINKAT
3015
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
3016
#else
3017
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3018
#endif
3019
3020
#ifdef HAVE_MKDIRAT
3021
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3022
#else
3023
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3024
#endif
3025
3026
#ifdef HAVE_MKFIFOAT
3027
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3028
#else
3029
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3030
#endif
3031
3032
#ifdef HAVE_MKNODAT
3033
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3034
#else
3035
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3036
#endif
3037
3038
#ifdef HAVE_OPENAT
3039
91.1k
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3040
#else
3041
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3042
#endif
3043
3044
#ifdef HAVE_READLINKAT
3045
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3046
#else
3047
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3048
#endif
3049
3050
#ifdef HAVE_SYMLINKAT
3051
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3052
#else
3053
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3054
#endif
3055
3056
#ifdef HAVE_UNLINKAT
3057
109k
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3058
#else
3059
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3060
#endif
3061
3062
#ifdef HAVE_FCHDIR
3063
    #define PATH_HAVE_FCHDIR 1
3064
#else
3065
    #define PATH_HAVE_FCHDIR 0
3066
#endif
3067
3068
#ifdef HAVE_FCHMOD
3069
    #define PATH_HAVE_FCHMOD 1
3070
#else
3071
    #define PATH_HAVE_FCHMOD 0
3072
#endif
3073
3074
#ifdef HAVE_FCHOWN
3075
    #define PATH_HAVE_FCHOWN 1
3076
#else
3077
    #define PATH_HAVE_FCHOWN 0
3078
#endif
3079
3080
#ifdef HAVE_FDOPENDIR
3081
    #define PATH_HAVE_FDOPENDIR 1
3082
#else
3083
    #define PATH_HAVE_FDOPENDIR 0
3084
#endif
3085
3086
#ifdef HAVE_FEXECVE
3087
    #define PATH_HAVE_FEXECVE 1
3088
#else
3089
    #define PATH_HAVE_FEXECVE 0
3090
#endif
3091
3092
#ifdef HAVE_FPATHCONF
3093
    #define PATH_HAVE_FPATHCONF 1
3094
#else
3095
    #define PATH_HAVE_FPATHCONF 0
3096
#endif
3097
3098
#ifdef HAVE_FSTATVFS
3099
    #define PATH_HAVE_FSTATVFS 1
3100
#else
3101
    #define PATH_HAVE_FSTATVFS 0
3102
#endif
3103
3104
#ifdef HAVE_FTRUNCATE
3105
    #define PATH_HAVE_FTRUNCATE 1
3106
#else
3107
    #define PATH_HAVE_FTRUNCATE 0
3108
#endif
3109
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3110
3111
#ifdef MS_WINDOWS
3112
    #undef PATH_HAVE_FTRUNCATE
3113
    #define PATH_HAVE_FTRUNCATE 1
3114
    #undef PATH_HAVE_FCHMOD
3115
    #define PATH_HAVE_FCHMOD 1
3116
#endif
3117
3118
/*[python input]
3119
3120
class path_t_converter(CConverter):
3121
3122
    type = "path_t"
3123
    impl_by_reference = True
3124
    parse_by_reference = True
3125
    default_type = ()
3126
    c_init_default = "<placeholder>"  # overridden in pre_render()
3127
3128
    converter = 'path_converter'
3129
3130
    def converter_init(self, *, allow_fd=False, make_wide=None,
3131
                       nonstrict=False, nullable=False,
3132
                       suppress_value_error=False):
3133
3134
        self.nullable = nullable
3135
        self.nonstrict = nonstrict
3136
        self.make_wide = make_wide
3137
        self.suppress_value_error = suppress_value_error
3138
        self.allow_fd = allow_fd
3139
        if nullable:
3140
            self.default_type = NoneType
3141
3142
    def pre_render(self):
3143
        def strify(value):
3144
            if isinstance(value, str):
3145
                return value
3146
            return str(int(bool(value)))
3147
3148
        # add self.py_name here when merging with posixmodule conversion
3149
        if self.make_wide is None:
3150
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3151
                self.function.name,
3152
                self.name,
3153
                strify(self.nullable),
3154
                strify(self.nonstrict),
3155
                strify(self.suppress_value_error),
3156
                strify(self.allow_fd),
3157
            )
3158
        else:
3159
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3160
                self.function.name,
3161
                self.name,
3162
                strify(self.nullable),
3163
                strify(self.nonstrict),
3164
                strify(self.make_wide),
3165
                strify(self.suppress_value_error),
3166
                strify(self.allow_fd),
3167
            )
3168
3169
    def cleanup(self):
3170
        return "path_cleanup(&" + self.name + ");\n"
3171
3172
3173
class dir_fd_converter(CConverter):
3174
    type = 'int'
3175
    default_type = NoneType
3176
    c_init_default = 'DEFAULT_DIR_FD'
3177
3178
    def converter_init(self, requires=None):
3179
        if self.default in (unspecified, None):
3180
            self.c_default = 'DEFAULT_DIR_FD'
3181
        if isinstance(requires, str):
3182
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3183
        else:
3184
            self.converter = 'dir_fd_converter'
3185
3186
    def c_default_init(self):
3187
        self.c_default = 'DEFAULT_DIR_FD'
3188
3189
class uid_t_converter(CConverter):
3190
    type = "uid_t"
3191
    converter = '_Py_Uid_Converter'
3192
3193
class gid_t_converter(CConverter):
3194
    type = "gid_t"
3195
    converter = '_Py_Gid_Converter'
3196
3197
class dev_t_converter(CConverter):
3198
    type = 'dev_t'
3199
    converter = '_Py_Dev_Converter'
3200
3201
class dev_t_return_converter(unsigned_long_return_converter):
3202
    type = 'dev_t'
3203
    conversion_fn = '_PyLong_FromDev'
3204
    unsigned_cast = '(dev_t)'
3205
3206
class pid_t_converter(CConverter):
3207
    type = 'pid_t'
3208
    format_unit = '" _Py_PARSE_PID "'
3209
3210
    def parse_arg(self, argname, displayname, *, limited_capi):
3211
        return self.format_code("""
3212
            {paramname} = PyLong_AsPid({argname});
3213
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3214
                goto exit;
3215
            }}}}
3216
            """, argname=argname)
3217
3218
class idtype_t_converter(CConverter):
3219
    type = 'idtype_t'
3220
    converter = 'idtype_t_converter'
3221
3222
class id_t_converter(CConverter):
3223
    type = 'id_t'
3224
    format_unit = '" _Py_PARSE_PID "'
3225
3226
    def parse_arg(self, argname, displayname, *, limited_capi):
3227
        return self.format_code("""
3228
            {paramname} = (id_t)PyLong_AsPid({argname});
3229
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3230
                goto exit;
3231
            }}}}
3232
            """, argname=argname)
3233
3234
class intptr_t_converter(CConverter):
3235
    type = 'intptr_t'
3236
    format_unit = '" _Py_PARSE_INTPTR "'
3237
3238
    def parse_arg(self, argname, displayname, *, limited_capi):
3239
        return self.format_code("""
3240
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3241
            if (!{paramname} && PyErr_Occurred()) {{{{
3242
                goto exit;
3243
            }}}}
3244
            """, argname=argname)
3245
3246
class Py_off_t_converter(CConverter):
3247
    type = 'Py_off_t'
3248
    converter = 'Py_off_t_converter'
3249
3250
class Py_off_t_return_converter(long_return_converter):
3251
    type = 'Py_off_t'
3252
    conversion_fn = 'PyLong_FromPy_off_t'
3253
3254
class confname_converter(CConverter):
3255
    type="int"
3256
    converter="conv_confname"
3257
3258
    def converter_init(self, *, table):
3259
        self.table = table
3260
3261
    def parse_arg(self, argname, displayname, *, limited_capi):
3262
        return self.format_code("""
3263
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3264
                goto exit;
3265
            }}}}
3266
        """, argname=argname, converter=self.converter, table=self.table)
3267
3268
[python start generated code]*/
3269
/*[python end generated code: output=da39a3ee5e6b4b0d input=ddbf3ac90a981122]*/
3270
3271
/*[clinic input]
3272
3273
os.stat
3274
3275
    path : path_t(allow_fd=True)
3276
        Path to be examined; can be string, bytes, a path-like object or
3277
        open-file-descriptor int.
3278
3279
    *
3280
3281
    dir_fd : dir_fd(requires='fstatat') = None
3282
        If not None, it should be a file descriptor open to a directory,
3283
        and path should be a relative string; path will then be relative to
3284
        that directory.
3285
3286
    follow_symlinks: bool = True
3287
        If False, and the last element of the path is a symbolic link,
3288
        stat will examine the symbolic link itself instead of the file
3289
        the link points to.
3290
3291
Perform a stat system call on the given path.
3292
3293
dir_fd and follow_symlinks may not be implemented
3294
  on your platform.  If they are unavailable, using them will raise a
3295
  NotImplementedError.
3296
3297
It's an error to use dir_fd or follow_symlinks when specifying path as
3298
  an open file descriptor.
3299
3300
[clinic start generated code]*/
3301
3302
static PyObject *
3303
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3304
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3305
240k
{
3306
240k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3307
240k
}
3308
3309
3310
/*[clinic input]
3311
@permit_long_summary
3312
os.lstat
3313
3314
    path : path_t
3315
3316
    *
3317
3318
    dir_fd : dir_fd(requires='fstatat') = None
3319
3320
Perform a stat system call on the given path, without following symbolic links.
3321
3322
Like stat(), but do not follow symbolic links.
3323
Equivalent to stat(path, follow_symlinks=False).
3324
[clinic start generated code]*/
3325
3326
static PyObject *
3327
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3328
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3329
11.5k
{
3330
11.5k
    int follow_symlinks = 0;
3331
11.5k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3332
11.5k
}
3333
3334
3335
#ifdef HAVE_STATX
3336
typedef struct {
3337
    PyObject_HEAD
3338
    dev_t rdev, dev;
3339
    struct statx stx;
3340
} Py_statx_result;
3341
3342
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3343
3344
#define M(attr, type, offset, doc) \
3345
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3346
#define MM(attr, type, member, doc) \
3347
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3348
#define MX(attr, type, member, doc) \
3349
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3350
3351
static PyMemberDef pystatx_result_members[] = {
3352
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3353
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3354
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3355
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3356
        "Mask of supported bits in stx_attributes"),
3357
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3358
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3359
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3360
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3361
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3362
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3363
    {NULL},
3364
};
3365
3366
#undef MX
3367
#undef MM
3368
#undef M
3369
3370
3371
#define STATX_GET_UINT(ATTR, MASK) \
3372
    static PyObject* \
3373
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3374
0
    { \
3375
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3376
0
        if (!(self->stx.stx_mask & MASK)) { \
3377
0
            Py_RETURN_NONE; \
3378
0
        } \
3379
0
        unsigned long value = self->stx.ATTR; \
3380
0
        return PyLong_FromUnsignedLong(value); \
3381
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
3382
3383
STATX_GET_UINT(stx_uid, STATX_UID)
3384
STATX_GET_UINT(stx_gid, STATX_GID)
3385
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3386
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3387
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3388
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3389
#endif
3390
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3391
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3392
#endif
3393
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3394
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3395
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3396
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3397
#endif
3398
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3399
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3400
#endif
3401
3402
3403
static PyObject*
3404
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3405
0
{
3406
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3407
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3408
0
        Py_RETURN_NONE;
3409
0
    }
3410
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3411
0
}
3412
3413
3414
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3415
    static PyObject* \
3416
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3417
0
    { \
3418
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3419
0
        if (!(self->stx.stx_mask & MASK)) { \
3420
0
            Py_RETURN_NONE; \
3421
0
        } \
3422
0
        unsigned long long value = self->stx.ATTR; \
3423
0
        return PyLong_FromUnsignedLongLong(value); \
3424
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
3425
3426
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3427
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3428
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3429
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3430
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3431
#endif
3432
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3433
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3434
#endif
3435
3436
3437
#define STATX_GET_DOUBLE(ATTR, MASK) \
3438
    static PyObject* \
3439
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3440
0
    { \
3441
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3442
0
        if (!(self->stx.stx_mask & MASK)) { \
3443
0
            Py_RETURN_NONE; \
3444
0
        } \
3445
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3446
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3447
0
        return PyFloat_FromDouble(sec); \
3448
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
3449
3450
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3451
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3452
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3453
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3454
3455
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3456
    static PyObject* \
3457
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3458
0
    { \
3459
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3460
0
        if (!(self->stx.stx_mask & MASK)) { \
3461
0
            Py_RETURN_NONE; \
3462
0
        } \
3463
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3464
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3465
0
        assert(state != NULL); \
3466
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3467
0
    }
3468
3469
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3470
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3471
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3472
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3473
3474
#define G(attr, doc) \
3475
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3476
3477
static PyGetSetDef pystatx_result_getset[] = {
3478
    G(stx_mode, "protection bits"),
3479
    G(stx_nlink, "number of hard links"),
3480
    G(stx_uid, "user ID of owner"),
3481
    G(stx_gid, "group ID of owner"),
3482
    G(stx_ino, "inode"),
3483
    G(stx_size, "total size, in bytes"),
3484
    G(stx_blocks, "number of blocks allocated"),
3485
    G(stx_atime, "time of last access"),
3486
    G(stx_atime_ns, "time of last access in nanoseconds"),
3487
    G(stx_btime, "time of creation"),
3488
    G(stx_btime_ns, "time of creation in nanoseconds"),
3489
    G(stx_ctime, "time of last change"),
3490
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3491
    G(stx_mtime, "time of last modification"),
3492
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3493
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3494
    G(stx_mnt_id, "mount ID"),
3495
#endif
3496
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3497
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3498
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3499
#endif
3500
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3501
    G(stx_subvol, "subvolume ID"),
3502
#endif
3503
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3504
    G(stx_atomic_write_unit_min,
3505
      "minimum size for direct I/O with torn-write protection"),
3506
    G(stx_atomic_write_unit_max,
3507
        "maximum size for direct I/O with torn-write protection"),
3508
    G(stx_atomic_write_segments_max,
3509
        "maximum iovecs for direct I/O with torn-write protection"),
3510
#endif
3511
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3512
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3513
#endif
3514
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3515
    G(stx_atomic_write_unit_max_opt,
3516
        "maximum optimized size for direct I/O with torn-write protection"),
3517
#endif
3518
    {NULL},
3519
};
3520
3521
#undef G
3522
3523
static PyObject *
3524
pystatx_result_repr(PyObject *op)
3525
0
{
3526
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3527
0
    if (writer == NULL) {
3528
0
        return NULL;
3529
0
    }
3530
0
#define WRITE_ASCII(s) \
3531
0
    do { \
3532
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3533
0
            goto error; \
3534
0
        } \
3535
0
    } while (0)
3536
3537
0
    WRITE_ASCII("os.statx_result(");
3538
3539
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3540
0
        if (i > 0) {
3541
0
            WRITE_ASCII(", ");
3542
0
        }
3543
3544
0
        PyMemberDef *d = &pystatx_result_members[i];
3545
0
        WRITE_ASCII(d->name);
3546
0
        WRITE_ASCII("=");
3547
3548
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3549
0
        if (o == NULL) {
3550
0
            goto error;
3551
0
        }
3552
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3553
0
            Py_DECREF(o);
3554
0
            goto error;
3555
0
        }
3556
0
        Py_DECREF(o);
3557
0
    }
3558
3559
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3560
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3561
0
        PyObject *o = d->get(op, d->closure);
3562
0
        if (o == NULL) {
3563
0
            goto error;
3564
0
        }
3565
0
        if (o == Py_None) {
3566
0
            continue;
3567
0
        }
3568
3569
0
        WRITE_ASCII(", ");
3570
0
        WRITE_ASCII(d->name);
3571
0
        WRITE_ASCII("=");
3572
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3573
0
            Py_DECREF(o);
3574
0
            goto error;
3575
0
        }
3576
0
        Py_DECREF(o);
3577
0
    }
3578
3579
0
    WRITE_ASCII(")");
3580
0
    return PyUnicodeWriter_Finish(writer);
3581
0
#undef WRITE_ASCII
3582
3583
0
error:
3584
0
    PyUnicodeWriter_Discard(writer);
3585
0
    return NULL;
3586
0
}
3587
3588
static int
3589
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3590
0
{
3591
0
    Py_VISIT(Py_TYPE(self));
3592
0
    return 0;
3593
0
}
3594
3595
static void
3596
pystatx_result_dealloc(PyObject *op)
3597
0
{
3598
0
    Py_statx_result *self = (Py_statx_result *) op;
3599
0
    PyTypeObject *tp = Py_TYPE(self);
3600
0
    PyObject_GC_UnTrack(self);
3601
0
    tp->tp_free(self);
3602
0
    Py_DECREF(tp);
3603
0
}
3604
3605
static PyType_Slot pystatx_result_slots[] = {
3606
    {Py_tp_repr, pystatx_result_repr},
3607
    {Py_tp_traverse, pystatx_result_traverse},
3608
    {Py_tp_dealloc, pystatx_result_dealloc},
3609
    {Py_tp_members, pystatx_result_members},
3610
    {Py_tp_getset, pystatx_result_getset},
3611
    {0, NULL},
3612
};
3613
3614
static PyType_Spec pystatx_result_spec = {
3615
    .name = "os.statx_result",
3616
    .basicsize = sizeof(Py_statx_result),
3617
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3618
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3619
    .slots = pystatx_result_slots,
3620
};
3621
3622
/*[clinic input]
3623
3624
os.statx
3625
3626
    path : path_t(allow_fd=True)
3627
        Path to be examined; can be string, bytes, a path-like object or
3628
        open-file-descriptor int.
3629
3630
    mask: unsigned_int(bitwise=True)
3631
        A bitmask of STATX_* constants defining the requested information.
3632
3633
    *
3634
3635
    flags: int = 0
3636
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3637
3638
    dir_fd : dir_fd = None
3639
        If not None, it should be a file descriptor open to a directory,
3640
        and path should be a relative string; path will then be relative to
3641
        that directory.
3642
3643
    follow_symlinks: bool = True
3644
        If False, and the last element of the path is a symbolic link,
3645
        statx will examine the symbolic link itself instead of the file
3646
        the link points to.
3647
3648
Perform a statx system call on the given path.
3649
3650
It's an error to use dir_fd or follow_symlinks when specifying path as
3651
  an open file descriptor.
3652
3653
[clinic start generated code]*/
3654
3655
static PyObject *
3656
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3657
              int dir_fd, int follow_symlinks)
3658
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3659
0
{
3660
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3661
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3662
0
        fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) {
3663
0
        return NULL;
3664
0
    }
3665
3666
    /* reject flags covered by kwargs, but allow unknown flags that may be
3667
       future AT_STATX_* extensions */
3668
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3669
0
        PyErr_Format(PyExc_ValueError,
3670
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3671
0
        return NULL;
3672
0
    }
3673
0
    if (flags & AT_EMPTY_PATH) {
3674
0
        PyErr_Format(PyExc_ValueError,
3675
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3676
0
        return NULL;
3677
0
    }
3678
3679
    /* Future bits may refer to members beyond the current size of struct
3680
       statx, so we need to mask them off to prevent memory corruption. */
3681
0
    mask &= _Py_STATX_KNOWN;
3682
3683
0
    _posixstate *state = get_posix_state(module);
3684
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3685
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3686
0
    if (v == NULL) {
3687
0
        return NULL;
3688
0
    }
3689
3690
0
    int result;
3691
0
    Py_BEGIN_ALLOW_THREADS
3692
0
    if (path->is_fd) {
3693
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3694
0
    }
3695
0
    else {
3696
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3697
0
    }
3698
0
    Py_END_ALLOW_THREADS
3699
3700
0
    if (result != 0) {
3701
0
        Py_DECREF(v);
3702
0
        return path_error(path);
3703
0
    }
3704
3705
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3706
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3707
3708
0
    assert(!PyErr_Occurred());
3709
0
    return (PyObject *)v;
3710
0
}
3711
#endif /* HAVE_STATX */
3712
3713
3714
/*[clinic input]
3715
os.access -> bool
3716
3717
    path: path_t
3718
        Path to be tested; can be string, bytes, or a path-like object.
3719
3720
    mode: int
3721
        Operating-system mode bitfield.  Can be F_OK to test existence,
3722
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3723
3724
    *
3725
3726
    dir_fd : dir_fd(requires='faccessat') = None
3727
        If not None, it should be a file descriptor open to a directory,
3728
        and path should be relative; path will then be relative to that
3729
        directory.
3730
3731
    effective_ids: bool = False
3732
        If True, access will use the effective uid/gid instead of
3733
        the real uid/gid.
3734
3735
    follow_symlinks: bool = True
3736
        If False, and the last element of the path is a symbolic link,
3737
        access will examine the symbolic link itself instead of the file
3738
        the link points to.
3739
3740
Use the real uid/gid to test for access to a path.
3741
3742
{parameters}
3743
dir_fd, effective_ids, and follow_symlinks may not be implemented
3744
  on your platform.  If they are unavailable, using them will raise a
3745
  NotImplementedError.
3746
3747
Note that most operations will use the effective uid/gid, therefore this
3748
  routine can be used in a suid/sgid environment to test if the invoking
3749
  user has the specified access to the path.
3750
3751
[clinic start generated code]*/
3752
3753
static int
3754
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3755
               int effective_ids, int follow_symlinks)
3756
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3757
0
{
3758
0
    int return_value;
3759
3760
#ifdef MS_WINDOWS
3761
    DWORD attr;
3762
#else
3763
0
    int result;
3764
0
#endif
3765
3766
0
#ifdef HAVE_FACCESSAT
3767
0
    int faccessat_unavailable = 0;
3768
0
#endif
3769
3770
#ifndef HAVE_FACCESSAT
3771
    if (follow_symlinks_specified("access", follow_symlinks))
3772
        return -1;
3773
3774
    if (effective_ids) {
3775
        argument_unavailable_error("access", "effective_ids");
3776
        return -1;
3777
    }
3778
#endif
3779
3780
#ifdef MS_WINDOWS
3781
    Py_BEGIN_ALLOW_THREADS
3782
    attr = GetFileAttributesW(path->wide);
3783
    Py_END_ALLOW_THREADS
3784
3785
    /*
3786
     * Access is possible if
3787
     *   * we didn't get a -1, and
3788
     *     * write access wasn't requested,
3789
     *     * or the file isn't read-only,
3790
     *     * or it's a directory.
3791
     * (Directories cannot be read-only on Windows.)
3792
    */
3793
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3794
            (!(mode & 2) ||
3795
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3796
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3797
#else
3798
3799
0
    Py_BEGIN_ALLOW_THREADS
3800
0
#ifdef HAVE_FACCESSAT
3801
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3802
0
        effective_ids ||
3803
0
        !follow_symlinks) {
3804
3805
0
        if (HAVE_FACCESSAT_RUNTIME) {
3806
0
            int flags = 0;
3807
0
            if (!follow_symlinks)
3808
0
                flags |= AT_SYMLINK_NOFOLLOW;
3809
0
            if (effective_ids)
3810
0
                flags |= AT_EACCESS;
3811
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3812
0
        } else {
3813
0
            faccessat_unavailable = 1;
3814
0
        }
3815
0
    }
3816
0
    else
3817
0
#endif
3818
0
        result = access(path->narrow, mode);
3819
0
    Py_END_ALLOW_THREADS
3820
3821
0
#ifdef HAVE_FACCESSAT
3822
0
    if (faccessat_unavailable) {
3823
0
        if (dir_fd != DEFAULT_DIR_FD) {
3824
0
            argument_unavailable_error("access", "dir_fd");
3825
0
            return -1;
3826
0
        }
3827
0
        if (follow_symlinks_specified("access", follow_symlinks))
3828
0
            return -1;
3829
3830
0
        if (effective_ids) {
3831
0
            argument_unavailable_error("access", "effective_ids");
3832
0
            return -1;
3833
0
        }
3834
        /* should be unreachable */
3835
0
        return -1;
3836
0
    }
3837
0
#endif
3838
0
    return_value = !result;
3839
0
#endif
3840
3841
0
    return return_value;
3842
0
}
3843
3844
#ifndef F_OK
3845
#define F_OK 0
3846
#endif
3847
#ifndef R_OK
3848
#define R_OK 4
3849
#endif
3850
#ifndef W_OK
3851
#define W_OK 2
3852
#endif
3853
#ifndef X_OK
3854
#define X_OK 1
3855
#endif
3856
3857
3858
#ifdef HAVE_TTYNAME_R
3859
/*[clinic input]
3860
os.ttyname
3861
3862
    fd: int
3863
        Integer file descriptor handle.
3864
3865
    /
3866
3867
Return the name of the terminal device connected to 'fd'.
3868
[clinic start generated code]*/
3869
3870
static PyObject *
3871
os_ttyname_impl(PyObject *module, int fd)
3872
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3873
0
{
3874
3875
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3876
0
    if (size == -1) {
3877
0
        return posix_error();
3878
0
    }
3879
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3880
0
    if (buffer == NULL) {
3881
0
        return PyErr_NoMemory();
3882
0
    }
3883
0
    int ret = ttyname_r(fd, buffer, size);
3884
0
    if (ret != 0) {
3885
0
        PyMem_RawFree(buffer);
3886
0
        errno = ret;
3887
0
        return posix_error();
3888
0
    }
3889
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3890
0
    PyMem_RawFree(buffer);
3891
0
    return res;
3892
0
}
3893
#endif
3894
3895
#ifdef HAVE_CTERMID
3896
/*[clinic input]
3897
os.ctermid
3898
3899
Return the name of the controlling terminal for this process.
3900
[clinic start generated code]*/
3901
3902
static PyObject *
3903
os_ctermid_impl(PyObject *module)
3904
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3905
0
{
3906
0
    char *ret;
3907
0
    char buffer[L_ctermid];
3908
3909
#ifdef USE_CTERMID_R
3910
    ret = ctermid_r(buffer);
3911
#else
3912
0
    ret = ctermid(buffer);
3913
0
#endif
3914
0
    if (ret == NULL)
3915
0
        return posix_error();
3916
0
    return PyUnicode_DecodeFSDefault(buffer);
3917
0
}
3918
#endif /* HAVE_CTERMID */
3919
3920
3921
/*[clinic input]
3922
os.chdir
3923
3924
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3925
3926
Change the current working directory to the specified path.
3927
3928
path may always be specified as a string.  On some platforms, path may
3929
also be specified as an open file descriptor.  If this functionality is
3930
unavailable, using it raises an exception.
3931
[clinic start generated code]*/
3932
3933
static PyObject *
3934
os_chdir_impl(PyObject *module, path_t *path)
3935
/*[clinic end generated code: output=3be6400eee26eaae input=64673c342e4369f1]*/
3936
0
{
3937
0
    int result;
3938
3939
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3940
0
        return NULL;
3941
0
    }
3942
3943
0
    Py_BEGIN_ALLOW_THREADS
3944
#ifdef MS_WINDOWS
3945
    /* on unix, success = 0, on windows, success = !0 */
3946
    result = !win32_wchdir(path->wide);
3947
#else
3948
0
#ifdef HAVE_FCHDIR
3949
0
    if (path->is_fd)
3950
0
        result = fchdir(path->fd);
3951
0
    else
3952
0
#endif
3953
0
        result = chdir(path->narrow);
3954
0
#endif
3955
0
    Py_END_ALLOW_THREADS
3956
3957
0
    if (result) {
3958
0
        return path_error(path);
3959
0
    }
3960
3961
0
    Py_RETURN_NONE;
3962
0
}
3963
3964
3965
#ifdef HAVE_FCHDIR
3966
/*[clinic input]
3967
os.fchdir
3968
3969
    fd: fildes
3970
3971
Change to the directory of the given file descriptor.
3972
3973
fd must be opened on a directory, not a file.
3974
Equivalent to os.chdir(fd).
3975
3976
[clinic start generated code]*/
3977
3978
static PyObject *
3979
os_fchdir_impl(PyObject *module, int fd)
3980
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3981
0
{
3982
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3983
0
        return NULL;
3984
0
    }
3985
0
    return posix_fildes_fd(fd, fchdir);
3986
0
}
3987
#endif /* HAVE_FCHDIR */
3988
3989
#ifdef MS_WINDOWS
3990
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3991
#else
3992
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3993
#endif
3994
3995
#ifdef MS_WINDOWS
3996
static int
3997
win32_lchmod(LPCWSTR path, int mode)
3998
{
3999
    DWORD attr = GetFileAttributesW(path);
4000
    if (attr == INVALID_FILE_ATTRIBUTES) {
4001
        return 0;
4002
    }
4003
    if (mode & _S_IWRITE) {
4004
        attr &= ~FILE_ATTRIBUTE_READONLY;
4005
    }
4006
    else {
4007
        attr |= FILE_ATTRIBUTE_READONLY;
4008
    }
4009
    return SetFileAttributesW(path, attr);
4010
}
4011
4012
static int
4013
win32_hchmod(HANDLE hfile, int mode)
4014
{
4015
    FILE_BASIC_INFO info;
4016
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4017
                                      &info, sizeof(info)))
4018
    {
4019
        return 0;
4020
    }
4021
    if (mode & _S_IWRITE) {
4022
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4023
    }
4024
    else {
4025
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4026
    }
4027
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4028
                                      &info, sizeof(info));
4029
}
4030
4031
static int
4032
win32_fchmod(int fd, int mode)
4033
{
4034
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4035
    if (hfile == INVALID_HANDLE_VALUE) {
4036
        SetLastError(ERROR_INVALID_HANDLE);
4037
        return 0;
4038
    }
4039
    return win32_hchmod(hfile, mode);
4040
}
4041
4042
#endif /* MS_WINDOWS */
4043
4044
/*[clinic input]
4045
os.chmod
4046
4047
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4048
        Path to be modified.  May always be specified as a str, bytes, or
4049
        a path-like object.  On some platforms, path may also be specified
4050
        as an open file descriptor.  If this functionality is unavailable,
4051
        using it raises an exception.
4052
4053
    mode: int
4054
        Operating-system mode bitfield.
4055
        Be careful when using number literals for *mode*. The conventional
4056
        UNIX notation for numeric modes uses an octal base, which needs to
4057
        be indicated with a ``0o`` prefix in Python.
4058
4059
    *
4060
4061
    dir_fd : dir_fd(requires='fchmodat') = None
4062
        If not None, it should be a file descriptor open to a directory,
4063
        and path should be relative; path will then be relative to that
4064
        directory.
4065
4066
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4067
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4068
        If False, and the last element of the path is a symbolic link,
4069
        chmod will modify the symbolic link itself instead of the file
4070
        the link points to.
4071
4072
Change the access permissions of a file.
4073
4074
It is an error to use dir_fd or follow_symlinks when specifying path as
4075
  an open file descriptor.
4076
dir_fd and follow_symlinks may not be implemented on your platform.
4077
  If they are unavailable, using them will raise a NotImplementedError.
4078
4079
[clinic start generated code]*/
4080
4081
static PyObject *
4082
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4083
              int follow_symlinks)
4084
/*[clinic end generated code: output=5cf6a94915cc7bff input=7b6e2eeadd8bf199]*/
4085
0
{
4086
0
    int result;
4087
4088
0
#ifdef HAVE_FCHMODAT
4089
0
    int fchmodat_nofollow_unsupported = 0;
4090
0
    int fchmodat_unsupported = 0;
4091
0
#endif
4092
4093
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4094
    if (follow_symlinks_specified("chmod", follow_symlinks))
4095
        return NULL;
4096
#endif
4097
4098
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4099
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4100
0
        return NULL;
4101
0
    }
4102
4103
#ifdef MS_WINDOWS
4104
    result = 0;
4105
    Py_BEGIN_ALLOW_THREADS
4106
    if (path->is_fd) {
4107
        result = win32_fchmod(path->fd, mode);
4108
    }
4109
    else if (follow_symlinks) {
4110
        HANDLE hfile = CreateFileW(path->wide,
4111
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4112
                                   0, NULL,
4113
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4114
        if (hfile != INVALID_HANDLE_VALUE) {
4115
            result = win32_hchmod(hfile, mode);
4116
            (void)CloseHandle(hfile);
4117
        }
4118
    }
4119
    else {
4120
        result = win32_lchmod(path->wide, mode);
4121
    }
4122
    Py_END_ALLOW_THREADS
4123
    if (!result) {
4124
        return path_error(path);
4125
    }
4126
#else /* MS_WINDOWS */
4127
0
    Py_BEGIN_ALLOW_THREADS
4128
0
#ifdef HAVE_FCHMOD
4129
0
    if (path->is_fd) {
4130
0
        result = fchmod(path->fd, mode);
4131
0
    }
4132
0
    else
4133
0
#endif /* HAVE_CHMOD */
4134
#ifdef HAVE_LCHMOD
4135
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4136
        result = lchmod(path->narrow, mode);
4137
    else
4138
#endif /* HAVE_LCHMOD */
4139
0
#ifdef HAVE_FCHMODAT
4140
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4141
0
        if (HAVE_FCHMODAT_RUNTIME) {
4142
            /*
4143
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4144
             * The documentation specifically shows how to use it,
4145
             * and then says it isn't implemented yet.
4146
             * (true on linux with glibc 2.15, and openindiana 3.x)
4147
             *
4148
             * Once it is supported, os.chmod will automatically
4149
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4150
             * Until then, we need to be careful what exception we raise.
4151
             */
4152
0
            result = fchmodat(dir_fd, path->narrow, mode,
4153
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4154
            /*
4155
             * But wait!  We can't throw the exception without allowing threads,
4156
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4157
             */
4158
0
            fchmodat_nofollow_unsupported =
4159
0
                             result &&
4160
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4161
0
                             !follow_symlinks;
4162
0
        } else {
4163
0
            fchmodat_unsupported = 1;
4164
0
            fchmodat_nofollow_unsupported = 1;
4165
4166
0
            result = -1;
4167
0
        }
4168
0
    }
4169
0
    else
4170
0
#endif /* HAVE_FHCMODAT */
4171
0
    {
4172
0
#ifdef HAVE_CHMOD
4173
0
        result = chmod(path->narrow, mode);
4174
#elif defined(__wasi__)
4175
        // WASI SDK 15.0 does not support chmod.
4176
        // Ignore missing syscall for now.
4177
        result = 0;
4178
#else
4179
        result = -1;
4180
        errno = ENOSYS;
4181
#endif
4182
0
    }
4183
0
    Py_END_ALLOW_THREADS
4184
4185
0
    if (result) {
4186
0
#ifdef HAVE_FCHMODAT
4187
0
        if (fchmodat_unsupported) {
4188
0
            if (dir_fd != DEFAULT_DIR_FD) {
4189
0
                argument_unavailable_error("chmod", "dir_fd");
4190
0
                return NULL;
4191
0
            }
4192
0
        }
4193
4194
0
        if (fchmodat_nofollow_unsupported) {
4195
0
            if (dir_fd != DEFAULT_DIR_FD)
4196
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4197
0
                                                   dir_fd, follow_symlinks);
4198
0
            else
4199
0
                follow_symlinks_specified("chmod", follow_symlinks);
4200
0
            return NULL;
4201
0
        }
4202
0
        else
4203
0
#endif /* HAVE_FCHMODAT */
4204
0
        return path_error(path);
4205
0
    }
4206
0
#endif /* MS_WINDOWS */
4207
4208
0
    Py_RETURN_NONE;
4209
0
}
4210
4211
4212
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4213
/*[clinic input]
4214
os.fchmod
4215
4216
    fd: int
4217
        The file descriptor of the file to be modified.
4218
    mode: int
4219
        Operating-system mode bitfield.
4220
        Be careful when using number literals for *mode*.  The conventional
4221
        UNIX notation for numeric modes uses an octal base, which needs to
4222
        be indicated with a ``0o`` prefix in Python.
4223
4224
Change the access permissions of the file given by file descriptor fd.
4225
4226
Equivalent to os.chmod(fd, mode).
4227
[clinic start generated code]*/
4228
4229
static PyObject *
4230
os_fchmod_impl(PyObject *module, int fd, int mode)
4231
/*[clinic end generated code: output=afd9bc05b4e426b3 input=d24331f9fdc17f49]*/
4232
0
{
4233
0
    int res;
4234
4235
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4236
0
        return NULL;
4237
0
    }
4238
4239
#ifdef MS_WINDOWS
4240
    res = 0;
4241
    Py_BEGIN_ALLOW_THREADS
4242
    res = win32_fchmod(fd, mode);
4243
    Py_END_ALLOW_THREADS
4244
    if (!res) {
4245
        return PyErr_SetFromWindowsErr(0);
4246
    }
4247
#else /* MS_WINDOWS */
4248
0
    int async_err = 0;
4249
0
    do {
4250
0
        Py_BEGIN_ALLOW_THREADS
4251
0
        res = fchmod(fd, mode);
4252
0
        Py_END_ALLOW_THREADS
4253
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4254
0
    if (res != 0)
4255
0
        return (!async_err) ? posix_error() : NULL;
4256
0
#endif /* MS_WINDOWS */
4257
4258
0
    Py_RETURN_NONE;
4259
0
}
4260
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4261
4262
4263
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4264
/*[clinic input]
4265
@permit_long_summary
4266
os.lchmod
4267
4268
    path: path_t
4269
    mode: int
4270
4271
Change the access permissions of a file, without following symbolic links.
4272
4273
If path is a symlink, this affects the link itself rather than the
4274
target.  Equivalent to chmod(path, mode, follow_symlinks=False).
4275
[clinic start generated code]*/
4276
4277
static PyObject *
4278
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4279
/*[clinic end generated code: output=082344022b51a1d5 input=13110fb62911b015]*/
4280
{
4281
    int res;
4282
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4283
        return NULL;
4284
    }
4285
#ifdef MS_WINDOWS
4286
    Py_BEGIN_ALLOW_THREADS
4287
    res = win32_lchmod(path->wide, mode);
4288
    Py_END_ALLOW_THREADS
4289
    if (!res) {
4290
        path_error(path);
4291
        return NULL;
4292
    }
4293
#else /* MS_WINDOWS */
4294
    Py_BEGIN_ALLOW_THREADS
4295
    res = lchmod(path->narrow, mode);
4296
    Py_END_ALLOW_THREADS
4297
    if (res < 0) {
4298
        path_error(path);
4299
        return NULL;
4300
    }
4301
#endif /* MS_WINDOWS */
4302
    Py_RETURN_NONE;
4303
}
4304
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4305
4306
4307
#ifdef HAVE_CHFLAGS
4308
/*[clinic input]
4309
os.chflags
4310
4311
    path: path_t
4312
    flags: unsigned_long(bitwise=True)
4313
    follow_symlinks: bool=True
4314
4315
Set file flags.
4316
4317
If follow_symlinks is False, and the last element of the path is
4318
a symbolic link, chflags() will change flags on the symbolic link itself
4319
instead of the file the link points to.
4320
follow_symlinks may not be implemented on your platform.  If it is
4321
unavailable, using it will raise a NotImplementedError.
4322
4323
[clinic start generated code]*/
4324
4325
static PyObject *
4326
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4327
                int follow_symlinks)
4328
/*[clinic end generated code: output=85571c6737661ce9 input=31391927707be1de]*/
4329
{
4330
    int result;
4331
4332
#ifndef HAVE_LCHFLAGS
4333
    if (follow_symlinks_specified("chflags", follow_symlinks))
4334
        return NULL;
4335
#endif
4336
4337
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4338
        return NULL;
4339
    }
4340
4341
    Py_BEGIN_ALLOW_THREADS
4342
#ifdef HAVE_LCHFLAGS
4343
    if (!follow_symlinks)
4344
        result = lchflags(path->narrow, flags);
4345
    else
4346
#endif
4347
        result = chflags(path->narrow, flags);
4348
    Py_END_ALLOW_THREADS
4349
4350
    if (result)
4351
        return path_error(path);
4352
4353
    Py_RETURN_NONE;
4354
}
4355
#endif /* HAVE_CHFLAGS */
4356
4357
4358
#ifdef HAVE_LCHFLAGS
4359
/*[clinic input]
4360
os.lchflags
4361
4362
    path: path_t
4363
    flags: unsigned_long(bitwise=True)
4364
4365
Set file flags.
4366
4367
This function will not follow symbolic links.
4368
Equivalent to chflags(path, flags, follow_symlinks=False).
4369
[clinic start generated code]*/
4370
4371
static PyObject *
4372
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4373
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4374
{
4375
    int res;
4376
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4377
        return NULL;
4378
    }
4379
    Py_BEGIN_ALLOW_THREADS
4380
    res = lchflags(path->narrow, flags);
4381
    Py_END_ALLOW_THREADS
4382
    if (res < 0) {
4383
        return path_error(path);
4384
    }
4385
    Py_RETURN_NONE;
4386
}
4387
#endif /* HAVE_LCHFLAGS */
4388
4389
4390
#ifdef HAVE_CHROOT
4391
/*[clinic input]
4392
os.chroot
4393
    path: path_t
4394
4395
Change root directory to path.
4396
4397
[clinic start generated code]*/
4398
4399
static PyObject *
4400
os_chroot_impl(PyObject *module, path_t *path)
4401
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4402
0
{
4403
0
    int res;
4404
0
    Py_BEGIN_ALLOW_THREADS
4405
0
    res = chroot(path->narrow);
4406
0
    Py_END_ALLOW_THREADS
4407
0
    if (res < 0)
4408
0
        return path_error(path);
4409
0
    Py_RETURN_NONE;
4410
0
}
4411
#endif /* HAVE_CHROOT */
4412
4413
4414
#ifdef HAVE_FSYNC
4415
/*[clinic input]
4416
os.fsync
4417
4418
    fd: fildes
4419
4420
Force write of fd to disk.
4421
[clinic start generated code]*/
4422
4423
static PyObject *
4424
os_fsync_impl(PyObject *module, int fd)
4425
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4426
0
{
4427
0
    return posix_fildes_fd(fd, fsync);
4428
0
}
4429
#endif /* HAVE_FSYNC */
4430
4431
4432
#ifdef HAVE_SYNC
4433
/*[clinic input]
4434
os.sync
4435
4436
Force write of everything to disk.
4437
[clinic start generated code]*/
4438
4439
static PyObject *
4440
os_sync_impl(PyObject *module)
4441
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4442
0
{
4443
0
    Py_BEGIN_ALLOW_THREADS
4444
0
    sync();
4445
0
    Py_END_ALLOW_THREADS
4446
0
    Py_RETURN_NONE;
4447
0
}
4448
#endif /* HAVE_SYNC */
4449
4450
4451
#ifdef HAVE_FDATASYNC
4452
#ifdef __hpux
4453
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4454
#endif
4455
4456
/*[clinic input]
4457
os.fdatasync
4458
4459
    fd: fildes
4460
4461
Force write of fd to disk without forcing update of metadata.
4462
[clinic start generated code]*/
4463
4464
static PyObject *
4465
os_fdatasync_impl(PyObject *module, int fd)
4466
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4467
0
{
4468
0
    return posix_fildes_fd(fd, fdatasync);
4469
0
}
4470
#endif /* HAVE_FDATASYNC */
4471
4472
4473
#ifdef HAVE_CHOWN
4474
/*[clinic input]
4475
os.chown
4476
4477
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4478
        Path to be examined; can be string, bytes, a path-like object, or
4479
        open-file-descriptor int.
4480
4481
    uid: uid_t
4482
4483
    gid: gid_t
4484
4485
    *
4486
4487
    dir_fd: dir_fd(requires='fchownat') = None
4488
        If not None, it should be a file descriptor open to a directory,
4489
        and path should be relative; path will then be relative to that
4490
        directory.
4491
4492
    follow_symlinks: bool = True
4493
        If False, and the last element of the path is a symbolic link,
4494
        stat will examine the symbolic link itself instead of the file
4495
        the link points to.
4496
4497
Change the owner and group id of path to the numeric uid and gid.
4498
4499
path may always be specified as a string.  On some platforms, path may
4500
also be specified as an open file descriptor.  If this functionality is
4501
unavailable, using it raises an exception.
4502
If dir_fd is not None, it should be a file descriptor open to
4503
a directory, and path should be relative; path will then be relative to
4504
that directory.
4505
If follow_symlinks is False, and the last element of the path is
4506
a symbolic link, chown will modify the symbolic link itself instead of
4507
the file the link points to.
4508
It is an error to use dir_fd or follow_symlinks when specifying path as
4509
an open file descriptor.
4510
dir_fd and follow_symlinks may not be implemented on your platform.  If
4511
they are unavailable, using them will raise a NotImplementedError.
4512
4513
[clinic start generated code]*/
4514
4515
static PyObject *
4516
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4517
              int dir_fd, int follow_symlinks)
4518
/*[clinic end generated code: output=4beadab0db5f70cd input=509c91b7a0e72f52]*/
4519
0
{
4520
0
    int result;
4521
4522
0
#if defined(HAVE_FCHOWNAT)
4523
0
    int fchownat_unsupported = 0;
4524
0
#endif
4525
4526
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4527
    if (follow_symlinks_specified("chown", follow_symlinks))
4528
        return NULL;
4529
#endif
4530
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4531
0
        fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
4532
0
        return NULL;
4533
4534
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4535
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4536
0
        return NULL;
4537
0
    }
4538
4539
0
    Py_BEGIN_ALLOW_THREADS
4540
0
#ifdef HAVE_FCHOWN
4541
0
    if (path->is_fd)
4542
0
        result = fchown(path->fd, uid, gid);
4543
0
    else
4544
0
#endif
4545
0
#ifdef HAVE_LCHOWN
4546
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4547
0
        result = lchown(path->narrow, uid, gid);
4548
0
    else
4549
0
#endif
4550
0
#ifdef HAVE_FCHOWNAT
4551
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4552
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4553
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4554
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4555
0
      } else {
4556
0
         fchownat_unsupported = 1;
4557
0
      }
4558
0
    } else
4559
0
#endif
4560
0
        result = chown(path->narrow, uid, gid);
4561
0
    Py_END_ALLOW_THREADS
4562
4563
0
#ifdef HAVE_FCHOWNAT
4564
0
    if (fchownat_unsupported) {
4565
        /* This would be incorrect if the current platform
4566
         * doesn't support lchown.
4567
         */
4568
0
        argument_unavailable_error(NULL, "dir_fd");
4569
0
        return NULL;
4570
0
    }
4571
0
#endif
4572
4573
0
    if (result)
4574
0
        return path_error(path);
4575
4576
0
    Py_RETURN_NONE;
4577
0
}
4578
#endif /* HAVE_CHOWN */
4579
4580
4581
#ifdef HAVE_FCHOWN
4582
/*[clinic input]
4583
os.fchown
4584
4585
    fd: int
4586
    uid: uid_t
4587
    gid: gid_t
4588
4589
Change the owner and group id of the file specified by file descriptor.
4590
4591
Equivalent to os.chown(fd, uid, gid).
4592
4593
[clinic start generated code]*/
4594
4595
static PyObject *
4596
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4597
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4598
0
{
4599
0
    int res;
4600
0
    int async_err = 0;
4601
4602
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4603
0
        return NULL;
4604
0
    }
4605
4606
0
    do {
4607
0
        Py_BEGIN_ALLOW_THREADS
4608
0
        res = fchown(fd, uid, gid);
4609
0
        Py_END_ALLOW_THREADS
4610
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4611
0
    if (res != 0)
4612
0
        return (!async_err) ? posix_error() : NULL;
4613
4614
0
    Py_RETURN_NONE;
4615
0
}
4616
#endif /* HAVE_FCHOWN */
4617
4618
4619
#ifdef HAVE_LCHOWN
4620
/*[clinic input]
4621
os.lchown
4622
4623
    path : path_t
4624
    uid: uid_t
4625
    gid: gid_t
4626
4627
Change the owner and group id of path to the numeric uid and gid.
4628
4629
This function will not follow symbolic links.
4630
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4631
[clinic start generated code]*/
4632
4633
static PyObject *
4634
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4635
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4636
0
{
4637
0
    int res;
4638
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4639
0
        return NULL;
4640
0
    }
4641
0
    Py_BEGIN_ALLOW_THREADS
4642
0
    res = lchown(path->narrow, uid, gid);
4643
0
    Py_END_ALLOW_THREADS
4644
0
    if (res < 0) {
4645
0
        return path_error(path);
4646
0
    }
4647
0
    Py_RETURN_NONE;
4648
0
}
4649
#endif /* HAVE_LCHOWN */
4650
4651
4652
static PyObject *
4653
posix_getcwd(int use_bytes)
4654
6
{
4655
#ifdef MS_WINDOWS
4656
    wchar_t wbuf[MAXPATHLEN];
4657
    wchar_t *wbuf2 = wbuf;
4658
    DWORD len;
4659
4660
    Py_BEGIN_ALLOW_THREADS
4661
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4662
    /* If the buffer is large enough, len does not include the
4663
       terminating \0. If the buffer is too small, len includes
4664
       the space needed for the terminator. */
4665
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4666
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4667
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4668
        }
4669
        else {
4670
            wbuf2 = NULL;
4671
        }
4672
        if (wbuf2) {
4673
            len = GetCurrentDirectoryW(len, wbuf2);
4674
        }
4675
    }
4676
    Py_END_ALLOW_THREADS
4677
4678
    if (!wbuf2) {
4679
        PyErr_NoMemory();
4680
        return NULL;
4681
    }
4682
    if (!len) {
4683
        PyErr_SetFromWindowsErr(0);
4684
        if (wbuf2 != wbuf)
4685
            PyMem_RawFree(wbuf2);
4686
        return NULL;
4687
    }
4688
4689
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4690
    if (wbuf2 != wbuf) {
4691
        PyMem_RawFree(wbuf2);
4692
    }
4693
4694
    if (use_bytes) {
4695
        if (resobj == NULL) {
4696
            return NULL;
4697
        }
4698
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4699
    }
4700
4701
    return resobj;
4702
#else
4703
6
    const size_t chunk = 1024;
4704
4705
6
    char *buf = NULL;
4706
6
    char *cwd = NULL;
4707
6
    size_t buflen = 0;
4708
4709
6
    Py_BEGIN_ALLOW_THREADS
4710
6
    do {
4711
6
        char *newbuf;
4712
6
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4713
6
            buflen += chunk;
4714
6
            newbuf = PyMem_RawRealloc(buf, buflen);
4715
6
        }
4716
0
        else {
4717
0
            newbuf = NULL;
4718
0
        }
4719
6
        if (newbuf == NULL) {
4720
0
            PyMem_RawFree(buf);
4721
0
            buf = NULL;
4722
0
            break;
4723
0
        }
4724
6
        buf = newbuf;
4725
4726
6
        cwd = getcwd(buf, buflen);
4727
6
    } while (cwd == NULL && errno == ERANGE);
4728
6
    Py_END_ALLOW_THREADS
4729
4730
6
    if (buf == NULL) {
4731
0
        return PyErr_NoMemory();
4732
0
    }
4733
6
    if (cwd == NULL) {
4734
0
        posix_error();
4735
0
        PyMem_RawFree(buf);
4736
0
        return NULL;
4737
0
    }
4738
4739
6
    PyObject *obj;
4740
6
    if (use_bytes) {
4741
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4742
0
    }
4743
6
    else {
4744
6
        obj = PyUnicode_DecodeFSDefault(buf);
4745
6
    }
4746
6
#ifdef __linux__
4747
6
    if (buf[0] != '/') {
4748
        /*
4749
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4750
         * relative pathname starting with '(unreachable)'. We detect this
4751
         * and fail with ENOENT, matching newer glibc behaviour.
4752
         */
4753
0
        errno = ENOENT;
4754
0
        path_object_error(obj);
4755
0
        PyMem_RawFree(buf);
4756
0
        return NULL;
4757
0
    }
4758
6
#endif
4759
6
    assert(buf[0] == '/');
4760
6
    PyMem_RawFree(buf);
4761
4762
6
    return obj;
4763
6
#endif   /* !MS_WINDOWS */
4764
6
}
4765
4766
4767
/*[clinic input]
4768
os.getcwd
4769
4770
Return a unicode string representing the current working directory.
4771
[clinic start generated code]*/
4772
4773
static PyObject *
4774
os_getcwd_impl(PyObject *module)
4775
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4776
6
{
4777
6
    return posix_getcwd(0);
4778
6
}
4779
4780
4781
/*[clinic input]
4782
os.getcwdb
4783
4784
Return a bytes string representing the current working directory.
4785
[clinic start generated code]*/
4786
4787
static PyObject *
4788
os_getcwdb_impl(PyObject *module)
4789
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4790
0
{
4791
0
    return posix_getcwd(1);
4792
0
}
4793
4794
4795
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4796
#define HAVE_LINK 1
4797
#endif
4798
4799
#ifdef HAVE_LINK
4800
/*[clinic input]
4801
4802
os.link
4803
4804
    src : path_t
4805
    dst : path_t
4806
    *
4807
    src_dir_fd : dir_fd = None
4808
    dst_dir_fd : dir_fd = None
4809
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4810
4811
Create a hard link to a file.
4812
4813
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4814
descriptor open to a directory, and the respective path string (src or
4815
dst) should be relative; the path will then be relative to that
4816
directory.
4817
If follow_symlinks is False, and the last element of src is a symbolic
4818
link, link will create a link to the symbolic link itself instead of the
4819
file the link points to.
4820
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on
4821
your platform.  If they are unavailable, using them will raise
4822
a NotImplementedError.
4823
[clinic start generated code]*/
4824
4825
static PyObject *
4826
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4827
             int dst_dir_fd, int follow_symlinks)
4828
/*[clinic end generated code: output=7f00f6007fd5269a input=a28e6866fbd20a01]*/
4829
0
{
4830
#ifdef MS_WINDOWS
4831
    BOOL result = FALSE;
4832
#else
4833
0
    int result;
4834
0
#endif
4835
4836
0
#ifdef HAVE_LINKAT
4837
0
    if (HAVE_LINKAT_RUNTIME) {
4838
0
        if (follow_symlinks < 0) {
4839
0
            follow_symlinks = 1;
4840
0
        }
4841
0
    }
4842
0
    else
4843
0
#endif
4844
0
    {
4845
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4846
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4847
0
            return NULL;
4848
0
        }
4849
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4850
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4851
0
#if defined(MS_WINDOWS) || defined(__linux__)
4852
0
        if (follow_symlinks == 1) {
4853
0
            argument_unavailable_error("link", "follow_symlinks=True");
4854
0
            return NULL;
4855
0
        }
4856
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4857
        if (follow_symlinks == 0) {
4858
            argument_unavailable_error("link", "follow_symlinks=False");
4859
            return NULL;
4860
        }
4861
#else
4862
        if (follow_symlinks >= 0) {
4863
            argument_unavailable_error("link", "follow_symlinks");
4864
            return NULL;
4865
        }
4866
#endif
4867
0
    }
4868
4869
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4870
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4871
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4872
0
        return NULL;
4873
0
    }
4874
4875
#ifdef MS_WINDOWS
4876
    Py_BEGIN_ALLOW_THREADS
4877
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4878
    Py_END_ALLOW_THREADS
4879
4880
    if (!result)
4881
        return path_error2(src, dst);
4882
#else
4883
0
    Py_BEGIN_ALLOW_THREADS
4884
0
#ifdef HAVE_LINKAT
4885
0
    if (HAVE_LINKAT_RUNTIME) {
4886
0
        result = linkat(src_dir_fd, src->narrow,
4887
0
            dst_dir_fd, dst->narrow,
4888
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4889
0
    }
4890
0
    else
4891
0
#endif
4892
0
    {
4893
        /* linkat not available */
4894
0
        result = link(src->narrow, dst->narrow);
4895
0
    }
4896
0
    Py_END_ALLOW_THREADS
4897
4898
0
    if (result)
4899
0
        return path_error2(src, dst);
4900
0
#endif /* MS_WINDOWS */
4901
4902
0
    Py_RETURN_NONE;
4903
0
}
4904
#endif
4905
4906
4907
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4908
static wchar_t *
4909
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,
4910
                    int normalize);
4911
4912
static PyObject *
4913
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4914
{
4915
    PyObject *v;
4916
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4917
    BOOL result, return_bytes;
4918
    wchar_t *wnamebuf = NULL;
4919
4920
    WIN32_FIND_DATAW wFileData;
4921
    const wchar_t *po_wchars;
4922
4923
    if (!path->wide) { /* Default arg: "." */
4924
        po_wchars = L".";
4925
        return_bytes = 0;
4926
    } else {
4927
        po_wchars = path->wide;
4928
        return_bytes = PyBytes_Check(path->object);
4929
    }
4930
4931
    wnamebuf = join_path_filenameW(po_wchars, L"*.*", 1);
4932
    if (wnamebuf == NULL) {
4933
        goto exit;
4934
    }
4935
4936
    if ((list = PyList_New(0)) == NULL) {
4937
        goto exit;
4938
    }
4939
    Py_BEGIN_ALLOW_THREADS
4940
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4941
    Py_END_ALLOW_THREADS
4942
    if (hFindFile == INVALID_HANDLE_VALUE) {
4943
        int error = GetLastError();
4944
        if (error == ERROR_FILE_NOT_FOUND)
4945
            goto exit;
4946
        path_error(path);
4947
        Py_CLEAR(list);
4948
        goto exit;
4949
    }
4950
    do {
4951
        /* Skip over . and .. */
4952
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4953
            wcscmp(wFileData.cFileName, L"..") != 0) {
4954
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4955
                                       wcslen(wFileData.cFileName));
4956
            if (return_bytes && v) {
4957
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4958
            }
4959
            if (v == NULL) {
4960
                Py_CLEAR(list);
4961
                break;
4962
            }
4963
            if (PyList_Append(list, v) != 0) {
4964
                Py_DECREF(v);
4965
                Py_CLEAR(list);
4966
                break;
4967
            }
4968
            Py_DECREF(v);
4969
        }
4970
        Py_BEGIN_ALLOW_THREADS
4971
        result = FindNextFileW(hFindFile, &wFileData);
4972
        Py_END_ALLOW_THREADS
4973
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4974
           it got to the end of the directory. */
4975
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4976
            path_error(path);
4977
            Py_CLEAR(list);
4978
            goto exit;
4979
        }
4980
    } while (result == TRUE);
4981
4982
exit:
4983
    if (hFindFile != INVALID_HANDLE_VALUE) {
4984
        if (FindClose(hFindFile) == FALSE) {
4985
            if (list != NULL) {
4986
                path_error(path);
4987
                Py_CLEAR(list);
4988
            }
4989
        }
4990
    }
4991
    PyMem_Free(wnamebuf);
4992
4993
    return list;
4994
}  /* end of _listdir_windows_no_opendir */
4995
4996
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4997
4998
static PyObject *
4999
_posix_listdir(path_t *path, PyObject *list)
5000
384
{
5001
384
    PyObject *v;
5002
384
    DIR *dirp = NULL;
5003
384
    struct dirent *ep;
5004
384
    int return_str; /* if false, return bytes */
5005
384
#ifdef HAVE_FDOPENDIR
5006
384
    int fd = -1;
5007
384
#endif
5008
5009
384
    errno = 0;
5010
384
#ifdef HAVE_FDOPENDIR
5011
384
    if (path->is_fd) {
5012
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5013
        /* closedir() closes the FD, so we duplicate it */
5014
0
        fd = _Py_dup(path->fd);
5015
0
        if (fd == -1)
5016
0
            return NULL;
5017
5018
0
        return_str = 1;
5019
5020
0
        Py_BEGIN_ALLOW_THREADS
5021
0
        dirp = fdopendir(fd);
5022
0
        Py_END_ALLOW_THREADS
5023
0
      } else {
5024
0
        PyErr_SetString(PyExc_TypeError,
5025
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5026
0
        return NULL;
5027
0
      }
5028
0
    }
5029
384
    else
5030
384
#endif
5031
384
    {
5032
384
        const char *name;
5033
384
        if (path->narrow) {
5034
384
            name = path->narrow;
5035
            /* only return bytes if they specified a bytes object */
5036
384
            return_str = !PyBytes_Check(path->object);
5037
384
        }
5038
0
        else {
5039
0
            name = ".";
5040
0
            return_str = 1;
5041
0
        }
5042
5043
384
        Py_BEGIN_ALLOW_THREADS
5044
384
        dirp = opendir(name);
5045
384
        Py_END_ALLOW_THREADS
5046
384
    }
5047
5048
384
    if (dirp == NULL) {
5049
4
        path_error(path);
5050
4
        list = NULL;
5051
4
#ifdef HAVE_FDOPENDIR
5052
4
        if (fd != -1) {
5053
0
            Py_BEGIN_ALLOW_THREADS
5054
0
            close(fd);
5055
0
            Py_END_ALLOW_THREADS
5056
0
        }
5057
4
#endif
5058
4
        goto exit;
5059
4
    }
5060
380
    if ((list = PyList_New(0)) == NULL) {
5061
0
        goto exit;
5062
0
    }
5063
20.1k
    for (;;) {
5064
20.1k
        errno = 0;
5065
20.1k
        Py_BEGIN_ALLOW_THREADS
5066
20.1k
        ep = readdir(dirp);
5067
20.1k
        Py_END_ALLOW_THREADS
5068
20.1k
        if (ep == NULL) {
5069
380
            if (errno == 0) {
5070
380
                break;
5071
380
            } else {
5072
0
                path_error(path);
5073
0
                Py_CLEAR(list);
5074
0
                goto exit;
5075
0
            }
5076
380
        }
5077
19.7k
        if (ep->d_name[0] == '.' &&
5078
800
            (NAMLEN(ep) == 1 ||
5079
420
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5080
760
            continue;
5081
18.9k
        if (return_str)
5082
18.9k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5083
0
        else
5084
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5085
18.9k
        if (v == NULL) {
5086
0
            Py_CLEAR(list);
5087
0
            break;
5088
0
        }
5089
18.9k
        if (PyList_Append(list, v) != 0) {
5090
0
            Py_DECREF(v);
5091
0
            Py_CLEAR(list);
5092
0
            break;
5093
0
        }
5094
18.9k
        Py_DECREF(v);
5095
18.9k
    }
5096
5097
384
exit:
5098
384
    if (dirp != NULL) {
5099
380
        Py_BEGIN_ALLOW_THREADS
5100
380
#ifdef HAVE_FDOPENDIR
5101
380
        if (fd > -1)
5102
0
            rewinddir(dirp);
5103
380
#endif
5104
380
        closedir(dirp);
5105
380
        Py_END_ALLOW_THREADS
5106
380
    }
5107
5108
384
    return list;
5109
380
}  /* end of _posix_listdir */
5110
#endif  /* which OS */
5111
5112
5113
/*[clinic input]
5114
os.listdir
5115
5116
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5117
5118
Return a list containing the names of the files in the directory.
5119
5120
path can be specified as either str, bytes, or a path-like object.  If
5121
path is bytes, the filenames returned will also be bytes; in all other
5122
circumstances the filenames returned will be str.
5123
If path is None, uses the path='.'.
5124
On some platforms, path may also be specified as an open file
5125
descriptor; the file descriptor must refer to a directory.  If this
5126
functionality is unavailable, using it raises NotImplementedError.
5127
5128
The list is in arbitrary order.  It does not include the special
5129
entries '.' and '..' even if they are present in the directory.
5130
5131
[clinic start generated code]*/
5132
5133
static PyObject *
5134
os_listdir_impl(PyObject *module, path_t *path)
5135
/*[clinic end generated code: output=293045673fcd1a75 input=4eefe7c6a42ec9b2]*/
5136
384
{
5137
384
    if (PySys_Audit("os.listdir", "O",
5138
384
                    path->object ? path->object : Py_None) < 0) {
5139
0
        return NULL;
5140
0
    }
5141
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5142
    return _listdir_windows_no_opendir(path, NULL);
5143
#else
5144
384
    return _posix_listdir(path, NULL);
5145
384
#endif
5146
384
}
5147
5148
5149
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5150
5151
/*[clinic input]
5152
os.listdrives
5153
5154
Return a list containing the names of drives in the system.
5155
5156
A drive name typically looks like 'C:\\'.
5157
5158
[clinic start generated code]*/
5159
5160
static PyObject *
5161
os_listdrives_impl(PyObject *module)
5162
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5163
{
5164
    /* Number of possible drives is limited, so 256 should always be enough.
5165
       On the day when it is not, listmounts() will have to be used. */
5166
    wchar_t buffer[256];
5167
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5168
    PyObject *result = NULL;
5169
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5170
        return NULL;
5171
    }
5172
5173
    Py_BEGIN_ALLOW_THREADS;
5174
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5175
    Py_END_ALLOW_THREADS;
5176
5177
    if (!buflen) {
5178
        PyErr_SetFromWindowsErr(0);
5179
        return NULL;
5180
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5181
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5182
        return NULL;
5183
    }
5184
5185
    /* buflen includes a null terminator, so remove it */
5186
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5187
    if (str) {
5188
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5189
        if (nullchar) {
5190
            result = PyUnicode_Split(str, nullchar, -1);
5191
            Py_DECREF(nullchar);
5192
        }
5193
        Py_DECREF(str);
5194
    }
5195
    return result;
5196
}
5197
5198
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5199
5200
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5201
5202
/*[clinic input]
5203
os.listvolumes
5204
5205
Return a list containing the volumes in the system.
5206
5207
Volumes are typically represented as a GUID path.
5208
5209
[clinic start generated code]*/
5210
5211
static PyObject *
5212
os_listvolumes_impl(PyObject *module)
5213
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5214
{
5215
    PyObject *result = PyList_New(0);
5216
    HANDLE find = INVALID_HANDLE_VALUE;
5217
    wchar_t buffer[MAX_PATH + 1];
5218
    if (!result) {
5219
        return NULL;
5220
    }
5221
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5222
        Py_DECREF(result);
5223
        return NULL;
5224
    }
5225
5226
    int err = 0;
5227
    Py_BEGIN_ALLOW_THREADS;
5228
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5229
    if (find == INVALID_HANDLE_VALUE) {
5230
        err = GetLastError();
5231
    }
5232
    Py_END_ALLOW_THREADS;
5233
5234
    while (!err) {
5235
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5236
        if (!s || PyList_Append(result, s) < 0) {
5237
            Py_XDECREF(s);
5238
            Py_CLEAR(result);
5239
            break;
5240
        }
5241
        Py_DECREF(s);
5242
5243
        Py_BEGIN_ALLOW_THREADS;
5244
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5245
            err = GetLastError();
5246
        }
5247
        Py_END_ALLOW_THREADS;
5248
    }
5249
5250
    if (find != INVALID_HANDLE_VALUE) {
5251
        Py_BEGIN_ALLOW_THREADS;
5252
        FindVolumeClose(find);
5253
        Py_END_ALLOW_THREADS;
5254
    }
5255
    if (err && err != ERROR_NO_MORE_FILES) {
5256
        PyErr_SetFromWindowsErr(err);
5257
        Py_XDECREF(result);
5258
        result = NULL;
5259
    }
5260
    return result;
5261
}
5262
5263
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5264
5265
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5266
5267
/*[clinic input]
5268
os.listmounts
5269
5270
    volume: path_t
5271
5272
Return a list containing mount points for a particular volume.
5273
5274
'volume' should be a GUID path as returned from os.listvolumes.
5275
5276
[clinic start generated code]*/
5277
5278
static PyObject *
5279
os_listmounts_impl(PyObject *module, path_t *volume)
5280
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5281
{
5282
    wchar_t default_buffer[MAX_PATH + 1];
5283
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5284
    LPWSTR buffer = default_buffer;
5285
    DWORD attributes;
5286
    PyObject *str = NULL;
5287
    PyObject *nullchar = NULL;
5288
    PyObject *result = NULL;
5289
5290
    /* Ensure we have a valid volume path before continuing */
5291
    Py_BEGIN_ALLOW_THREADS
5292
    attributes = GetFileAttributesW(volume->wide);
5293
    Py_END_ALLOW_THREADS
5294
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5295
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5296
    {
5297
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5298
    }
5299
5300
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5301
        return NULL;
5302
    }
5303
5304
    while (1) {
5305
        BOOL success;
5306
        Py_BEGIN_ALLOW_THREADS
5307
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5308
                                                   buflen, &buflen);
5309
        Py_END_ALLOW_THREADS
5310
        if (success) {
5311
            break;
5312
        }
5313
        if (GetLastError() != ERROR_MORE_DATA) {
5314
            PyErr_SetFromWindowsErr(0);
5315
            goto exit;
5316
        }
5317
        if (buffer != default_buffer) {
5318
            PyMem_Free((void *)buffer);
5319
        }
5320
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5321
        if (!buffer) {
5322
            PyErr_NoMemory();
5323
            goto exit;
5324
        }
5325
    }
5326
    if (buflen < 2) {
5327
        result = PyList_New(0);
5328
        goto exit;
5329
    }
5330
    // buflen includes two null terminators, one for the last string
5331
    // and one for the array of strings.
5332
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5333
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5334
    if (str && nullchar) {
5335
        result = PyUnicode_Split(str, nullchar, -1);
5336
    }
5337
exit:
5338
    if (buffer != default_buffer) {
5339
        PyMem_Free(buffer);
5340
    }
5341
    Py_XDECREF(nullchar);
5342
    Py_XDECREF(str);
5343
    return result;
5344
}
5345
5346
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5347
5348
#ifdef MS_WINDOWS
5349
5350
/*[clinic input]
5351
os._path_isdevdrive
5352
5353
    path: path_t
5354
5355
Determines whether the specified path is on a Windows Dev Drive.
5356
5357
[clinic start generated code]*/
5358
5359
static PyObject *
5360
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5361
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5362
{
5363
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5364
    /* This flag will be documented at
5365
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5366
       after release, and will be available in the latest WinSDK.
5367
       We include the flag to avoid a specific version dependency
5368
       on the latest WinSDK. */
5369
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5370
#endif
5371
    int err = 0;
5372
    PyObject *r = NULL;
5373
    wchar_t volume[MAX_PATH];
5374
5375
    Py_BEGIN_ALLOW_THREADS
5376
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5377
        /* invalid path of some kind */
5378
        /* Note that this also includes the case where a volume is mounted
5379
           in a path longer than 260 characters. This is likely to be rare
5380
           and problematic for other reasons, so a (soft) failure in this
5381
           check seems okay. */
5382
        err = GetLastError();
5383
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5384
        /* only care about local dev drives */
5385
        r = Py_False;
5386
    } else {
5387
        HANDLE hVolume = CreateFileW(
5388
            volume,
5389
            FILE_READ_ATTRIBUTES,
5390
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5391
            NULL,
5392
            OPEN_EXISTING,
5393
            FILE_FLAG_BACKUP_SEMANTICS,
5394
            NULL
5395
        );
5396
        if (hVolume == INVALID_HANDLE_VALUE) {
5397
            err = GetLastError();
5398
        } else {
5399
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5400
            volumeState.Version = 1;
5401
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5402
            if (!DeviceIoControl(
5403
                hVolume,
5404
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5405
                &volumeState,
5406
                sizeof(volumeState),
5407
                &volumeState,
5408
                sizeof(volumeState),
5409
                NULL,
5410
                NULL
5411
            )) {
5412
                err = GetLastError();
5413
            }
5414
            CloseHandle(hVolume);
5415
            if (err == ERROR_INVALID_PARAMETER) {
5416
                /* not supported on this platform */
5417
                r = Py_False;
5418
            } else if (!err) {
5419
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5420
                    ? Py_True : Py_False;
5421
            }
5422
        }
5423
    }
5424
    Py_END_ALLOW_THREADS
5425
5426
    if (err) {
5427
        PyErr_SetFromWindowsErr(err);
5428
        return NULL;
5429
    }
5430
5431
    if (r) {
5432
        return Py_NewRef(r);
5433
    }
5434
5435
    return NULL;
5436
}
5437
5438
5439
int
5440
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5441
{
5442
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5443
    DWORD result;
5444
5445
    result = GetFullPathNameW(path,
5446
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5447
                              NULL);
5448
    if (!result) {
5449
        return -1;
5450
    }
5451
5452
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5453
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5454
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5455
        }
5456
        else {
5457
            woutbufp = NULL;
5458
        }
5459
        if (!woutbufp) {
5460
            *abspath_p = NULL;
5461
            return 0;
5462
        }
5463
5464
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5465
        if (!result) {
5466
            PyMem_RawFree(woutbufp);
5467
            return -1;
5468
        }
5469
    }
5470
5471
    if (woutbufp != woutbuf) {
5472
        *abspath_p = woutbufp;
5473
        return 0;
5474
    }
5475
5476
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5477
    return 0;
5478
}
5479
5480
5481
/* A helper function for abspath on win32 */
5482
/*[clinic input]
5483
os._getfullpathname
5484
5485
    path: path_t
5486
    /
5487
5488
[clinic start generated code]*/
5489
5490
static PyObject *
5491
os__getfullpathname_impl(PyObject *module, path_t *path)
5492
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5493
{
5494
    wchar_t *abspath;
5495
5496
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5497
        return win32_error_object("GetFullPathNameW", path->object);
5498
    }
5499
    if (abspath == NULL) {
5500
        return PyErr_NoMemory();
5501
    }
5502
5503
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5504
    PyMem_RawFree(abspath);
5505
    if (str == NULL) {
5506
        return NULL;
5507
    }
5508
    if (PyBytes_Check(path->object)) {
5509
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5510
    }
5511
    return str;
5512
}
5513
5514
5515
/*[clinic input]
5516
os._getfinalpathname
5517
5518
    path: path_t
5519
    /
5520
5521
A helper function for samepath on windows.
5522
[clinic start generated code]*/
5523
5524
static PyObject *
5525
os__getfinalpathname_impl(PyObject *module, path_t *path)
5526
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5527
{
5528
    HANDLE hFile;
5529
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5530
    int buf_size = Py_ARRAY_LENGTH(buf);
5531
    int result_length;
5532
    PyObject *result;
5533
5534
    Py_BEGIN_ALLOW_THREADS
5535
    hFile = CreateFileW(
5536
        path->wide,
5537
        0, /* desired access */
5538
        0, /* share mode */
5539
        NULL, /* security attributes */
5540
        OPEN_EXISTING,
5541
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5542
        FILE_FLAG_BACKUP_SEMANTICS,
5543
        NULL);
5544
    Py_END_ALLOW_THREADS
5545
5546
    if (hFile == INVALID_HANDLE_VALUE) {
5547
        return win32_error_object("CreateFileW", path->object);
5548
    }
5549
5550
    /* We have a good handle to the target, use it to determine the
5551
       target path name. */
5552
    while (1) {
5553
        Py_BEGIN_ALLOW_THREADS
5554
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5555
                                                  buf_size, VOLUME_NAME_DOS);
5556
        Py_END_ALLOW_THREADS
5557
5558
        if (!result_length) {
5559
            result = win32_error_object("GetFinalPathNameByHandleW",
5560
                                         path->object);
5561
            goto cleanup;
5562
        }
5563
5564
        if (result_length < buf_size) {
5565
            break;
5566
        }
5567
5568
        wchar_t *tmp;
5569
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5570
                            result_length * sizeof(*tmp));
5571
        if (!tmp) {
5572
            result = PyErr_NoMemory();
5573
            goto cleanup;
5574
        }
5575
5576
        buf_size = result_length;
5577
        target_path = tmp;
5578
    }
5579
5580
    result = PyUnicode_FromWideChar(target_path, result_length);
5581
    if (result && PyBytes_Check(path->object)) {
5582
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5583
    }
5584
5585
cleanup:
5586
    if (target_path != buf) {
5587
        PyMem_Free(target_path);
5588
    }
5589
    CloseHandle(hFile);
5590
    return result;
5591
}
5592
5593
/*[clinic input]
5594
@permit_long_summary
5595
os._findfirstfile
5596
    path: path_t
5597
    /
5598
A function to get the real file name without accessing the file in Windows.
5599
[clinic start generated code]*/
5600
5601
static PyObject *
5602
os__findfirstfile_impl(PyObject *module, path_t *path)
5603
/*[clinic end generated code: output=106dd3f0779c83dd input=48c319aaa48d05d4]*/
5604
{
5605
    PyObject *result;
5606
    HANDLE hFindFile;
5607
    WIN32_FIND_DATAW wFileData;
5608
    WCHAR *wRealFileName;
5609
5610
    Py_BEGIN_ALLOW_THREADS
5611
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5612
    Py_END_ALLOW_THREADS
5613
5614
    if (hFindFile == INVALID_HANDLE_VALUE) {
5615
        path_error(path);
5616
        return NULL;
5617
    }
5618
5619
    wRealFileName = wFileData.cFileName;
5620
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5621
    FindClose(hFindFile);
5622
    return result;
5623
}
5624
5625
5626
/*[clinic input]
5627
os._getvolumepathname
5628
5629
    path: path_t
5630
5631
A helper function for ismount on Win32.
5632
[clinic start generated code]*/
5633
5634
static PyObject *
5635
os__getvolumepathname_impl(PyObject *module, path_t *path)
5636
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5637
{
5638
    PyObject *result;
5639
    wchar_t *mountpath=NULL;
5640
    size_t buflen;
5641
    BOOL ret;
5642
5643
    /* Volume path should be shorter than entire path */
5644
    buflen = Py_MAX(path->length, MAX_PATH);
5645
5646
    if (buflen > PY_DWORD_MAX) {
5647
        PyErr_SetString(PyExc_OverflowError, "path too long");
5648
        return NULL;
5649
    }
5650
5651
    mountpath = PyMem_New(wchar_t, buflen);
5652
    if (mountpath == NULL)
5653
        return PyErr_NoMemory();
5654
5655
    Py_BEGIN_ALLOW_THREADS
5656
    ret = GetVolumePathNameW(path->wide, mountpath,
5657
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5658
    Py_END_ALLOW_THREADS
5659
5660
    if (!ret) {
5661
        result = win32_error_object("_getvolumepathname", path->object);
5662
        goto exit;
5663
    }
5664
    result = PyUnicode_FromWideChar(mountpath, -1);
5665
    if (PyBytes_Check(path->object))
5666
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5667
5668
exit:
5669
    PyMem_Free(mountpath);
5670
    return result;
5671
}
5672
5673
5674
/*[clinic input]
5675
os._path_splitroot
5676
5677
    path: path_t
5678
    /
5679
5680
Removes everything after the root on Win32.
5681
[clinic start generated code]*/
5682
5683
static PyObject *
5684
os__path_splitroot_impl(PyObject *module, path_t *path)
5685
/*[clinic end generated code: output=ab7f1a88b654581c input=d356de1edb6050a2]*/
5686
{
5687
    wchar_t *buffer;
5688
    wchar_t *end;
5689
    PyObject *result = NULL;
5690
    HRESULT ret;
5691
5692
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5693
    if (!buffer) {
5694
        return PyErr_NoMemory();
5695
    }
5696
    wcscpy(buffer, path->wide);
5697
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5698
        *p = L'\\';
5699
    }
5700
5701
    Py_BEGIN_ALLOW_THREADS
5702
    ret = PathCchSkipRoot(buffer, &end);
5703
    Py_END_ALLOW_THREADS
5704
    if (FAILED(ret)) {
5705
        result = Py_BuildValue("sO", "", path->object);
5706
    } else if (end != buffer) {
5707
        size_t rootLen = (size_t)(end - buffer);
5708
        result = Py_BuildValue("NN",
5709
            PyUnicode_FromWideChar(path->wide, rootLen),
5710
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5711
        );
5712
    } else {
5713
        result = Py_BuildValue("Os", path->object, "");
5714
    }
5715
    PyMem_Free(buffer);
5716
5717
    return result;
5718
}
5719
5720
5721
#define PY_IFREG  1 // Regular file
5722
#define PY_IFDIR  2 // Directory
5723
#define PY_IFLNK  4 // Symlink
5724
#define PY_IFMNT  8 // Mount Point (junction)
5725
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5726
#define PY_IFRRP 32 // Regular Reparse Point
5727
5728
static inline BOOL
5729
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5730
{
5731
    switch (testedType) {
5732
    case PY_IFREG:
5733
        return diskDevice && attributes &&
5734
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5735
    case PY_IFDIR:
5736
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5737
    case PY_IFLNK:
5738
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5739
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5740
    case PY_IFMNT:
5741
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5742
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5743
    case PY_IFLRP:
5744
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5745
               IsReparseTagNameSurrogate(reparseTag);
5746
    case PY_IFRRP:
5747
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5748
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5749
    }
5750
5751
    return FALSE;
5752
}
5753
5754
static BOOL
5755
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5756
{
5757
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5758
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5759
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5760
5761
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5762
    if (diskOnly && !diskDevice) {
5763
        return FALSE;
5764
    }
5765
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5766
        FILE_ATTRIBUTE_TAG_INFO info;
5767
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5768
                                            sizeof(info)) &&
5769
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5770
                         testedType);
5771
    }
5772
    FILE_BASIC_INFO info;
5773
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5774
                                        sizeof(info)) &&
5775
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5776
}
5777
5778
static BOOL
5779
_testFileTypeByName(LPCWSTR path, int testedType)
5780
{
5781
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5782
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5783
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5784
5785
    FILE_STAT_BASIC_INFORMATION info;
5786
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5787
                                     sizeof(info)))
5788
    {
5789
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5790
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5791
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5792
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5793
                                diskDevice, testedType);
5794
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5795
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5796
        {
5797
            return result;
5798
        }
5799
    }
5800
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5801
                GetLastError()))
5802
    {
5803
        return FALSE;
5804
    }
5805
5806
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5807
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5808
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5809
    }
5810
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5811
                               OPEN_EXISTING, flags, NULL);
5812
    if (hfile != INVALID_HANDLE_VALUE) {
5813
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5814
        CloseHandle(hfile);
5815
        return result;
5816
    }
5817
5818
    switch (GetLastError()) {
5819
    case ERROR_ACCESS_DENIED:
5820
    case ERROR_SHARING_VIOLATION:
5821
    case ERROR_CANT_ACCESS_FILE:
5822
    case ERROR_INVALID_PARAMETER:
5823
        int rc;
5824
        STRUCT_STAT st;
5825
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5826
            rc = STAT(path, &st);
5827
        }
5828
        else {
5829
            // PY_IFRRP is not generally supported in this case, except for
5830
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5831
            rc = LSTAT(path, &st);
5832
        }
5833
        if (!rc) {
5834
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5835
                             st.st_mode & S_IFREG, testedType);
5836
        }
5837
    }
5838
5839
    return FALSE;
5840
}
5841
5842
5843
static BOOL
5844
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5845
{
5846
    FILE_STAT_BASIC_INFORMATION info;
5847
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5848
                                     sizeof(info)))
5849
    {
5850
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5851
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5852
        {
5853
            return TRUE;
5854
        }
5855
    }
5856
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5857
                    GetLastError()))
5858
    {
5859
        return FALSE;
5860
    }
5861
5862
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5863
    if (!followLinks) {
5864
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5865
    }
5866
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5867
                               OPEN_EXISTING, flags, NULL);
5868
    if (hfile != INVALID_HANDLE_VALUE) {
5869
        if (followLinks) {
5870
            CloseHandle(hfile);
5871
            return TRUE;
5872
        }
5873
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5874
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5875
        CloseHandle(hfile);
5876
        if (!result) {
5877
            return TRUE;
5878
        }
5879
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5880
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5881
        if (hfile != INVALID_HANDLE_VALUE) {
5882
            CloseHandle(hfile);
5883
            return TRUE;
5884
        }
5885
    }
5886
5887
    switch (GetLastError()) {
5888
    case ERROR_ACCESS_DENIED:
5889
    case ERROR_SHARING_VIOLATION:
5890
    case ERROR_CANT_ACCESS_FILE:
5891
    case ERROR_INVALID_PARAMETER:
5892
        STRUCT_STAT _st;
5893
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5894
    }
5895
5896
    return FALSE;
5897
}
5898
5899
5900
static BOOL
5901
_testFileExists(path_t *path, BOOL followLinks)
5902
{
5903
    BOOL result = FALSE;
5904
    if (path->value_error) {
5905
        return FALSE;
5906
    }
5907
5908
    Py_BEGIN_ALLOW_THREADS
5909
    if (path->is_fd) {
5910
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5911
        if (hfile != INVALID_HANDLE_VALUE) {
5912
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5913
                result = TRUE;
5914
            }
5915
        }
5916
    }
5917
    else if (path->wide) {
5918
        result = _testFileExistsByName(path->wide, followLinks);
5919
    }
5920
    Py_END_ALLOW_THREADS
5921
5922
    return result;
5923
}
5924
5925
5926
static BOOL
5927
_testFileType(path_t *path, int testedType)
5928
{
5929
    BOOL result = FALSE;
5930
    if (path->value_error) {
5931
        return FALSE;
5932
    }
5933
5934
    Py_BEGIN_ALLOW_THREADS
5935
    if (path->is_fd) {
5936
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5937
        if (hfile != INVALID_HANDLE_VALUE) {
5938
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5939
        }
5940
    }
5941
    else if (path->wide) {
5942
        result = _testFileTypeByName(path->wide, testedType);
5943
    }
5944
    Py_END_ALLOW_THREADS
5945
5946
    return result;
5947
}
5948
5949
5950
/*[clinic input]
5951
os._path_exists -> bool
5952
5953
    path: path_t(allow_fd=True, suppress_value_error=True)
5954
5955
Test whether a path exists.  Returns False for broken symbolic links.
5956
5957
[clinic start generated code]*/
5958
5959
static int
5960
os__path_exists_impl(PyObject *module, path_t *path)
5961
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5962
{
5963
    return _testFileExists(path, TRUE);
5964
}
5965
5966
5967
/*[clinic input]
5968
os._path_lexists -> bool
5969
5970
    path: path_t(allow_fd=True, suppress_value_error=True)
5971
5972
Test whether a path exists.  Returns True for broken symbolic links.
5973
5974
[clinic start generated code]*/
5975
5976
static int
5977
os__path_lexists_impl(PyObject *module, path_t *path)
5978
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5979
{
5980
    return _testFileExists(path, FALSE);
5981
}
5982
5983
5984
/*[clinic input]
5985
os._path_isdir -> bool
5986
5987
    path: path_t(allow_fd=True, suppress_value_error=True)
5988
    /
5989
5990
Return true if the pathname refers to an existing directory.
5991
5992
[clinic start generated code]*/
5993
5994
static int
5995
os__path_isdir_impl(PyObject *module, path_t *path)
5996
/*[clinic end generated code: output=d5786196f9e2fa7a input=b15f9b697a7a759f]*/
5997
{
5998
    return _testFileType(path, PY_IFDIR);
5999
}
6000
6001
6002
/*[clinic input]
6003
os._path_isfile -> bool
6004
6005
    path: path_t(allow_fd=True, suppress_value_error=True)
6006
6007
Test whether a path is a regular file
6008
6009
[clinic start generated code]*/
6010
6011
static int
6012
os__path_isfile_impl(PyObject *module, path_t *path)
6013
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6014
{
6015
    return _testFileType(path, PY_IFREG);
6016
}
6017
6018
6019
/*[clinic input]
6020
os._path_islink -> bool
6021
6022
    path: path_t(allow_fd=True, suppress_value_error=True)
6023
6024
Test whether a path is a symbolic link
6025
6026
[clinic start generated code]*/
6027
6028
static int
6029
os__path_islink_impl(PyObject *module, path_t *path)
6030
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6031
{
6032
    return _testFileType(path, PY_IFLNK);
6033
}
6034
6035
6036
/*[clinic input]
6037
os._path_isjunction -> bool
6038
6039
    path: path_t(allow_fd=True, suppress_value_error=True)
6040
6041
Test whether a path is a junction
6042
6043
[clinic start generated code]*/
6044
6045
static int
6046
os__path_isjunction_impl(PyObject *module, path_t *path)
6047
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6048
{
6049
    return _testFileType(path, PY_IFMNT);
6050
}
6051
6052
#undef PY_IFREG
6053
#undef PY_IFDIR
6054
#undef PY_IFLNK
6055
#undef PY_IFMNT
6056
#undef PY_IFLRP
6057
#undef PY_IFRRP
6058
6059
#endif /* MS_WINDOWS */
6060
6061
6062
/*[clinic input]
6063
os._path_splitroot_ex
6064
6065
    path: path_t(make_wide=True, nonstrict=True)
6066
    /
6067
6068
Split a pathname into drive, root and tail.
6069
6070
The tail contains anything after the root.
6071
[clinic start generated code]*/
6072
6073
static PyObject *
6074
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6075
/*[clinic end generated code: output=4b0072b6cdf4b611 input=012fbfad14888b2b]*/
6076
132k
{
6077
132k
    Py_ssize_t drvsize, rootsize;
6078
132k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6079
6080
132k
    const wchar_t *buffer = path->wide;
6081
132k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6082
132k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6083
132k
    if (drv == NULL) {
6084
0
        goto exit;
6085
0
    }
6086
132k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6087
132k
    if (root == NULL) {
6088
0
        goto exit;
6089
0
    }
6090
132k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6091
132k
                                  path->length - drvsize - rootsize);
6092
132k
    if (tail == NULL) {
6093
0
        goto exit;
6094
0
    }
6095
132k
    if (PyBytes_Check(path->object)) {
6096
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6097
0
        if (drv == NULL) {
6098
0
            goto exit;
6099
0
        }
6100
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6101
0
        if (root == NULL) {
6102
0
            goto exit;
6103
0
        }
6104
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6105
0
        if (tail == NULL) {
6106
0
            goto exit;
6107
0
        }
6108
0
    }
6109
132k
    result = PyTuple_Pack(3, drv, root, tail);
6110
132k
exit:
6111
132k
    Py_XDECREF(drv);
6112
132k
    Py_XDECREF(root);
6113
132k
    Py_XDECREF(tail);
6114
132k
    return result;
6115
132k
}
6116
6117
6118
/*[clinic input]
6119
os._path_normpath
6120
6121
    path: path_t(make_wide=True, nonstrict=True)
6122
6123
Normalize path, eliminating double slashes, etc.
6124
[clinic start generated code]*/
6125
6126
static PyObject *
6127
os__path_normpath_impl(PyObject *module, path_t *path)
6128
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6129
26.7k
{
6130
26.7k
    PyObject *result;
6131
26.7k
    Py_ssize_t norm_len;
6132
26.7k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6133
26.7k
                                               path->length, &norm_len);
6134
26.7k
    if (!norm_len) {
6135
0
        result = PyUnicode_FromOrdinal('.');
6136
0
    }
6137
26.7k
    else {
6138
26.7k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6139
26.7k
    }
6140
26.7k
    if (result == NULL) {
6141
0
        return NULL;
6142
0
    }
6143
26.7k
    if (PyBytes_Check(path->object)) {
6144
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6145
0
    }
6146
26.7k
    return result;
6147
26.7k
}
6148
6149
/*[clinic input]
6150
os.mkdir
6151
6152
    path : path_t
6153
6154
    mode: int = 0o777
6155
6156
    *
6157
6158
    dir_fd : dir_fd(requires='mkdirat') = None
6159
6160
Create a directory.
6161
6162
If dir_fd is not None, it should be a file descriptor open to
6163
a directory, and path should be relative; path will then be relative to
6164
that directory.
6165
dir_fd may not be implemented on your platform.  If it is unavailable,
6166
using it will raise a NotImplementedError.
6167
6168
The mode argument is ignored on Windows.  Where it is used, the current
6169
umask value is first masked out.
6170
[clinic start generated code]*/
6171
6172
static PyObject *
6173
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6174
/*[clinic end generated code: output=a70446903abe821f input=30270d369599634b]*/
6175
91.4k
{
6176
91.4k
    int result;
6177
#ifdef MS_WINDOWS
6178
    int error = 0;
6179
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6180
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6181
#endif
6182
91.4k
#ifdef HAVE_MKDIRAT
6183
91.4k
    int mkdirat_unavailable = 0;
6184
91.4k
#endif
6185
6186
91.4k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6187
91.4k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6188
0
        return NULL;
6189
0
    }
6190
6191
#ifdef MS_WINDOWS
6192
    Py_BEGIN_ALLOW_THREADS
6193
    // For API sets that don't support these APIs, we have no choice
6194
    // but to silently create a directory with default ACL.
6195
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6196
    if (mode == 0700 /* 0o700 */) {
6197
        ULONG sdSize;
6198
        pSecAttr = &secAttr;
6199
        // Set a discretionary ACL (D) that is protected (P) and includes
6200
        // inheritable (OICI) entries that allow (A) full control (FA) to
6201
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6202
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6203
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6204
            SDDL_REVISION_1,
6205
            &secAttr.lpSecurityDescriptor,
6206
            &sdSize
6207
        )) {
6208
            error = GetLastError();
6209
        }
6210
    }
6211
#endif
6212
    if (!error) {
6213
        result = CreateDirectoryW(path->wide, pSecAttr);
6214
        if (secAttr.lpSecurityDescriptor &&
6215
            // uncommonly, LocalFree returns non-zero on error, but still uses
6216
            // GetLastError() to see what the error code is
6217
            LocalFree(secAttr.lpSecurityDescriptor)) {
6218
            error = GetLastError();
6219
        }
6220
    }
6221
    Py_END_ALLOW_THREADS
6222
6223
    if (error) {
6224
        return PyErr_SetFromWindowsErr(error);
6225
    }
6226
    if (!result) {
6227
        return path_error(path);
6228
    }
6229
#else
6230
91.4k
    Py_BEGIN_ALLOW_THREADS
6231
91.4k
#if HAVE_MKDIRAT
6232
91.4k
    if (dir_fd != DEFAULT_DIR_FD) {
6233
0
      if (HAVE_MKDIRAT_RUNTIME) {
6234
0
        result = mkdirat(dir_fd, path->narrow, mode);
6235
6236
0
      } else {
6237
0
        mkdirat_unavailable = 1;
6238
0
      }
6239
0
    } else
6240
91.4k
#endif
6241
#if defined(__WATCOMC__) && !defined(__QNX__)
6242
        result = mkdir(path->narrow);
6243
#else
6244
91.4k
        result = mkdir(path->narrow, mode);
6245
91.4k
#endif
6246
91.4k
    Py_END_ALLOW_THREADS
6247
6248
91.4k
#if HAVE_MKDIRAT
6249
91.4k
    if (mkdirat_unavailable) {
6250
0
        argument_unavailable_error(NULL, "dir_fd");
6251
0
        return NULL;
6252
0
    }
6253
91.4k
#endif
6254
6255
91.4k
    if (result < 0)
6256
330
        return path_error(path);
6257
91.1k
#endif /* MS_WINDOWS */
6258
91.4k
    Py_RETURN_NONE;
6259
91.4k
}
6260
6261
6262
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6263
#if defined(HAVE_SYS_RESOURCE_H)
6264
#include <sys/resource.h>
6265
#endif
6266
6267
6268
#ifdef HAVE_NICE
6269
/*[clinic input]
6270
os.nice
6271
6272
    increment: int
6273
    /
6274
6275
Add increment to the priority of process and return the new priority.
6276
[clinic start generated code]*/
6277
6278
static PyObject *
6279
os_nice_impl(PyObject *module, int increment)
6280
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6281
0
{
6282
0
    int value;
6283
6284
    /* There are two flavours of 'nice': one that returns the new
6285
       priority (as required by almost all standards out there) and the
6286
       Linux/FreeBSD one, which returns '0' on success and advices
6287
       the use of getpriority() to get the new priority.
6288
6289
       If we are of the nice family that returns the new priority, we
6290
       need to clear errno before the call, and check if errno is filled
6291
       before calling posix_error() on a returnvalue of -1, because the
6292
       -1 may be the actual new priority! */
6293
6294
0
    errno = 0;
6295
0
    value = nice(increment);
6296
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6297
    if (value == 0)
6298
        value = getpriority(PRIO_PROCESS, 0);
6299
#endif
6300
0
    if (value == -1 && errno != 0)
6301
        /* either nice() or getpriority() returned an error */
6302
0
        return posix_error();
6303
0
    return PyLong_FromLong((long) value);
6304
0
}
6305
#endif /* HAVE_NICE */
6306
6307
6308
#ifdef HAVE_GETPRIORITY
6309
/*[clinic input]
6310
os.getpriority
6311
6312
    which: int
6313
    who: int
6314
6315
Return program scheduling priority.
6316
[clinic start generated code]*/
6317
6318
static PyObject *
6319
os_getpriority_impl(PyObject *module, int which, int who)
6320
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6321
0
{
6322
0
    int retval;
6323
6324
0
    errno = 0;
6325
0
    retval = getpriority(which, who);
6326
0
    if (errno != 0)
6327
0
        return posix_error();
6328
0
    return PyLong_FromLong((long)retval);
6329
0
}
6330
#endif /* HAVE_GETPRIORITY */
6331
6332
6333
#ifdef HAVE_SETPRIORITY
6334
/*[clinic input]
6335
os.setpriority
6336
6337
    which: int
6338
    who: int
6339
    priority: int
6340
6341
Set program scheduling priority.
6342
[clinic start generated code]*/
6343
6344
static PyObject *
6345
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6346
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6347
0
{
6348
0
    int retval;
6349
6350
0
    retval = setpriority(which, who, priority);
6351
0
    if (retval == -1)
6352
0
        return posix_error();
6353
0
    Py_RETURN_NONE;
6354
0
}
6355
#endif /* HAVE_SETPRIORITY */
6356
6357
6358
static PyObject *
6359
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6360
142
{
6361
142
    const char *function_name = is_replace ? "replace" : "rename";
6362
142
    int dir_fd_specified;
6363
6364
142
#ifdef HAVE_RENAMEAT
6365
142
    int renameat_unavailable = 0;
6366
142
#endif
6367
6368
#ifdef MS_WINDOWS
6369
    BOOL result;
6370
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6371
#else
6372
142
    int result;
6373
142
#endif
6374
6375
142
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6376
142
                       (dst_dir_fd != DEFAULT_DIR_FD);
6377
#ifndef HAVE_RENAMEAT
6378
    if (dir_fd_specified) {
6379
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6380
        return NULL;
6381
    }
6382
#endif
6383
6384
142
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6385
142
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6386
142
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6387
0
        return NULL;
6388
0
    }
6389
6390
#ifdef MS_WINDOWS
6391
    Py_BEGIN_ALLOW_THREADS
6392
    result = MoveFileExW(src->wide, dst->wide, flags);
6393
    Py_END_ALLOW_THREADS
6394
6395
    if (!result)
6396
        return path_error2(src, dst);
6397
6398
#else
6399
142
    Py_BEGIN_ALLOW_THREADS
6400
142
#ifdef HAVE_RENAMEAT
6401
142
    if (dir_fd_specified) {
6402
0
        if (HAVE_RENAMEAT_RUNTIME) {
6403
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6404
0
        } else {
6405
0
            renameat_unavailable = 1;
6406
0
        }
6407
0
    } else
6408
142
#endif
6409
142
    result = rename(src->narrow, dst->narrow);
6410
142
    Py_END_ALLOW_THREADS
6411
6412
6413
142
#ifdef HAVE_RENAMEAT
6414
142
    if (renameat_unavailable) {
6415
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6416
0
        return NULL;
6417
0
    }
6418
142
#endif
6419
6420
142
    if (result)
6421
0
        return path_error2(src, dst);
6422
142
#endif
6423
142
    Py_RETURN_NONE;
6424
142
}
6425
6426
6427
/*[clinic input]
6428
os.rename
6429
6430
    src : path_t
6431
    dst : path_t
6432
    *
6433
    src_dir_fd : dir_fd = None
6434
    dst_dir_fd : dir_fd = None
6435
6436
Rename a file or directory.
6437
6438
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6439
descriptor open to a directory, and the respective path string (src or
6440
dst) should be relative; the path will then be relative to that
6441
directory.
6442
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6443
If they are unavailable, using them will raise a NotImplementedError.
6444
[clinic start generated code]*/
6445
6446
static PyObject *
6447
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6448
               int dst_dir_fd)
6449
/*[clinic end generated code: output=59e803072cf41230 input=7d320d687c715fd6]*/
6450
5
{
6451
5
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6452
5
}
6453
6454
6455
/*[clinic input]
6456
os.replace = os.rename
6457
6458
Rename a file or directory, overwriting the destination.
6459
6460
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6461
descriptor open to a directory, and the respective path string (src or
6462
dst) should be relative; the path will then be relative to that
6463
directory.
6464
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6465
If they are unavailable, using them will raise a NotImplementedError.
6466
[clinic start generated code]*/
6467
6468
static PyObject *
6469
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6470
                int dst_dir_fd)
6471
/*[clinic end generated code: output=1968c02e7857422b input=44ed6b762d5953fc]*/
6472
137
{
6473
137
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6474
137
}
6475
6476
6477
/*[clinic input]
6478
os.rmdir
6479
6480
    path: path_t
6481
    *
6482
    dir_fd: dir_fd(requires='unlinkat') = None
6483
6484
Remove a directory.
6485
6486
If dir_fd is not None, it should be a file descriptor open to
6487
a directory, and path should be relative; path will then be relative
6488
to that directory.
6489
dir_fd may not be implemented on your platform.
6490
If it is unavailable, using it will raise a NotImplementedError.
6491
[clinic start generated code]*/
6492
6493
static PyObject *
6494
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6495
/*[clinic end generated code: output=080eb54f506e8301 input=84325211e33a98e0]*/
6496
91.1k
{
6497
91.1k
    int result;
6498
91.1k
#ifdef HAVE_UNLINKAT
6499
91.1k
    int unlinkat_unavailable = 0;
6500
91.1k
#endif
6501
6502
91.1k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6503
91.1k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6504
0
        return NULL;
6505
0
    }
6506
6507
91.1k
    Py_BEGIN_ALLOW_THREADS
6508
#ifdef MS_WINDOWS
6509
    /* Windows, success=1, UNIX, success=0 */
6510
    result = !RemoveDirectoryW(path->wide);
6511
#else
6512
91.1k
#ifdef HAVE_UNLINKAT
6513
91.1k
    if (dir_fd != DEFAULT_DIR_FD) {
6514
86.8k
      if (HAVE_UNLINKAT_RUNTIME) {
6515
86.8k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6516
86.8k
      } else {
6517
0
        unlinkat_unavailable = 1;
6518
0
        result = -1;
6519
0
      }
6520
86.8k
    } else
6521
4.30k
#endif
6522
4.30k
        result = rmdir(path->narrow);
6523
91.1k
#endif
6524
91.1k
    Py_END_ALLOW_THREADS
6525
6526
91.1k
#ifdef HAVE_UNLINKAT
6527
91.1k
    if (unlinkat_unavailable) {
6528
0
        argument_unavailable_error("rmdir", "dir_fd");
6529
0
        return NULL;
6530
0
    }
6531
91.1k
#endif
6532
6533
91.1k
    if (result)
6534
5
        return path_error(path);
6535
6536
91.1k
    Py_RETURN_NONE;
6537
91.1k
}
6538
6539
6540
#ifdef HAVE_SYSTEM
6541
#ifdef MS_WINDOWS
6542
/*[clinic input]
6543
os.system -> long
6544
6545
    command: Py_UNICODE
6546
6547
Execute the command in a subshell.
6548
[clinic start generated code]*/
6549
6550
static long
6551
os_system_impl(PyObject *module, const wchar_t *command)
6552
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6553
{
6554
    long result;
6555
6556
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6557
        return -1;
6558
    }
6559
6560
    Py_BEGIN_ALLOW_THREADS
6561
    _Py_BEGIN_SUPPRESS_IPH
6562
    result = _wsystem(command);
6563
    _Py_END_SUPPRESS_IPH
6564
    Py_END_ALLOW_THREADS
6565
    return result;
6566
}
6567
#else /* MS_WINDOWS */
6568
/*[clinic input]
6569
os.system -> long
6570
6571
    command: unicode_fs_encoded
6572
6573
Execute the command in a subshell.
6574
[clinic start generated code]*/
6575
6576
static long
6577
os_system_impl(PyObject *module, PyObject *command)
6578
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6579
0
{
6580
0
    long result;
6581
0
    const char *bytes = PyBytes_AsString(command);
6582
6583
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6584
0
        return -1;
6585
0
    }
6586
6587
0
    Py_BEGIN_ALLOW_THREADS
6588
0
    result = system(bytes);
6589
0
    Py_END_ALLOW_THREADS
6590
0
    return result;
6591
0
}
6592
#endif
6593
#endif /* HAVE_SYSTEM */
6594
6595
6596
#ifdef HAVE_UMASK
6597
/*[clinic input]
6598
os.umask
6599
6600
    mask: int
6601
    /
6602
6603
Set the current numeric umask and return the previous umask.
6604
[clinic start generated code]*/
6605
6606
static PyObject *
6607
os_umask_impl(PyObject *module, int mask)
6608
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6609
0
{
6610
0
    int i = (int)umask(mask);
6611
0
    if (i < 0)
6612
0
        return posix_error();
6613
0
    return PyLong_FromLong((long)i);
6614
0
}
6615
#endif
6616
6617
#ifdef MS_WINDOWS
6618
6619
/* override the default DeleteFileW behavior so that directory
6620
symlinks can be removed with this function, the same as with
6621
Unix symlinks */
6622
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6623
{
6624
    WIN32_FILE_ATTRIBUTE_DATA info;
6625
    WIN32_FIND_DATAW find_data;
6626
    HANDLE find_data_handle;
6627
    int is_directory = 0;
6628
    int is_link = 0;
6629
6630
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6631
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6632
6633
        /* Get WIN32_FIND_DATA structure for the path to determine if
6634
           it is a symlink */
6635
        if(is_directory &&
6636
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6637
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6638
6639
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6640
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6641
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6642
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6643
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6644
                FindClose(find_data_handle);
6645
            }
6646
        }
6647
    }
6648
6649
    if (is_directory && is_link)
6650
        return RemoveDirectoryW(lpFileName);
6651
6652
    return DeleteFileW(lpFileName);
6653
}
6654
#endif /* MS_WINDOWS */
6655
6656
6657
/*[clinic input]
6658
os.unlink
6659
6660
    path: path_t
6661
    *
6662
    dir_fd: dir_fd(requires='unlinkat')=None
6663
6664
Remove a file (same as remove()).
6665
6666
If dir_fd is not None, it should be a file descriptor open to
6667
a directory, and path should be relative; path will then be relative to
6668
that directory.
6669
dir_fd may not be implemented on your platform.
6670
If it is unavailable, using it will raise a NotImplementedError.
6671
6672
[clinic start generated code]*/
6673
6674
static PyObject *
6675
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6676
/*[clinic end generated code: output=621797807b9963b1 input=1a2ef2579207eab1]*/
6677
18.0k
{
6678
18.0k
    int result;
6679
18.0k
#ifdef HAVE_UNLINKAT
6680
18.0k
    int unlinkat_unavailable = 0;
6681
18.0k
#endif
6682
6683
18.0k
    if (PySys_Audit("os.remove", "Oi", path->object,
6684
18.0k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6685
0
        return NULL;
6686
0
    }
6687
6688
18.0k
    Py_BEGIN_ALLOW_THREADS
6689
18.0k
    _Py_BEGIN_SUPPRESS_IPH
6690
#ifdef MS_WINDOWS
6691
    /* Windows, success=1, UNIX, success=0 */
6692
    result = !Py_DeleteFileW(path->wide);
6693
#else
6694
18.0k
#ifdef HAVE_UNLINKAT
6695
18.0k
    if (dir_fd != DEFAULT_DIR_FD) {
6696
18.0k
      if (HAVE_UNLINKAT_RUNTIME) {
6697
6698
18.0k
        result = unlinkat(dir_fd, path->narrow, 0);
6699
18.0k
      } else {
6700
0
        unlinkat_unavailable = 1;
6701
0
      }
6702
18.0k
    } else
6703
2
#endif /* HAVE_UNLINKAT */
6704
2
        result = unlink(path->narrow);
6705
18.0k
#endif
6706
18.0k
    _Py_END_SUPPRESS_IPH
6707
18.0k
    Py_END_ALLOW_THREADS
6708
6709
18.0k
#ifdef HAVE_UNLINKAT
6710
18.0k
    if (unlinkat_unavailable) {
6711
0
        argument_unavailable_error(NULL, "dir_fd");
6712
0
        return NULL;
6713
0
    }
6714
18.0k
#endif
6715
6716
18.0k
    if (result)
6717
0
        return path_error(path);
6718
6719
18.0k
    Py_RETURN_NONE;
6720
18.0k
}
6721
6722
6723
/*[clinic input]
6724
os.remove = os.unlink
6725
6726
Remove a file (same as unlink()).
6727
6728
If dir_fd is not None, it should be a file descriptor open to
6729
a directory, and path should be relative; path will then be relative
6730
to that directory.
6731
dir_fd may not be implemented on your platform.
6732
If it is unavailable, using it will raise a NotImplementedError.
6733
[clinic start generated code]*/
6734
6735
static PyObject *
6736
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6737
/*[clinic end generated code: output=a8535b28f0068883 input=9f6e66912126bd56]*/
6738
0
{
6739
0
    return os_unlink_impl(module, path, dir_fd);
6740
0
}
6741
6742
6743
static PyStructSequence_Field uname_result_fields[] = {
6744
    {"sysname",    "operating system name"},
6745
    {"nodename",   "name of machine on network (implementation-defined)"},
6746
    {"release",    "operating system release"},
6747
    {"version",    "operating system version"},
6748
    {"machine",    "hardware identifier"},
6749
    {NULL}
6750
};
6751
6752
PyDoc_STRVAR(uname_result__doc__,
6753
"uname_result: Result from os.uname().\n\n\
6754
This object may be accessed either as a tuple of\n\
6755
  (sysname, nodename, release, version, machine),\n\
6756
or via the attributes sysname, nodename, release, version, and machine.\n\
6757
\n\
6758
See os.uname for more information.");
6759
6760
static PyStructSequence_Desc uname_result_desc = {
6761
    MODNAME ".uname_result", /* name */
6762
    uname_result__doc__, /* doc */
6763
    uname_result_fields,
6764
    5
6765
};
6766
6767
#ifdef HAVE_UNAME
6768
/*[clinic input]
6769
os.uname
6770
6771
Return an object identifying the current operating system.
6772
6773
The object behaves like a named tuple with the following fields:
6774
  (sysname, nodename, release, version, machine)
6775
6776
[clinic start generated code]*/
6777
6778
static PyObject *
6779
os_uname_impl(PyObject *module)
6780
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6781
4
{
6782
4
    struct utsname u;
6783
4
    int res;
6784
4
    PyObject *value;
6785
6786
4
    Py_BEGIN_ALLOW_THREADS
6787
4
    res = uname(&u);
6788
4
    Py_END_ALLOW_THREADS
6789
4
    if (res < 0)
6790
0
        return posix_error();
6791
6792
4
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6793
4
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6794
4
    if (value == NULL)
6795
0
        return NULL;
6796
6797
4
#define SET(i, field) \
6798
20
    { \
6799
20
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6800
20
    if (!o) { \
6801
0
        Py_DECREF(value); \
6802
0
        return NULL; \
6803
0
    } \
6804
20
    PyStructSequence_SET_ITEM(value, i, o); \
6805
20
    } \
6806
4
6807
8
    SET(0, u.sysname);
6808
8
    SET(1, u.nodename);
6809
4
    SET(2, u.release);
6810
4
    SET(3, u.version);
6811
4
    SET(4, u.machine);
6812
6813
4
#undef SET
6814
6815
4
    return value;
6816
4
}
6817
#endif /* HAVE_UNAME */
6818
6819
6820
6821
typedef struct {
6822
    int    now;
6823
    time_t atime_s;
6824
    long   atime_ns;
6825
    time_t mtime_s;
6826
    long   mtime_ns;
6827
} utime_t;
6828
6829
/*
6830
 * these macros assume that "ut" is a pointer to a utime_t
6831
 * they also intentionally leak the declaration of a pointer named "time"
6832
 */
6833
#define UTIME_TO_TIMESPEC \
6834
0
    struct timespec ts[2]; \
6835
0
    struct timespec *time; \
6836
0
    if (ut->now) \
6837
0
        time = NULL; \
6838
0
    else { \
6839
0
        ts[0].tv_sec = ut->atime_s; \
6840
0
        ts[0].tv_nsec = ut->atime_ns; \
6841
0
        ts[1].tv_sec = ut->mtime_s; \
6842
0
        ts[1].tv_nsec = ut->mtime_ns; \
6843
0
        time = ts; \
6844
0
    } \
6845
6846
#define UTIME_TO_TIMEVAL \
6847
0
    struct timeval tv[2]; \
6848
0
    struct timeval *time; \
6849
0
    if (ut->now) \
6850
0
        time = NULL; \
6851
0
    else { \
6852
0
        tv[0].tv_sec = ut->atime_s; \
6853
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6854
0
        tv[1].tv_sec = ut->mtime_s; \
6855
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6856
0
        time = tv; \
6857
0
    } \
6858
6859
#define UTIME_TO_UTIMBUF \
6860
    struct utimbuf u; \
6861
    struct utimbuf *time; \
6862
    if (ut->now) \
6863
        time = NULL; \
6864
    else { \
6865
        u.actime = ut->atime_s; \
6866
        u.modtime = ut->mtime_s; \
6867
        time = &u; \
6868
    }
6869
6870
#define UTIME_TO_TIME_T \
6871
    time_t timet[2]; \
6872
    time_t *time; \
6873
    if (ut->now) \
6874
        time = NULL; \
6875
    else { \
6876
        timet[0] = ut->atime_s; \
6877
        timet[1] = ut->mtime_s; \
6878
        time = timet; \
6879
    } \
6880
6881
6882
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6883
6884
static int
6885
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6886
0
{
6887
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6888
    if (HAVE_UTIMENSAT_RUNTIME) {
6889
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6890
        UTIME_TO_TIMESPEC;
6891
        return utimensat(dir_fd, path, time, flags);
6892
    }  else {
6893
        errno = ENOSYS;
6894
        return -1;
6895
    }
6896
#elif defined(HAVE_UTIMENSAT)
6897
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6898
0
    UTIME_TO_TIMESPEC;
6899
0
    return utimensat(dir_fd, path, time, flags);
6900
#elif defined(HAVE_FUTIMESAT)
6901
    UTIME_TO_TIMEVAL;
6902
    /*
6903
     * follow_symlinks will never be false here;
6904
     * we only allow !follow_symlinks and dir_fd together
6905
     * if we have utimensat()
6906
     */
6907
    assert(follow_symlinks);
6908
    return futimesat(dir_fd, path, time);
6909
#endif
6910
0
}
6911
6912
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6913
#else
6914
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6915
#endif
6916
6917
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6918
6919
static int
6920
utime_fd(utime_t *ut, int fd)
6921
0
{
6922
0
#ifdef HAVE_FUTIMENS
6923
6924
0
    if (HAVE_FUTIMENS_RUNTIME) {
6925
6926
0
    UTIME_TO_TIMESPEC;
6927
0
    return futimens(fd, time);
6928
6929
0
    } else
6930
#ifndef HAVE_FUTIMES
6931
    {
6932
        /* Not sure if this can happen */
6933
        PyErr_SetString(
6934
            PyExc_RuntimeError,
6935
            "neither futimens nor futimes are supported"
6936
            " on this system");
6937
        return -1;
6938
    }
6939
#endif
6940
6941
0
#endif
6942
0
#ifdef HAVE_FUTIMES
6943
0
    {
6944
0
    UTIME_TO_TIMEVAL;
6945
0
    return futimes(fd, time);
6946
0
    }
6947
0
#endif
6948
0
}
6949
6950
    #define PATH_UTIME_HAVE_FD 1
6951
#else
6952
    #define PATH_UTIME_HAVE_FD 0
6953
#endif
6954
6955
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6956
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6957
#endif
6958
6959
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6960
6961
static int
6962
utime_nofollow_symlinks(utime_t *ut, const char *path)
6963
0
{
6964
0
#ifdef HAVE_UTIMENSAT
6965
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6966
0
        UTIME_TO_TIMESPEC;
6967
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6968
0
    } else
6969
#ifndef HAVE_LUTIMES
6970
    {
6971
        /* Not sure if this can happen */
6972
        PyErr_SetString(
6973
            PyExc_RuntimeError,
6974
            "neither utimensat nor lutimes are supported"
6975
            " on this system");
6976
        return -1;
6977
    }
6978
#endif
6979
0
#endif
6980
6981
0
#ifdef HAVE_LUTIMES
6982
0
    {
6983
0
    UTIME_TO_TIMEVAL;
6984
0
    return lutimes(path, time);
6985
0
    }
6986
0
#endif
6987
0
}
6988
6989
#endif
6990
6991
#ifndef MS_WINDOWS
6992
6993
static int
6994
utime_default(utime_t *ut, const char *path)
6995
0
{
6996
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6997
    if (HAVE_UTIMENSAT_RUNTIME) {
6998
        UTIME_TO_TIMESPEC;
6999
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
7000
    } else {
7001
        UTIME_TO_TIMEVAL;
7002
        return utimes(path, time);
7003
    }
7004
#elif defined(HAVE_UTIMENSAT)
7005
0
    UTIME_TO_TIMESPEC;
7006
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
7007
#elif defined(HAVE_UTIMES)
7008
    UTIME_TO_TIMEVAL;
7009
    return utimes(path, time);
7010
#elif defined(HAVE_UTIME_H)
7011
    UTIME_TO_UTIMBUF;
7012
    return utime(path, time);
7013
#else
7014
    UTIME_TO_TIME_T;
7015
    return utime(path, time);
7016
#endif
7017
0
}
7018
7019
#endif
7020
7021
static int
7022
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7023
0
{
7024
0
    int result = 0;
7025
0
    PyObject *divmod;
7026
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7027
0
    if (!divmod)
7028
0
        goto exit;
7029
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7030
0
        PyErr_Format(PyExc_TypeError,
7031
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7032
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7033
0
        goto exit;
7034
0
    }
7035
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7036
0
    if ((*s == -1) && PyErr_Occurred())
7037
0
        goto exit;
7038
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7039
0
    if ((*ns == -1) && PyErr_Occurred())
7040
0
        goto exit;
7041
7042
0
    result = 1;
7043
0
exit:
7044
0
    Py_XDECREF(divmod);
7045
0
    return result;
7046
0
}
7047
7048
7049
/*[clinic input]
7050
os.utime
7051
7052
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7053
    times: object = None
7054
    *
7055
    ns: object = NULL
7056
    dir_fd: dir_fd(requires='futimensat') = None
7057
    follow_symlinks: bool=True
7058
7059
Set the access and modified time of path.
7060
7061
path may always be specified as a string.  On some platforms, path may
7062
also be specified as an open file descriptor.  If this functionality is
7063
unavailable, using it raises an exception.
7064
7065
If times is not None, it must be a tuple (atime, mtime);
7066
atime and mtime should be expressed as float seconds since the epoch.
7067
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7068
atime_ns and mtime_ns should be expressed as integer nanoseconds
7069
since the epoch.
7070
If times is None and ns is unspecified, utime uses the current time.
7071
Specifying tuples for both times and ns is an error.
7072
7073
If dir_fd is not None, it should be a file descriptor open to
7074
a directory, and path should be relative; path will then be relative to
7075
that directory.
7076
If follow_symlinks is False, and the last element of the path is
7077
a symbolic link, utime will modify the symbolic link itself instead of
7078
the file the link points to.
7079
It is an error to use dir_fd or follow_symlinks when specifying path as
7080
an open file descriptor.
7081
dir_fd and follow_symlinks may not be available on your platform.
7082
If they are unavailable, using them will raise a NotImplementedError.
7083
7084
[clinic start generated code]*/
7085
7086
static PyObject *
7087
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7088
              int dir_fd, int follow_symlinks)
7089
/*[clinic end generated code: output=cfcac69d027b82cf input=5ab470b2bc250788]*/
7090
0
{
7091
#ifdef MS_WINDOWS
7092
    HANDLE hFile;
7093
    FILETIME atime, mtime;
7094
#else
7095
0
    int result;
7096
0
#endif
7097
7098
0
    utime_t utime;
7099
7100
0
    memset(&utime, 0, sizeof(utime_t));
7101
7102
0
    if (times != Py_None && ns) {
7103
0
        PyErr_SetString(PyExc_ValueError,
7104
0
                     "utime: you may specify either 'times'"
7105
0
                     " or 'ns' but not both");
7106
0
        return NULL;
7107
0
    }
7108
7109
0
    if (times != Py_None) {
7110
0
        time_t a_sec, m_sec;
7111
0
        long a_nsec, m_nsec;
7112
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7113
0
            PyErr_SetString(PyExc_TypeError,
7114
0
                         "utime: 'times' must be either"
7115
0
                         " a tuple of two numbers or None");
7116
0
            return NULL;
7117
0
        }
7118
0
        utime.now = 0;
7119
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7120
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7121
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7122
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7123
0
            return NULL;
7124
0
        }
7125
0
        utime.atime_s = a_sec;
7126
0
        utime.atime_ns = a_nsec;
7127
0
        utime.mtime_s = m_sec;
7128
0
        utime.mtime_ns = m_nsec;
7129
0
    }
7130
0
    else if (ns) {
7131
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7132
0
            PyErr_SetString(PyExc_TypeError,
7133
0
                         "utime: 'ns' must be a tuple of two ints");
7134
0
            return NULL;
7135
0
        }
7136
0
        utime.now = 0;
7137
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7138
0
                                      &utime.atime_s, &utime.atime_ns) ||
7139
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7140
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7141
0
            return NULL;
7142
0
        }
7143
0
    }
7144
0
    else {
7145
        /* times and ns are both None/unspecified. use "now". */
7146
0
        utime.now = 1;
7147
0
    }
7148
7149
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7150
    if (follow_symlinks_specified("utime", follow_symlinks))
7151
        return NULL;
7152
#endif
7153
7154
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7155
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7156
0
        fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
7157
0
        return NULL;
7158
7159
#if !defined(HAVE_UTIMENSAT)
7160
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7161
        PyErr_SetString(PyExc_ValueError,
7162
                     "utime: cannot use dir_fd and follow_symlinks "
7163
                     "together on this platform");
7164
        return NULL;
7165
    }
7166
#endif
7167
7168
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7169
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7170
0
        return NULL;
7171
0
    }
7172
7173
#ifdef MS_WINDOWS
7174
    Py_BEGIN_ALLOW_THREADS
7175
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7176
                        NULL, OPEN_EXISTING,
7177
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7178
    Py_END_ALLOW_THREADS
7179
    if (hFile == INVALID_HANDLE_VALUE) {
7180
        path_error(path);
7181
        return NULL;
7182
    }
7183
7184
    if (utime.now) {
7185
        GetSystemTimeAsFileTime(&mtime);
7186
        atime = mtime;
7187
    }
7188
    else {
7189
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7190
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7191
    }
7192
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7193
        path_error(path);
7194
        CloseHandle(hFile);
7195
        return NULL;
7196
    }
7197
    CloseHandle(hFile);
7198
#else /* MS_WINDOWS */
7199
0
    Py_BEGIN_ALLOW_THREADS
7200
7201
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7202
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7203
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7204
0
    else
7205
0
#endif
7206
7207
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7208
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7209
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7210
7211
0
    } else
7212
0
#endif
7213
7214
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7215
0
    if (path->is_fd)
7216
0
        result = utime_fd(&utime, path->fd);
7217
0
    else
7218
0
#endif
7219
7220
0
    result = utime_default(&utime, path->narrow);
7221
7222
0
    Py_END_ALLOW_THREADS
7223
7224
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7225
    /* See utime_dir_fd implementation */
7226
    if (result == -1 && errno == ENOSYS) {
7227
        argument_unavailable_error(NULL, "dir_fd");
7228
        return NULL;
7229
    }
7230
#endif
7231
7232
0
    if (result < 0) {
7233
0
        path_error(path);
7234
0
        return NULL;
7235
0
    }
7236
7237
0
#endif /* MS_WINDOWS */
7238
7239
0
    Py_RETURN_NONE;
7240
0
}
7241
7242
/* Process operations */
7243
7244
7245
/*[clinic input]
7246
@permit_long_summary
7247
os._exit
7248
7249
    status: int
7250
7251
Exit to the system with specified status, without normal exit processing.
7252
[clinic start generated code]*/
7253
7254
static PyObject *
7255
os__exit_impl(PyObject *module, int status)
7256
/*[clinic end generated code: output=116e52d9c2260d54 input=c35d282acfebe8fd]*/
7257
0
{
7258
0
    _exit(status);
7259
0
    return NULL; /* Make gcc -Wall happy */
7260
0
}
7261
7262
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7263
#define EXECV_CHAR wchar_t
7264
#else
7265
0
#define EXECV_CHAR char
7266
#endif
7267
7268
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7269
static void
7270
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7271
0
{
7272
0
    Py_ssize_t i;
7273
0
    for (i = 0; i < count; i++)
7274
0
        PyMem_Free(array[i]);
7275
0
    PyMem_Free(array);
7276
0
}
7277
7278
static int
7279
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7280
0
{
7281
0
    Py_ssize_t size;
7282
0
    PyObject *ub;
7283
0
    int result = 0;
7284
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7285
    if (!PyUnicode_FSDecoder(o, &ub))
7286
        return 0;
7287
    *out = PyUnicode_AsWideCharString(ub, &size);
7288
    if (*out)
7289
        result = 1;
7290
#else
7291
0
    if (!PyUnicode_FSConverter(o, &ub))
7292
0
        return 0;
7293
0
    size = PyBytes_GET_SIZE(ub);
7294
0
    *out = PyMem_Malloc(size + 1);
7295
0
    if (*out) {
7296
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7297
0
        result = 1;
7298
0
    } else
7299
0
        PyErr_NoMemory();
7300
0
#endif
7301
0
    Py_DECREF(ub);
7302
0
    return result;
7303
0
}
7304
#endif
7305
7306
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7307
static EXECV_CHAR**
7308
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7309
0
{
7310
0
    Py_ssize_t i, pos, envc;
7311
0
    PyObject *keys = NULL, *vals = NULL;
7312
0
    PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
7313
0
    EXECV_CHAR **envlist;
7314
7315
0
    i = PyMapping_Size(env);
7316
0
    if (i < 0)
7317
0
        return NULL;
7318
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7319
0
    if (envlist == NULL) {
7320
0
        PyErr_NoMemory();
7321
0
        return NULL;
7322
0
    }
7323
0
    envc = 0;
7324
0
    keys = PyMapping_Keys(env);
7325
0
    if (!keys)
7326
0
        goto error;
7327
0
    vals = PyMapping_Values(env);
7328
0
    if (!vals)
7329
0
        goto error;
7330
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7331
0
        PyErr_Format(PyExc_TypeError,
7332
0
                     "env.keys() or env.values() is not a list");
7333
0
        goto error;
7334
0
    }
7335
7336
0
    for (pos = 0; pos < i; pos++) {
7337
        // The 'key' and 'val' must be strong references because of
7338
        // possible side-effects by PyUnicode_FS{Converter,Decoder}().
7339
0
        key = PyList_GetItemRef(keys, pos);
7340
0
        if (key == NULL) {
7341
0
            goto error;
7342
0
        }
7343
0
        val = PyList_GetItemRef(vals, pos);
7344
0
        if (val == NULL) {
7345
0
            goto error;
7346
0
        }
7347
7348
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7349
        if (!PyUnicode_FSDecoder(key, &key2)) {
7350
            goto error;
7351
        }
7352
        if (!PyUnicode_FSDecoder(val, &val2)) {
7353
            goto error;
7354
        }
7355
        /* Search from index 1 because on Windows starting '=' is allowed for
7356
           defining hidden environment variables. */
7357
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7358
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7359
        {
7360
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7361
            goto error;
7362
        }
7363
        PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7364
#else
7365
0
        if (!PyUnicode_FSConverter(key, &key2)) {
7366
0
            goto error;
7367
0
        }
7368
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7369
0
            goto error;
7370
0
        }
7371
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7372
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7373
0
        {
7374
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7375
0
            goto error;
7376
0
        }
7377
0
        PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7378
0
                                              PyBytes_AS_STRING(val2));
7379
0
#endif
7380
0
        if (!keyval) {
7381
0
            goto error;
7382
0
        }
7383
7384
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7385
0
            Py_DECREF(keyval);
7386
0
            goto error;
7387
0
        }
7388
7389
0
        Py_CLEAR(key);
7390
0
        Py_CLEAR(val);
7391
0
        Py_CLEAR(key2);
7392
0
        Py_CLEAR(val2);
7393
0
        Py_DECREF(keyval);
7394
0
    }
7395
0
    Py_DECREF(vals);
7396
0
    Py_DECREF(keys);
7397
7398
0
    envlist[envc] = 0;
7399
0
    *envc_ptr = envc;
7400
0
    return envlist;
7401
7402
0
error:
7403
0
    Py_XDECREF(key);
7404
0
    Py_XDECREF(val);
7405
0
    Py_XDECREF(key2);
7406
0
    Py_XDECREF(val2);
7407
0
    Py_XDECREF(keys);
7408
0
    Py_XDECREF(vals);
7409
0
    free_string_array(envlist, envc);
7410
0
    return NULL;
7411
0
}
7412
7413
static EXECV_CHAR**
7414
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7415
0
{
7416
0
    int i;
7417
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7418
0
    if (argvlist == NULL) {
7419
0
        PyErr_NoMemory();
7420
0
        return NULL;
7421
0
    }
7422
0
    for (i = 0; i < *argc; i++) {
7423
0
        PyObject* item = PySequence_ITEM(argv, i);
7424
0
        if (item == NULL)
7425
0
            goto fail;
7426
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7427
0
            Py_DECREF(item);
7428
0
            goto fail;
7429
0
        }
7430
0
        Py_DECREF(item);
7431
0
    }
7432
0
    argvlist[*argc] = NULL;
7433
0
    return argvlist;
7434
0
fail:
7435
0
    *argc = i;
7436
0
    free_string_array(argvlist, *argc);
7437
0
    return NULL;
7438
0
}
7439
7440
#endif
7441
7442
7443
#ifdef HAVE_EXECV
7444
/*[clinic input]
7445
os.execv
7446
7447
    path: path_t
7448
        Path of executable file.
7449
    argv: object
7450
        Tuple or list of strings.
7451
    /
7452
7453
Execute an executable path with arguments, replacing current process.
7454
[clinic start generated code]*/
7455
7456
static PyObject *
7457
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7458
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7459
0
{
7460
0
    EXECV_CHAR **argvlist;
7461
0
    Py_ssize_t argc;
7462
7463
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7464
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7465
0
        PyErr_SetString(PyExc_RuntimeError,
7466
0
                        "exec not supported for isolated subinterpreters");
7467
0
        return NULL;
7468
0
    }
7469
7470
    /* execv has two arguments: (path, argv), where
7471
       argv is a list or tuple of strings. */
7472
7473
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7474
0
        PyErr_SetString(PyExc_TypeError,
7475
0
                        "execv() arg 2 must be a tuple or list");
7476
0
        return NULL;
7477
0
    }
7478
0
    argc = PySequence_Size(argv);
7479
0
    if (argc < 1) {
7480
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7481
0
        return NULL;
7482
0
    }
7483
7484
0
    argvlist = parse_arglist(argv, &argc);
7485
0
    if (argvlist == NULL) {
7486
0
        return NULL;
7487
0
    }
7488
0
    if (!argvlist[0][0]) {
7489
0
        PyErr_SetString(PyExc_ValueError,
7490
0
            "execv() arg 2 first element cannot be empty");
7491
0
        free_string_array(argvlist, argc);
7492
0
        return NULL;
7493
0
    }
7494
7495
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7496
0
        free_string_array(argvlist, argc);
7497
0
        return NULL;
7498
0
    }
7499
7500
0
    _Py_BEGIN_SUPPRESS_IPH
7501
#ifdef HAVE_WEXECV
7502
    _wexecv(path->wide, argvlist);
7503
#else
7504
0
    execv(path->narrow, argvlist);
7505
0
#endif
7506
0
    _Py_END_SUPPRESS_IPH
7507
7508
    /* If we get here it's definitely an error */
7509
7510
0
    posix_error();
7511
0
    free_string_array(argvlist, argc);
7512
0
    return NULL;
7513
0
}
7514
7515
7516
/*[clinic input]
7517
os.execve
7518
7519
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7520
        Path of executable file.
7521
    argv: object
7522
        Tuple or list of strings.
7523
    env: object
7524
        Dictionary of strings mapping to strings.
7525
7526
Execute an executable path with arguments, replacing current process.
7527
[clinic start generated code]*/
7528
7529
static PyObject *
7530
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7531
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7532
0
{
7533
0
    EXECV_CHAR **argvlist = NULL;
7534
0
    EXECV_CHAR **envlist;
7535
0
    Py_ssize_t argc, envc;
7536
7537
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7538
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7539
0
        PyErr_SetString(PyExc_RuntimeError,
7540
0
                        "exec not supported for isolated subinterpreters");
7541
0
        return NULL;
7542
0
    }
7543
7544
    /* execve has three arguments: (path, argv, env), where
7545
       argv is a list or tuple of strings and env is a dictionary
7546
       like posix.environ. */
7547
7548
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7549
0
        PyErr_SetString(PyExc_TypeError,
7550
0
                        "execve: argv must be a tuple or list");
7551
0
        goto fail_0;
7552
0
    }
7553
0
    argc = PySequence_Size(argv);
7554
0
    if (argc < 1) {
7555
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7556
0
        return NULL;
7557
0
    }
7558
7559
0
    if (!PyMapping_Check(env)) {
7560
0
        PyErr_SetString(PyExc_TypeError,
7561
0
                        "execve: environment must be a mapping object");
7562
0
        goto fail_0;
7563
0
    }
7564
7565
0
    argvlist = parse_arglist(argv, &argc);
7566
0
    if (argvlist == NULL) {
7567
0
        goto fail_0;
7568
0
    }
7569
0
    if (!argvlist[0][0]) {
7570
0
        PyErr_SetString(PyExc_ValueError,
7571
0
            "execve: argv first element cannot be empty");
7572
0
        goto fail_0;
7573
0
    }
7574
7575
0
    envlist = parse_envlist(env, &envc);
7576
0
    if (envlist == NULL)
7577
0
        goto fail_0;
7578
7579
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7580
0
        goto fail_1;
7581
0
    }
7582
7583
0
    _Py_BEGIN_SUPPRESS_IPH
7584
0
#ifdef HAVE_FEXECVE
7585
0
    if (path->is_fd)
7586
0
        fexecve(path->fd, argvlist, envlist);
7587
0
    else
7588
0
#endif
7589
#ifdef HAVE_WEXECV
7590
        _wexecve(path->wide, argvlist, envlist);
7591
#else
7592
0
        execve(path->narrow, argvlist, envlist);
7593
0
#endif
7594
0
    _Py_END_SUPPRESS_IPH
7595
7596
    /* If we get here it's definitely an error */
7597
7598
0
    posix_path_error(path);
7599
0
  fail_1:
7600
0
    free_string_array(envlist, envc);
7601
0
  fail_0:
7602
0
    if (argvlist)
7603
0
        free_string_array(argvlist, argc);
7604
0
    return NULL;
7605
0
}
7606
7607
#endif /* HAVE_EXECV */
7608
7609
#ifdef HAVE_POSIX_SPAWN
7610
7611
enum posix_spawn_file_actions_identifier {
7612
    POSIX_SPAWN_OPEN,
7613
    POSIX_SPAWN_CLOSE,
7614
    POSIX_SPAWN_DUP2
7615
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7616
    ,POSIX_SPAWN_CLOSEFROM
7617
#endif
7618
};
7619
7620
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7621
static int
7622
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7623
#endif
7624
7625
static int
7626
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7627
                        int resetids, int setsid, PyObject *setsigmask,
7628
                        PyObject *setsigdef, PyObject *scheduler,
7629
                        posix_spawnattr_t *attrp)
7630
0
{
7631
0
    assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
7632
0
    long all_flags = 0;
7633
7634
0
    errno = posix_spawnattr_init(attrp);
7635
0
    if (errno) {
7636
0
        posix_error();
7637
0
        return -1;
7638
0
    }
7639
7640
0
    if (setpgroup && setpgroup != Py_None) {
7641
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7642
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7643
0
            goto fail;
7644
0
        }
7645
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7646
0
        if (errno) {
7647
0
            posix_error();
7648
0
            goto fail;
7649
0
        }
7650
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7651
0
    }
7652
7653
0
    if (resetids) {
7654
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7655
0
    }
7656
7657
0
    if (setsid) {
7658
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7659
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7660
#endif
7661
0
#ifdef POSIX_SPAWN_SETSID
7662
0
        all_flags |= POSIX_SPAWN_SETSID;
7663
#elif defined(POSIX_SPAWN_SETSID_NP)
7664
        all_flags |= POSIX_SPAWN_SETSID_NP;
7665
#else
7666
        argument_unavailable_error(func_name, "setsid");
7667
        return -1;
7668
#endif
7669
7670
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7671
        } else {
7672
            argument_unavailable_error(func_name, "setsid");
7673
            return -1;
7674
        }
7675
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7676
7677
0
    }
7678
7679
0
#ifdef HAVE_SIGSET_T
7680
0
   if (setsigmask) {
7681
0
        sigset_t set;
7682
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7683
0
            goto fail;
7684
0
        }
7685
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7686
0
        if (errno) {
7687
0
            posix_error();
7688
0
            goto fail;
7689
0
        }
7690
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7691
0
    }
7692
7693
0
    if (setsigdef) {
7694
0
        sigset_t set;
7695
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7696
0
            goto fail;
7697
0
        }
7698
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7699
0
        if (errno) {
7700
0
            posix_error();
7701
0
            goto fail;
7702
0
        }
7703
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7704
0
    }
7705
#else
7706
    if (setsigmask || setsigdef) {
7707
        PyErr_SetString(PyExc_NotImplementedError,
7708
                        "sigset is not supported on this platform");
7709
        goto fail;
7710
    }
7711
#endif
7712
7713
0
    if (scheduler && scheduler != Py_None) {
7714
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7715
0
        PyObject *py_schedpolicy;
7716
0
        PyObject *schedparam_obj;
7717
0
        struct sched_param schedparam;
7718
7719
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7720
0
                        ";A scheduler tuple must have two elements",
7721
0
                        &py_schedpolicy, &schedparam_obj)) {
7722
0
            goto fail;
7723
0
        }
7724
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7725
0
            goto fail;
7726
0
        }
7727
0
        if (py_schedpolicy != Py_None) {
7728
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7729
7730
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7731
0
                goto fail;
7732
0
            }
7733
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7734
0
            if (errno) {
7735
0
                posix_error();
7736
0
                goto fail;
7737
0
            }
7738
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7739
0
        }
7740
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7741
0
        if (errno) {
7742
0
            posix_error();
7743
0
            goto fail;
7744
0
        }
7745
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7746
#else
7747
        PyErr_SetString(PyExc_NotImplementedError,
7748
                "The scheduler option is not supported in this system.");
7749
        goto fail;
7750
#endif
7751
0
    }
7752
7753
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7754
0
    if (errno) {
7755
0
        posix_error();
7756
0
        goto fail;
7757
0
    }
7758
7759
0
    return 0;
7760
7761
0
fail:
7762
0
    (void)posix_spawnattr_destroy(attrp);
7763
0
    return -1;
7764
0
}
7765
7766
static int
7767
parse_file_actions(PyObject *file_actions,
7768
                   posix_spawn_file_actions_t *file_actionsp,
7769
                   PyObject *temp_buffer)
7770
0
{
7771
0
    PyObject *seq;
7772
0
    PyObject *file_action = NULL;
7773
0
    PyObject *tag_obj;
7774
7775
0
    seq = PySequence_Fast(file_actions,
7776
0
                          "file_actions must be a sequence or None");
7777
0
    if (seq == NULL) {
7778
0
        return -1;
7779
0
    }
7780
7781
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7782
0
    if (errno) {
7783
0
        posix_error();
7784
0
        Py_DECREF(seq);
7785
0
        return -1;
7786
0
    }
7787
7788
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7789
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7790
0
        Py_INCREF(file_action);
7791
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7792
0
            PyErr_SetString(PyExc_TypeError,
7793
0
                "Each file_actions element must be a non-empty tuple");
7794
0
            goto fail;
7795
0
        }
7796
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7797
0
        if (tag == -1 && PyErr_Occurred()) {
7798
0
            goto fail;
7799
0
        }
7800
7801
        /* Populate the file_actions object */
7802
0
        switch (tag) {
7803
0
            case POSIX_SPAWN_OPEN: {
7804
0
                int fd, oflag;
7805
0
                PyObject *path;
7806
0
                unsigned long mode;
7807
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7808
0
                        ";A open file_action tuple must have 5 elements",
7809
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7810
0
                        &oflag, &mode))
7811
0
                {
7812
0
                    goto fail;
7813
0
                }
7814
0
                if (PyList_Append(temp_buffer, path)) {
7815
0
                    Py_DECREF(path);
7816
0
                    goto fail;
7817
0
                }
7818
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7819
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7820
0
                if (errno) {
7821
0
                    posix_error();
7822
0
                    Py_DECREF(path);
7823
0
                    goto fail;
7824
0
                }
7825
0
                Py_DECREF(path);
7826
0
                break;
7827
0
            }
7828
0
            case POSIX_SPAWN_CLOSE: {
7829
0
                int fd;
7830
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7831
0
                        ";A close file_action tuple must have 2 elements",
7832
0
                        &tag_obj, &fd))
7833
0
                {
7834
0
                    goto fail;
7835
0
                }
7836
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7837
0
                if (errno) {
7838
0
                    posix_error();
7839
0
                    goto fail;
7840
0
                }
7841
0
                break;
7842
0
            }
7843
0
            case POSIX_SPAWN_DUP2: {
7844
0
                int fd1, fd2;
7845
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7846
0
                        ";A dup2 file_action tuple must have 3 elements",
7847
0
                        &tag_obj, &fd1, &fd2))
7848
0
                {
7849
0
                    goto fail;
7850
0
                }
7851
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7852
0
                                                         fd1, fd2);
7853
0
                if (errno) {
7854
0
                    posix_error();
7855
0
                    goto fail;
7856
0
                }
7857
0
                break;
7858
0
            }
7859
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7860
            case POSIX_SPAWN_CLOSEFROM: {
7861
                int fd;
7862
                if (!PyArg_ParseTuple(file_action, "Oi"
7863
                        ";A closefrom file_action tuple must have 2 elements",
7864
                        &tag_obj, &fd))
7865
                {
7866
                    goto fail;
7867
                }
7868
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7869
                                                                 fd);
7870
                if (errno) {
7871
                    posix_error();
7872
                    goto fail;
7873
                }
7874
                break;
7875
            }
7876
#endif
7877
0
            default: {
7878
0
                PyErr_SetString(PyExc_TypeError,
7879
0
                                "Unknown file_actions identifier");
7880
0
                goto fail;
7881
0
            }
7882
0
        }
7883
0
        Py_DECREF(file_action);
7884
0
    }
7885
7886
0
    Py_DECREF(seq);
7887
0
    return 0;
7888
7889
0
fail:
7890
0
    Py_DECREF(seq);
7891
0
    Py_DECREF(file_action);
7892
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7893
0
    return -1;
7894
0
}
7895
7896
7897
static PyObject *
7898
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7899
               PyObject *env, PyObject *file_actions,
7900
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7901
               PyObject *setsigdef, PyObject *scheduler)
7902
0
{
7903
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7904
0
    EXECV_CHAR **argvlist = NULL;
7905
0
    EXECV_CHAR **envlist = NULL;
7906
0
    posix_spawn_file_actions_t file_actions_buf;
7907
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7908
0
    posix_spawnattr_t attr;
7909
0
    posix_spawnattr_t *attrp = NULL;
7910
0
    Py_ssize_t argc, envc;
7911
0
    PyObject *result = NULL;
7912
0
    PyObject *temp_buffer = NULL;
7913
0
    pid_t pid;
7914
0
    int err_code;
7915
7916
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7917
       argv is a list or tuple of strings and env is a dictionary
7918
       like posix.environ. */
7919
7920
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7921
0
        PyErr_Format(PyExc_TypeError,
7922
0
                     "%s: argv must be a tuple or list", func_name);
7923
0
        goto exit;
7924
0
    }
7925
0
    argc = PySequence_Size(argv);
7926
0
    if (argc < 1) {
7927
0
        PyErr_Format(PyExc_ValueError,
7928
0
                     "%s: argv must not be empty", func_name);
7929
0
        goto exit;
7930
0
    }
7931
7932
0
    if (!PyMapping_Check(env) && env != Py_None) {
7933
0
        PyErr_Format(PyExc_TypeError,
7934
0
                     "%s: environment must be a mapping object or None", func_name);
7935
0
        goto exit;
7936
0
    }
7937
7938
0
    if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7939
0
        PyErr_Format(PyExc_TypeError,
7940
0
                     "%s: scheduler must be a tuple or None", func_name);
7941
0
        goto exit;
7942
0
    }
7943
7944
0
    argvlist = parse_arglist(argv, &argc);
7945
0
    if (argvlist == NULL) {
7946
0
        goto exit;
7947
0
    }
7948
0
    if (!argvlist[0][0]) {
7949
0
        PyErr_Format(PyExc_ValueError,
7950
0
                     "%s: argv first element cannot be empty", func_name);
7951
0
        goto exit;
7952
0
    }
7953
7954
#ifdef USE_DARWIN_NS_GET_ENVIRON
7955
    // There is no environ global in this situation.
7956
    char **environ = NULL;
7957
#endif
7958
7959
0
    if (env == Py_None) {
7960
#ifdef USE_DARWIN_NS_GET_ENVIRON
7961
        environ = *_NSGetEnviron();
7962
#endif
7963
0
        envlist = environ;
7964
0
    } else {
7965
0
        envlist = parse_envlist(env, &envc);
7966
0
        if (envlist == NULL) {
7967
0
            goto exit;
7968
0
        }
7969
0
    }
7970
7971
0
    if (file_actions != NULL && file_actions != Py_None) {
7972
        /* There is a bug in old versions of glibc that makes some of the
7973
         * helper functions for manipulating file actions not copy the provided
7974
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7975
         * copy the value of path for some old versions of glibc (<2.20).
7976
         * The use of temp_buffer here is a workaround that keeps the
7977
         * python objects that own the buffers alive until posix_spawn gets called.
7978
         * Check https://bugs.python.org/issue33630 and
7979
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7980
0
        temp_buffer = PyList_New(0);
7981
0
        if (!temp_buffer) {
7982
0
            goto exit;
7983
0
        }
7984
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7985
0
            goto exit;
7986
0
        }
7987
0
        file_actionsp = &file_actions_buf;
7988
0
    }
7989
7990
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7991
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7992
0
        goto exit;
7993
0
    }
7994
0
    attrp = &attr;
7995
7996
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7997
0
        goto exit;
7998
0
    }
7999
8000
0
    _Py_BEGIN_SUPPRESS_IPH
8001
0
#ifdef HAVE_POSIX_SPAWNP
8002
0
    if (use_posix_spawnp) {
8003
0
        err_code = posix_spawnp(&pid, path->narrow,
8004
0
                                file_actionsp, attrp, argvlist, envlist);
8005
0
    }
8006
0
    else
8007
0
#endif /* HAVE_POSIX_SPAWNP */
8008
0
    {
8009
0
        err_code = posix_spawn(&pid, path->narrow,
8010
0
                               file_actionsp, attrp, argvlist, envlist);
8011
0
    }
8012
0
    _Py_END_SUPPRESS_IPH
8013
8014
0
    if (err_code) {
8015
0
        errno = err_code;
8016
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8017
0
        goto exit;
8018
0
    }
8019
#ifdef _Py_MEMORY_SANITIZER
8020
    __msan_unpoison(&pid, sizeof(pid));
8021
#endif
8022
0
    result = PyLong_FromPid(pid);
8023
8024
0
exit:
8025
0
    if (file_actionsp) {
8026
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
8027
0
    }
8028
0
    if (attrp) {
8029
0
        (void)posix_spawnattr_destroy(attrp);
8030
0
    }
8031
0
    if (envlist && envlist != environ) {
8032
0
        free_string_array(envlist, envc);
8033
0
    }
8034
0
    if (argvlist) {
8035
0
        free_string_array(argvlist, argc);
8036
0
    }
8037
0
    Py_XDECREF(temp_buffer);
8038
0
    return result;
8039
0
}
8040
8041
8042
/*[clinic input]
8043
8044
os.posix_spawn
8045
    path: path_t
8046
        Path of executable file.
8047
    argv: object
8048
        Tuple or list of strings.
8049
    env: object
8050
        Dictionary of strings mapping to strings.
8051
    /
8052
    *
8053
    file_actions: object(c_default='NULL') = ()
8054
        A sequence of file action tuples.
8055
    setpgroup: object(c_default='NULL') = None
8056
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8057
    resetids: bool = False
8058
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8059
    setsid: bool = False
8060
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP
8061
        will be activated.
8062
    setsigmask: object(c_default='NULL') = ()
8063
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8064
    setsigdef: object(c_default='NULL') = ()
8065
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8066
    scheduler: object(c_default='NULL') = None
8067
        A tuple with the scheduler policy (optional) and parameters.
8068
8069
Execute the program specified by path in a new process.
8070
[clinic start generated code]*/
8071
8072
static PyObject *
8073
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8074
                    PyObject *env, PyObject *file_actions,
8075
                    PyObject *setpgroup, int resetids, int setsid,
8076
                    PyObject *setsigmask, PyObject *setsigdef,
8077
                    PyObject *scheduler)
8078
/*[clinic end generated code: output=14a1098c566bc675 input=c7592dcbc96e8114]*/
8079
0
{
8080
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8081
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8082
0
                          scheduler);
8083
0
}
8084
 #endif /* HAVE_POSIX_SPAWN */
8085
8086
8087
8088
#ifdef HAVE_POSIX_SPAWNP
8089
/*[clinic input]
8090
8091
os.posix_spawnp
8092
    path: path_t
8093
        Path of executable file.
8094
    argv: object
8095
        Tuple or list of strings.
8096
    env: object
8097
        Dictionary of strings mapping to strings.
8098
    /
8099
    *
8100
    file_actions: object(c_default='NULL') = ()
8101
        A sequence of file action tuples.
8102
    setpgroup: object(c_default='NULL') = None
8103
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8104
    resetids: bool = False
8105
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8106
    setsid: bool = False
8107
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP
8108
        will be activated.
8109
    setsigmask: object(c_default='NULL') = ()
8110
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8111
    setsigdef: object(c_default='NULL') = ()
8112
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8113
    scheduler: object(c_default='NULL') = None
8114
        A tuple with the scheduler policy (optional) and parameters.
8115
8116
Execute the program specified by path in a new process.
8117
[clinic start generated code]*/
8118
8119
static PyObject *
8120
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8121
                     PyObject *env, PyObject *file_actions,
8122
                     PyObject *setpgroup, int resetids, int setsid,
8123
                     PyObject *setsigmask, PyObject *setsigdef,
8124
                     PyObject *scheduler)
8125
/*[clinic end generated code: output=7b9aaefe3031238d input=43ccc1452cae2be3]*/
8126
0
{
8127
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8128
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8129
0
                          scheduler);
8130
0
}
8131
#endif /* HAVE_POSIX_SPAWNP */
8132
8133
#ifdef HAVE_RTPSPAWN
8134
static intptr_t
8135
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8136
               const char  *envp[])
8137
{
8138
     RTP_ID rtpid;
8139
     int status;
8140
     pid_t res;
8141
     int async_err = 0;
8142
8143
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8144
        uStackSize=0 cannot be used, the default stack size is too small for
8145
        Python. */
8146
     if (envp) {
8147
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8148
                          100, 0x1000000, 0, VX_FP_TASK);
8149
     }
8150
     else {
8151
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8152
                          100, 0x1000000, 0, VX_FP_TASK);
8153
     }
8154
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8155
         do {
8156
             res = waitpid((pid_t)rtpid, &status, 0);
8157
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8158
8159
         if (res < 0)
8160
             return RTP_ID_ERROR;
8161
         return ((intptr_t)status);
8162
     }
8163
     return ((intptr_t)rtpid);
8164
}
8165
#endif
8166
8167
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8168
/*[clinic input]
8169
os.spawnv
8170
8171
    mode: int
8172
        Mode of process creation.
8173
    path: path_t
8174
        Path of executable file.
8175
    argv: object
8176
        Tuple or list of strings.
8177
    /
8178
8179
Execute the program specified by path in a new process.
8180
[clinic start generated code]*/
8181
8182
static PyObject *
8183
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8184
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8185
{
8186
    EXECV_CHAR **argvlist;
8187
    int i;
8188
    Py_ssize_t argc;
8189
    intptr_t spawnval;
8190
8191
    /* spawnv has three arguments: (mode, path, argv), where
8192
       argv is a list or tuple of strings. */
8193
8194
    if (PyList_Check(argv)) {
8195
        argc = PyList_Size(argv);
8196
    }
8197
    else if (PyTuple_Check(argv)) {
8198
        argc = PyTuple_Size(argv);
8199
    }
8200
    else {
8201
        PyErr_SetString(PyExc_TypeError,
8202
                        "spawnv() arg 2 must be a tuple or list");
8203
        return NULL;
8204
    }
8205
    if (argc == 0) {
8206
        PyErr_SetString(PyExc_ValueError,
8207
            "spawnv() arg 2 cannot be empty");
8208
        return NULL;
8209
    }
8210
8211
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8212
    if (argvlist == NULL) {
8213
        return PyErr_NoMemory();
8214
    }
8215
    for (i = 0; i < argc; i++) {
8216
        // The item must be a strong reference because of possible
8217
        // side-effects of PyUnicode_FS{Converter,Decoder}() in
8218
        // fsconvert_strdup(): an item's __fspath__() can mutate a list
8219
        // *argv*, releasing the list's reference to the item (gh-151416).
8220
        PyObject *item = PySequence_ITEM(argv, i);
8221
        if (item == NULL) {
8222
            free_string_array(argvlist, i);
8223
            return NULL;
8224
        }
8225
        if (!fsconvert_strdup(item, &argvlist[i])) {
8226
            Py_DECREF(item);
8227
            free_string_array(argvlist, i);
8228
            // Add argument context to the converter's terse TypeError, but
8229
            // let MemoryError, codec errors, embedded-null ValueError, etc.
8230
            // propagate unmasked.
8231
            if (PyErr_ExceptionMatches(PyExc_TypeError)) {
8232
                PyErr_SetString(
8233
                    PyExc_TypeError,
8234
                    "spawnv() arg 2 must contain only strings");
8235
            }
8236
            return NULL;
8237
        }
8238
        Py_DECREF(item);
8239
        if (i == 0 && !argvlist[0][0]) {
8240
            free_string_array(argvlist, i + 1);
8241
            PyErr_SetString(
8242
                PyExc_ValueError,
8243
                "spawnv() arg 2 first element cannot be empty");
8244
            return NULL;
8245
        }
8246
    }
8247
    argvlist[argc] = NULL;
8248
8249
#if !defined(HAVE_RTPSPAWN)
8250
    if (mode == _OLD_P_OVERLAY)
8251
        mode = _P_OVERLAY;
8252
#endif
8253
8254
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8255
                    Py_None) < 0) {
8256
        free_string_array(argvlist, argc);
8257
        return NULL;
8258
    }
8259
8260
    Py_BEGIN_ALLOW_THREADS
8261
    _Py_BEGIN_SUPPRESS_IPH
8262
#ifdef HAVE_WSPAWNV
8263
    spawnval = _wspawnv(mode, path->wide, argvlist);
8264
#elif defined(HAVE_RTPSPAWN)
8265
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8266
#else
8267
    spawnval = _spawnv(mode, path->narrow, argvlist);
8268
#endif
8269
    _Py_END_SUPPRESS_IPH
8270
    Py_END_ALLOW_THREADS
8271
8272
    int saved_errno = errno;
8273
    free_string_array(argvlist, argc);
8274
8275
    if (spawnval == -1) {
8276
        errno = saved_errno;
8277
        posix_error();
8278
        return NULL;
8279
    }
8280
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8281
}
8282
8283
/*[clinic input]
8284
os.spawnve
8285
8286
    mode: int
8287
        Mode of process creation.
8288
    path: path_t
8289
        Path of executable file.
8290
    argv: object
8291
        Tuple or list of strings.
8292
    env: object
8293
        Dictionary of strings mapping to strings.
8294
    /
8295
8296
Execute the program specified by path in a new process.
8297
[clinic start generated code]*/
8298
8299
static PyObject *
8300
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8301
                PyObject *env)
8302
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8303
{
8304
    EXECV_CHAR **argvlist;
8305
    EXECV_CHAR **envlist;
8306
    PyObject *res = NULL;
8307
    Py_ssize_t argc, i, envc;
8308
    intptr_t spawnval;
8309
    Py_ssize_t lastarg = 0;
8310
8311
    /* spawnve has four arguments: (mode, path, argv, env), where
8312
       argv is a list or tuple of strings and env is a dictionary
8313
       like posix.environ. */
8314
8315
    if (PyList_Check(argv)) {
8316
        argc = PyList_Size(argv);
8317
    }
8318
    else if (PyTuple_Check(argv)) {
8319
        argc = PyTuple_Size(argv);
8320
    }
8321
    else {
8322
        PyErr_SetString(PyExc_TypeError,
8323
                        "spawnve() arg 2 must be a tuple or list");
8324
        goto fail_0;
8325
    }
8326
    if (argc == 0) {
8327
        PyErr_SetString(PyExc_ValueError,
8328
            "spawnve() arg 2 cannot be empty");
8329
        goto fail_0;
8330
    }
8331
    if (!PyMapping_Check(env)) {
8332
        PyErr_SetString(PyExc_TypeError,
8333
                        "spawnve() arg 3 must be a mapping object");
8334
        goto fail_0;
8335
    }
8336
8337
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8338
    if (argvlist == NULL) {
8339
        PyErr_NoMemory();
8340
        goto fail_0;
8341
    }
8342
    for (i = 0; i < argc; i++) {
8343
        // The item must be a strong reference because of possible
8344
        // side-effects of PyUnicode_FS{Converter,Decoder}() in
8345
        // fsconvert_strdup(): an item's __fspath__() can mutate a list
8346
        // *argv*, releasing the list's reference to the item (gh-151416).
8347
        PyObject *item = PySequence_ITEM(argv, i);
8348
        if (item == NULL) {
8349
            lastarg = i;
8350
            goto fail_1;
8351
        }
8352
        if (!fsconvert_strdup(item, &argvlist[i])) {
8353
            Py_DECREF(item);
8354
            lastarg = i;
8355
            goto fail_1;
8356
        }
8357
        Py_DECREF(item);
8358
        if (i == 0 && !argvlist[0][0]) {
8359
            lastarg = i + 1;
8360
            PyErr_SetString(
8361
                PyExc_ValueError,
8362
                "spawnv() arg 2 first element cannot be empty");
8363
            goto fail_1;
8364
        }
8365
    }
8366
    lastarg = argc;
8367
    argvlist[argc] = NULL;
8368
8369
    envlist = parse_envlist(env, &envc);
8370
    if (envlist == NULL)
8371
        goto fail_1;
8372
8373
#if !defined(HAVE_RTPSPAWN)
8374
    if (mode == _OLD_P_OVERLAY)
8375
        mode = _P_OVERLAY;
8376
#endif
8377
8378
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8379
        goto fail_2;
8380
    }
8381
8382
    Py_BEGIN_ALLOW_THREADS
8383
    _Py_BEGIN_SUPPRESS_IPH
8384
#ifdef HAVE_WSPAWNV
8385
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8386
#elif defined(HAVE_RTPSPAWN)
8387
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8388
                           (const char **)envlist);
8389
#else
8390
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8391
#endif
8392
    _Py_END_SUPPRESS_IPH
8393
    Py_END_ALLOW_THREADS
8394
8395
    if (spawnval == -1)
8396
        (void) posix_error();
8397
    else
8398
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8399
8400
  fail_2:
8401
    while (--envc >= 0) {
8402
        PyMem_Free(envlist[envc]);
8403
    }
8404
    PyMem_Free(envlist);
8405
  fail_1:
8406
    free_string_array(argvlist, lastarg);
8407
  fail_0:
8408
    return res;
8409
}
8410
8411
#endif /* HAVE_SPAWNV */
8412
8413
#ifdef HAVE_FORK
8414
8415
/* Helper function to validate arguments.
8416
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8417
   If obj is non-NULL it must be callable.  */
8418
static int
8419
check_null_or_callable(PyObject *obj, const char* obj_name)
8420
60
{
8421
60
    if (obj && !PyCallable_Check(obj)) {
8422
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8423
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8424
0
        return -1;
8425
0
    }
8426
60
    return 0;
8427
60
}
8428
8429
/*[clinic input]
8430
os.register_at_fork
8431
8432
    *
8433
    before: object=NULL
8434
        A callable to be called in the parent before the fork() syscall.
8435
    after_in_child: object=NULL
8436
        A callable to be called in the child after fork().
8437
    after_in_parent: object=NULL
8438
        A callable to be called in the parent after fork().
8439
8440
Register callables to be called when forking a new process.
8441
8442
'before' callbacks are called in reverse order.
8443
'after_in_child' and 'after_in_parent' callbacks are called in order.
8444
8445
[clinic start generated code]*/
8446
8447
static PyObject *
8448
os_register_at_fork_impl(PyObject *module, PyObject *before,
8449
                         PyObject *after_in_child, PyObject *after_in_parent)
8450
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8451
20
{
8452
20
    PyInterpreterState *interp;
8453
8454
20
    if (!before && !after_in_child && !after_in_parent) {
8455
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8456
0
        return NULL;
8457
0
    }
8458
20
    if (check_null_or_callable(before, "before") ||
8459
20
        check_null_or_callable(after_in_child, "after_in_child") ||
8460
20
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8461
0
        return NULL;
8462
0
    }
8463
20
    interp = _PyInterpreterState_GET();
8464
8465
20
    if (register_at_forker(&interp->before_forkers, before)) {
8466
0
        return NULL;
8467
0
    }
8468
20
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8469
0
        return NULL;
8470
0
    }
8471
20
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8472
0
        return NULL;
8473
0
    }
8474
20
    Py_RETURN_NONE;
8475
20
}
8476
#endif /* HAVE_FORK */
8477
8478
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8479
// Common code to raise a warning if we detect there is more than one thread
8480
// running in the process. Best effort, silent if unable to count threads.
8481
// Constraint: Quick. Never overcounts. Never leaves an error set.
8482
//
8483
// This MUST only be called from the parent process after
8484
// PyOS_AfterFork_Parent().
8485
static int
8486
warn_about_fork_with_threads(
8487
    const char* name,  // Name of the API to use in the warning message.
8488
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8489
)
8490
0
{
8491
    // It's not safe to issue the warning while the world is stopped, because
8492
    // other threads might be holding locks that we need, which would deadlock.
8493
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8494
8495
0
    Py_ssize_t num_python_threads = num_os_threads;
8496
0
    if (num_python_threads <= 0) {
8497
        // Fall back to just the number our threading module knows about.
8498
        // An incomplete view of the world, but better than nothing.
8499
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8500
0
        if (!threading) {
8501
0
            PyErr_Clear();
8502
0
            return 0;
8503
0
        }
8504
0
        PyObject *threading_active =
8505
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8506
0
        if (!threading_active) {
8507
0
            PyErr_Clear();
8508
0
            Py_DECREF(threading);
8509
0
            return 0;
8510
0
        }
8511
0
        PyObject *threading_limbo =
8512
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8513
0
        if (!threading_limbo) {
8514
0
            PyErr_Clear();
8515
0
            Py_DECREF(threading);
8516
0
            Py_DECREF(threading_active);
8517
0
            return 0;
8518
0
        }
8519
0
        Py_DECREF(threading);
8520
        // Duplicating what threading.active_count() does but without holding
8521
        // threading._active_limbo_lock so our count could be inaccurate if
8522
        // these dicts are mid-update from another thread.  Not a big deal.
8523
        // Worst case if someone replaced threading._active or threading._limbo
8524
        // with non-dicts, we get -1 from *Length() below and undercount.
8525
        // Nobody should, but we're best effort so we clear errors and move on.
8526
0
        num_python_threads = (PyMapping_Length(threading_active)
8527
0
                              + PyMapping_Length(threading_limbo));
8528
0
        PyErr_Clear();
8529
0
        Py_DECREF(threading_active);
8530
0
        Py_DECREF(threading_limbo);
8531
0
    }
8532
0
    if (num_python_threads > 1) {
8533
0
        return PyErr_WarnFormat(
8534
0
                PyExc_DeprecationWarning, 1,
8535
0
#ifdef HAVE_GETPID
8536
0
                "This process (pid=%d) is multi-threaded, "
8537
#else
8538
                "This process is multi-threaded, "
8539
#endif
8540
0
                "use of %s() may lead to deadlocks in the child.",
8541
0
#ifdef HAVE_GETPID
8542
0
                getpid(),
8543
0
#endif
8544
0
                name);
8545
0
    }
8546
0
    return 0;
8547
0
}
8548
8549
// If this returns <= 0, we were unable to successfully use any OS APIs.
8550
// Returns a positive number of threads otherwise.
8551
static Py_ssize_t get_number_of_os_threads(void)
8552
0
{
8553
    // TODO: Consider making an `os` module API to return the current number
8554
    // of threads in the process. That'd presumably use this platform code but
8555
    // raise an error rather than using the inaccurate fallback.
8556
0
    Py_ssize_t num_python_threads = 0;
8557
#if defined(__APPLE__) && defined(HAVE_GETPID)
8558
    mach_port_t macos_self = mach_task_self();
8559
    mach_port_t macos_task;
8560
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8561
        thread_array_t macos_threads;
8562
        mach_msg_type_number_t macos_n_threads;
8563
        if (task_threads(macos_task, &macos_threads,
8564
                         &macos_n_threads) == KERN_SUCCESS) {
8565
            num_python_threads = macos_n_threads;
8566
        }
8567
    }
8568
#elif defined(__linux__)
8569
    // Linux /proc/self/stat 20th field is the number of threads.
8570
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8571
0
    if (proc_stat) {
8572
0
        size_t n;
8573
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8574
        // observed on the author's workstation.
8575
0
        char stat_line[160];
8576
0
        n = fread(&stat_line, 1, 159, proc_stat);
8577
0
        stat_line[n] = '\0';
8578
0
        fclose(proc_stat);
8579
8580
0
        char *saveptr = NULL;
8581
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8582
0
        unsigned int idx;
8583
0
        for (idx = 19; idx && field; --idx) {
8584
0
            field = strtok_r(NULL, " ", &saveptr);
8585
0
        }
8586
0
        if (idx == 0 && field) {  // found the 20th field
8587
0
            num_python_threads = atoi(field);  // 0 on error
8588
0
        }
8589
0
    }
8590
0
#endif
8591
0
    return num_python_threads;
8592
0
}
8593
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8594
8595
#ifdef HAVE_FORK1
8596
/*[clinic input]
8597
os.fork1
8598
8599
Fork a child process with a single multiplexed (i.e., not bound) thread.
8600
8601
Return 0 to child process and PID of child to parent process.
8602
[clinic start generated code]*/
8603
8604
static PyObject *
8605
os_fork1_impl(PyObject *module)
8606
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8607
{
8608
    pid_t pid;
8609
8610
    PyInterpreterState *interp = _PyInterpreterState_GET();
8611
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8612
        PyErr_SetString(PyExc_PythonFinalizationError,
8613
                        "can't fork at interpreter shutdown");
8614
        return NULL;
8615
    }
8616
    if (!_Py_IsMainInterpreter(interp)) {
8617
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8618
        return NULL;
8619
    }
8620
    PyOS_BeforeFork();
8621
    pid = fork1();
8622
    int saved_errno = errno;
8623
    if (pid == 0) {
8624
        /* child: this clobbers and resets the import lock. */
8625
        PyOS_AfterFork_Child();
8626
    } else {
8627
        // Called before AfterFork_Parent in case those hooks start threads.
8628
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8629
        /* parent: release the import lock. */
8630
        PyOS_AfterFork_Parent();
8631
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8632
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8633
            return NULL;
8634
        }
8635
    }
8636
    if (pid == -1) {
8637
        errno = saved_errno;
8638
        return posix_error();
8639
    }
8640
    return PyLong_FromPid(pid);
8641
}
8642
#endif /* HAVE_FORK1 */
8643
8644
8645
#ifdef HAVE_FORK
8646
/*[clinic input]
8647
os.fork
8648
8649
Fork a child process.
8650
8651
Return 0 to child process and PID of child to parent process.
8652
[clinic start generated code]*/
8653
8654
static PyObject *
8655
os_fork_impl(PyObject *module)
8656
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8657
0
{
8658
0
    pid_t pid;
8659
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8660
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8661
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8662
0
                        "can't fork at interpreter shutdown");
8663
0
        return NULL;
8664
0
    }
8665
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8666
0
        PyErr_SetString(PyExc_RuntimeError,
8667
0
                        "fork not supported for isolated subinterpreters");
8668
0
        return NULL;
8669
0
    }
8670
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8671
0
        return NULL;
8672
0
    }
8673
0
    PyOS_BeforeFork();
8674
0
    pid = fork();
8675
0
    int saved_errno = errno;
8676
0
    if (pid == 0) {
8677
        /* child: this clobbers and resets the import lock. */
8678
0
        PyOS_AfterFork_Child();
8679
0
    } else {
8680
        // Called before AfterFork_Parent in case those hooks start threads.
8681
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8682
        /* parent: release the import lock. */
8683
0
        PyOS_AfterFork_Parent();
8684
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8685
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8686
0
            return NULL;
8687
0
    }
8688
0
    if (pid == -1) {
8689
0
        errno = saved_errno;
8690
0
        return posix_error();
8691
0
    }
8692
0
    return PyLong_FromPid(pid);
8693
0
}
8694
#endif /* HAVE_FORK */
8695
8696
8697
#ifdef HAVE_SCHED_H
8698
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8699
/*[clinic input]
8700
os.sched_get_priority_max
8701
8702
    policy: int
8703
8704
Get the maximum scheduling priority for policy.
8705
[clinic start generated code]*/
8706
8707
static PyObject *
8708
os_sched_get_priority_max_impl(PyObject *module, int policy)
8709
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8710
0
{
8711
    /* make sure that errno is cleared before the call */
8712
0
    errno = 0;
8713
0
    int max = sched_get_priority_max(policy);
8714
0
    if (max == -1 && errno)
8715
0
        return posix_error();
8716
0
    return PyLong_FromLong(max);
8717
0
}
8718
8719
8720
/*[clinic input]
8721
os.sched_get_priority_min
8722
8723
    policy: int
8724
8725
Get the minimum scheduling priority for policy.
8726
[clinic start generated code]*/
8727
8728
static PyObject *
8729
os_sched_get_priority_min_impl(PyObject *module, int policy)
8730
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8731
0
{
8732
    /* make sure that errno is cleared before the call */
8733
0
    errno = 0;
8734
0
    int min = sched_get_priority_min(policy);
8735
0
    if (min == -1 && errno)
8736
0
        return posix_error();
8737
0
    return PyLong_FromLong(min);
8738
0
}
8739
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8740
8741
8742
#ifdef HAVE_SCHED_SETSCHEDULER
8743
/*[clinic input]
8744
os.sched_getscheduler
8745
    pid: pid_t
8746
    /
8747
8748
Get the scheduling policy for the process identified by pid.
8749
8750
Passing 0 for pid returns the scheduling policy for the calling process.
8751
[clinic start generated code]*/
8752
8753
static PyObject *
8754
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8755
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8756
0
{
8757
0
    int policy;
8758
8759
0
    policy = sched_getscheduler(pid);
8760
0
    if (policy < 0)
8761
0
        return posix_error();
8762
0
    return PyLong_FromLong(policy);
8763
0
}
8764
#endif /* HAVE_SCHED_SETSCHEDULER */
8765
8766
8767
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8768
/*[clinic input]
8769
class os.sched_param "PyObject *" "SchedParamType"
8770
8771
@classmethod
8772
os.sched_param.__new__
8773
8774
    sched_priority: object
8775
        A scheduling parameter.
8776
8777
Currently has only one field: sched_priority
8778
[clinic start generated code]*/
8779
8780
static PyObject *
8781
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8782
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8783
0
{
8784
0
    PyObject *res;
8785
8786
0
    res = PyStructSequence_New(type);
8787
0
    if (!res)
8788
0
        return NULL;
8789
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8790
0
    return res;
8791
0
}
8792
8793
static PyObject *
8794
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8795
0
{
8796
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8797
0
}
8798
8799
static PyMethodDef os_sched_param_reduce_method = {
8800
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8801
};
8802
8803
PyDoc_VAR(os_sched_param__doc__);
8804
8805
static PyStructSequence_Field sched_param_fields[] = {
8806
    {"sched_priority", "the scheduling priority"},
8807
    {0}
8808
};
8809
8810
static PyStructSequence_Desc sched_param_desc = {
8811
    MODNAME ".sched_param", /* name */
8812
    os_sched_param__doc__, /* doc */
8813
    sched_param_fields,
8814
    1
8815
};
8816
8817
static int
8818
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8819
0
{
8820
0
    long priority;
8821
8822
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8823
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8824
0
        return 0;
8825
0
    }
8826
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8827
0
    if (priority == -1 && PyErr_Occurred())
8828
0
        return 0;
8829
0
    if (priority > INT_MAX || priority < INT_MIN) {
8830
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8831
0
        return 0;
8832
0
    }
8833
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8834
0
    return 1;
8835
0
}
8836
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8837
8838
8839
#ifdef HAVE_SCHED_SETSCHEDULER
8840
/*[clinic input]
8841
os.sched_setscheduler
8842
8843
    pid: pid_t
8844
    policy: int
8845
    param as param_obj: object
8846
    /
8847
8848
Set the scheduling policy for the process identified by pid.
8849
8850
If pid is 0, the calling process is changed.
8851
param is an instance of sched_param.
8852
[clinic start generated code]*/
8853
8854
static PyObject *
8855
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8856
                           PyObject *param_obj)
8857
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8858
0
{
8859
0
    struct sched_param param;
8860
0
    if (!convert_sched_param(module, param_obj, &param)) {
8861
0
        return NULL;
8862
0
    }
8863
8864
    /*
8865
    ** sched_setscheduler() returns 0 in Linux, but the previous
8866
    ** scheduling policy under Solaris/Illumos, and others.
8867
    ** On error, -1 is returned in all Operating Systems.
8868
    */
8869
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8870
0
        return posix_error();
8871
0
    Py_RETURN_NONE;
8872
0
}
8873
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8874
8875
8876
#ifdef HAVE_SCHED_SETPARAM
8877
/*[clinic input]
8878
os.sched_getparam
8879
    pid: pid_t
8880
    /
8881
8882
Returns scheduling parameters for the process identified by pid.
8883
8884
If pid is 0, returns parameters for the calling process.
8885
Return value is an instance of sched_param.
8886
[clinic start generated code]*/
8887
8888
static PyObject *
8889
os_sched_getparam_impl(PyObject *module, pid_t pid)
8890
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8891
0
{
8892
0
    struct sched_param param;
8893
0
    PyObject *result;
8894
0
    PyObject *priority;
8895
8896
0
    if (sched_getparam(pid, &param))
8897
0
        return posix_error();
8898
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8899
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8900
0
    if (!result)
8901
0
        return NULL;
8902
0
    priority = PyLong_FromLong(param.sched_priority);
8903
0
    if (!priority) {
8904
0
        Py_DECREF(result);
8905
0
        return NULL;
8906
0
    }
8907
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8908
0
    return result;
8909
0
}
8910
8911
8912
/*[clinic input]
8913
os.sched_setparam
8914
    pid: pid_t
8915
    param as param_obj: object
8916
    /
8917
8918
Set scheduling parameters for the process identified by pid.
8919
8920
If pid is 0, sets parameters for the calling process.
8921
param should be an instance of sched_param.
8922
[clinic start generated code]*/
8923
8924
static PyObject *
8925
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8926
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8927
0
{
8928
0
    struct sched_param param;
8929
0
    if (!convert_sched_param(module, param_obj, &param)) {
8930
0
        return NULL;
8931
0
    }
8932
8933
0
    if (sched_setparam(pid, &param))
8934
0
        return posix_error();
8935
0
    Py_RETURN_NONE;
8936
0
}
8937
#endif /* HAVE_SCHED_SETPARAM */
8938
8939
8940
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8941
/*[clinic input]
8942
@permit_long_summary
8943
os.sched_rr_get_interval -> double
8944
    pid: pid_t
8945
    /
8946
8947
Return the round-robin quantum for the process identified by pid, in seconds.
8948
8949
Value returned is a float.
8950
[clinic start generated code]*/
8951
8952
static double
8953
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8954
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8955
0
{
8956
0
    struct timespec interval;
8957
0
    if (sched_rr_get_interval(pid, &interval)) {
8958
0
        posix_error();
8959
0
        return -1.0;
8960
0
    }
8961
#ifdef _Py_MEMORY_SANITIZER
8962
    __msan_unpoison(&interval, sizeof(interval));
8963
#endif
8964
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8965
0
}
8966
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8967
8968
8969
/*[clinic input]
8970
os.sched_yield
8971
8972
Voluntarily relinquish the CPU.
8973
[clinic start generated code]*/
8974
8975
static PyObject *
8976
os_sched_yield_impl(PyObject *module)
8977
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8978
0
{
8979
0
    int result;
8980
0
    Py_BEGIN_ALLOW_THREADS
8981
0
    result = sched_yield();
8982
0
    Py_END_ALLOW_THREADS
8983
0
    if (result < 0) {
8984
0
        return posix_error();
8985
0
    }
8986
0
    Py_RETURN_NONE;
8987
0
}
8988
8989
#ifdef HAVE_SCHED_SETAFFINITY
8990
/* The minimum number of CPUs allocated in a cpu_set_t */
8991
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8992
8993
/*[clinic input]
8994
os.sched_setaffinity
8995
    pid: pid_t
8996
    mask : object
8997
    /
8998
8999
Set the CPU affinity of the process identified by pid to mask.
9000
9001
mask should be an iterable of integers identifying CPUs.
9002
[clinic start generated code]*/
9003
9004
static PyObject *
9005
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
9006
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
9007
0
{
9008
0
    int ncpus;
9009
0
    size_t setsize;
9010
0
    cpu_set_t *cpu_set = NULL;
9011
0
    PyObject *iterator = NULL, *item;
9012
9013
0
    iterator = PyObject_GetIter(mask);
9014
0
    if (iterator == NULL)
9015
0
        return NULL;
9016
9017
0
    ncpus = NCPUS_START;
9018
0
    setsize = CPU_ALLOC_SIZE(ncpus);
9019
0
    cpu_set = CPU_ALLOC(ncpus);
9020
0
    if (cpu_set == NULL) {
9021
0
        PyErr_NoMemory();
9022
0
        goto error;
9023
0
    }
9024
0
    CPU_ZERO_S(setsize, cpu_set);
9025
9026
0
    while ((item = PyIter_Next(iterator))) {
9027
0
        long cpu;
9028
0
        if (!PyIndex_Check(item)) {
9029
0
            PyErr_Format(PyExc_TypeError,
9030
0
                        "expected an iterator of ints, "
9031
0
                        "but iterator yielded %R",
9032
0
                        Py_TYPE(item));
9033
0
            Py_DECREF(item);
9034
0
            goto error;
9035
0
        }
9036
0
        cpu = PyLong_AsLong(item);
9037
0
        Py_DECREF(item);
9038
0
        if (cpu < 0) {
9039
0
            if (!PyErr_Occurred())
9040
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9041
0
            goto error;
9042
0
        }
9043
0
        if (cpu > INT_MAX - 1) {
9044
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9045
0
            goto error;
9046
0
        }
9047
0
        if (cpu >= ncpus) {
9048
            /* Grow CPU mask to fit the CPU number */
9049
0
            int newncpus = ncpus;
9050
0
            cpu_set_t *newmask;
9051
0
            size_t newsetsize;
9052
0
            while (newncpus <= cpu) {
9053
0
                if (newncpus > INT_MAX / 2)
9054
0
                    newncpus = cpu + 1;
9055
0
                else
9056
0
                    newncpus = newncpus * 2;
9057
0
            }
9058
0
            newmask = CPU_ALLOC(newncpus);
9059
0
            if (newmask == NULL) {
9060
0
                PyErr_NoMemory();
9061
0
                goto error;
9062
0
            }
9063
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9064
0
            CPU_ZERO_S(newsetsize, newmask);
9065
0
            memcpy(newmask, cpu_set, setsize);
9066
0
            CPU_FREE(cpu_set);
9067
0
            setsize = newsetsize;
9068
0
            cpu_set = newmask;
9069
0
            ncpus = newncpus;
9070
0
        }
9071
0
        CPU_SET_S(cpu, setsize, cpu_set);
9072
0
    }
9073
0
    if (PyErr_Occurred()) {
9074
0
        goto error;
9075
0
    }
9076
0
    Py_CLEAR(iterator);
9077
9078
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9079
0
        posix_error();
9080
0
        goto error;
9081
0
    }
9082
0
    CPU_FREE(cpu_set);
9083
0
    Py_RETURN_NONE;
9084
9085
0
error:
9086
0
    if (cpu_set)
9087
0
        CPU_FREE(cpu_set);
9088
0
    Py_XDECREF(iterator);
9089
0
    return NULL;
9090
0
}
9091
9092
9093
/*[clinic input]
9094
@permit_long_summary
9095
os.sched_getaffinity
9096
    pid: pid_t
9097
    /
9098
9099
Return the affinity of the process identified by pid (or the current process if zero).
9100
9101
The affinity is returned as a set of CPU identifiers.
9102
[clinic start generated code]*/
9103
9104
static PyObject *
9105
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9106
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9107
0
{
9108
0
    int ncpus = NCPUS_START;
9109
0
    size_t setsize;
9110
0
    cpu_set_t *mask;
9111
9112
0
    while (1) {
9113
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9114
0
        mask = CPU_ALLOC(ncpus);
9115
0
        if (mask == NULL) {
9116
0
            return PyErr_NoMemory();
9117
0
        }
9118
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9119
0
            break;
9120
0
        }
9121
0
        CPU_FREE(mask);
9122
0
        if (errno != EINVAL) {
9123
0
            return posix_error();
9124
0
        }
9125
0
        if (ncpus > INT_MAX / 2) {
9126
0
            PyErr_SetString(PyExc_OverflowError,
9127
0
                            "could not allocate a large enough CPU set");
9128
0
            return NULL;
9129
0
        }
9130
0
        ncpus *= 2;
9131
0
    }
9132
9133
0
    PyObject *res = PySet_New(NULL);
9134
0
    if (res == NULL) {
9135
0
        goto error;
9136
0
    }
9137
9138
0
    int cpu = 0;
9139
0
    int count = CPU_COUNT_S(setsize, mask);
9140
0
    for (; count; cpu++) {
9141
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9142
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9143
0
            --count;
9144
0
            if (cpu_num == NULL) {
9145
0
                goto error;
9146
0
            }
9147
0
            if (PySet_Add(res, cpu_num)) {
9148
0
                Py_DECREF(cpu_num);
9149
0
                goto error;
9150
0
            }
9151
0
            Py_DECREF(cpu_num);
9152
0
        }
9153
0
    }
9154
0
    CPU_FREE(mask);
9155
0
    return res;
9156
9157
0
error:
9158
0
    if (mask) {
9159
0
        CPU_FREE(mask);
9160
0
    }
9161
0
    Py_XDECREF(res);
9162
0
    return NULL;
9163
0
}
9164
#endif /* HAVE_SCHED_SETAFFINITY */
9165
9166
#endif /* HAVE_SCHED_H */
9167
9168
9169
#ifdef HAVE_POSIX_OPENPT
9170
/*[clinic input]
9171
os.posix_openpt -> int
9172
9173
    oflag: int
9174
    /
9175
9176
Open and return a file descriptor for a master pseudo-terminal device.
9177
9178
Performs a posix_openpt() C function call. The oflag argument is used to
9179
set file status flags and file access modes as specified in the manual
9180
page of posix_openpt() of your system.
9181
[clinic start generated code]*/
9182
9183
static int
9184
os_posix_openpt_impl(PyObject *module, int oflag)
9185
/*[clinic end generated code: output=ee0bc2624305fc79 input=3ce4eb297fa64307]*/
9186
0
{
9187
0
    int fd;
9188
9189
0
#if defined(O_CLOEXEC)
9190
0
    oflag |= O_CLOEXEC;
9191
0
#endif
9192
9193
0
    fd = posix_openpt(oflag);
9194
0
    if (fd == -1) {
9195
0
        posix_error();
9196
0
        return -1;
9197
0
    }
9198
9199
    // Just in case, likely a no-op given O_CLOEXEC above.
9200
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9201
0
        close(fd);
9202
0
        return -1;
9203
0
    }
9204
9205
0
    return fd;
9206
0
}
9207
#endif /* HAVE_POSIX_OPENPT */
9208
9209
#ifdef HAVE_GRANTPT
9210
/*[clinic input]
9211
os.grantpt
9212
9213
    fd: fildes
9214
        File descriptor of a master pseudo-terminal device.
9215
    /
9216
9217
Grant access to the slave pseudo-terminal device.
9218
9219
Performs a grantpt() C function call.
9220
[clinic start generated code]*/
9221
9222
static PyObject *
9223
os_grantpt_impl(PyObject *module, int fd)
9224
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9225
0
{
9226
0
    int ret;
9227
0
    int saved_errno;
9228
0
    PyOS_sighandler_t sig_saved;
9229
9230
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9231
9232
0
    ret = grantpt(fd);
9233
0
    if (ret == -1)
9234
0
        saved_errno = errno;
9235
9236
0
    PyOS_setsig(SIGCHLD, sig_saved);
9237
9238
0
    if (ret == -1) {
9239
0
        errno = saved_errno;
9240
0
        return posix_error();
9241
0
    }
9242
9243
0
    Py_RETURN_NONE;
9244
0
}
9245
#endif /* HAVE_GRANTPT */
9246
9247
#ifdef HAVE_UNLOCKPT
9248
/*[clinic input]
9249
os.unlockpt
9250
9251
    fd: fildes
9252
        File descriptor of a master pseudo-terminal device.
9253
    /
9254
9255
Unlock a pseudo-terminal master/slave pair.
9256
9257
Performs an unlockpt() C function call.
9258
[clinic start generated code]*/
9259
9260
static PyObject *
9261
os_unlockpt_impl(PyObject *module, int fd)
9262
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9263
0
{
9264
0
    if (unlockpt(fd) == -1)
9265
0
        return posix_error();
9266
9267
0
    Py_RETURN_NONE;
9268
0
}
9269
#endif /* HAVE_UNLOCKPT */
9270
9271
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9272
static PyObject *
9273
py_ptsname(int fd)
9274
0
{
9275
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9276
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9277
0
    errno = 0;
9278
0
    char *name = ptsname(fd);
9279
0
    if (name == NULL) {
9280
0
        return posix_error();
9281
0
    }
9282
0
    return PyUnicode_DecodeFSDefault(name);
9283
0
}
9284
9285
/*[clinic input]
9286
os.ptsname
9287
9288
    fd: fildes
9289
        File descriptor of a master pseudo-terminal device.
9290
    /
9291
9292
Return the name of the slave pseudo-terminal device.
9293
9294
If the ptsname_r() C function is available, it is called;
9295
otherwise, performs a ptsname() C function call.
9296
[clinic start generated code]*/
9297
9298
static PyObject *
9299
os_ptsname_impl(PyObject *module, int fd)
9300
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9301
0
{
9302
0
#ifdef HAVE_PTSNAME_R
9303
0
    int ret;
9304
0
    char name[MAXPATHLEN+1];
9305
9306
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9307
0
        ret = ptsname_r(fd, name, sizeof(name));
9308
0
    }
9309
0
    else {
9310
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9311
0
        return py_ptsname(fd);
9312
0
    }
9313
0
    if (ret != 0) {
9314
0
        errno = ret;
9315
0
        return posix_error();
9316
0
    }
9317
9318
0
    return PyUnicode_DecodeFSDefault(name);
9319
#else
9320
    return py_ptsname(fd);
9321
#endif /* HAVE_PTSNAME_R */
9322
0
}
9323
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9324
9325
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9326
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9327
#  define DEV_PTY_FILE "/dev/ptc"
9328
#  define HAVE_DEV_PTMX
9329
#else
9330
#  define DEV_PTY_FILE "/dev/ptmx"
9331
#endif
9332
9333
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9334
#ifdef HAVE_PTY_H
9335
#include <pty.h>
9336
#elif defined(HAVE_LIBUTIL_H)
9337
#include <libutil.h>
9338
#elif defined(HAVE_UTIL_H)
9339
#include <util.h>
9340
#endif /* HAVE_PTY_H */
9341
#ifdef HAVE_UTMP_H
9342
#include <utmp.h>
9343
#endif /* HAVE_UTMP_H */
9344
#ifdef HAVE_STROPTS_H
9345
#include <stropts.h>
9346
#endif
9347
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9348
9349
9350
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9351
/*[clinic input]
9352
os.openpty
9353
9354
Open a pseudo-terminal.
9355
9356
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9357
for both the master and slave ends.
9358
[clinic start generated code]*/
9359
9360
static PyObject *
9361
os_openpty_impl(PyObject *module)
9362
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9363
0
{
9364
0
    int master_fd = -1, slave_fd = -1;
9365
#ifndef HAVE_OPENPTY
9366
    char * slave_name;
9367
#endif
9368
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9369
    PyOS_sighandler_t sig_saved;
9370
#if defined(__sun) && defined(__SVR4)
9371
    extern char *ptsname(int fildes);
9372
#endif
9373
#endif
9374
9375
0
#ifdef HAVE_OPENPTY
9376
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9377
0
        goto posix_error;
9378
9379
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9380
0
        goto error;
9381
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9382
0
        goto error;
9383
9384
#elif defined(HAVE__GETPTY)
9385
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9386
    if (slave_name == NULL)
9387
        goto posix_error;
9388
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9389
        goto error;
9390
9391
    slave_fd = _Py_open(slave_name, O_RDWR);
9392
    if (slave_fd < 0)
9393
        goto error;
9394
9395
#else
9396
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9397
    if (master_fd < 0)
9398
        goto posix_error;
9399
9400
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9401
9402
    /* change permission of slave */
9403
    if (grantpt(master_fd) < 0) {
9404
        int saved_errno = errno;
9405
        PyOS_setsig(SIGCHLD, sig_saved);
9406
        errno = saved_errno;
9407
        goto posix_error;
9408
    }
9409
9410
    /* unlock slave */
9411
    if (unlockpt(master_fd) < 0) {
9412
        int saved_errno = errno;
9413
        PyOS_setsig(SIGCHLD, sig_saved);
9414
        errno = saved_errno;
9415
        goto posix_error;
9416
    }
9417
9418
    PyOS_setsig(SIGCHLD, sig_saved);
9419
9420
    slave_name = ptsname(master_fd); /* get name of slave */
9421
    if (slave_name == NULL)
9422
        goto posix_error;
9423
9424
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9425
    if (slave_fd == -1)
9426
        goto error;
9427
9428
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9429
        goto posix_error;
9430
9431
#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC)
9432
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9433
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9434
#ifndef __hpux
9435
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9436
#endif /* __hpux */
9437
#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
9438
#endif /* HAVE_OPENPTY */
9439
9440
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9441
9442
0
posix_error:
9443
0
    posix_error();
9444
0
error:
9445
0
    if (master_fd != -1)
9446
0
        close(master_fd);
9447
0
    if (slave_fd != -1)
9448
0
        close(slave_fd);
9449
0
    return NULL;
9450
0
}
9451
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9452
9453
9454
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9455
#define HAVE_FALLBACK_LOGIN_TTY 1
9456
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9457
9458
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9459
/*[clinic input]
9460
@permit_long_summary
9461
os.login_tty
9462
9463
    fd: fildes
9464
    /
9465
9466
Prepare the tty of which fd is a file descriptor for a new login session.
9467
9468
Make the calling process a session leader; make the tty the
9469
controlling tty, the stdin, the stdout, and the stderr of the
9470
calling process; close fd.
9471
[clinic start generated code]*/
9472
9473
static PyObject *
9474
os_login_tty_impl(PyObject *module, int fd)
9475
/*[clinic end generated code: output=495a79911b4cc1bc input=b102a7c36e8baf00]*/
9476
0
{
9477
0
#ifdef HAVE_LOGIN_TTY
9478
0
    if (login_tty(fd) == -1) {
9479
0
        return posix_error();
9480
0
    }
9481
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9482
    /* Establish a new session. */
9483
    if (setsid() == -1) {
9484
        return posix_error();
9485
    }
9486
9487
    /* The tty becomes the controlling terminal. */
9488
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9489
        return posix_error();
9490
    }
9491
9492
    /* The tty becomes stdin/stdout/stderr */
9493
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9494
        return posix_error();
9495
    }
9496
    if (fd > 2) {
9497
        close(fd);
9498
    }
9499
#endif /* HAVE_LOGIN_TTY */
9500
0
    Py_RETURN_NONE;
9501
0
}
9502
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9503
9504
9505
#ifdef HAVE_FORKPTY
9506
/*[clinic input]
9507
os.forkpty
9508
9509
Fork a new process with a new pseudo-terminal as controlling tty.
9510
9511
Returns a tuple of (pid, master_fd).
9512
Like fork(), return pid of 0 to the child process,
9513
and pid of child to the parent process.
9514
To both, return fd of newly opened pseudo-terminal.
9515
The master_fd is non-inheritable.
9516
[clinic start generated code]*/
9517
9518
static PyObject *
9519
os_forkpty_impl(PyObject *module)
9520
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9521
0
{
9522
0
    int master_fd = -1;
9523
0
    pid_t pid;
9524
9525
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9526
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9527
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9528
0
                        "can't fork at interpreter shutdown");
9529
0
        return NULL;
9530
0
    }
9531
0
    if (!_Py_IsMainInterpreter(interp)) {
9532
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9533
0
        return NULL;
9534
0
    }
9535
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9536
0
        return NULL;
9537
0
    }
9538
0
    PyOS_BeforeFork();
9539
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9540
0
    if (pid == 0) {
9541
        /* child: this clobbers and resets the import lock. */
9542
0
        PyOS_AfterFork_Child();
9543
0
    } else {
9544
        // Called before AfterFork_Parent in case those hooks start threads.
9545
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9546
        /* parent: release the import lock. */
9547
0
        PyOS_AfterFork_Parent();
9548
        /* set O_CLOEXEC on master_fd */
9549
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9550
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9551
0
                                   "non-inheritable in forkpty()");
9552
0
        }
9553
9554
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9555
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9556
0
            return NULL;
9557
0
    }
9558
0
    if (pid == -1) {
9559
0
        return posix_error();
9560
0
    }
9561
9562
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9563
0
}
9564
#endif /* HAVE_FORKPTY */
9565
9566
9567
#ifdef HAVE_GETEGID
9568
/*[clinic input]
9569
os.getegid
9570
9571
Return the current process's effective group id.
9572
[clinic start generated code]*/
9573
9574
static PyObject *
9575
os_getegid_impl(PyObject *module)
9576
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9577
36
{
9578
36
    return _PyLong_FromGid(getegid());
9579
36
}
9580
#endif /* HAVE_GETEGID */
9581
9582
9583
#ifdef HAVE_GETEUID
9584
/*[clinic input]
9585
os.geteuid
9586
9587
Return the current process's effective user id.
9588
[clinic start generated code]*/
9589
9590
static PyObject *
9591
os_geteuid_impl(PyObject *module)
9592
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9593
36
{
9594
36
    return _PyLong_FromUid(geteuid());
9595
36
}
9596
#endif /* HAVE_GETEUID */
9597
9598
9599
#ifdef HAVE_GETGID
9600
/*[clinic input]
9601
os.getgid
9602
9603
Return the current process's group id.
9604
[clinic start generated code]*/
9605
9606
static PyObject *
9607
os_getgid_impl(PyObject *module)
9608
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9609
36
{
9610
36
    return _PyLong_FromGid(getgid());
9611
36
}
9612
#endif /* HAVE_GETGID */
9613
9614
9615
#if defined(HAVE_GETPID)
9616
/*[clinic input]
9617
os.getpid
9618
9619
Return the current process id.
9620
[clinic start generated code]*/
9621
9622
static PyObject *
9623
os_getpid_impl(PyObject *module)
9624
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9625
4.30k
{
9626
4.30k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9627
4.30k
    return PyLong_FromPid(getpid());
9628
#else
9629
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9630
#endif
9631
4.30k
}
9632
#endif /* defined(HAVE_GETPID) */
9633
9634
#ifdef NGROUPS_MAX
9635
0
#define MAX_GROUPS NGROUPS_MAX
9636
#else
9637
    /* defined to be 16 on Solaris7, so this should be a small number */
9638
#define MAX_GROUPS 64
9639
#endif
9640
9641
#ifdef HAVE_GETGROUPLIST
9642
9643
#ifdef __APPLE__
9644
/*[clinic input]
9645
os.getgrouplist
9646
9647
    user: str
9648
        username to lookup
9649
    group as basegid: int
9650
        base group id of the user
9651
    /
9652
9653
Returns a list of groups to which a user belongs.
9654
[clinic start generated code]*/
9655
9656
static PyObject *
9657
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9658
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9659
#else
9660
/*[clinic input]
9661
os.getgrouplist
9662
9663
    user: str
9664
        username to lookup
9665
    group as basegid: gid_t
9666
        base group id of the user
9667
    /
9668
9669
Returns a list of groups to which a user belongs.
9670
[clinic start generated code]*/
9671
9672
static PyObject *
9673
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9674
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9675
#endif
9676
0
{
9677
0
    int i, ngroups;
9678
0
    PyObject *list;
9679
#ifdef __APPLE__
9680
    int *groups;
9681
#else
9682
0
    gid_t *groups;
9683
0
#endif
9684
9685
    /*
9686
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9687
     * number of supplemental groups a users can belong to.
9688
     * We have to increment it by one because
9689
     * getgrouplist() returns both the supplemental groups
9690
     * and the primary group, i.e. all of the groups the
9691
     * user belongs to.
9692
     */
9693
0
    ngroups = 1 + MAX_GROUPS;
9694
9695
0
    while (1) {
9696
#ifdef __APPLE__
9697
        groups = PyMem_New(int, ngroups);
9698
#else
9699
0
        groups = PyMem_New(gid_t, ngroups);
9700
0
#endif
9701
0
        if (groups == NULL) {
9702
0
            return PyErr_NoMemory();
9703
0
        }
9704
9705
0
        int old_ngroups = ngroups;
9706
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9707
            /* Success */
9708
0
            break;
9709
0
        }
9710
9711
        /* getgrouplist() fails if the group list is too small */
9712
0
        PyMem_Free(groups);
9713
9714
0
        if (ngroups > old_ngroups) {
9715
            /* If the group list is too small, the glibc implementation of
9716
               getgrouplist() sets ngroups to the total number of groups and
9717
               returns -1. */
9718
0
        }
9719
0
        else {
9720
            /* Double the group list size */
9721
0
            if (ngroups > INT_MAX / 2) {
9722
0
                return PyErr_NoMemory();
9723
0
            }
9724
0
            ngroups *= 2;
9725
0
        }
9726
9727
        /* Retry getgrouplist() with a larger group list */
9728
0
    }
9729
9730
#ifdef _Py_MEMORY_SANITIZER
9731
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9732
    __msan_unpoison(&ngroups, sizeof(ngroups));
9733
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9734
#endif
9735
9736
0
    list = PyList_New(ngroups);
9737
0
    if (list == NULL) {
9738
0
        PyMem_Free(groups);
9739
0
        return NULL;
9740
0
    }
9741
9742
0
    for (i = 0; i < ngroups; i++) {
9743
#ifdef __APPLE__
9744
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9745
#else
9746
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9747
0
#endif
9748
0
        if (o == NULL) {
9749
0
            Py_DECREF(list);
9750
0
            PyMem_Free(groups);
9751
0
            return NULL;
9752
0
        }
9753
0
        PyList_SET_ITEM(list, i, o);
9754
0
    }
9755
9756
0
    PyMem_Free(groups);
9757
9758
0
    return list;
9759
0
}
9760
#endif /* HAVE_GETGROUPLIST */
9761
9762
9763
#ifdef HAVE_GETGROUPS
9764
/*[clinic input]
9765
os.getgroups
9766
9767
Return list of supplemental group IDs for the process.
9768
[clinic start generated code]*/
9769
9770
static PyObject *
9771
os_getgroups_impl(PyObject *module)
9772
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9773
0
{
9774
    // Call getgroups with length 0 to get the actual number of groups
9775
0
    int n = getgroups(0, NULL);
9776
0
    if (n < 0) {
9777
0
        return posix_error();
9778
0
    }
9779
9780
0
    if (n == 0) {
9781
0
        return PyList_New(0);
9782
0
    }
9783
9784
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9785
0
    if (grouplist == NULL) {
9786
0
        return PyErr_NoMemory();
9787
0
    }
9788
9789
0
    n = getgroups(n, grouplist);
9790
0
    if (n == -1) {
9791
0
        posix_error();
9792
0
        PyMem_Free(grouplist);
9793
0
        return NULL;
9794
0
    }
9795
9796
0
    PyObject *result = PyList_New(n);
9797
0
    if (result == NULL) {
9798
0
        goto error;
9799
0
    }
9800
9801
0
    for (int i = 0; i < n; ++i) {
9802
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9803
0
        if (group == NULL) {
9804
0
            goto error;
9805
0
        }
9806
0
        PyList_SET_ITEM(result, i, group);
9807
0
    }
9808
0
    PyMem_Free(grouplist);
9809
9810
0
    return result;
9811
9812
0
error:
9813
0
    PyMem_Free(grouplist);
9814
0
    Py_XDECREF(result);
9815
0
    return NULL;
9816
0
}
9817
#endif /* HAVE_GETGROUPS */
9818
9819
#ifdef HAVE_INITGROUPS
9820
#ifdef __APPLE__
9821
/*[clinic input]
9822
os.initgroups
9823
9824
    username as oname: unicode_fs_encoded
9825
    gid: int
9826
    /
9827
9828
Initialize the group access list.
9829
9830
Call the system initgroups() to initialize the group access list with
9831
all of the groups of which the specified username is a member, plus the
9832
specified group id.
9833
[clinic start generated code]*/
9834
9835
static PyObject *
9836
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9837
/*[clinic end generated code: output=7f074d30a425fd3a input=35f2d4fb7fcc0bdf]*/
9838
#else
9839
/*[clinic input]
9840
os.initgroups
9841
9842
    username as oname: unicode_fs_encoded
9843
    gid: gid_t
9844
    /
9845
9846
Initialize the group access list.
9847
9848
Call the system initgroups() to initialize the group access list with
9849
all of the groups of which the specified username is a member, plus the
9850
specified group id.
9851
[clinic start generated code]*/
9852
9853
static PyObject *
9854
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9855
/*[clinic end generated code: output=59341244521a9e3f input=7e4514dff4526a95]*/
9856
#endif
9857
0
{
9858
0
    const char *username = PyBytes_AS_STRING(oname);
9859
9860
0
    if (initgroups(username, gid) == -1)
9861
0
        return PyErr_SetFromErrno(PyExc_OSError);
9862
9863
0
    Py_RETURN_NONE;
9864
0
}
9865
#endif /* HAVE_INITGROUPS */
9866
9867
9868
#ifdef HAVE_GETPGID
9869
/*[clinic input]
9870
os.getpgid
9871
9872
    pid: pid_t
9873
9874
Call the system call getpgid(), and return the result.
9875
[clinic start generated code]*/
9876
9877
static PyObject *
9878
os_getpgid_impl(PyObject *module, pid_t pid)
9879
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9880
0
{
9881
0
    pid_t pgid = getpgid(pid);
9882
0
    if (pgid < 0)
9883
0
        return posix_error();
9884
0
    return PyLong_FromPid(pgid);
9885
0
}
9886
#endif /* HAVE_GETPGID */
9887
9888
9889
#ifdef HAVE_GETPGRP
9890
/*[clinic input]
9891
os.getpgrp
9892
9893
Return the current process group id.
9894
[clinic start generated code]*/
9895
9896
static PyObject *
9897
os_getpgrp_impl(PyObject *module)
9898
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9899
0
{
9900
#ifdef GETPGRP_HAVE_ARG
9901
    return PyLong_FromPid(getpgrp(0));
9902
#else /* GETPGRP_HAVE_ARG */
9903
0
    return PyLong_FromPid(getpgrp());
9904
0
#endif /* GETPGRP_HAVE_ARG */
9905
0
}
9906
#endif /* HAVE_GETPGRP */
9907
9908
9909
#ifdef HAVE_SETPGRP
9910
/*[clinic input]
9911
os.setpgrp
9912
9913
Make the current process the leader of its process group.
9914
[clinic start generated code]*/
9915
9916
static PyObject *
9917
os_setpgrp_impl(PyObject *module)
9918
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9919
0
{
9920
#ifdef SETPGRP_HAVE_ARG
9921
    if (setpgrp(0, 0) < 0)
9922
#else /* SETPGRP_HAVE_ARG */
9923
0
    if (setpgrp() < 0)
9924
0
#endif /* SETPGRP_HAVE_ARG */
9925
0
        return posix_error();
9926
0
    Py_RETURN_NONE;
9927
0
}
9928
#endif /* HAVE_SETPGRP */
9929
9930
#ifdef HAVE_GETPPID
9931
9932
#ifdef MS_WINDOWS
9933
#include <winternl.h>
9934
#include <ProcessSnapshot.h>
9935
9936
// The structure definition in winternl.h may be incomplete.
9937
// This structure is the full version from the MSDN documentation.
9938
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9939
    NTSTATUS ExitStatus;
9940
    PVOID PebBaseAddress;
9941
    ULONG_PTR AffinityMask;
9942
    LONG BasePriority;
9943
    ULONG_PTR UniqueProcessId;
9944
    ULONG_PTR InheritedFromUniqueProcessId;
9945
} PROCESS_BASIC_INFORMATION_FULL;
9946
9947
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9948
    IN    HANDLE           ProcessHandle,
9949
    IN    PROCESSINFOCLASS ProcessInformationClass,
9950
    OUT   PVOID            ProcessInformation,
9951
    IN    ULONG            ProcessInformationLength,
9952
    OUT   PULONG           ReturnLength OPTIONAL);
9953
9954
// This function returns the process ID of the parent process.
9955
// Returns 0 on failure.
9956
static ULONG
9957
win32_getppid_fast(void)
9958
{
9959
    NTSTATUS status;
9960
    HMODULE ntdll;
9961
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9962
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9963
    static ULONG cached_ppid = 0;
9964
9965
    if (cached_ppid) {
9966
        // No need to query the kernel again.
9967
        return cached_ppid;
9968
    }
9969
9970
    ntdll = GetModuleHandleW(L"ntdll.dll");
9971
    if (!ntdll) {
9972
        return 0;
9973
    }
9974
9975
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9976
    if (!pNtQueryInformationProcess) {
9977
        return 0;
9978
    }
9979
9980
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9981
                                        ProcessBasicInformation,
9982
                                        &basic_information,
9983
                                        sizeof(basic_information),
9984
                                        NULL);
9985
9986
    if (!NT_SUCCESS(status)) {
9987
        return 0;
9988
    }
9989
9990
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9991
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9992
    // zero and (ULONG) -1.
9993
9994
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9995
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9996
    {
9997
        return 0;
9998
    }
9999
10000
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
10001
    // structure member contains a ULONG_PTR which represents the process ID of our parent
10002
    // process. This process ID will be correctly returned even if the parent process has
10003
    // exited or been terminated.
10004
10005
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
10006
    return cached_ppid;
10007
}
10008
10009
static PyObject*
10010
win32_getppid(void)
10011
{
10012
    DWORD error;
10013
    PyObject* result = NULL;
10014
    HANDLE process = GetCurrentProcess();
10015
    HPSS snapshot = NULL;
10016
    ULONG pid;
10017
10018
    pid = win32_getppid_fast();
10019
    if (pid != 0) {
10020
        return PyLong_FromUnsignedLong(pid);
10021
    }
10022
10023
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
10024
10025
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
10026
    if (error != ERROR_SUCCESS) {
10027
        return PyErr_SetFromWindowsErr(error);
10028
    }
10029
10030
    PSS_PROCESS_INFORMATION info;
10031
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
10032
                             sizeof(info));
10033
    if (error == ERROR_SUCCESS) {
10034
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
10035
    }
10036
    else {
10037
        result = PyErr_SetFromWindowsErr(error);
10038
    }
10039
10040
    PssFreeSnapshot(process, snapshot);
10041
    return result;
10042
}
10043
#endif /*MS_WINDOWS*/
10044
10045
10046
/*[clinic input]
10047
os.getppid
10048
10049
Return the parent's process id.
10050
10051
If the parent process has already exited, Windows machines will still
10052
return its id; others systems will return the id of the 'init' proces
10053
(1).
10054
[clinic start generated code]*/
10055
10056
static PyObject *
10057
os_getppid_impl(PyObject *module)
10058
/*[clinic end generated code: output=43b2a946a8c603b4 input=e17c1de18f41316b]*/
10059
0
{
10060
#ifdef MS_WINDOWS
10061
    return win32_getppid();
10062
#else
10063
0
    return PyLong_FromPid(getppid());
10064
0
#endif
10065
0
}
10066
#endif /* HAVE_GETPPID */
10067
10068
10069
#ifdef HAVE_GETLOGIN
10070
/*[clinic input]
10071
os.getlogin
10072
10073
Return the actual login name.
10074
[clinic start generated code]*/
10075
10076
static PyObject *
10077
os_getlogin_impl(PyObject *module)
10078
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10079
0
{
10080
0
    PyObject *result = NULL;
10081
#ifdef MS_WINDOWS
10082
    wchar_t user_name[UNLEN + 1];
10083
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10084
10085
    if (GetUserNameW(user_name, &num_chars)) {
10086
        /* num_chars is the number of unicode chars plus null terminator */
10087
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10088
    }
10089
    else
10090
        result = PyErr_SetFromWindowsErr(GetLastError());
10091
#elif defined (HAVE_GETLOGIN_R)
10092
# if defined (HAVE_MAXLOGNAME)
10093
    char name[MAXLOGNAME + 1];
10094
# elif defined (HAVE_UT_NAMESIZE)
10095
    char name[UT_NAMESIZE + 1];
10096
# else
10097
    char name[256];
10098
# endif
10099
0
    int err = getlogin_r(name, sizeof(name));
10100
0
    if (err) {
10101
0
        int old_errno = errno;
10102
0
        errno = err;
10103
0
        posix_error();
10104
0
        errno = old_errno;
10105
0
    }
10106
0
    else {
10107
0
        result = PyUnicode_DecodeFSDefault(name);
10108
0
    }
10109
#else
10110
    char *name;
10111
    int old_errno = errno;
10112
10113
    errno = 0;
10114
    name = getlogin();
10115
    if (name == NULL) {
10116
        if (errno)
10117
            posix_error();
10118
        else
10119
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10120
    }
10121
    else
10122
        result = PyUnicode_DecodeFSDefault(name);
10123
    errno = old_errno;
10124
#endif
10125
0
    return result;
10126
0
}
10127
#endif /* HAVE_GETLOGIN */
10128
10129
10130
#ifdef HAVE_GETUID
10131
/*[clinic input]
10132
os.getuid
10133
10134
Return the current process's user id.
10135
[clinic start generated code]*/
10136
10137
static PyObject *
10138
os_getuid_impl(PyObject *module)
10139
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10140
36
{
10141
36
    return _PyLong_FromUid(getuid());
10142
36
}
10143
#endif /* HAVE_GETUID */
10144
10145
10146
#ifdef MS_WINDOWS
10147
#define HAVE_KILL
10148
#endif /* MS_WINDOWS */
10149
10150
#ifdef HAVE_KILL
10151
/*[clinic input]
10152
os.kill
10153
10154
    pid: pid_t
10155
    signal: Py_ssize_t
10156
    /
10157
10158
Kill a process with a signal.
10159
[clinic start generated code]*/
10160
10161
static PyObject *
10162
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10163
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10164
0
{
10165
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10166
0
        return NULL;
10167
0
    }
10168
0
#ifndef MS_WINDOWS
10169
0
    if (kill(pid, (int)signal) == -1) {
10170
0
        return posix_error();
10171
0
    }
10172
10173
    // Check immediately if the signal was sent to the current process.
10174
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10175
    // is cheap.
10176
0
    if (PyErr_CheckSignals()) {
10177
0
        return NULL;
10178
0
    }
10179
10180
0
    Py_RETURN_NONE;
10181
#else /* !MS_WINDOWS */
10182
    DWORD sig = (DWORD)signal;
10183
10184
#ifdef HAVE_WINDOWS_CONSOLE_IO
10185
    /* Console processes which share a common console can be sent CTRL+C or
10186
       CTRL+BREAK events, provided they handle said events. */
10187
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10188
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10189
            return PyErr_SetFromWindowsErr(0);
10190
        }
10191
        Py_RETURN_NONE;
10192
    }
10193
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10194
10195
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10196
       attempt to open and terminate the process. */
10197
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10198
    if (handle == NULL) {
10199
        return PyErr_SetFromWindowsErr(0);
10200
    }
10201
10202
    BOOL res = TerminateProcess(handle, sig);
10203
    CloseHandle(handle);
10204
    if (res == 0) {
10205
        return PyErr_SetFromWindowsErr(0);
10206
    }
10207
10208
    Py_RETURN_NONE;
10209
#endif /* !MS_WINDOWS */
10210
0
}
10211
#endif /* HAVE_KILL */
10212
10213
10214
#ifdef HAVE_KILLPG
10215
/*[clinic input]
10216
os.killpg
10217
10218
    pgid: pid_t
10219
    signal: int
10220
    /
10221
10222
Kill a process group with a signal.
10223
[clinic start generated code]*/
10224
10225
static PyObject *
10226
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10227
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10228
0
{
10229
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10230
0
        return NULL;
10231
0
    }
10232
    /* XXX some man pages make the `pgid` parameter an int, others
10233
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10234
       take the same type. Moreover, pid_t is always at least as wide as
10235
       int (else compilation of this module fails), which is safe. */
10236
0
    if (killpg(pgid, signal) == -1)
10237
0
        return posix_error();
10238
0
    Py_RETURN_NONE;
10239
0
}
10240
#endif /* HAVE_KILLPG */
10241
10242
10243
#ifdef HAVE_PLOCK
10244
#ifdef HAVE_SYS_LOCK_H
10245
#include <sys/lock.h>
10246
#endif
10247
10248
/*[clinic input]
10249
os.plock
10250
    op: int
10251
    /
10252
10253
Lock program segments into memory.");
10254
[clinic start generated code]*/
10255
10256
static PyObject *
10257
os_plock_impl(PyObject *module, int op)
10258
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10259
{
10260
    if (plock(op) == -1)
10261
        return posix_error();
10262
    Py_RETURN_NONE;
10263
}
10264
#endif /* HAVE_PLOCK */
10265
10266
10267
#ifdef HAVE_SETUID
10268
/*[clinic input]
10269
os.setuid
10270
10271
    uid: uid_t
10272
    /
10273
10274
Set the current process's user id.
10275
[clinic start generated code]*/
10276
10277
static PyObject *
10278
os_setuid_impl(PyObject *module, uid_t uid)
10279
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10280
0
{
10281
0
    if (setuid(uid) < 0)
10282
0
        return posix_error();
10283
0
    Py_RETURN_NONE;
10284
0
}
10285
#endif /* HAVE_SETUID */
10286
10287
10288
#ifdef HAVE_SETEUID
10289
/*[clinic input]
10290
os.seteuid
10291
10292
    euid: uid_t
10293
    /
10294
10295
Set the current process's effective user id.
10296
[clinic start generated code]*/
10297
10298
static PyObject *
10299
os_seteuid_impl(PyObject *module, uid_t euid)
10300
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10301
0
{
10302
0
    if (seteuid(euid) < 0)
10303
0
        return posix_error();
10304
0
    Py_RETURN_NONE;
10305
0
}
10306
#endif /* HAVE_SETEUID */
10307
10308
10309
#ifdef HAVE_SETEGID
10310
/*[clinic input]
10311
os.setegid
10312
10313
    egid: gid_t
10314
    /
10315
10316
Set the current process's effective group id.
10317
[clinic start generated code]*/
10318
10319
static PyObject *
10320
os_setegid_impl(PyObject *module, gid_t egid)
10321
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10322
0
{
10323
0
    if (setegid(egid) < 0)
10324
0
        return posix_error();
10325
0
    Py_RETURN_NONE;
10326
0
}
10327
#endif /* HAVE_SETEGID */
10328
10329
10330
#ifdef HAVE_SETREUID
10331
/*[clinic input]
10332
os.setreuid
10333
10334
    ruid: uid_t
10335
    euid: uid_t
10336
    /
10337
10338
Set the current process's real and effective user ids.
10339
[clinic start generated code]*/
10340
10341
static PyObject *
10342
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10343
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10344
0
{
10345
0
    if (setreuid(ruid, euid) < 0) {
10346
0
        return posix_error();
10347
0
    } else {
10348
0
        Py_RETURN_NONE;
10349
0
    }
10350
0
}
10351
#endif /* HAVE_SETREUID */
10352
10353
10354
#ifdef HAVE_SETREGID
10355
/*[clinic input]
10356
os.setregid
10357
10358
    rgid: gid_t
10359
    egid: gid_t
10360
    /
10361
10362
Set the current process's real and effective group ids.
10363
[clinic start generated code]*/
10364
10365
static PyObject *
10366
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10367
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10368
0
{
10369
0
    if (setregid(rgid, egid) < 0)
10370
0
        return posix_error();
10371
0
    Py_RETURN_NONE;
10372
0
}
10373
#endif /* HAVE_SETREGID */
10374
10375
10376
#ifdef HAVE_SETGID
10377
/*[clinic input]
10378
os.setgid
10379
    gid: gid_t
10380
    /
10381
10382
Set the current process's group id.
10383
[clinic start generated code]*/
10384
10385
static PyObject *
10386
os_setgid_impl(PyObject *module, gid_t gid)
10387
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10388
0
{
10389
0
    if (setgid(gid) < 0)
10390
0
        return posix_error();
10391
0
    Py_RETURN_NONE;
10392
0
}
10393
#endif /* HAVE_SETGID */
10394
10395
10396
#ifdef HAVE_SETGROUPS
10397
/*[clinic input]
10398
os.setgroups
10399
10400
    groups: object
10401
    /
10402
10403
Set the groups of the current process to list.
10404
[clinic start generated code]*/
10405
10406
static PyObject *
10407
os_setgroups(PyObject *module, PyObject *groups)
10408
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10409
0
{
10410
0
    if (!PySequence_Check(groups)) {
10411
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10412
0
        return NULL;
10413
0
    }
10414
0
    Py_ssize_t len = PySequence_Size(groups);
10415
0
    if (len < 0) {
10416
0
        return NULL;
10417
0
    }
10418
0
    if (len > MAX_GROUPS) {
10419
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10420
0
        return NULL;
10421
0
    }
10422
10423
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10424
0
    if (grouplist == NULL) {
10425
0
        PyErr_NoMemory();
10426
0
        return NULL;
10427
0
    }
10428
0
    for (Py_ssize_t i = 0; i < len; i++) {
10429
0
        PyObject *elem;
10430
0
        elem = PySequence_GetItem(groups, i);
10431
0
        if (!elem) {
10432
0
            PyMem_Free(grouplist);
10433
0
            return NULL;
10434
0
        }
10435
0
        if (!PyIndex_Check(elem)) {
10436
0
            PyErr_SetString(PyExc_TypeError,
10437
0
                            "groups must be integers");
10438
0
            Py_DECREF(elem);
10439
0
            PyMem_Free(grouplist);
10440
0
            return NULL;
10441
0
        } else {
10442
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10443
0
                Py_DECREF(elem);
10444
0
                PyMem_Free(grouplist);
10445
0
                return NULL;
10446
0
            }
10447
0
        }
10448
0
        Py_DECREF(elem);
10449
0
    }
10450
10451
0
    if (setgroups(len, grouplist) < 0) {
10452
0
        posix_error();
10453
0
        PyMem_Free(grouplist);
10454
0
        return NULL;
10455
0
    }
10456
0
    PyMem_Free(grouplist);
10457
0
    Py_RETURN_NONE;
10458
0
}
10459
#endif /* HAVE_SETGROUPS */
10460
10461
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10462
static PyObject *
10463
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10464
0
{
10465
0
    PyObject *result;
10466
0
    PyObject *struct_rusage;
10467
10468
0
    if (pid == -1)
10469
0
        return posix_error();
10470
10471
    // If wait succeeded but no child was ready to report status, ru will not
10472
    // have been populated.
10473
0
    if (pid == 0) {
10474
0
        memset(ru, 0, sizeof(*ru));
10475
0
    }
10476
10477
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10478
0
    if (struct_rusage == NULL)
10479
0
        return NULL;
10480
10481
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10482
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10483
0
    Py_DECREF(struct_rusage);
10484
0
    if (!result)
10485
0
        return NULL;
10486
10487
0
    int pos = 0;
10488
10489
0
#ifndef doubletime
10490
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10491
0
#endif
10492
10493
0
#define SET_RESULT(CALL)                                     \
10494
0
    do {                                                     \
10495
0
        PyObject *item = (CALL);                             \
10496
0
        if (item == NULL) {                                  \
10497
0
            Py_DECREF(result);                               \
10498
0
            return NULL;                                     \
10499
0
        }                                                    \
10500
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10501
0
    } while(0)
10502
10503
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10504
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10505
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10506
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10507
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10508
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10509
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10510
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10511
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10512
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10513
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10514
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10515
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10516
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10517
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10518
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10519
0
#undef SET_RESULT
10520
10521
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10522
0
}
10523
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10524
10525
10526
#ifdef HAVE_WAIT3
10527
/*[clinic input]
10528
os.wait3
10529
10530
    options: int
10531
Wait for completion of a child process.
10532
10533
Returns a tuple of information about the child process:
10534
  (pid, status, rusage)
10535
[clinic start generated code]*/
10536
10537
static PyObject *
10538
os_wait3_impl(PyObject *module, int options)
10539
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10540
0
{
10541
0
    pid_t pid;
10542
0
    struct rusage ru;
10543
0
    int async_err = 0;
10544
0
    WAIT_TYPE status;
10545
0
    WAIT_STATUS_INT(status) = 0;
10546
10547
0
    do {
10548
0
        Py_BEGIN_ALLOW_THREADS
10549
0
        pid = wait3(&status, options, &ru);
10550
0
        Py_END_ALLOW_THREADS
10551
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10552
0
    if (pid < 0)
10553
0
        return (!async_err) ? posix_error() : NULL;
10554
10555
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10556
0
}
10557
#endif /* HAVE_WAIT3 */
10558
10559
10560
#ifdef HAVE_WAIT4
10561
/*[clinic input]
10562
10563
os.wait4
10564
10565
    pid: pid_t
10566
    options: int
10567
10568
Wait for completion of a specific child process.
10569
10570
Returns a tuple of information about the child process:
10571
  (pid, status, rusage)
10572
[clinic start generated code]*/
10573
10574
static PyObject *
10575
os_wait4_impl(PyObject *module, pid_t pid, int options)
10576
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10577
0
{
10578
0
    pid_t res;
10579
0
    struct rusage ru;
10580
0
    int async_err = 0;
10581
0
    WAIT_TYPE status;
10582
0
    WAIT_STATUS_INT(status) = 0;
10583
10584
0
    do {
10585
0
        Py_BEGIN_ALLOW_THREADS
10586
0
        res = wait4(pid, &status, options, &ru);
10587
0
        Py_END_ALLOW_THREADS
10588
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10589
0
    if (res < 0)
10590
0
        return (!async_err) ? posix_error() : NULL;
10591
10592
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10593
0
}
10594
#endif /* HAVE_WAIT4 */
10595
10596
10597
#if defined(HAVE_WAITID)
10598
/*[clinic input]
10599
os.waitid
10600
10601
    idtype: idtype_t
10602
        Must be one of be P_PID, P_PGID or P_ALL.
10603
    id: id_t
10604
        The id to wait on.
10605
    options: int
10606
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10607
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10608
    /
10609
10610
Returns the result of waiting for a process or processes.
10611
10612
Returns either waitid_result or None if WNOHANG is specified and there
10613
are no children in a waitable state.
10614
[clinic start generated code]*/
10615
10616
static PyObject *
10617
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10618
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=14956bc8d102b5db]*/
10619
0
{
10620
0
    PyObject *result;
10621
0
    int res;
10622
0
    int async_err = 0;
10623
0
    siginfo_t si;
10624
0
    si.si_pid = 0;
10625
10626
0
    do {
10627
0
        Py_BEGIN_ALLOW_THREADS
10628
0
        res = waitid(idtype, id, &si, options);
10629
0
        Py_END_ALLOW_THREADS
10630
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10631
0
    if (res < 0)
10632
0
        return (!async_err) ? posix_error() : NULL;
10633
10634
0
    if (si.si_pid == 0)
10635
0
        Py_RETURN_NONE;
10636
10637
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10638
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10639
0
    if (!result)
10640
0
        return NULL;
10641
10642
0
    int pos = 0;
10643
10644
0
#define SET_RESULT(CALL)                                     \
10645
0
    do {                                                     \
10646
0
        PyObject *item = (CALL);                             \
10647
0
        if (item == NULL) {                                  \
10648
0
            Py_DECREF(result);                               \
10649
0
            return NULL;                                     \
10650
0
        }                                                    \
10651
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10652
0
    } while(0)
10653
10654
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10655
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10656
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10657
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10658
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10659
10660
0
#undef SET_RESULT
10661
10662
0
    return result;
10663
0
}
10664
#endif /* defined(HAVE_WAITID) */
10665
10666
10667
#if defined(HAVE_WAITPID)
10668
/*[clinic input]
10669
os.waitpid
10670
    pid: pid_t
10671
    options: int
10672
    /
10673
10674
Wait for completion of a given child process.
10675
10676
Returns a tuple of information regarding the child process:
10677
    (pid, status)
10678
10679
The options argument is ignored on Windows.
10680
[clinic start generated code]*/
10681
10682
static PyObject *
10683
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10684
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10685
0
{
10686
0
    pid_t res;
10687
0
    int async_err = 0;
10688
0
    WAIT_TYPE status;
10689
0
    WAIT_STATUS_INT(status) = 0;
10690
10691
0
    do {
10692
0
        Py_BEGIN_ALLOW_THREADS
10693
0
        res = waitpid(pid, &status, options);
10694
0
        Py_END_ALLOW_THREADS
10695
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10696
0
    if (res < 0)
10697
0
        return (!async_err) ? posix_error() : NULL;
10698
10699
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10700
0
}
10701
#elif defined(HAVE_CWAIT)
10702
/* MS C has a variant of waitpid() that's usable for most purposes. */
10703
/*[clinic input]
10704
os.waitpid
10705
    pid: intptr_t
10706
    options: int
10707
    /
10708
10709
Wait for completion of a given process.
10710
10711
Returns a tuple of information regarding the process:
10712
    (pid, status << 8)
10713
10714
The options argument is ignored on Windows.
10715
[clinic start generated code]*/
10716
10717
static PyObject *
10718
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10719
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10720
{
10721
    int status;
10722
    intptr_t res;
10723
    int async_err = 0;
10724
10725
    do {
10726
        Py_BEGIN_ALLOW_THREADS
10727
        _Py_BEGIN_SUPPRESS_IPH
10728
        res = _cwait(&status, pid, options);
10729
        _Py_END_SUPPRESS_IPH
10730
        Py_END_ALLOW_THREADS
10731
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10732
    if (res < 0)
10733
        return (!async_err) ? posix_error() : NULL;
10734
10735
    unsigned long long ustatus = (unsigned int)status;
10736
10737
    /* shift the status left a byte so this is more like the POSIX waitpid */
10738
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10739
}
10740
#endif
10741
10742
10743
#ifdef HAVE_WAIT
10744
/*[clinic input]
10745
os.wait
10746
10747
Wait for completion of a child process.
10748
10749
Returns a tuple of information about the child process:
10750
    (pid, status)
10751
[clinic start generated code]*/
10752
10753
static PyObject *
10754
os_wait_impl(PyObject *module)
10755
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10756
0
{
10757
0
    pid_t pid;
10758
0
    int async_err = 0;
10759
0
    WAIT_TYPE status;
10760
0
    WAIT_STATUS_INT(status) = 0;
10761
10762
0
    do {
10763
0
        Py_BEGIN_ALLOW_THREADS
10764
0
        pid = wait(&status);
10765
0
        Py_END_ALLOW_THREADS
10766
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10767
0
    if (pid < 0)
10768
0
        return (!async_err) ? posix_error() : NULL;
10769
10770
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10771
0
}
10772
#endif /* HAVE_WAIT */
10773
10774
10775
// This system call always crashes on older Android versions.
10776
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10777
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10778
/*[clinic input]
10779
os.pidfd_open
10780
  pid: pid_t
10781
  flags: unsigned_int = 0
10782
10783
Return a file descriptor referring to the process *pid*.
10784
10785
The descriptor can be used to perform process management without races
10786
and signals.
10787
[clinic start generated code]*/
10788
10789
static PyObject *
10790
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10791
/*[clinic end generated code: output=5c7252698947dc41 input=03058b32c389f874]*/
10792
4
{
10793
4
    int fd = syscall(__NR_pidfd_open, pid, flags);
10794
4
    if (fd < 0) {
10795
0
        return posix_error();
10796
0
    }
10797
4
    return PyLong_FromLong(fd);
10798
4
}
10799
#endif
10800
10801
10802
#if defined(__linux__) && defined(__NR_pidfd_getfd) && \
10803
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10804
/*[clinic input]
10805
os.pidfd_getfd
10806
  pidfd: int
10807
    A process file descriptor.
10808
  targetfd: int
10809
    The file descriptor to duplicate from the target process.
10810
  *
10811
  flags: unsigned_int = 0
10812
    Reserved, must be 0.
10813
10814
Duplicate a file descriptor from the process referred to by *pidfd*.
10815
[clinic start generated code]*/
10816
10817
static PyObject *
10818
os_pidfd_getfd_impl(PyObject *module, int pidfd, int targetfd,
10819
                    unsigned int flags)
10820
/*[clinic end generated code: output=e1a1415a13c7137f input=ef6417fb10deb1cc]*/
10821
{
10822
    int fd = syscall(__NR_pidfd_getfd, pidfd, targetfd, flags);
10823
    if (fd < 0) {
10824
        return posix_error();
10825
    }
10826
    return PyLong_FromLong(fd);
10827
}
10828
#endif
10829
10830
10831
#ifdef HAVE_SETNS
10832
/*[clinic input]
10833
os.setns
10834
  fd: fildes
10835
    A file descriptor to a namespace.
10836
  nstype: int = 0
10837
    Type of namespace.
10838
10839
Move the calling thread into different namespaces.
10840
[clinic start generated code]*/
10841
10842
static PyObject *
10843
os_setns_impl(PyObject *module, int fd, int nstype)
10844
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10845
0
{
10846
0
    int res;
10847
10848
0
    Py_BEGIN_ALLOW_THREADS
10849
0
    res = setns(fd, nstype);
10850
0
    Py_END_ALLOW_THREADS
10851
10852
0
    if (res != 0) {
10853
0
        return posix_error();
10854
0
    }
10855
10856
0
    Py_RETURN_NONE;
10857
0
}
10858
#endif
10859
10860
10861
#ifdef HAVE_UNSHARE
10862
/*[clinic input]
10863
os.unshare
10864
  flags: int
10865
    Namespaces to be unshared.
10866
10867
Disassociate parts of a process (or thread) execution context.
10868
[clinic start generated code]*/
10869
10870
static PyObject *
10871
os_unshare_impl(PyObject *module, int flags)
10872
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10873
0
{
10874
0
    int res;
10875
10876
0
    Py_BEGIN_ALLOW_THREADS
10877
0
    res = unshare(flags);
10878
0
    Py_END_ALLOW_THREADS
10879
10880
0
    if (res != 0) {
10881
0
        return posix_error();
10882
0
    }
10883
10884
0
    Py_RETURN_NONE;
10885
0
}
10886
#endif
10887
10888
10889
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10890
/*[clinic input]
10891
os.readlink
10892
10893
    path: path_t
10894
    *
10895
    dir_fd: dir_fd(requires='readlinkat') = None
10896
10897
Return a string representing the path to which the symbolic link points.
10898
10899
If dir_fd is not None, it should be a file descriptor open to
10900
a directory, and path should be relative; path will then be relative to
10901
that directory.
10902
10903
dir_fd may not be implemented on your platform.  If it is unavailable,
10904
using it will raise a NotImplementedError.
10905
[clinic start generated code]*/
10906
10907
static PyObject *
10908
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10909
/*[clinic end generated code: output=d21b732a2e814030 input=03d10130870dbca8]*/
10910
6
{
10911
6
#if defined(HAVE_READLINK)
10912
6
    char buffer[MAXPATHLEN+1];
10913
6
    ssize_t length;
10914
6
#ifdef HAVE_READLINKAT
10915
6
    int readlinkat_unavailable = 0;
10916
6
#endif
10917
10918
6
    Py_BEGIN_ALLOW_THREADS
10919
6
#ifdef HAVE_READLINKAT
10920
6
    if (dir_fd != DEFAULT_DIR_FD) {
10921
0
        if (HAVE_READLINKAT_RUNTIME) {
10922
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10923
0
        } else {
10924
0
            readlinkat_unavailable = 1;
10925
0
        }
10926
0
    } else
10927
6
#endif
10928
6
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10929
6
    Py_END_ALLOW_THREADS
10930
10931
6
#ifdef HAVE_READLINKAT
10932
6
    if (readlinkat_unavailable) {
10933
0
        argument_unavailable_error(NULL, "dir_fd");
10934
0
        return NULL;
10935
0
    }
10936
6
#endif
10937
10938
6
    if (length < 0) {
10939
0
        return path_error(path);
10940
0
    }
10941
6
    buffer[length] = '\0';
10942
10943
6
    if (PyUnicode_Check(path->object))
10944
6
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10945
0
    else
10946
0
        return PyBytes_FromStringAndSize(buffer, length);
10947
#elif defined(MS_WINDOWS)
10948
    DWORD n_bytes_returned;
10949
    DWORD io_result = 0;
10950
    HANDLE reparse_point_handle;
10951
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10952
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10953
    PyObject *result = NULL;
10954
10955
    /* First get a handle to the reparse point */
10956
    Py_BEGIN_ALLOW_THREADS
10957
    reparse_point_handle = CreateFileW(
10958
        path->wide,
10959
        0,
10960
        0,
10961
        0,
10962
        OPEN_EXISTING,
10963
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10964
        0);
10965
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10966
        /* New call DeviceIoControl to read the reparse point */
10967
        io_result = DeviceIoControl(
10968
            reparse_point_handle,
10969
            FSCTL_GET_REPARSE_POINT,
10970
            0, 0, /* in buffer */
10971
            target_buffer, sizeof(target_buffer),
10972
            &n_bytes_returned,
10973
            0 /* we're not using OVERLAPPED_IO */
10974
            );
10975
        CloseHandle(reparse_point_handle);
10976
    }
10977
    Py_END_ALLOW_THREADS
10978
10979
    if (io_result == 0) {
10980
        return path_error(path);
10981
    }
10982
10983
    wchar_t *name = NULL;
10984
    Py_ssize_t nameLen = 0;
10985
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10986
    {
10987
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10988
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10989
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10990
    }
10991
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10992
    {
10993
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10994
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10995
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10996
    }
10997
    else
10998
    {
10999
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
11000
    }
11001
    if (name) {
11002
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
11003
            /* Our buffer is mutable, so this is okay */
11004
            name[1] = L'\\';
11005
        }
11006
        result = PyUnicode_FromWideChar(name, nameLen);
11007
        if (result && PyBytes_Check(path->object)) {
11008
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
11009
        }
11010
    }
11011
    return result;
11012
#endif
11013
6
}
11014
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
11015
11016
#if defined(MS_WINDOWS)
11017
11018
/* Remove the last portion of the path - return 0 on success */
11019
static int
11020
_dirnameW(WCHAR *path)
11021
{
11022
    WCHAR *ptr;
11023
    size_t length = wcsnlen_s(path, MAX_PATH);
11024
    if (length == MAX_PATH) {
11025
        return -1;
11026
    }
11027
11028
    /* walk the path from the end until a backslash is encountered */
11029
    for(ptr = path + length; ptr != path; ptr--) {
11030
        if (*ptr == L'\\' || *ptr == L'/') {
11031
            break;
11032
        }
11033
    }
11034
    *ptr = 0;
11035
    return 0;
11036
}
11037
11038
#endif
11039
11040
#ifdef HAVE_SYMLINK
11041
11042
#if defined(MS_WINDOWS)
11043
11044
/* Is this path absolute? */
11045
static int
11046
_is_absW(const WCHAR *path)
11047
{
11048
    return path[0] == L'\\' || path[0] == L'/' ||
11049
        (path[0] && path[1] == L':');
11050
}
11051
11052
/* join root and rest with a backslash - return 0 on success */
11053
static int
11054
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
11055
{
11056
    if (_is_absW(rest)) {
11057
        return wcscpy_s(dest_path, MAX_PATH, rest);
11058
    }
11059
11060
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
11061
        return -1;
11062
    }
11063
11064
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
11065
        return -1;
11066
    }
11067
11068
    return wcscat_s(dest_path, MAX_PATH, rest);
11069
}
11070
11071
/* Return True if the path at src relative to dest is a directory */
11072
static int
11073
_check_dirW(LPCWSTR src, LPCWSTR dest)
11074
{
11075
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11076
    WCHAR dest_parent[MAX_PATH];
11077
    WCHAR src_resolved[MAX_PATH] = L"";
11078
11079
    /* dest_parent = os.path.dirname(dest) */
11080
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11081
        _dirnameW(dest_parent)) {
11082
        return 0;
11083
    }
11084
    /* src_resolved = os.path.join(dest_parent, src) */
11085
    if (_joinW(src_resolved, dest_parent, src)) {
11086
        return 0;
11087
    }
11088
    return (
11089
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11090
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11091
    );
11092
}
11093
#endif
11094
11095
11096
/*[clinic input]
11097
os.symlink
11098
    src: path_t
11099
    dst: path_t
11100
    target_is_directory: bool = False
11101
    *
11102
    dir_fd: dir_fd(requires='symlinkat')=None
11103
11104
Create a symbolic link pointing to src named dst.
11105
11106
target_is_directory is required on Windows if the target is to be
11107
interpreted as a directory.  (On Windows, symlink requires Windows 6.0
11108
or greater, and raises a NotImplementedError otherwise.)
11109
target_is_directory is ignored on non-Windows platforms.
11110
11111
If dir_fd is not None, it should be a file descriptor open to
11112
a directory, and path should be relative; path will then be relative
11113
to that directory.
11114
dir_fd may not be implemented on your platform.  If it is unavailable,
11115
using it will raise a NotImplementedError.
11116
11117
[clinic start generated code]*/
11118
11119
static PyObject *
11120
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11121
                int target_is_directory, int dir_fd)
11122
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=71b75467b31c45f7]*/
11123
0
{
11124
#ifdef MS_WINDOWS
11125
    DWORD result;
11126
    DWORD flags = 0;
11127
11128
    /* Assumed true, set to false if detected to not be available. */
11129
    static int windows_has_symlink_unprivileged_flag = TRUE;
11130
#else
11131
0
    int result;
11132
0
#ifdef HAVE_SYMLINKAT
11133
0
    int symlinkat_unavailable = 0;
11134
0
#endif
11135
0
#endif
11136
11137
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11138
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11139
0
        return NULL;
11140
0
    }
11141
11142
#ifdef MS_WINDOWS
11143
11144
    if (windows_has_symlink_unprivileged_flag) {
11145
        /* Allow non-admin symlinks if system allows it. */
11146
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11147
    }
11148
11149
    Py_BEGIN_ALLOW_THREADS
11150
    _Py_BEGIN_SUPPRESS_IPH
11151
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11152
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11153
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11154
    }
11155
11156
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11157
    _Py_END_SUPPRESS_IPH
11158
    Py_END_ALLOW_THREADS
11159
11160
    if (windows_has_symlink_unprivileged_flag && !result &&
11161
        ERROR_INVALID_PARAMETER == GetLastError()) {
11162
11163
        Py_BEGIN_ALLOW_THREADS
11164
        _Py_BEGIN_SUPPRESS_IPH
11165
        /* This error might be caused by
11166
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11167
        Try again, and update windows_has_symlink_unprivileged_flag if we
11168
        are successful this time.
11169
11170
        NOTE: There is a risk of a race condition here if there are other
11171
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11172
        another process (or thread) changes that condition in between our
11173
        calls to CreateSymbolicLink.
11174
        */
11175
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11176
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11177
        _Py_END_SUPPRESS_IPH
11178
        Py_END_ALLOW_THREADS
11179
11180
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11181
            windows_has_symlink_unprivileged_flag = FALSE;
11182
        }
11183
    }
11184
11185
    if (!result)
11186
        return path_error2(src, dst);
11187
11188
#else
11189
11190
0
    Py_BEGIN_ALLOW_THREADS
11191
0
#ifdef HAVE_SYMLINKAT
11192
0
    if (dir_fd != DEFAULT_DIR_FD) {
11193
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11194
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11195
0
        } else {
11196
0
            symlinkat_unavailable = 1;
11197
0
        }
11198
0
    } else
11199
0
#endif
11200
0
        result = symlink(src->narrow, dst->narrow);
11201
0
    Py_END_ALLOW_THREADS
11202
11203
0
#ifdef HAVE_SYMLINKAT
11204
0
    if (symlinkat_unavailable) {
11205
0
          argument_unavailable_error(NULL, "dir_fd");
11206
0
          return NULL;
11207
0
    }
11208
0
#endif
11209
11210
0
    if (result)
11211
0
        return path_error2(src, dst);
11212
0
#endif
11213
11214
0
    Py_RETURN_NONE;
11215
0
}
11216
#endif /* HAVE_SYMLINK */
11217
11218
11219
static PyStructSequence_Field times_result_fields[] = {
11220
    {"user",    "user time"},
11221
    {"system",   "system time"},
11222
    {"children_user",    "user time of children"},
11223
    {"children_system",    "system time of children"},
11224
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11225
    {NULL}
11226
};
11227
11228
PyDoc_STRVAR(times_result__doc__,
11229
"times_result: Result from os.times().\n\n\
11230
This object may be accessed either as a tuple of\n\
11231
  (user, system, children_user, children_system, elapsed),\n\
11232
or via the attributes user, system, children_user, children_system,\n\
11233
and elapsed.\n\
11234
\n\
11235
See os.times for more information.");
11236
11237
static PyStructSequence_Desc times_result_desc = {
11238
    MODNAME ".times_result", /* name */
11239
    times_result__doc__, /* doc */
11240
    times_result_fields,
11241
    5
11242
};
11243
11244
static PyObject *
11245
build_times_result(PyObject *module, double user, double system,
11246
    double children_user, double children_system,
11247
    double elapsed)
11248
0
{
11249
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11250
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11251
0
    if (value == NULL)
11252
0
        return NULL;
11253
11254
0
#define SET(i, field) \
11255
0
    { \
11256
0
    PyObject *o = PyFloat_FromDouble(field); \
11257
0
    if (!o) { \
11258
0
        Py_DECREF(value); \
11259
0
        return NULL; \
11260
0
    } \
11261
0
    PyStructSequence_SET_ITEM(value, i, o); \
11262
0
    } \
11263
0
11264
0
    SET(0, user);
11265
0
    SET(1, system);
11266
0
    SET(2, children_user);
11267
0
    SET(3, children_system);
11268
0
    SET(4, elapsed);
11269
11270
0
#undef SET
11271
11272
0
    return value;
11273
0
}
11274
11275
11276
/*[clinic input]
11277
os.times
11278
11279
Return a collection containing process timing information.
11280
11281
The object returned behaves like a named tuple with these fields:
11282
  (utime, stime, cutime, cstime, elapsed_time)
11283
All fields are floating-point numbers.
11284
[clinic start generated code]*/
11285
11286
static PyObject *
11287
os_times_impl(PyObject *module)
11288
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11289
0
{
11290
#ifdef MS_WINDOWS
11291
    FILETIME create, exit, kernel, user;
11292
    HANDLE hProc;
11293
    hProc = GetCurrentProcess();
11294
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11295
    /* The fields of a FILETIME structure are the hi and lo part
11296
       of a 64-bit value expressed in 100 nanosecond units.
11297
       1e7 is one second in such units; 1e-7 the inverse.
11298
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11299
    */
11300
    return build_times_result(module,
11301
        (double)(user.dwHighDateTime*429.4967296 +
11302
                 user.dwLowDateTime*1e-7),
11303
        (double)(kernel.dwHighDateTime*429.4967296 +
11304
                 kernel.dwLowDateTime*1e-7),
11305
        (double)0,
11306
        (double)0,
11307
        (double)0);
11308
#else /* MS_WINDOWS */
11309
0
    _posixstate *state = get_posix_state(module);
11310
0
    long ticks_per_second = state->ticks_per_second;
11311
11312
0
    struct tms process;
11313
0
    clock_t elapsed;
11314
0
    errno = 0;
11315
0
    elapsed = times(&process);
11316
0
    if (elapsed == (clock_t) -1) {
11317
0
        return posix_error();
11318
0
    }
11319
11320
0
    return build_times_result(module,
11321
0
        (double)process.tms_utime / ticks_per_second,
11322
0
        (double)process.tms_stime / ticks_per_second,
11323
0
        (double)process.tms_cutime / ticks_per_second,
11324
0
        (double)process.tms_cstime / ticks_per_second,
11325
0
        (double)elapsed / ticks_per_second);
11326
0
#endif /* MS_WINDOWS */
11327
0
}
11328
11329
11330
#if defined(HAVE_TIMERFD_CREATE)
11331
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11332
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11333
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11334
11335
static PyObject *
11336
build_itimerspec(const struct itimerspec* curr_value)
11337
0
{
11338
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11339
0
                                                          curr_value->it_value.tv_nsec);
11340
0
    PyObject *value = PyFloat_FromDouble(_value);
11341
0
    if (value == NULL) {
11342
0
        return NULL;
11343
0
    }
11344
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11345
0
                                                   curr_value->it_interval.tv_nsec);
11346
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11347
0
    if (interval == NULL) {
11348
0
        Py_DECREF(value);
11349
0
        return NULL;
11350
0
    }
11351
0
    return _PyTuple_FromPairSteal(value, interval);
11352
0
}
11353
11354
static PyObject *
11355
build_itimerspec_ns(const struct itimerspec* curr_value)
11356
0
{
11357
0
    PyTime_t value, interval;
11358
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11359
0
        return NULL;
11360
0
    }
11361
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11362
0
        return NULL;
11363
0
    }
11364
0
    return Py_BuildValue("LL", value, interval);
11365
0
}
11366
11367
/*[clinic input]
11368
os.timerfd_create
11369
11370
    clockid: int
11371
        A valid clock ID constant as timer file descriptor.
11372
11373
        time.CLOCK_REALTIME
11374
        time.CLOCK_MONOTONIC
11375
        time.CLOCK_BOOTTIME
11376
    /
11377
    *
11378
    flags: int = 0
11379
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11380
11381
        os.TFD_NONBLOCK
11382
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11383
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11384
11385
        os.TFD_CLOEXEC
11386
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11387
11388
Create and return a timer file descriptor.
11389
[clinic start generated code]*/
11390
11391
static PyObject *
11392
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11393
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11394
11395
0
{
11396
0
    int fd;
11397
0
    Py_BEGIN_ALLOW_THREADS
11398
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11399
0
    fd = timerfd_create(clockid, flags);
11400
0
    Py_END_ALLOW_THREADS
11401
0
    if (fd == -1) {
11402
0
        return PyErr_SetFromErrno(PyExc_OSError);
11403
0
    }
11404
0
    return PyLong_FromLong(fd);
11405
0
}
11406
11407
/*[clinic input]
11408
os.timerfd_settime
11409
11410
    fd: fildes
11411
        A timer file descriptor.
11412
    /
11413
    *
11414
    flags: int = 0
11415
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11416
    initial as initial_double: double = 0.0
11417
        The initial expiration time, in seconds.
11418
    interval as interval_double: double = 0.0
11419
        The timer's interval, in seconds.
11420
11421
Alter a timer file descriptor's internal timer in seconds.
11422
[clinic start generated code]*/
11423
11424
static PyObject *
11425
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11426
                        double initial_double, double interval_double)
11427
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11428
0
{
11429
0
    PyTime_t initial, interval;
11430
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11431
0
                                  &initial) < 0) {
11432
0
        return NULL;
11433
0
    }
11434
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11435
0
                                  &interval) < 0) {
11436
0
        return NULL;
11437
0
    }
11438
11439
0
    struct itimerspec new_value, old_value;
11440
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11441
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11442
0
        return NULL;
11443
0
    }
11444
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11445
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11446
0
        return NULL;
11447
0
    }
11448
11449
0
    int result;
11450
0
    Py_BEGIN_ALLOW_THREADS
11451
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11452
0
    Py_END_ALLOW_THREADS
11453
0
    if (result == -1) {
11454
0
        return PyErr_SetFromErrno(PyExc_OSError);
11455
0
    }
11456
0
    return build_itimerspec(&old_value);
11457
0
}
11458
11459
11460
/*[clinic input]
11461
os.timerfd_settime_ns
11462
11463
    fd: fildes
11464
        A timer file descriptor.
11465
    /
11466
    *
11467
    flags: int = 0
11468
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11469
    initial: long_long = 0
11470
        initial expiration timing in seconds.
11471
    interval: long_long = 0
11472
        interval for the timer in seconds.
11473
11474
Alter a timer file descriptor's internal timer in nanoseconds.
11475
[clinic start generated code]*/
11476
11477
static PyObject *
11478
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11479
                           long long initial, long long interval)
11480
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11481
0
{
11482
0
    struct itimerspec new_value;
11483
0
    struct itimerspec old_value;
11484
0
    int result;
11485
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11486
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11487
0
        return NULL;
11488
0
    }
11489
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11490
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11491
0
        return NULL;
11492
0
    }
11493
0
    Py_BEGIN_ALLOW_THREADS
11494
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11495
0
    Py_END_ALLOW_THREADS
11496
0
    if (result == -1) {
11497
0
        return PyErr_SetFromErrno(PyExc_OSError);
11498
0
    }
11499
0
    return build_itimerspec_ns(&old_value);
11500
0
}
11501
11502
/*[clinic input]
11503
@permit_long_summary
11504
os.timerfd_gettime
11505
11506
    fd: fildes
11507
        A timer file descriptor.
11508
    /
11509
11510
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11511
[clinic start generated code]*/
11512
11513
static PyObject *
11514
os_timerfd_gettime_impl(PyObject *module, int fd)
11515
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11516
0
{
11517
0
    struct itimerspec curr_value;
11518
0
    int result;
11519
0
    Py_BEGIN_ALLOW_THREADS
11520
0
    result = timerfd_gettime(fd, &curr_value);
11521
0
    Py_END_ALLOW_THREADS
11522
0
    if (result == -1) {
11523
0
        return PyErr_SetFromErrno(PyExc_OSError);
11524
0
    }
11525
0
    return build_itimerspec(&curr_value);
11526
0
}
11527
11528
11529
/*[clinic input]
11530
@permit_long_summary
11531
os.timerfd_gettime_ns
11532
11533
    fd: fildes
11534
        A timer file descriptor.
11535
    /
11536
11537
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11538
[clinic start generated code]*/
11539
11540
static PyObject *
11541
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11542
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11543
0
{
11544
0
    struct itimerspec curr_value;
11545
0
    int result;
11546
0
    Py_BEGIN_ALLOW_THREADS
11547
0
    result = timerfd_gettime(fd, &curr_value);
11548
0
    Py_END_ALLOW_THREADS
11549
0
    if (result == -1) {
11550
0
        return PyErr_SetFromErrno(PyExc_OSError);
11551
0
    }
11552
0
    return build_itimerspec_ns(&curr_value);
11553
0
}
11554
11555
#undef ONE_SECOND_IN_NS
11556
#undef EXTRACT_NSEC
11557
11558
#endif  /* HAVE_TIMERFD_CREATE */
11559
11560
#ifdef HAVE_GETSID
11561
/*[clinic input]
11562
os.getsid
11563
11564
    pid: pid_t
11565
    /
11566
11567
Call the system call getsid(pid) and return the result.
11568
[clinic start generated code]*/
11569
11570
static PyObject *
11571
os_getsid_impl(PyObject *module, pid_t pid)
11572
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11573
0
{
11574
0
    int sid;
11575
0
    sid = getsid(pid);
11576
0
    if (sid < 0)
11577
0
        return posix_error();
11578
0
    return PyLong_FromLong((long)sid);
11579
0
}
11580
#endif /* HAVE_GETSID */
11581
11582
11583
#ifdef HAVE_SETSID
11584
/*[clinic input]
11585
os.setsid
11586
11587
Call the system call setsid().
11588
[clinic start generated code]*/
11589
11590
static PyObject *
11591
os_setsid_impl(PyObject *module)
11592
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11593
0
{
11594
0
    if (setsid() < 0)
11595
0
        return posix_error();
11596
0
    Py_RETURN_NONE;
11597
0
}
11598
#endif /* HAVE_SETSID */
11599
11600
11601
#ifdef HAVE_SETPGID
11602
/*[clinic input]
11603
os.setpgid
11604
11605
    pid: pid_t
11606
    pgrp: pid_t
11607
    /
11608
11609
Call the system call setpgid(pid, pgrp).
11610
[clinic start generated code]*/
11611
11612
static PyObject *
11613
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11614
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11615
0
{
11616
0
    if (setpgid(pid, pgrp) < 0)
11617
0
        return posix_error();
11618
0
    Py_RETURN_NONE;
11619
0
}
11620
#endif /* HAVE_SETPGID */
11621
11622
11623
#ifdef HAVE_TCGETPGRP
11624
/*[clinic input]
11625
os.tcgetpgrp
11626
11627
    fd: int
11628
    /
11629
11630
Return the process group associated with the terminal specified by fd.
11631
[clinic start generated code]*/
11632
11633
static PyObject *
11634
os_tcgetpgrp_impl(PyObject *module, int fd)
11635
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11636
0
{
11637
0
    pid_t pgid = tcgetpgrp(fd);
11638
0
    if (pgid < 0)
11639
0
        return posix_error();
11640
0
    return PyLong_FromPid(pgid);
11641
0
}
11642
#endif /* HAVE_TCGETPGRP */
11643
11644
11645
#ifdef HAVE_TCSETPGRP
11646
/*[clinic input]
11647
os.tcsetpgrp
11648
11649
    fd: int
11650
    pgid: pid_t
11651
    /
11652
11653
Set the process group associated with the terminal specified by fd.
11654
[clinic start generated code]*/
11655
11656
static PyObject *
11657
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11658
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11659
0
{
11660
0
    if (tcsetpgrp(fd, pgid) < 0)
11661
0
        return posix_error();
11662
0
    Py_RETURN_NONE;
11663
0
}
11664
#endif /* HAVE_TCSETPGRP */
11665
11666
/* Functions acting on file descriptors */
11667
11668
#ifdef O_CLOEXEC
11669
extern int _Py_open_cloexec_works;
11670
#endif
11671
11672
11673
/*[clinic input]
11674
os.open -> int
11675
    path: path_t
11676
    flags: int
11677
    mode: int = 0o777
11678
    *
11679
    dir_fd: dir_fd(requires='openat') = None
11680
11681
Open a file for low level IO.  Returns a file descriptor (integer).
11682
11683
If dir_fd is not None, it should be a file descriptor open to
11684
a directory, and path should be relative; path will then be relative to
11685
that directory.
11686
dir_fd may not be implemented on your platform.  If it is unavailable,
11687
using it will raise a NotImplementedError.
11688
[clinic start generated code]*/
11689
11690
static int
11691
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11692
/*[clinic end generated code: output=abc7227888c8bc73 input=75f7b4eaf92f2225]*/
11693
91.2k
{
11694
91.2k
    int fd;
11695
91.2k
    int async_err = 0;
11696
91.2k
#ifdef HAVE_OPENAT
11697
91.2k
    int openat_unavailable = 0;
11698
91.2k
#endif
11699
11700
91.2k
#ifdef O_CLOEXEC
11701
91.2k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11702
#elif !defined(MS_WINDOWS)
11703
    int *atomic_flag_works = NULL;
11704
#endif
11705
11706
#ifdef MS_WINDOWS
11707
    flags |= O_NOINHERIT;
11708
#elif defined(O_CLOEXEC)
11709
91.2k
    flags |= O_CLOEXEC;
11710
91.2k
#endif
11711
11712
91.2k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11713
0
        return -1;
11714
0
    }
11715
11716
91.2k
    _Py_BEGIN_SUPPRESS_IPH
11717
91.2k
    do {
11718
91.2k
        Py_BEGIN_ALLOW_THREADS
11719
#ifdef MS_WINDOWS
11720
        fd = _wopen(path->wide, flags, mode);
11721
#else
11722
91.2k
#ifdef HAVE_OPENAT
11723
91.2k
        if (dir_fd != DEFAULT_DIR_FD) {
11724
86.8k
            if (HAVE_OPENAT_RUNTIME) {
11725
86.8k
                fd = openat(dir_fd, path->narrow, flags, mode);
11726
11727
86.8k
            } else {
11728
0
                openat_unavailable = 1;
11729
0
                fd = -1;
11730
0
            }
11731
86.8k
        } else
11732
4.44k
#endif /* HAVE_OPENAT */
11733
4.44k
            fd = open(path->narrow, flags, mode);
11734
91.2k
#endif /* !MS_WINDOWS */
11735
91.2k
        Py_END_ALLOW_THREADS
11736
91.2k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11737
91.2k
    _Py_END_SUPPRESS_IPH
11738
11739
91.2k
#ifdef HAVE_OPENAT
11740
91.2k
    if (openat_unavailable) {
11741
0
        argument_unavailable_error(NULL, "dir_fd");
11742
0
        return -1;
11743
0
    }
11744
91.2k
#endif
11745
11746
91.2k
    if (fd < 0) {
11747
0
        if (!async_err)
11748
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11749
0
        return -1;
11750
0
    }
11751
11752
91.2k
#ifndef MS_WINDOWS
11753
91.2k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11754
0
        close(fd);
11755
0
        return -1;
11756
0
    }
11757
91.2k
#endif
11758
11759
91.2k
    return fd;
11760
91.2k
}
11761
11762
11763
/*[clinic input]
11764
os.close
11765
11766
    fd: int
11767
11768
Close a file descriptor.
11769
[clinic start generated code]*/
11770
11771
static PyObject *
11772
os_close_impl(PyObject *module, int fd)
11773
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11774
91.1k
{
11775
91.1k
    int res;
11776
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11777
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11778
     * for more details.
11779
     */
11780
91.1k
    Py_BEGIN_ALLOW_THREADS
11781
91.1k
    _Py_BEGIN_SUPPRESS_IPH
11782
91.1k
    res = close(fd);
11783
91.1k
    _Py_END_SUPPRESS_IPH
11784
91.1k
    Py_END_ALLOW_THREADS
11785
91.1k
    if (res < 0)
11786
0
        return posix_error();
11787
91.1k
    Py_RETURN_NONE;
11788
91.1k
}
11789
11790
/*[clinic input]
11791
os.closerange
11792
11793
    fd_low: int
11794
    fd_high: int
11795
    /
11796
11797
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11798
[clinic start generated code]*/
11799
11800
static PyObject *
11801
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11802
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11803
0
{
11804
0
    Py_BEGIN_ALLOW_THREADS
11805
0
    _Py_closerange(fd_low, fd_high - 1);
11806
0
    Py_END_ALLOW_THREADS
11807
0
    Py_RETURN_NONE;
11808
0
}
11809
11810
11811
/*[clinic input]
11812
os.dup -> int
11813
11814
    fd: int
11815
    /
11816
11817
Return a duplicate of a file descriptor.
11818
[clinic start generated code]*/
11819
11820
static int
11821
os_dup_impl(PyObject *module, int fd)
11822
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11823
0
{
11824
0
    return _Py_dup(fd);
11825
0
}
11826
11827
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11828
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11829
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11830
/*[clinic input]
11831
os.dup2 -> int
11832
    fd: int
11833
    fd2: int
11834
    inheritable: bool=True
11835
11836
Duplicate file descriptor.
11837
[clinic start generated code]*/
11838
11839
static int
11840
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11841
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11842
0
{
11843
0
    int res = 0;
11844
0
#if defined(HAVE_DUP3) && \
11845
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11846
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11847
0
    static int dup3_works = -1;
11848
0
#endif
11849
11850
    /* dup2() can fail with EINTR if the target FD is already open, because it
11851
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11852
     * upon close(), and therefore below.
11853
     */
11854
#ifdef MS_WINDOWS
11855
    Py_BEGIN_ALLOW_THREADS
11856
    _Py_BEGIN_SUPPRESS_IPH
11857
    res = dup2(fd, fd2);
11858
    _Py_END_SUPPRESS_IPH
11859
    Py_END_ALLOW_THREADS
11860
    if (res < 0) {
11861
        posix_error();
11862
        return -1;
11863
    }
11864
    res = fd2; // msvcrt dup2 returns 0 on success.
11865
11866
    /* Character files like console cannot be make non-inheritable */
11867
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11868
        close(fd2);
11869
        return -1;
11870
    }
11871
11872
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11873
    Py_BEGIN_ALLOW_THREADS
11874
    if (!inheritable)
11875
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11876
    else
11877
        res = dup2(fd, fd2);
11878
    Py_END_ALLOW_THREADS
11879
    if (res < 0) {
11880
        posix_error();
11881
        return -1;
11882
    }
11883
11884
#else
11885
11886
0
#ifdef HAVE_DUP3
11887
0
    if (!inheritable && dup3_works != 0) {
11888
0
        Py_BEGIN_ALLOW_THREADS
11889
0
        res = dup3(fd, fd2, O_CLOEXEC);
11890
0
        Py_END_ALLOW_THREADS
11891
0
        if (res < 0) {
11892
0
            if (dup3_works == -1)
11893
0
                dup3_works = (errno != ENOSYS);
11894
0
            if (dup3_works) {
11895
0
                posix_error();
11896
0
                return -1;
11897
0
            }
11898
0
        }
11899
0
    }
11900
11901
0
    if (inheritable || dup3_works == 0)
11902
0
    {
11903
0
#endif
11904
0
        Py_BEGIN_ALLOW_THREADS
11905
0
        res = dup2(fd, fd2);
11906
0
        Py_END_ALLOW_THREADS
11907
0
        if (res < 0) {
11908
0
            posix_error();
11909
0
            return -1;
11910
0
        }
11911
11912
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11913
0
            close(fd2);
11914
0
            return -1;
11915
0
        }
11916
0
#ifdef HAVE_DUP3
11917
0
    }
11918
0
#endif
11919
11920
0
#endif
11921
11922
0
    return res;
11923
0
}
11924
#endif
11925
11926
11927
#ifdef HAVE_LOCKF
11928
/*[clinic input]
11929
os.lockf
11930
11931
    fd: int
11932
        An open file descriptor.
11933
    command: int
11934
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11935
    length: Py_off_t
11936
        The number of bytes to lock, starting at the current position.
11937
    /
11938
11939
Apply, test or remove a POSIX lock on an open file descriptor.
11940
11941
[clinic start generated code]*/
11942
11943
static PyObject *
11944
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11945
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11946
0
{
11947
0
    int res;
11948
11949
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11950
0
        return NULL;
11951
0
    }
11952
11953
0
    Py_BEGIN_ALLOW_THREADS
11954
0
    res = lockf(fd, command, length);
11955
0
    Py_END_ALLOW_THREADS
11956
11957
0
    if (res < 0)
11958
0
        return posix_error();
11959
11960
0
    Py_RETURN_NONE;
11961
0
}
11962
#endif /* HAVE_LOCKF */
11963
11964
11965
/*[clinic input]
11966
os.lseek -> Py_off_t
11967
11968
    fd: int
11969
        An open file descriptor, as returned by os.open().
11970
    position: Py_off_t
11971
        Position, interpreted relative to 'whence'.
11972
    whence as how: int
11973
        The relative position to seek from. Valid values are:
11974
        - SEEK_SET: seek from the start of the file.
11975
        - SEEK_CUR: seek from the current file position.
11976
        - SEEK_END: seek from the end of the file.
11977
    /
11978
11979
Set the position of a file descriptor.  Return the new position.
11980
11981
The return value is the number of bytes relative to the beginning of
11982
the file.
11983
[clinic start generated code]*/
11984
11985
static Py_off_t
11986
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11987
/*[clinic end generated code: output=971e1efb6b30bd2f input=32ea0788da7cb44b]*/
11988
0
{
11989
0
    Py_off_t result;
11990
11991
0
#ifdef SEEK_SET
11992
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11993
0
    switch (how) {
11994
0
        case 0: how = SEEK_SET; break;
11995
0
        case 1: how = SEEK_CUR; break;
11996
0
        case 2: how = SEEK_END; break;
11997
0
    }
11998
0
#endif /* SEEK_END */
11999
12000
0
    Py_BEGIN_ALLOW_THREADS
12001
0
    _Py_BEGIN_SUPPRESS_IPH
12002
#ifdef MS_WINDOWS
12003
    result = _lseeki64(fd, position, how);
12004
#else
12005
0
    result = lseek(fd, position, how);
12006
0
#endif
12007
0
    _Py_END_SUPPRESS_IPH
12008
0
    Py_END_ALLOW_THREADS
12009
0
    if (result < 0)
12010
0
        posix_error();
12011
12012
0
    return result;
12013
0
}
12014
12015
12016
/*[clinic input]
12017
os.read
12018
    fd: int
12019
    length: Py_ssize_t
12020
    /
12021
12022
Read from a file descriptor.  Returns a bytes object.
12023
[clinic start generated code]*/
12024
12025
static PyObject *
12026
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
12027
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
12028
0
{
12029
0
    if (length < 0) {
12030
0
        errno = EINVAL;
12031
0
        return posix_error();
12032
0
    }
12033
12034
0
    length = Py_MIN(length, _PY_READ_MAX);
12035
12036
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12037
0
    if (writer == NULL) {
12038
0
        return NULL;
12039
0
    }
12040
12041
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
12042
0
    if (n == -1) {
12043
0
        PyBytesWriter_Discard(writer);
12044
0
        return NULL;
12045
0
    }
12046
12047
0
    return PyBytesWriter_FinishWithSize(writer, n);
12048
0
}
12049
12050
/*[clinic input]
12051
os.readinto -> Py_ssize_t
12052
    fd: int
12053
    buffer: Py_buffer(accept={rwbuffer})
12054
    /
12055
12056
Read into a buffer object from a file descriptor.
12057
12058
The buffer should be mutable and bytes-like.  On success, returns the
12059
number of bytes read.  Less bytes may be read than the size of the
12060
buffer.  The underlying system call will be retried when interrupted by
12061
a signal, unless the signal handler raises an exception.  Other errors
12062
will not be retried and an error will be raised.
12063
12064
Returns 0 if *fd* is at end of file or if the provided *buffer* has
12065
length 0 (which can be used to check for errors without reading data).
12066
Never returns negative.
12067
[clinic start generated code]*/
12068
12069
static Py_ssize_t
12070
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12071
/*[clinic end generated code: output=8091a3513c683a80 input=2a5f8b212cb5730c]*/
12072
0
{
12073
0
    assert(buffer->len >= 0);
12074
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12075
    /* Ensure negative is never returned without an error. Simplifies calling
12076
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12077
        error. */
12078
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12079
0
    return result;
12080
0
}
12081
12082
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12083
                                || defined(__APPLE__))) \
12084
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12085
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12086
static int
12087
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12088
0
{
12089
0
    Py_ssize_t i, j;
12090
12091
0
    *iov = PyMem_New(struct iovec, cnt);
12092
0
    if (*iov == NULL) {
12093
0
        PyErr_NoMemory();
12094
0
        return -1;
12095
0
    }
12096
12097
0
    *buf = PyMem_New(Py_buffer, cnt);
12098
0
    if (*buf == NULL) {
12099
0
        PyMem_Free(*iov);
12100
0
        PyErr_NoMemory();
12101
0
        return -1;
12102
0
    }
12103
12104
0
    for (i = 0; i < cnt; i++) {
12105
0
        PyObject *item = PySequence_GetItem(seq, i);
12106
0
        if (item == NULL)
12107
0
            goto fail;
12108
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12109
0
            Py_DECREF(item);
12110
0
            goto fail;
12111
0
        }
12112
0
        Py_DECREF(item);
12113
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12114
0
        (*iov)[i].iov_len = (*buf)[i].len;
12115
0
    }
12116
0
    return 0;
12117
12118
0
fail:
12119
0
    PyMem_Free(*iov);
12120
0
    for (j = 0; j < i; j++) {
12121
0
        PyBuffer_Release(&(*buf)[j]);
12122
0
    }
12123
0
    PyMem_Free(*buf);
12124
0
    return -1;
12125
0
}
12126
12127
static void
12128
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12129
0
{
12130
0
    int i;
12131
0
    PyMem_Free(iov);
12132
0
    for (i = 0; i < cnt; i++) {
12133
0
        PyBuffer_Release(&buf[i]);
12134
0
    }
12135
0
    PyMem_Free(buf);
12136
0
}
12137
#endif
12138
12139
12140
#ifdef HAVE_READV
12141
/*[clinic input]
12142
os.readv -> Py_ssize_t
12143
12144
    fd: int
12145
    buffers: object
12146
    /
12147
12148
Read from a file descriptor fd into an iterable of buffers.
12149
12150
The buffers should be mutable buffers accepting bytes.
12151
readv will transfer data into each buffer until it is full
12152
and then move on to the next buffer in the sequence to hold
12153
the rest of the data.
12154
12155
readv returns the total number of bytes read,
12156
which may be less than the total capacity of all the buffers.
12157
[clinic start generated code]*/
12158
12159
static Py_ssize_t
12160
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12161
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12162
0
{
12163
0
    Py_ssize_t cnt, n;
12164
0
    int async_err = 0;
12165
0
    struct iovec *iov;
12166
0
    Py_buffer *buf;
12167
12168
0
    if (!PySequence_Check(buffers)) {
12169
0
        PyErr_SetString(PyExc_TypeError,
12170
0
            "readv() arg 2 must be a sequence");
12171
0
        return -1;
12172
0
    }
12173
12174
0
    cnt = PySequence_Size(buffers);
12175
0
    if (cnt < 0)
12176
0
        return -1;
12177
12178
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12179
0
        return -1;
12180
12181
0
    do {
12182
0
        Py_BEGIN_ALLOW_THREADS
12183
0
        n = readv(fd, iov, cnt);
12184
0
        Py_END_ALLOW_THREADS
12185
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12186
12187
0
    int saved_errno = errno;
12188
0
    iov_cleanup(iov, buf, cnt);
12189
0
    if (n < 0) {
12190
0
        if (!async_err) {
12191
0
            errno = saved_errno;
12192
0
            posix_error();
12193
0
        }
12194
0
        return -1;
12195
0
    }
12196
12197
0
    return n;
12198
0
}
12199
#endif /* HAVE_READV */
12200
12201
12202
#ifdef HAVE_PREAD
12203
/*[clinic input]
12204
@permit_long_summary
12205
os.pread
12206
12207
    fd: int
12208
    length: Py_ssize_t
12209
    offset: Py_off_t
12210
    /
12211
12212
Read a number of bytes from a file descriptor starting at a particular offset.
12213
12214
Read length bytes from file descriptor fd, starting at offset bytes from
12215
the beginning of the file.  The file offset remains unchanged.
12216
[clinic start generated code]*/
12217
12218
static PyObject *
12219
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12220
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12221
0
{
12222
0
    Py_ssize_t n;
12223
0
    int async_err = 0;
12224
12225
0
    if (length < 0) {
12226
0
        errno = EINVAL;
12227
0
        return posix_error();
12228
0
    }
12229
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12230
0
    if (writer == NULL) {
12231
0
        return NULL;
12232
0
    }
12233
12234
0
    do {
12235
0
        Py_BEGIN_ALLOW_THREADS
12236
0
        _Py_BEGIN_SUPPRESS_IPH
12237
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12238
0
        _Py_END_SUPPRESS_IPH
12239
0
        Py_END_ALLOW_THREADS
12240
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12241
12242
0
    if (n < 0) {
12243
0
        if (!async_err) {
12244
0
            posix_error();
12245
0
        }
12246
0
        PyBytesWriter_Discard(writer);
12247
0
        return NULL;
12248
0
    }
12249
0
    return PyBytesWriter_FinishWithSize(writer, n);
12250
0
}
12251
#endif /* HAVE_PREAD */
12252
12253
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12254
/*[clinic input]
12255
@permit_long_summary
12256
os.preadv -> Py_ssize_t
12257
12258
    fd: int
12259
    buffers: object
12260
    offset: Py_off_t
12261
    flags: int = 0
12262
    /
12263
12264
Reads from a file descriptor into a number of mutable bytes-like objects.
12265
12266
Combines the functionality of readv() and pread().  As readv(), it will
12267
transfer data into each buffer until it is full and then move on to the
12268
next buffer in the sequence to hold the rest of the data.  Its fourth
12269
argument, specifies the file offset at which the input operation is to
12270
be performed.  It will return the total number of bytes read (which can
12271
be less than the total capacity of all the objects).
12272
12273
The flags argument contains a bitwise OR of zero or more of the
12274
following flags:
12275
12276
- RWF_HIPRI
12277
- RWF_NOWAIT
12278
- RWF_DONTCACHE
12279
12280
Using non-zero flags requires Linux 4.6 or newer.
12281
[clinic start generated code]*/
12282
12283
static Py_ssize_t
12284
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12285
               int flags)
12286
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=bbc70c63b4f4e877]*/
12287
0
{
12288
0
    Py_ssize_t cnt, n;
12289
0
    int async_err = 0;
12290
0
    struct iovec *iov;
12291
0
    Py_buffer *buf;
12292
12293
0
    if (!PySequence_Check(buffers)) {
12294
0
        PyErr_SetString(PyExc_TypeError,
12295
0
            "preadv2() arg 2 must be a sequence");
12296
0
        return -1;
12297
0
    }
12298
12299
0
    cnt = PySequence_Size(buffers);
12300
0
    if (cnt < 0) {
12301
0
        return -1;
12302
0
    }
12303
12304
#ifndef HAVE_PREADV2
12305
    if(flags != 0) {
12306
        argument_unavailable_error("preadv2", "flags");
12307
        return -1;
12308
    }
12309
#endif
12310
12311
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12312
0
        return -1;
12313
0
    }
12314
0
#ifdef HAVE_PREADV2
12315
0
    do {
12316
0
        Py_BEGIN_ALLOW_THREADS
12317
0
        _Py_BEGIN_SUPPRESS_IPH
12318
0
        n = preadv2(fd, iov, cnt, offset, flags);
12319
0
        _Py_END_SUPPRESS_IPH
12320
0
        Py_END_ALLOW_THREADS
12321
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12322
#else
12323
    do {
12324
#if defined(__APPLE__) && defined(__clang__)
12325
/* This entire function will be removed from the module dict when the API
12326
 * is not available.
12327
 */
12328
#pragma clang diagnostic push
12329
#pragma clang diagnostic ignored "-Wunguarded-availability"
12330
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12331
#endif
12332
        Py_BEGIN_ALLOW_THREADS
12333
        _Py_BEGIN_SUPPRESS_IPH
12334
        n = preadv(fd, iov, cnt, offset);
12335
        _Py_END_SUPPRESS_IPH
12336
        Py_END_ALLOW_THREADS
12337
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12338
12339
#if defined(__APPLE__) && defined(__clang__)
12340
#pragma clang diagnostic pop
12341
#endif
12342
12343
#endif
12344
12345
0
    int saved_errno = errno;
12346
0
    iov_cleanup(iov, buf, cnt);
12347
0
    if (n < 0) {
12348
0
        if (!async_err) {
12349
0
            errno = saved_errno;
12350
0
            posix_error();
12351
0
        }
12352
0
        return -1;
12353
0
    }
12354
12355
0
    return n;
12356
0
}
12357
#endif /* HAVE_PREADV */
12358
12359
12360
/*[clinic input]
12361
os.write -> Py_ssize_t
12362
12363
    fd: int
12364
    data: Py_buffer
12365
    /
12366
12367
Write a bytes object to a file descriptor.
12368
[clinic start generated code]*/
12369
12370
static Py_ssize_t
12371
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12372
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12373
2
{
12374
2
    return _Py_write(fd, data->buf, data->len);
12375
2
}
12376
12377
#ifdef HAVE_SENDFILE
12378
#ifdef __APPLE__
12379
/*[clinic input]
12380
os.sendfile
12381
12382
    out_fd: int
12383
    in_fd: int
12384
    offset: Py_off_t
12385
    count as sbytes: Py_off_t
12386
    headers: object(c_default="NULL") = ()
12387
    trailers: object(c_default="NULL") = ()
12388
    flags: int = 0
12389
12390
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12391
[clinic start generated code]*/
12392
12393
static PyObject *
12394
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12395
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12396
                 int flags)
12397
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12398
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12399
/*[clinic input]
12400
os.sendfile
12401
12402
    out_fd: int
12403
    in_fd: int
12404
    offset: Py_off_t
12405
    count: Py_ssize_t(allow_negative=False)
12406
    headers: object(c_default="NULL") = ()
12407
    trailers: object(c_default="NULL") = ()
12408
    flags: int = 0
12409
12410
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12411
[clinic start generated code]*/
12412
12413
static PyObject *
12414
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12415
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12416
                 int flags)
12417
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12418
#else
12419
/*[clinic input]
12420
os.sendfile
12421
12422
    out_fd: int
12423
    in_fd: int
12424
    offset as offobj: object
12425
    count: Py_ssize_t(allow_negative=False)
12426
12427
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12428
[clinic start generated code]*/
12429
12430
static PyObject *
12431
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12432
                 Py_ssize_t count)
12433
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12434
#endif
12435
0
{
12436
0
    Py_ssize_t ret;
12437
0
    int async_err = 0;
12438
12439
#ifdef __APPLE__
12440
    if(sbytes < 0) {
12441
        PyErr_SetString(PyExc_ValueError,
12442
                        "count cannot be negative");
12443
        return NULL;
12444
    }
12445
#else
12446
0
    assert(count >= 0);
12447
0
#endif
12448
12449
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12450
#ifndef __APPLE__
12451
    off_t sbytes;
12452
#endif
12453
    Py_buffer *hbuf, *tbuf;
12454
    struct sf_hdtr sf;
12455
12456
    sf.headers = NULL;
12457
    sf.trailers = NULL;
12458
12459
    if (headers != NULL) {
12460
        if (!PySequence_Check(headers)) {
12461
            PyErr_SetString(PyExc_TypeError,
12462
                "sendfile() headers must be a sequence");
12463
            return NULL;
12464
        } else {
12465
            Py_ssize_t i = PySequence_Size(headers);
12466
            if (i < 0)
12467
                return NULL;
12468
            if (i > INT_MAX) {
12469
                PyErr_SetString(PyExc_OverflowError,
12470
                    "sendfile() header is too large");
12471
                return NULL;
12472
            }
12473
            if (i > 0) {
12474
                sf.hdr_cnt = (int)i;
12475
                if (iov_setup(&(sf.headers), &hbuf,
12476
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12477
                    return NULL;
12478
#ifdef __APPLE__
12479
                for (i = 0; i < sf.hdr_cnt; i++) {
12480
                    Py_ssize_t blen = sf.headers[i].iov_len;
12481
# define OFF_T_MAX 0x7fffffffffffffff
12482
                    if (sbytes >= OFF_T_MAX - blen) {
12483
                        PyErr_SetString(PyExc_OverflowError,
12484
                            "sendfile() header is too large");
12485
                        return NULL;
12486
                    }
12487
                    sbytes += blen;
12488
                }
12489
#endif
12490
            }
12491
        }
12492
    }
12493
    if (trailers != NULL) {
12494
        if (!PySequence_Check(trailers)) {
12495
            PyErr_SetString(PyExc_TypeError,
12496
                "sendfile() trailers must be a sequence");
12497
            return NULL;
12498
        } else {
12499
            Py_ssize_t i = PySequence_Size(trailers);
12500
            if (i < 0)
12501
                return NULL;
12502
            if (i > INT_MAX) {
12503
                PyErr_SetString(PyExc_OverflowError,
12504
                    "sendfile() trailer is too large");
12505
                return NULL;
12506
            }
12507
            if (i > 0) {
12508
                sf.trl_cnt = (int)i;
12509
                if (iov_setup(&(sf.trailers), &tbuf,
12510
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12511
                    return NULL;
12512
            }
12513
        }
12514
    }
12515
12516
    _Py_BEGIN_SUPPRESS_IPH
12517
    do {
12518
        Py_BEGIN_ALLOW_THREADS
12519
#ifdef __APPLE__
12520
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12521
#else
12522
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12523
#endif
12524
        Py_END_ALLOW_THREADS
12525
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12526
    _Py_END_SUPPRESS_IPH
12527
12528
    int saved_errno = errno;
12529
    if (sf.headers != NULL)
12530
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12531
    if (sf.trailers != NULL)
12532
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12533
12534
    if (ret < 0) {
12535
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12536
            if (sbytes != 0) {
12537
                // some data has been sent
12538
                goto done;
12539
            }
12540
            // no data has been sent; upper application is supposed
12541
            // to retry on EAGAIN or EBUSY
12542
        }
12543
        if (!async_err) {
12544
            errno = saved_errno;
12545
            posix_error();
12546
        }
12547
        return NULL;
12548
    }
12549
    goto done;
12550
12551
done:
12552
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12553
        return PyLong_FromLong(sbytes);
12554
    #else
12555
        return PyLong_FromLongLong(sbytes);
12556
    #endif
12557
12558
#else
12559
0
#ifdef __linux__
12560
0
    if (offobj == Py_None) {
12561
0
        do {
12562
0
            Py_BEGIN_ALLOW_THREADS
12563
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12564
0
            Py_END_ALLOW_THREADS
12565
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12566
0
        if (ret < 0)
12567
0
            return (!async_err) ? posix_error() : NULL;
12568
0
        return PyLong_FromSsize_t(ret);
12569
0
    }
12570
0
#endif
12571
0
    off_t offset;
12572
0
    if (!Py_off_t_converter(offobj, &offset))
12573
0
        return NULL;
12574
12575
#if defined(__sun) && defined(__SVR4)
12576
    // On Solaris, sendfile raises EINVAL rather than returning 0
12577
    // when the offset is equal or bigger than the in_fd size.
12578
    struct stat st;
12579
12580
    do {
12581
        Py_BEGIN_ALLOW_THREADS
12582
        ret = fstat(in_fd, &st);
12583
        Py_END_ALLOW_THREADS
12584
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12585
    if (ret < 0)
12586
        return (!async_err) ? posix_error() : NULL;
12587
12588
    if (offset >= st.st_size) {
12589
        return PyLong_FromLong(0);
12590
    }
12591
12592
    // On illumos specifically sendfile() may perform a partial write but
12593
    // return -1/an error (in one confirmed case the destination socket
12594
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12595
    // code to check if the offset parameter was modified by sendfile().
12596
    //
12597
    // We need this variable to track said change.
12598
    off_t original_offset = offset;
12599
#endif
12600
12601
0
    do {
12602
0
        Py_BEGIN_ALLOW_THREADS
12603
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12604
#if defined(__sun) && defined(__SVR4)
12605
        // This handles illumos-specific sendfile() partial write behavior,
12606
        // see a comment above for more details.
12607
        if (ret < 0 && offset != original_offset) {
12608
            ret = offset - original_offset;
12609
        }
12610
#endif
12611
0
        Py_END_ALLOW_THREADS
12612
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12613
0
    if (ret < 0)
12614
0
        return (!async_err) ? posix_error() : NULL;
12615
0
    return PyLong_FromSsize_t(ret);
12616
0
#endif
12617
0
}
12618
#endif /* HAVE_SENDFILE */
12619
12620
12621
#if defined(__APPLE__)
12622
/*[clinic input]
12623
@permit_long_summary
12624
os._fcopyfile
12625
12626
    in_fd: int
12627
    out_fd: int
12628
    flags: int
12629
    /
12630
12631
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12632
[clinic start generated code]*/
12633
12634
static PyObject *
12635
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12636
/*[clinic end generated code: output=c9d1a35a992e401b input=80b53ad8863c9101]*/
12637
{
12638
    int ret;
12639
12640
    Py_BEGIN_ALLOW_THREADS
12641
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12642
    Py_END_ALLOW_THREADS
12643
    if (ret < 0)
12644
        return posix_error();
12645
    Py_RETURN_NONE;
12646
}
12647
#endif
12648
12649
12650
/*[clinic input]
12651
os.fstat
12652
12653
    fd : int
12654
12655
Perform a stat system call on the given file descriptor.
12656
12657
Like stat(), but for an open file descriptor.
12658
Equivalent to os.stat(fd).
12659
[clinic start generated code]*/
12660
12661
static PyObject *
12662
os_fstat_impl(PyObject *module, int fd)
12663
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12664
91.1k
{
12665
91.1k
    STRUCT_STAT st;
12666
91.1k
    int res;
12667
91.1k
    int async_err = 0;
12668
12669
91.1k
    do {
12670
91.1k
        Py_BEGIN_ALLOW_THREADS
12671
91.1k
        res = FSTAT(fd, &st);
12672
91.1k
        Py_END_ALLOW_THREADS
12673
91.1k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12674
91.1k
    if (res != 0) {
12675
#ifdef MS_WINDOWS
12676
        return PyErr_SetFromWindowsErr(0);
12677
#else
12678
0
        return (!async_err) ? posix_error() : NULL;
12679
0
#endif
12680
0
    }
12681
12682
91.1k
    return _pystat_fromstructstat(module, &st);
12683
91.1k
}
12684
12685
12686
/*[clinic input]
12687
os.isatty -> bool
12688
    fd: int
12689
    /
12690
12691
Return True if the fd is connected to a terminal.
12692
12693
Return True if the file descriptor is an open file descriptor
12694
connected to the slave end of a terminal.
12695
[clinic start generated code]*/
12696
12697
static int
12698
os_isatty_impl(PyObject *module, int fd)
12699
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12700
0
{
12701
0
    int return_value;
12702
0
    Py_BEGIN_ALLOW_THREADS
12703
0
    _Py_BEGIN_SUPPRESS_IPH
12704
0
    return_value = isatty(fd);
12705
0
    _Py_END_SUPPRESS_IPH
12706
0
    Py_END_ALLOW_THREADS
12707
0
    return return_value;
12708
0
}
12709
12710
12711
#ifdef HAVE_PIPE
12712
/*[clinic input]
12713
os.pipe
12714
12715
Create a pipe.
12716
12717
Returns a tuple of two file descriptors:
12718
  (read_fd, write_fd)
12719
[clinic start generated code]*/
12720
12721
static PyObject *
12722
os_pipe_impl(PyObject *module)
12723
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12724
0
{
12725
0
    int fds[2];
12726
#ifdef MS_WINDOWS
12727
    HANDLE read, write;
12728
    SECURITY_ATTRIBUTES attr;
12729
    BOOL ok;
12730
#else
12731
0
    int res;
12732
0
#endif
12733
12734
#ifdef MS_WINDOWS
12735
    attr.nLength = sizeof(attr);
12736
    attr.lpSecurityDescriptor = NULL;
12737
    attr.bInheritHandle = FALSE;
12738
12739
    Py_BEGIN_ALLOW_THREADS
12740
    ok = CreatePipe(&read, &write, &attr, 0);
12741
    if (ok) {
12742
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12743
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12744
        if (fds[0] == -1 || fds[1] == -1) {
12745
            CloseHandle(read);
12746
            CloseHandle(write);
12747
            ok = 0;
12748
        }
12749
    }
12750
    Py_END_ALLOW_THREADS
12751
12752
    if (!ok)
12753
        return PyErr_SetFromWindowsErr(0);
12754
#else
12755
12756
0
#ifdef HAVE_PIPE2
12757
0
    Py_BEGIN_ALLOW_THREADS
12758
0
    res = pipe2(fds, O_CLOEXEC);
12759
0
    Py_END_ALLOW_THREADS
12760
12761
0
    if (res != 0 && errno == ENOSYS)
12762
0
    {
12763
0
#endif
12764
0
        Py_BEGIN_ALLOW_THREADS
12765
0
        res = pipe(fds);
12766
0
        Py_END_ALLOW_THREADS
12767
12768
0
        if (res == 0) {
12769
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12770
0
                close(fds[0]);
12771
0
                close(fds[1]);
12772
0
                return NULL;
12773
0
            }
12774
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12775
0
                close(fds[0]);
12776
0
                close(fds[1]);
12777
0
                return NULL;
12778
0
            }
12779
0
        }
12780
0
#ifdef HAVE_PIPE2
12781
0
    }
12782
0
#endif
12783
12784
0
    if (res != 0)
12785
0
        return PyErr_SetFromErrno(PyExc_OSError);
12786
0
#endif /* !MS_WINDOWS */
12787
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12788
0
}
12789
#endif  /* HAVE_PIPE */
12790
12791
12792
#ifdef HAVE_PIPE2
12793
/*[clinic input]
12794
os.pipe2
12795
12796
    flags: int
12797
    /
12798
12799
Create a pipe with flags set atomically.
12800
12801
Returns a tuple of two file descriptors:
12802
  (read_fd, write_fd)
12803
12804
flags can be constructed by ORing together one or more of these values:
12805
O_NONBLOCK, O_CLOEXEC.
12806
[clinic start generated code]*/
12807
12808
static PyObject *
12809
os_pipe2_impl(PyObject *module, int flags)
12810
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12811
0
{
12812
0
    int fds[2];
12813
0
    int res;
12814
12815
0
    res = pipe2(fds, flags);
12816
0
    if (res != 0)
12817
0
        return posix_error();
12818
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12819
0
}
12820
#endif /* HAVE_PIPE2 */
12821
12822
12823
#ifdef HAVE_WRITEV
12824
/*[clinic input]
12825
@permit_long_summary
12826
os.writev -> Py_ssize_t
12827
    fd: int
12828
    buffers: object
12829
    /
12830
12831
Iterate over buffers, and write the contents of each to a file descriptor.
12832
12833
Returns the total number of bytes written.
12834
buffers must be a sequence of bytes-like objects.
12835
[clinic start generated code]*/
12836
12837
static Py_ssize_t
12838
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12839
/*[clinic end generated code: output=56565cfac3aac15b input=5771a0f0c2b326f2]*/
12840
0
{
12841
0
    Py_ssize_t cnt;
12842
0
    Py_ssize_t result;
12843
0
    int async_err = 0;
12844
0
    struct iovec *iov;
12845
0
    Py_buffer *buf;
12846
12847
0
    if (!PySequence_Check(buffers)) {
12848
0
        PyErr_SetString(PyExc_TypeError,
12849
0
            "writev() arg 2 must be a sequence");
12850
0
        return -1;
12851
0
    }
12852
0
    cnt = PySequence_Size(buffers);
12853
0
    if (cnt < 0)
12854
0
        return -1;
12855
12856
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12857
0
        return -1;
12858
0
    }
12859
12860
0
    do {
12861
0
        Py_BEGIN_ALLOW_THREADS
12862
0
        result = writev(fd, iov, cnt);
12863
0
        Py_END_ALLOW_THREADS
12864
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12865
12866
0
    if (result < 0 && !async_err)
12867
0
        posix_error();
12868
12869
0
    iov_cleanup(iov, buf, cnt);
12870
0
    return result;
12871
0
}
12872
#endif /* HAVE_WRITEV */
12873
12874
12875
#ifdef HAVE_PWRITE
12876
/*[clinic input]
12877
os.pwrite -> Py_ssize_t
12878
12879
    fd: int
12880
    buffer: Py_buffer
12881
    offset: Py_off_t
12882
    /
12883
12884
Write bytes to a file descriptor starting at a particular offset.
12885
12886
Write buffer to fd, starting at offset bytes from the beginning of
12887
the file.  Returns the number of bytes written.  Does not change the
12888
current file offset.
12889
[clinic start generated code]*/
12890
12891
static Py_ssize_t
12892
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12893
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12894
0
{
12895
0
    Py_ssize_t size;
12896
0
    int async_err = 0;
12897
12898
0
    do {
12899
0
        Py_BEGIN_ALLOW_THREADS
12900
0
        _Py_BEGIN_SUPPRESS_IPH
12901
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12902
0
        _Py_END_SUPPRESS_IPH
12903
0
        Py_END_ALLOW_THREADS
12904
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12905
12906
0
    if (size < 0 && !async_err)
12907
0
        posix_error();
12908
0
    return size;
12909
0
}
12910
#endif /* HAVE_PWRITE */
12911
12912
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12913
/*[clinic input]
12914
@permit_long_summary
12915
os.pwritev -> Py_ssize_t
12916
12917
    fd: int
12918
    buffers: object
12919
    offset: Py_off_t
12920
    flags: int = 0
12921
    /
12922
12923
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12924
12925
Combines the functionality of writev() and pwrite(). All buffers must be
12926
a sequence of bytes-like objects.  Buffers are processed in array order.
12927
Entire contents of first buffer is written before proceeding to second,
12928
and so on. The operating system may set a limit (sysconf() value
12929
SC_IOV_MAX) on the number of buffers that can be used.
12930
This function writes the contents of each object to the file descriptor
12931
and returns the total number of bytes written.
12932
12933
The flags argument contains a bitwise OR of zero or more of the
12934
following flags:
12935
12936
- RWF_DSYNC
12937
- RWF_SYNC
12938
- RWF_APPEND
12939
- RWF_DONTCACHE
12940
- RWF_ATOMIC
12941
12942
Using non-zero flags requires Linux 4.7 or newer.
12943
[clinic start generated code]*/
12944
12945
static Py_ssize_t
12946
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12947
                int flags)
12948
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=b2e352a22f030e9a]*/
12949
0
{
12950
0
    Py_ssize_t cnt;
12951
0
    Py_ssize_t result;
12952
0
    int async_err = 0;
12953
0
    struct iovec *iov;
12954
0
    Py_buffer *buf;
12955
12956
0
    if (!PySequence_Check(buffers)) {
12957
0
        PyErr_SetString(PyExc_TypeError,
12958
0
            "pwritev() arg 2 must be a sequence");
12959
0
        return -1;
12960
0
    }
12961
12962
0
    cnt = PySequence_Size(buffers);
12963
0
    if (cnt < 0) {
12964
0
        return -1;
12965
0
    }
12966
12967
#ifndef HAVE_PWRITEV2
12968
    if(flags != 0) {
12969
        argument_unavailable_error("pwritev2", "flags");
12970
        return -1;
12971
    }
12972
#endif
12973
12974
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12975
0
        return -1;
12976
0
    }
12977
0
#ifdef HAVE_PWRITEV2
12978
0
    do {
12979
0
        Py_BEGIN_ALLOW_THREADS
12980
0
        _Py_BEGIN_SUPPRESS_IPH
12981
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12982
0
        _Py_END_SUPPRESS_IPH
12983
0
        Py_END_ALLOW_THREADS
12984
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12985
#else
12986
12987
#if defined(__APPLE__) && defined(__clang__)
12988
/* This entire function will be removed from the module dict when the API
12989
 * is not available.
12990
 */
12991
#pragma clang diagnostic push
12992
#pragma clang diagnostic ignored "-Wunguarded-availability"
12993
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12994
#endif
12995
    do {
12996
        Py_BEGIN_ALLOW_THREADS
12997
        _Py_BEGIN_SUPPRESS_IPH
12998
        result = pwritev(fd, iov, cnt, offset);
12999
        _Py_END_SUPPRESS_IPH
13000
        Py_END_ALLOW_THREADS
13001
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13002
13003
#if defined(__APPLE__) && defined(__clang__)
13004
#pragma clang diagnostic pop
13005
#endif
13006
13007
#endif
13008
13009
0
    if (result < 0) {
13010
0
        if (!async_err) {
13011
0
            posix_error();
13012
0
        }
13013
0
        result = -1;
13014
0
    }
13015
0
    iov_cleanup(iov, buf, cnt);
13016
13017
0
    return result;
13018
0
}
13019
#endif /* HAVE_PWRITEV */
13020
13021
#ifdef HAVE_COPY_FILE_RANGE
13022
/*[clinic input]
13023
13024
os.copy_file_range
13025
    src: int
13026
        Source file descriptor.
13027
    dst: int
13028
        Destination file descriptor.
13029
    count: Py_ssize_t(allow_negative=False)
13030
        Number of bytes to copy.
13031
    offset_src: object = None
13032
        Starting offset in src.
13033
    offset_dst: object = None
13034
        Starting offset in dst.
13035
13036
Copy count bytes from one file descriptor to another.
13037
13038
If offset_src is None, then src is read from the current position;
13039
respectively for offset_dst.
13040
[clinic start generated code]*/
13041
13042
static PyObject *
13043
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13044
                        PyObject *offset_src, PyObject *offset_dst)
13045
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
13046
0
{
13047
0
    off_t offset_src_val, offset_dst_val;
13048
0
    off_t *p_offset_src = NULL;
13049
0
    off_t *p_offset_dst = NULL;
13050
0
    Py_ssize_t ret;
13051
0
    int async_err = 0;
13052
    /* The flags argument is provided to allow
13053
     * for future extensions and currently must be to 0. */
13054
0
    int flags = 0;
13055
13056
13057
0
    if (offset_src != Py_None) {
13058
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13059
0
            return NULL;
13060
0
        }
13061
0
        p_offset_src = &offset_src_val;
13062
0
    }
13063
13064
0
    if (offset_dst != Py_None) {
13065
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13066
0
            return NULL;
13067
0
        }
13068
0
        p_offset_dst = &offset_dst_val;
13069
0
    }
13070
13071
0
    do {
13072
0
        Py_BEGIN_ALLOW_THREADS
13073
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13074
0
        Py_END_ALLOW_THREADS
13075
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13076
13077
0
    if (ret < 0) {
13078
0
        return (!async_err) ? posix_error() : NULL;
13079
0
    }
13080
13081
0
    return PyLong_FromSsize_t(ret);
13082
0
}
13083
#endif /* HAVE_COPY_FILE_RANGE*/
13084
13085
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13086
/*[clinic input]
13087
13088
os.splice
13089
    src: int
13090
        Source file descriptor.
13091
    dst: int
13092
        Destination file descriptor.
13093
    count: Py_ssize_t(allow_negative=False)
13094
        Number of bytes to copy.
13095
    offset_src: object = None
13096
        Starting offset in src.
13097
    offset_dst: object = None
13098
        Starting offset in dst.
13099
    flags: unsigned_int = 0
13100
        Flags to modify the semantics of the call.
13101
13102
Transfer count bytes from one pipe to a descriptor or vice versa.
13103
13104
If offset_src is None, then src is read from the current position;
13105
respectively for offset_dst. The offset associated to the file
13106
descriptor that refers to a pipe must be None.
13107
[clinic start generated code]*/
13108
13109
static PyObject *
13110
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13111
               PyObject *offset_src, PyObject *offset_dst,
13112
               unsigned int flags)
13113
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13114
0
{
13115
0
    off_t offset_src_val, offset_dst_val;
13116
0
    off_t *p_offset_src = NULL;
13117
0
    off_t *p_offset_dst = NULL;
13118
0
    Py_ssize_t ret;
13119
0
    int async_err = 0;
13120
13121
13122
0
    if (offset_src != Py_None) {
13123
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13124
0
            return NULL;
13125
0
        }
13126
0
        p_offset_src = &offset_src_val;
13127
0
    }
13128
13129
0
    if (offset_dst != Py_None) {
13130
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13131
0
            return NULL;
13132
0
        }
13133
0
        p_offset_dst = &offset_dst_val;
13134
0
    }
13135
13136
0
    do {
13137
0
        Py_BEGIN_ALLOW_THREADS
13138
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13139
0
        Py_END_ALLOW_THREADS
13140
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13141
13142
0
    if (ret < 0) {
13143
0
        return (!async_err) ? posix_error() : NULL;
13144
0
    }
13145
13146
0
    return PyLong_FromSsize_t(ret);
13147
0
}
13148
#endif /* HAVE_SPLICE*/
13149
13150
#ifdef HAVE_MKFIFO
13151
/*[clinic input]
13152
os.mkfifo
13153
13154
    path: path_t
13155
    mode: int=0o666
13156
    *
13157
    dir_fd: dir_fd(requires='mkfifoat')=None
13158
13159
Create a "fifo" (a POSIX named pipe).
13160
13161
If dir_fd is not None, it should be a file descriptor open to
13162
a directory, and path should be relative; path will then be relative to
13163
that directory.
13164
dir_fd may not be implemented on your platform.  If it is unavailable,
13165
using it will raise a NotImplementedError.
13166
[clinic start generated code]*/
13167
13168
static PyObject *
13169
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13170
/*[clinic end generated code: output=ce41cfad0e68c940 input=d2fb917c01e888d6]*/
13171
0
{
13172
0
    int result;
13173
0
    int async_err = 0;
13174
0
#ifdef HAVE_MKFIFOAT
13175
0
    int mkfifoat_unavailable = 0;
13176
0
#endif
13177
13178
0
    do {
13179
0
        Py_BEGIN_ALLOW_THREADS
13180
0
#ifdef HAVE_MKFIFOAT
13181
0
        if (dir_fd != DEFAULT_DIR_FD) {
13182
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13183
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13184
13185
0
            } else {
13186
0
                mkfifoat_unavailable = 1;
13187
0
                result = 0;
13188
0
            }
13189
0
        } else
13190
0
#endif
13191
0
            result = mkfifo(path->narrow, mode);
13192
0
        Py_END_ALLOW_THREADS
13193
0
    } while (result != 0 && errno == EINTR &&
13194
0
             !(async_err = PyErr_CheckSignals()));
13195
13196
0
#ifdef HAVE_MKFIFOAT
13197
0
    if (mkfifoat_unavailable) {
13198
0
        argument_unavailable_error(NULL, "dir_fd");
13199
0
        return NULL;
13200
0
    }
13201
0
#endif
13202
13203
0
    if (result != 0)
13204
0
        return (!async_err) ? posix_error() : NULL;
13205
13206
0
    Py_RETURN_NONE;
13207
0
}
13208
#endif /* HAVE_MKFIFO */
13209
13210
13211
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13212
/*[clinic input]
13213
os.mknod
13214
13215
    path: path_t
13216
    mode: int=0o600
13217
    device: dev_t=0
13218
    *
13219
    dir_fd: dir_fd(requires='mknodat')=None
13220
13221
Create a node in the file system.
13222
13223
Create a node in the file system (file, device special file or named
13224
pipe) at path.  mode specifies both the permissions to use and the
13225
type of node to be created, being combined (bitwise OR) with one of
13226
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set
13227
on mode, device defines the newly created device special file (probably
13228
using os.makedev()).  Otherwise device is ignored.
13229
13230
If dir_fd is not None, it should be a file descriptor open to
13231
a directory, and path should be relative; path will then be relative
13232
to that directory.
13233
dir_fd may not be implemented on your platform.  If it is unavailable,
13234
using it will raise a NotImplementedError.
13235
[clinic start generated code]*/
13236
13237
static PyObject *
13238
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13239
              int dir_fd)
13240
/*[clinic end generated code: output=92e55d3ca8917461 input=7d0099e85c6b4cba]*/
13241
0
{
13242
0
    int result;
13243
0
    int async_err = 0;
13244
0
#ifdef HAVE_MKNODAT
13245
0
    int mknodat_unavailable = 0;
13246
0
#endif
13247
13248
0
    do {
13249
0
        Py_BEGIN_ALLOW_THREADS
13250
0
#ifdef HAVE_MKNODAT
13251
0
        if (dir_fd != DEFAULT_DIR_FD) {
13252
0
            if (HAVE_MKNODAT_RUNTIME) {
13253
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13254
13255
0
            } else {
13256
0
                mknodat_unavailable = 1;
13257
0
                result = 0;
13258
0
            }
13259
0
        } else
13260
0
#endif
13261
0
            result = mknod(path->narrow, mode, device);
13262
0
        Py_END_ALLOW_THREADS
13263
0
    } while (result != 0 && errno == EINTR &&
13264
0
             !(async_err = PyErr_CheckSignals()));
13265
0
#ifdef HAVE_MKNODAT
13266
0
    if (mknodat_unavailable) {
13267
0
        argument_unavailable_error(NULL, "dir_fd");
13268
0
        return NULL;
13269
0
    }
13270
0
#endif
13271
0
    if (result != 0)
13272
0
        return (!async_err) ? posix_error() : NULL;
13273
13274
0
    Py_RETURN_NONE;
13275
0
}
13276
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13277
13278
13279
#ifdef HAVE_DEVICE_MACROS
13280
static PyObject *
13281
major_minor_conv(unsigned int value)
13282
0
{
13283
0
#ifdef NODEV
13284
0
    if (value == (unsigned int)NODEV) {
13285
0
        return PyLong_FromLong((int)NODEV);
13286
0
    }
13287
0
#endif
13288
0
    return PyLong_FromUnsignedLong(value);
13289
0
}
13290
13291
static int
13292
major_minor_check(dev_t value)
13293
0
{
13294
0
#ifdef NODEV
13295
0
    if (value == NODEV) {
13296
0
        return 1;
13297
0
    }
13298
0
#endif
13299
0
    return (dev_t)(unsigned int)value == value;
13300
0
}
13301
13302
/*[clinic input]
13303
os.major
13304
13305
    device: dev_t
13306
    /
13307
13308
Extracts a device major number from a raw device number.
13309
[clinic start generated code]*/
13310
13311
static PyObject *
13312
os_major_impl(PyObject *module, dev_t device)
13313
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13314
0
{
13315
0
    return major_minor_conv(major(device));
13316
0
}
13317
13318
13319
/*[clinic input]
13320
os.minor
13321
13322
    device: dev_t
13323
    /
13324
13325
Extracts a device minor number from a raw device number.
13326
[clinic start generated code]*/
13327
13328
static PyObject *
13329
os_minor_impl(PyObject *module, dev_t device)
13330
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13331
0
{
13332
0
    return major_minor_conv(minor(device));
13333
0
}
13334
13335
13336
/*[clinic input]
13337
os.makedev -> dev_t
13338
13339
    major: dev_t
13340
    minor: dev_t
13341
    /
13342
13343
Composes a raw device number from the major and minor device numbers.
13344
[clinic start generated code]*/
13345
13346
static dev_t
13347
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13348
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13349
0
{
13350
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13351
0
        PyErr_SetString(PyExc_OverflowError,
13352
0
                        "Python int too large to convert to C unsigned int");
13353
0
        return (dev_t)-1;
13354
0
    }
13355
0
    return makedev(major, minor);
13356
0
}
13357
#endif /* HAVE_DEVICE_MACROS */
13358
13359
13360
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13361
/*[clinic input]
13362
os.ftruncate
13363
13364
    fd: int
13365
    length: Py_off_t
13366
    /
13367
13368
Truncate a file, specified by file descriptor, to a specific length.
13369
[clinic start generated code]*/
13370
13371
static PyObject *
13372
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13373
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13374
0
{
13375
0
    int result;
13376
0
    int async_err = 0;
13377
13378
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13379
0
        return NULL;
13380
0
    }
13381
13382
0
    do {
13383
0
        Py_BEGIN_ALLOW_THREADS
13384
0
        _Py_BEGIN_SUPPRESS_IPH
13385
#ifdef MS_WINDOWS
13386
        result = _chsize_s(fd, length);
13387
#else
13388
0
        result = ftruncate(fd, length);
13389
0
#endif
13390
0
        _Py_END_SUPPRESS_IPH
13391
0
        Py_END_ALLOW_THREADS
13392
0
    } while (result != 0 && errno == EINTR &&
13393
0
             !(async_err = PyErr_CheckSignals()));
13394
0
    if (result != 0)
13395
0
        return (!async_err) ? posix_error() : NULL;
13396
0
    Py_RETURN_NONE;
13397
0
}
13398
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13399
13400
13401
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13402
/*[clinic input]
13403
os.truncate
13404
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13405
    length: Py_off_t
13406
13407
Truncate a file, specified by path, to a specific length.
13408
13409
On some platforms, path may also be specified as an open file
13410
descriptor.  If this functionality is unavailable, using it raises
13411
an exception.
13412
[clinic start generated code]*/
13413
13414
static PyObject *
13415
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13416
/*[clinic end generated code: output=43009c8df5c0a12b input=ce33fd7808a511c4]*/
13417
0
{
13418
0
    int result;
13419
#ifdef MS_WINDOWS
13420
    int fd;
13421
#endif
13422
13423
0
    if (path->is_fd)
13424
0
        return os_ftruncate_impl(module, path->fd, length);
13425
13426
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13427
0
        return NULL;
13428
0
    }
13429
13430
0
    Py_BEGIN_ALLOW_THREADS
13431
0
    _Py_BEGIN_SUPPRESS_IPH
13432
#ifdef MS_WINDOWS
13433
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13434
    if (fd < 0)
13435
        result = -1;
13436
    else {
13437
        result = _chsize_s(fd, length);
13438
        close(fd);
13439
        if (result < 0)
13440
            errno = result;
13441
    }
13442
#else
13443
0
    result = truncate(path->narrow, length);
13444
0
#endif
13445
0
    _Py_END_SUPPRESS_IPH
13446
0
    Py_END_ALLOW_THREADS
13447
0
    if (result < 0)
13448
0
        return posix_path_error(path);
13449
13450
0
    Py_RETURN_NONE;
13451
0
}
13452
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13453
13454
13455
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13456
   OSs, support was dropped in WASI preview2. */
13457
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13458
/*[clinic input]
13459
@permit_long_summary
13460
os.posix_fallocate
13461
13462
    fd: int
13463
    offset: Py_off_t
13464
    length: Py_off_t
13465
    /
13466
13467
Ensure a file has allocated at least a particular number of bytes on disk.
13468
13469
Ensure that the file specified by fd encompasses a range of bytes
13470
starting at offset bytes from the beginning and continuing for length
13471
bytes.
13472
[clinic start generated code]*/
13473
13474
static PyObject *
13475
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13476
                        Py_off_t length)
13477
/*[clinic end generated code: output=73f107139564aa9d input=c718971d18b96896]*/
13478
0
{
13479
0
    int result;
13480
0
    int async_err = 0;
13481
13482
0
    do {
13483
0
        Py_BEGIN_ALLOW_THREADS
13484
0
        result = posix_fallocate(fd, offset, length);
13485
0
        Py_END_ALLOW_THREADS
13486
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13487
13488
0
    if (result == 0)
13489
0
        Py_RETURN_NONE;
13490
13491
0
    if (async_err)
13492
0
        return NULL;
13493
13494
0
    errno = result;
13495
0
    return posix_error();
13496
0
}
13497
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13498
13499
13500
#if defined(HAVE_POSIX_FADVISE)
13501
/*[clinic input]
13502
os.posix_fadvise
13503
13504
    fd: int
13505
    offset: Py_off_t
13506
    length: Py_off_t
13507
    advice: int
13508
    /
13509
13510
Announce an intention to access data in a specific pattern.
13511
13512
Announce an intention to access data in a specific pattern, thus
13513
allowing the kernel to make optimizations.
13514
The advice applies to the region of the file specified by fd starting at
13515
offset and continuing for length bytes.
13516
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13517
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13518
POSIX_FADV_DONTNEED.
13519
[clinic start generated code]*/
13520
13521
static PyObject *
13522
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13523
                      Py_off_t length, int advice)
13524
/*[clinic end generated code: output=412ef4aa70c98642 input=961b01a4518ef727]*/
13525
0
{
13526
0
    int result;
13527
0
    int async_err = 0;
13528
13529
0
    do {
13530
0
        Py_BEGIN_ALLOW_THREADS
13531
0
        result = posix_fadvise(fd, offset, length, advice);
13532
0
        Py_END_ALLOW_THREADS
13533
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13534
13535
0
    if (result == 0)
13536
0
        Py_RETURN_NONE;
13537
13538
0
    if (async_err)
13539
0
        return NULL;
13540
13541
0
    errno = result;
13542
0
    return posix_error();
13543
0
}
13544
#endif /* HAVE_POSIX_FADVISE */
13545
13546
13547
#ifdef MS_WINDOWS
13548
static PyObject*
13549
win32_putenv(PyObject *name, PyObject *value)
13550
{
13551
    /* Search from index 1 because on Windows starting '=' is allowed for
13552
       defining hidden environment variables. */
13553
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13554
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13555
    {
13556
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13557
        return NULL;
13558
    }
13559
    PyObject *unicode;
13560
    if (value != NULL) {
13561
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13562
    }
13563
    else {
13564
        unicode = PyUnicode_FromFormat("%U=", name);
13565
    }
13566
    if (unicode == NULL) {
13567
        return NULL;
13568
    }
13569
13570
    Py_ssize_t size;
13571
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13572
    Py_DECREF(unicode);
13573
13574
    if (env == NULL) {
13575
        return NULL;
13576
    }
13577
    if (size > _MAX_ENV) {
13578
        PyErr_Format(PyExc_ValueError,
13579
                     "the environment variable is longer than %u characters",
13580
                     _MAX_ENV);
13581
        PyMem_Free(env);
13582
        return NULL;
13583
    }
13584
    if (wcslen(env) != (size_t)size) {
13585
        PyErr_SetString(PyExc_ValueError,
13586
                        "embedded null character");
13587
        PyMem_Free(env);
13588
        return NULL;
13589
    }
13590
13591
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13592
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13593
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13594
13595
       Prefer _wputenv() to be compatible with C libraries using CRT
13596
       variables and CRT functions using these variables (ex: getenv()). */
13597
    int err = _wputenv(env);
13598
13599
    if (err) {
13600
        posix_error();
13601
        PyMem_Free(env);
13602
        return NULL;
13603
    }
13604
    PyMem_Free(env);
13605
13606
    Py_RETURN_NONE;
13607
}
13608
#endif
13609
13610
13611
#ifdef MS_WINDOWS
13612
/*[clinic input]
13613
os.putenv
13614
13615
    name: unicode
13616
    value: unicode
13617
    /
13618
13619
Change or add an environment variable.
13620
[clinic start generated code]*/
13621
13622
static PyObject *
13623
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13624
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13625
{
13626
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13627
        return NULL;
13628
    }
13629
    return win32_putenv(name, value);
13630
}
13631
#else
13632
/*[clinic input]
13633
os.putenv
13634
13635
    name: unicode_fs_encoded
13636
    value: unicode_fs_encoded
13637
    /
13638
13639
Change or add an environment variable.
13640
[clinic start generated code]*/
13641
13642
static PyObject *
13643
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13644
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13645
0
{
13646
0
    const char *name_string = PyBytes_AS_STRING(name);
13647
0
    const char *value_string = PyBytes_AS_STRING(value);
13648
13649
0
    if (strchr(name_string, '=') != NULL) {
13650
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13651
0
        return NULL;
13652
0
    }
13653
13654
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13655
0
        return NULL;
13656
0
    }
13657
13658
0
    if (setenv(name_string, value_string, 1)) {
13659
0
        return posix_error();
13660
0
    }
13661
0
    Py_RETURN_NONE;
13662
0
}
13663
#endif  /* !defined(MS_WINDOWS) */
13664
13665
13666
#ifdef MS_WINDOWS
13667
/*[clinic input]
13668
os.unsetenv
13669
    name: unicode
13670
    /
13671
13672
Delete an environment variable.
13673
[clinic start generated code]*/
13674
13675
static PyObject *
13676
os_unsetenv_impl(PyObject *module, PyObject *name)
13677
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13678
{
13679
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13680
        return NULL;
13681
    }
13682
    return win32_putenv(name, NULL);
13683
}
13684
#else
13685
/*[clinic input]
13686
os.unsetenv
13687
    name: unicode_fs_encoded
13688
    /
13689
13690
Delete an environment variable.
13691
[clinic start generated code]*/
13692
13693
static PyObject *
13694
os_unsetenv_impl(PyObject *module, PyObject *name)
13695
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13696
0
{
13697
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13698
0
        return NULL;
13699
0
    }
13700
#ifdef HAVE_BROKEN_UNSETENV
13701
    unsetenv(PyBytes_AS_STRING(name));
13702
#else
13703
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13704
0
    if (err) {
13705
0
        return posix_error();
13706
0
    }
13707
0
#endif
13708
13709
0
    Py_RETURN_NONE;
13710
0
}
13711
#endif /* !MS_WINDOWS */
13712
13713
13714
#ifdef HAVE_CLEARENV
13715
/*[clinic input]
13716
os._clearenv
13717
[clinic start generated code]*/
13718
13719
static PyObject *
13720
os__clearenv_impl(PyObject *module)
13721
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13722
0
{
13723
0
    if (PySys_Audit("os._clearenv", NULL) < 0) {
13724
0
        return NULL;
13725
0
    }
13726
13727
0
    errno = 0;
13728
0
    int err = clearenv();
13729
0
    if (err) {
13730
0
        return posix_error();
13731
0
    }
13732
0
    Py_RETURN_NONE;
13733
0
}
13734
#endif
13735
13736
13737
/*[clinic input]
13738
os.strerror
13739
13740
    code: int
13741
    /
13742
13743
Translate an error code to a message string.
13744
[clinic start generated code]*/
13745
13746
static PyObject *
13747
os_strerror_impl(PyObject *module, int code)
13748
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13749
0
{
13750
0
    char *message = strerror(code);
13751
0
    if (message == NULL) {
13752
0
        PyErr_SetString(PyExc_ValueError,
13753
0
                        "strerror() argument out of range");
13754
0
        return NULL;
13755
0
    }
13756
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13757
0
}
13758
13759
13760
#ifdef HAVE_SYS_WAIT_H
13761
#ifdef WCOREDUMP
13762
/*[clinic input]
13763
os.WCOREDUMP -> bool
13764
13765
    status: int
13766
    /
13767
13768
Return True if the process returning status was dumped to a core file.
13769
[clinic start generated code]*/
13770
13771
static int
13772
os_WCOREDUMP_impl(PyObject *module, int status)
13773
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13774
0
{
13775
0
    WAIT_TYPE wait_status;
13776
0
    WAIT_STATUS_INT(wait_status) = status;
13777
0
    return WCOREDUMP(wait_status);
13778
0
}
13779
#endif /* WCOREDUMP */
13780
13781
13782
#ifdef WIFCONTINUED
13783
/*[clinic input]
13784
@permit_long_summary
13785
os.WIFCONTINUED -> bool
13786
13787
    status: int
13788
13789
Return True if a particular process was continued from a job control stop.
13790
13791
Return True if the process returning status was continued from a
13792
job control stop.
13793
[clinic start generated code]*/
13794
13795
static int
13796
os_WIFCONTINUED_impl(PyObject *module, int status)
13797
/*[clinic end generated code: output=1e35295d844364bd input=7b577845a0f8b12f]*/
13798
0
{
13799
0
    WAIT_TYPE wait_status;
13800
0
    WAIT_STATUS_INT(wait_status) = status;
13801
0
    return WIFCONTINUED(wait_status);
13802
0
}
13803
#endif /* WIFCONTINUED */
13804
13805
13806
#ifdef WIFSTOPPED
13807
/*[clinic input]
13808
os.WIFSTOPPED -> bool
13809
13810
    status: int
13811
13812
Return True if the process returning status was stopped.
13813
[clinic start generated code]*/
13814
13815
static int
13816
os_WIFSTOPPED_impl(PyObject *module, int status)
13817
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13818
0
{
13819
0
    WAIT_TYPE wait_status;
13820
0
    WAIT_STATUS_INT(wait_status) = status;
13821
0
    return WIFSTOPPED(wait_status);
13822
0
}
13823
#endif /* WIFSTOPPED */
13824
13825
13826
#ifdef WIFSIGNALED
13827
/*[clinic input]
13828
os.WIFSIGNALED -> bool
13829
13830
    status: int
13831
13832
Return True if the process returning status was terminated by a signal.
13833
[clinic start generated code]*/
13834
13835
static int
13836
os_WIFSIGNALED_impl(PyObject *module, int status)
13837
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13838
0
{
13839
0
    WAIT_TYPE wait_status;
13840
0
    WAIT_STATUS_INT(wait_status) = status;
13841
0
    return WIFSIGNALED(wait_status);
13842
0
}
13843
#endif /* WIFSIGNALED */
13844
13845
13846
#ifdef WIFEXITED
13847
/*[clinic input]
13848
@permit_long_summary
13849
os.WIFEXITED -> bool
13850
13851
    status: int
13852
13853
Return True if the process returning status exited via the exit() system call.
13854
[clinic start generated code]*/
13855
13856
static int
13857
os_WIFEXITED_impl(PyObject *module, int status)
13858
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13859
0
{
13860
0
    WAIT_TYPE wait_status;
13861
0
    WAIT_STATUS_INT(wait_status) = status;
13862
0
    return WIFEXITED(wait_status);
13863
0
}
13864
#endif /* WIFEXITED */
13865
13866
13867
#ifdef WEXITSTATUS
13868
/*[clinic input]
13869
os.WEXITSTATUS -> int
13870
13871
    status: int
13872
13873
Return the process return code from status.
13874
[clinic start generated code]*/
13875
13876
static int
13877
os_WEXITSTATUS_impl(PyObject *module, int status)
13878
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13879
0
{
13880
0
    WAIT_TYPE wait_status;
13881
0
    WAIT_STATUS_INT(wait_status) = status;
13882
0
    return WEXITSTATUS(wait_status);
13883
0
}
13884
#endif /* WEXITSTATUS */
13885
13886
13887
#ifdef WTERMSIG
13888
/*[clinic input]
13889
@permit_long_summary
13890
os.WTERMSIG -> int
13891
13892
    status: int
13893
13894
Return the signal that terminated the process that provided the status value.
13895
[clinic start generated code]*/
13896
13897
static int
13898
os_WTERMSIG_impl(PyObject *module, int status)
13899
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13900
0
{
13901
0
    WAIT_TYPE wait_status;
13902
0
    WAIT_STATUS_INT(wait_status) = status;
13903
0
    return WTERMSIG(wait_status);
13904
0
}
13905
#endif /* WTERMSIG */
13906
13907
13908
#ifdef WSTOPSIG
13909
/*[clinic input]
13910
@permit_long_summary
13911
os.WSTOPSIG -> int
13912
13913
    status: int
13914
13915
Return the signal that stopped the process that provided the status value.
13916
[clinic start generated code]*/
13917
13918
static int
13919
os_WSTOPSIG_impl(PyObject *module, int status)
13920
/*[clinic end generated code: output=0ab7586396f5d82b input=4698db1a6a320433]*/
13921
0
{
13922
0
    WAIT_TYPE wait_status;
13923
0
    WAIT_STATUS_INT(wait_status) = status;
13924
0
    return WSTOPSIG(wait_status);
13925
0
}
13926
#endif /* WSTOPSIG */
13927
#endif /* HAVE_SYS_WAIT_H */
13928
13929
13930
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13931
#ifdef _SCO_DS
13932
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13933
   needed definitions in sys/statvfs.h */
13934
#define _SVID3
13935
#endif
13936
#include <sys/statvfs.h>
13937
13938
#ifdef __APPLE__
13939
/* On macOS struct statvfs uses 32-bit integers for block counts,
13940
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13941
 * os.statvfs is implemented in terms of statfs(2).
13942
 */
13943
13944
static PyObject*
13945
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13946
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13947
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13948
    if (v == NULL) {
13949
        return NULL;
13950
    }
13951
13952
    long flags = 0;
13953
    if (st.f_flags & MNT_RDONLY) {
13954
        flags |= ST_RDONLY;
13955
    }
13956
    if (st.f_flags & MNT_NOSUID) {
13957
        flags |= ST_NOSUID;
13958
    }
13959
13960
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13961
13962
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13963
    do {                                                 \
13964
        PyObject *obj = (EXPR);                          \
13965
        if (obj == NULL) {                               \
13966
            Py_DECREF((SEQ));                            \
13967
            return NULL;                                 \
13968
        }                                                \
13969
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13970
    } while (0)
13971
13972
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13973
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13974
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13975
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13976
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13977
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13978
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13979
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13980
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13981
13982
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13983
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13984
13985
#undef SET_ITEM
13986
13987
    return v;
13988
}
13989
13990
#else
13991
13992
13993
13994
static PyObject*
13995
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13996
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13997
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13998
0
    if (v == NULL)
13999
0
        return NULL;
14000
14001
0
    int pos = 0;
14002
14003
0
#define SET_RESULT(CALL)                                     \
14004
0
    do {                                                     \
14005
0
        PyObject *item = (CALL);                             \
14006
0
        if (item == NULL) {                                  \
14007
0
            Py_DECREF(v);                                    \
14008
0
            return NULL;                                     \
14009
0
        }                                                    \
14010
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
14011
0
    } while(0)
14012
14013
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
14014
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
14015
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
14016
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
14017
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
14018
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
14019
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
14020
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
14021
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
14022
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
14023
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
14024
#else
14025
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
14026
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
14027
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
14028
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
14029
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
14030
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
14031
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
14032
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
14033
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
14034
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
14035
#endif
14036
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
14037
 * (issue #32390). */
14038
#if defined(_AIX) && defined(_ALL_SOURCE)
14039
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
14040
#else
14041
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
14042
0
#endif
14043
14044
0
#undef SET_RESULT
14045
14046
0
    return v;
14047
0
}
14048
14049
#endif
14050
14051
14052
/*[clinic input]
14053
os.fstatvfs
14054
    fd: int
14055
    /
14056
14057
Perform an fstatvfs system call on the given fd.
14058
14059
Equivalent to statvfs(fd).
14060
[clinic start generated code]*/
14061
14062
static PyObject *
14063
os_fstatvfs_impl(PyObject *module, int fd)
14064
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
14065
0
{
14066
0
    int result;
14067
0
    int async_err = 0;
14068
#ifdef __APPLE__
14069
    struct statfs st;
14070
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
14071
     * the former uses 32-bit values for block counts.
14072
     */
14073
    do {
14074
        Py_BEGIN_ALLOW_THREADS
14075
        result = fstatfs(fd, &st);
14076
        Py_END_ALLOW_THREADS
14077
    } while (result != 0 && errno == EINTR &&
14078
             !(async_err = PyErr_CheckSignals()));
14079
    if (result != 0)
14080
        return (!async_err) ? posix_error() : NULL;
14081
14082
    return _pystatvfs_fromstructstatfs(module, st);
14083
#else
14084
0
    struct statvfs st;
14085
14086
0
    do {
14087
0
        Py_BEGIN_ALLOW_THREADS
14088
0
        result = fstatvfs(fd, &st);
14089
0
        Py_END_ALLOW_THREADS
14090
0
    } while (result != 0 && errno == EINTR &&
14091
0
             !(async_err = PyErr_CheckSignals()));
14092
0
    if (result != 0)
14093
0
        return (!async_err) ? posix_error() : NULL;
14094
14095
0
    return _pystatvfs_fromstructstatvfs(module, st);
14096
0
#endif
14097
0
}
14098
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14099
14100
14101
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14102
#include <sys/statvfs.h>
14103
/*[clinic input]
14104
os.statvfs
14105
14106
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14107
14108
Perform a statvfs system call on the given path.
14109
14110
path may always be specified as a string.
14111
On some platforms, path may also be specified as an open file
14112
descriptor.  If this functionality is unavailable, using it raises
14113
an exception.
14114
[clinic start generated code]*/
14115
14116
static PyObject *
14117
os_statvfs_impl(PyObject *module, path_t *path)
14118
/*[clinic end generated code: output=87106dd1beb8556e input=1cfd9a4fd36f7425]*/
14119
0
{
14120
0
    int result;
14121
14122
#ifdef __APPLE__
14123
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14124
     * the former uses 32-bit values for block counts.
14125
     */
14126
    struct statfs st;
14127
14128
    Py_BEGIN_ALLOW_THREADS
14129
    if (path->is_fd) {
14130
        result = fstatfs(path->fd, &st);
14131
    }
14132
    else
14133
        result = statfs(path->narrow, &st);
14134
    Py_END_ALLOW_THREADS
14135
14136
    if (result) {
14137
        return path_error(path);
14138
    }
14139
14140
    return _pystatvfs_fromstructstatfs(module, st);
14141
14142
#else
14143
0
    struct statvfs st;
14144
14145
0
    Py_BEGIN_ALLOW_THREADS
14146
0
#ifdef HAVE_FSTATVFS
14147
0
    if (path->is_fd) {
14148
0
        result = fstatvfs(path->fd, &st);
14149
0
    }
14150
0
    else
14151
0
#endif
14152
0
        result = statvfs(path->narrow, &st);
14153
0
    Py_END_ALLOW_THREADS
14154
14155
0
    if (result) {
14156
0
        return path_error(path);
14157
0
    }
14158
14159
0
    return _pystatvfs_fromstructstatvfs(module, st);
14160
0
#endif
14161
0
}
14162
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14163
14164
14165
#ifdef MS_WINDOWS
14166
/*[clinic input]
14167
@permit_long_summary
14168
os._getdiskusage
14169
14170
    path: path_t
14171
14172
Return disk usage statistics about the given path as a (total, free) tuple.
14173
[clinic start generated code]*/
14174
14175
static PyObject *
14176
os__getdiskusage_impl(PyObject *module, path_t *path)
14177
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=aee7e38bc3e7fb08]*/
14178
{
14179
    BOOL retval;
14180
    ULARGE_INTEGER _, total, free;
14181
    DWORD err = 0;
14182
14183
    Py_BEGIN_ALLOW_THREADS
14184
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14185
    Py_END_ALLOW_THREADS
14186
    if (retval == 0) {
14187
        if (GetLastError() == ERROR_DIRECTORY) {
14188
            wchar_t *dir_path = NULL;
14189
14190
            dir_path = PyMem_New(wchar_t, path->length + 1);
14191
            if (dir_path == NULL) {
14192
                return PyErr_NoMemory();
14193
            }
14194
14195
            wcscpy_s(dir_path, path->length + 1, path->wide);
14196
14197
            if (_dirnameW(dir_path) != -1) {
14198
                Py_BEGIN_ALLOW_THREADS
14199
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14200
                Py_END_ALLOW_THREADS
14201
            }
14202
            /* Record the last error in case it's modified by PyMem_Free. */
14203
            err = GetLastError();
14204
            PyMem_Free(dir_path);
14205
            if (retval) {
14206
                goto success;
14207
            }
14208
        }
14209
        return PyErr_SetFromWindowsErr(err);
14210
    }
14211
14212
success:
14213
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14214
}
14215
#endif /* MS_WINDOWS */
14216
14217
14218
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14219
 * It maps strings representing configuration variable names to
14220
 * integer values, allowing those functions to be called with the
14221
 * magic names instead of polluting the module's namespace with tons of
14222
 * rarely-used constants.  There are three separate tables that use
14223
 * these definitions.
14224
 *
14225
 * This code is always included, even if none of the interfaces that
14226
 * need it are included.  The #if hackery needed to avoid it would be
14227
 * sufficiently pervasive that it's not worth the loss of readability.
14228
 */
14229
struct constdef {
14230
    const char *name;
14231
    int value;
14232
};
14233
14234
static int
14235
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14236
4
{
14237
4
    if (PyUnicode_Check(arg)) {
14238
4
        PyObject *table = PyObject_GetAttrString(module, tablename);
14239
4
        if (table == NULL) {
14240
0
            return 0;
14241
0
        }
14242
14243
4
        arg = PyObject_GetItem(table, arg);
14244
4
        Py_DECREF(table);
14245
4
        if (arg == NULL) {
14246
0
            PyErr_SetString(
14247
0
                PyExc_ValueError, "unrecognized configuration name");
14248
0
            return 0;
14249
0
        }
14250
4
    } else {
14251
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14252
0
    }
14253
14254
4
    int success = 0;
14255
4
    if (!PyIndex_Check(arg)) {
14256
0
        PyErr_SetString(PyExc_TypeError,
14257
0
            "configuration names must be strings or integers");
14258
4
    } else {
14259
4
        int value = PyLong_AsInt(arg);
14260
4
        if (!(value == -1 && PyErr_Occurred())) {
14261
4
            *valuep = value;
14262
4
            success = 1;
14263
4
        }
14264
4
    }
14265
4
    Py_DECREF(arg);
14266
4
    return success;
14267
4
}
14268
14269
14270
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14271
static struct constdef  posix_constants_pathconf[] = {
14272
#ifdef _PC_ABI_AIO_XFER_MAX
14273
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14274
#endif
14275
#ifdef _PC_ABI_ASYNC_IO
14276
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14277
#endif
14278
#ifdef _PC_ASYNC_IO
14279
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14280
#endif
14281
#ifdef _PC_CHOWN_RESTRICTED
14282
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14283
#endif
14284
#ifdef _PC_FILESIZEBITS
14285
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14286
#endif
14287
#ifdef _PC_LAST
14288
    {"PC_LAST", _PC_LAST},
14289
#endif
14290
#ifdef _PC_LINK_MAX
14291
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14292
#endif
14293
#ifdef _PC_MAX_CANON
14294
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14295
#endif
14296
#ifdef _PC_MAX_INPUT
14297
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14298
#endif
14299
#ifdef _PC_NAME_MAX
14300
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14301
#endif
14302
#ifdef _PC_NO_TRUNC
14303
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14304
#endif
14305
#ifdef _PC_PATH_MAX
14306
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14307
#endif
14308
#ifdef _PC_PIPE_BUF
14309
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14310
#endif
14311
#ifdef _PC_PRIO_IO
14312
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14313
#endif
14314
#ifdef _PC_SOCK_MAXBUF
14315
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14316
#endif
14317
#ifdef _PC_SYNC_IO
14318
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14319
#endif
14320
#ifdef _PC_VDISABLE
14321
    {"PC_VDISABLE",     _PC_VDISABLE},
14322
#endif
14323
#ifdef _PC_ACL_ENABLED
14324
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14325
#endif
14326
#ifdef _PC_MIN_HOLE_SIZE
14327
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14328
#endif
14329
#ifdef _PC_ALLOC_SIZE_MIN
14330
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14331
#endif
14332
#ifdef _PC_REC_INCR_XFER_SIZE
14333
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14334
#endif
14335
#ifdef _PC_REC_MAX_XFER_SIZE
14336
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14337
#endif
14338
#ifdef _PC_REC_MIN_XFER_SIZE
14339
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14340
#endif
14341
#ifdef _PC_REC_XFER_ALIGN
14342
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14343
#endif
14344
#ifdef _PC_SYMLINK_MAX
14345
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14346
#endif
14347
#ifdef _PC_XATTR_ENABLED
14348
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14349
#endif
14350
#ifdef _PC_XATTR_EXISTS
14351
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14352
#endif
14353
#ifdef _PC_TIMESTAMP_RESOLUTION
14354
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14355
#endif
14356
};
14357
#endif
14358
14359
14360
#ifdef HAVE_FPATHCONF
14361
/*[clinic input]
14362
os.fpathconf -> long
14363
14364
    fd: fildes
14365
    name: confname(table="pathconf_names")
14366
    /
14367
14368
Return the configuration limit name for the file descriptor fd.
14369
14370
If there is no limit, return -1.
14371
[clinic start generated code]*/
14372
14373
static long
14374
os_fpathconf_impl(PyObject *module, int fd, int name)
14375
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14376
0
{
14377
0
    long limit;
14378
14379
0
    errno = 0;
14380
0
    limit = fpathconf(fd, name);
14381
0
    if (limit == -1 && errno != 0)
14382
0
        posix_error();
14383
14384
0
    return limit;
14385
0
}
14386
#endif /* HAVE_FPATHCONF */
14387
14388
14389
#ifdef HAVE_PATHCONF
14390
/*[clinic input]
14391
os.pathconf -> long
14392
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14393
    name: confname(table="pathconf_names")
14394
14395
Return the configuration limit name for the file or directory path.
14396
14397
If there is no limit, return -1.
14398
On some platforms, path may also be specified as an open file
14399
descriptor.  If this functionality is unavailable, using it raises
14400
an exception.
14401
[clinic start generated code]*/
14402
14403
static long
14404
os_pathconf_impl(PyObject *module, path_t *path, int name)
14405
/*[clinic end generated code: output=5bedee35b293a089 input=e86f6eacfa006426]*/
14406
0
{
14407
0
    long limit;
14408
14409
0
    errno = 0;
14410
0
#ifdef HAVE_FPATHCONF
14411
0
    if (path->is_fd) {
14412
0
        limit = fpathconf(path->fd, name);
14413
0
    }
14414
0
    else
14415
0
#endif
14416
0
        limit = pathconf(path->narrow, name);
14417
0
    if (limit == -1 && errno != 0) {
14418
0
        if (errno == EINVAL)
14419
            /* could be a path or name problem */
14420
0
            posix_error();
14421
0
        else
14422
0
            path_error(path);
14423
0
    }
14424
14425
0
    return limit;
14426
0
}
14427
#endif /* HAVE_PATHCONF */
14428
14429
#ifdef HAVE_CONFSTR
14430
static struct constdef posix_constants_confstr[] = {
14431
#ifdef _CS_ARCHITECTURE
14432
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14433
#endif
14434
#ifdef _CS_GNU_LIBC_VERSION
14435
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14436
#endif
14437
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14438
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14439
#endif
14440
#ifdef _CS_HOSTNAME
14441
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14442
#endif
14443
#ifdef _CS_HW_PROVIDER
14444
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14445
#endif
14446
#ifdef _CS_HW_SERIAL
14447
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14448
#endif
14449
#ifdef _CS_INITTAB_NAME
14450
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14451
#endif
14452
#ifdef _CS_LFS64_CFLAGS
14453
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14454
#endif
14455
#ifdef _CS_LFS64_LDFLAGS
14456
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14457
#endif
14458
#ifdef _CS_LFS64_LIBS
14459
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14460
#endif
14461
#ifdef _CS_LFS64_LINTFLAGS
14462
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14463
#endif
14464
#ifdef _CS_LFS_CFLAGS
14465
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14466
#endif
14467
#ifdef _CS_LFS_LDFLAGS
14468
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14469
#endif
14470
#ifdef _CS_LFS_LIBS
14471
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14472
#endif
14473
#ifdef _CS_LFS_LINTFLAGS
14474
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14475
#endif
14476
#ifdef _CS_MACHINE
14477
    {"CS_MACHINE",      _CS_MACHINE},
14478
#endif
14479
#ifdef _CS_PATH
14480
    {"CS_PATH", _CS_PATH},
14481
#endif
14482
#ifdef _CS_RELEASE
14483
    {"CS_RELEASE",      _CS_RELEASE},
14484
#endif
14485
#ifdef _CS_SRPC_DOMAIN
14486
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14487
#endif
14488
#ifdef _CS_SYSNAME
14489
    {"CS_SYSNAME",      _CS_SYSNAME},
14490
#endif
14491
#ifdef _CS_VERSION
14492
    {"CS_VERSION",      _CS_VERSION},
14493
#endif
14494
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14495
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14496
#endif
14497
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14498
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14499
#endif
14500
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14501
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14502
#endif
14503
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14504
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14505
#endif
14506
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14507
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14508
#endif
14509
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14510
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14511
#endif
14512
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14513
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14514
#endif
14515
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14516
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14517
#endif
14518
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14519
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14520
#endif
14521
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14522
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14523
#endif
14524
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14525
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14526
#endif
14527
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14528
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14529
#endif
14530
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14531
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14532
#endif
14533
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14534
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14535
#endif
14536
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14537
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14538
#endif
14539
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14540
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14541
#endif
14542
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14543
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14544
#endif
14545
#ifdef _MIPS_CS_BASE
14546
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14547
#endif
14548
#ifdef _MIPS_CS_HOSTID
14549
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14550
#endif
14551
#ifdef _MIPS_CS_HW_NAME
14552
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14553
#endif
14554
#ifdef _MIPS_CS_NUM_PROCESSORS
14555
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14556
#endif
14557
#ifdef _MIPS_CS_OSREL_MAJ
14558
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14559
#endif
14560
#ifdef _MIPS_CS_OSREL_MIN
14561
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14562
#endif
14563
#ifdef _MIPS_CS_OSREL_PATCH
14564
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14565
#endif
14566
#ifdef _MIPS_CS_OS_NAME
14567
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14568
#endif
14569
#ifdef _MIPS_CS_OS_PROVIDER
14570
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14571
#endif
14572
#ifdef _MIPS_CS_PROCESSORS
14573
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14574
#endif
14575
#ifdef _MIPS_CS_SERIAL
14576
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14577
#endif
14578
#ifdef _MIPS_CS_VENDOR
14579
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14580
#endif
14581
};
14582
14583
14584
/*[clinic input]
14585
os.confstr
14586
14587
    name: confname(table="confstr_names")
14588
    /
14589
14590
Return a string-valued system configuration variable.
14591
[clinic start generated code]*/
14592
14593
static PyObject *
14594
os_confstr_impl(PyObject *module, int name)
14595
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14596
4
{
14597
4
    PyObject *result = NULL;
14598
4
    char buffer[255];
14599
4
    size_t len;
14600
14601
4
    errno = 0;
14602
4
    len = confstr(name, buffer, sizeof(buffer));
14603
4
    if (len == 0) {
14604
0
        if (errno) {
14605
0
            posix_error();
14606
0
            return NULL;
14607
0
        }
14608
0
        else {
14609
0
            Py_RETURN_NONE;
14610
0
        }
14611
0
    }
14612
14613
4
    if (len >= sizeof(buffer)) {
14614
0
        size_t len2;
14615
0
        char *buf = PyMem_Malloc(len);
14616
0
        if (buf == NULL)
14617
0
            return PyErr_NoMemory();
14618
0
        len2 = confstr(name, buf, len);
14619
0
        assert(len == len2);
14620
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14621
0
        PyMem_Free(buf);
14622
0
    }
14623
4
    else
14624
4
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14625
4
    return result;
14626
4
}
14627
#endif /* HAVE_CONFSTR */
14628
14629
14630
#ifdef HAVE_SYSCONF
14631
static struct constdef posix_constants_sysconf[] = {
14632
#ifdef _SC_2_CHAR_TERM
14633
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14634
#endif
14635
#ifdef _SC_2_C_BIND
14636
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14637
#endif
14638
#ifdef _SC_2_C_DEV
14639
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14640
#endif
14641
#ifdef _SC_2_C_VERSION
14642
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14643
#endif
14644
#ifdef _SC_2_FORT_DEV
14645
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14646
#endif
14647
#ifdef _SC_2_FORT_RUN
14648
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14649
#endif
14650
#ifdef _SC_2_LOCALEDEF
14651
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14652
#endif
14653
#ifdef _SC_2_SW_DEV
14654
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14655
#endif
14656
#ifdef _SC_2_UPE
14657
    {"SC_2_UPE",        _SC_2_UPE},
14658
#endif
14659
#ifdef _SC_2_VERSION
14660
    {"SC_2_VERSION",    _SC_2_VERSION},
14661
#endif
14662
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14663
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14664
#endif
14665
#ifdef _SC_ACL
14666
    {"SC_ACL",  _SC_ACL},
14667
#endif
14668
#ifdef _SC_AIO_LISTIO_MAX
14669
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14670
#endif
14671
#ifdef _SC_AIO_MAX
14672
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14673
#endif
14674
#ifdef _SC_AIO_PRIO_DELTA_MAX
14675
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14676
#endif
14677
#ifdef _SC_ARG_MAX
14678
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14679
#endif
14680
#ifdef _SC_ASYNCHRONOUS_IO
14681
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14682
#endif
14683
#ifdef _SC_ATEXIT_MAX
14684
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14685
#endif
14686
#ifdef _SC_AUDIT
14687
    {"SC_AUDIT",        _SC_AUDIT},
14688
#endif
14689
#ifdef _SC_AVPHYS_PAGES
14690
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14691
#endif
14692
#ifdef _SC_BC_BASE_MAX
14693
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14694
#endif
14695
#ifdef _SC_BC_DIM_MAX
14696
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14697
#endif
14698
#ifdef _SC_BC_SCALE_MAX
14699
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14700
#endif
14701
#ifdef _SC_BC_STRING_MAX
14702
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14703
#endif
14704
#ifdef _SC_CAP
14705
    {"SC_CAP",  _SC_CAP},
14706
#endif
14707
#ifdef _SC_CHARCLASS_NAME_MAX
14708
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14709
#endif
14710
#ifdef _SC_CHAR_BIT
14711
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14712
#endif
14713
#ifdef _SC_CHAR_MAX
14714
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14715
#endif
14716
#ifdef _SC_CHAR_MIN
14717
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14718
#endif
14719
#ifdef _SC_CHILD_MAX
14720
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14721
#endif
14722
#ifdef _SC_CLK_TCK
14723
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14724
#endif
14725
#ifdef _SC_COHER_BLKSZ
14726
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14727
#endif
14728
#ifdef _SC_COLL_WEIGHTS_MAX
14729
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14730
#endif
14731
#ifdef _SC_DCACHE_ASSOC
14732
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14733
#endif
14734
#ifdef _SC_DCACHE_BLKSZ
14735
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14736
#endif
14737
#ifdef _SC_DCACHE_LINESZ
14738
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14739
#endif
14740
#ifdef _SC_DCACHE_SZ
14741
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14742
#endif
14743
#ifdef _SC_DCACHE_TBLKSZ
14744
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14745
#endif
14746
#ifdef _SC_DELAYTIMER_MAX
14747
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14748
#endif
14749
#ifdef _SC_EQUIV_CLASS_MAX
14750
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14751
#endif
14752
#ifdef _SC_EXPR_NEST_MAX
14753
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14754
#endif
14755
#ifdef _SC_FSYNC
14756
    {"SC_FSYNC",        _SC_FSYNC},
14757
#endif
14758
#ifdef _SC_GETGR_R_SIZE_MAX
14759
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14760
#endif
14761
#ifdef _SC_GETPW_R_SIZE_MAX
14762
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14763
#endif
14764
#ifdef _SC_ICACHE_ASSOC
14765
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14766
#endif
14767
#ifdef _SC_ICACHE_BLKSZ
14768
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14769
#endif
14770
#ifdef _SC_ICACHE_LINESZ
14771
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14772
#endif
14773
#ifdef _SC_ICACHE_SZ
14774
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14775
#endif
14776
#ifdef _SC_INF
14777
    {"SC_INF",  _SC_INF},
14778
#endif
14779
#ifdef _SC_INT_MAX
14780
    {"SC_INT_MAX",      _SC_INT_MAX},
14781
#endif
14782
#ifdef _SC_INT_MIN
14783
    {"SC_INT_MIN",      _SC_INT_MIN},
14784
#endif
14785
#ifdef _SC_IOV_MAX
14786
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14787
#endif
14788
#ifdef _SC_IP_SECOPTS
14789
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14790
#endif
14791
#ifdef _SC_JOB_CONTROL
14792
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14793
#endif
14794
#ifdef _SC_KERN_POINTERS
14795
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14796
#endif
14797
#ifdef _SC_KERN_SIM
14798
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14799
#endif
14800
#ifdef _SC_LINE_MAX
14801
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14802
#endif
14803
#ifdef _SC_LOGIN_NAME_MAX
14804
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14805
#endif
14806
#ifdef _SC_LOGNAME_MAX
14807
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14808
#endif
14809
#ifdef _SC_LONG_BIT
14810
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14811
#endif
14812
#ifdef _SC_MAC
14813
    {"SC_MAC",  _SC_MAC},
14814
#endif
14815
#ifdef _SC_MAPPED_FILES
14816
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14817
#endif
14818
#ifdef _SC_MAXPID
14819
    {"SC_MAXPID",       _SC_MAXPID},
14820
#endif
14821
#ifdef _SC_MB_LEN_MAX
14822
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14823
#endif
14824
#ifdef _SC_MEMLOCK
14825
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14826
#endif
14827
#ifdef _SC_MEMLOCK_RANGE
14828
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14829
#endif
14830
#ifdef _SC_MEMORY_PROTECTION
14831
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14832
#endif
14833
#ifdef _SC_MESSAGE_PASSING
14834
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14835
#endif
14836
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14837
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14838
#endif
14839
#ifdef _SC_MQ_OPEN_MAX
14840
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14841
#endif
14842
#ifdef _SC_MQ_PRIO_MAX
14843
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14844
#endif
14845
#ifdef _SC_NACLS_MAX
14846
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14847
#endif
14848
#ifdef _SC_NGROUPS_MAX
14849
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14850
#endif
14851
#ifdef _SC_NL_ARGMAX
14852
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14853
#endif
14854
#ifdef _SC_NL_LANGMAX
14855
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14856
#endif
14857
#ifdef _SC_NL_MSGMAX
14858
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14859
#endif
14860
#ifdef _SC_NL_NMAX
14861
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14862
#endif
14863
#ifdef _SC_NL_SETMAX
14864
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14865
#endif
14866
#ifdef _SC_NL_TEXTMAX
14867
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14868
#endif
14869
#ifdef _SC_NPROCESSORS_CONF
14870
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14871
#endif
14872
#ifdef _SC_NPROCESSORS_ONLN
14873
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14874
#endif
14875
#ifdef _SC_NPROC_CONF
14876
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14877
#endif
14878
#ifdef _SC_NPROC_ONLN
14879
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14880
#endif
14881
#ifdef _SC_NZERO
14882
    {"SC_NZERO",        _SC_NZERO},
14883
#endif
14884
#ifdef _SC_OPEN_MAX
14885
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14886
#endif
14887
#ifdef _SC_PAGESIZE
14888
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14889
#endif
14890
#ifdef _SC_PAGE_SIZE
14891
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14892
#endif
14893
#ifdef _SC_AIX_REALMEM
14894
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14895
#endif
14896
#ifdef _SC_PASS_MAX
14897
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14898
#endif
14899
#ifdef _SC_PHYS_PAGES
14900
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14901
#endif
14902
#ifdef _SC_PII
14903
    {"SC_PII",  _SC_PII},
14904
#endif
14905
#ifdef _SC_PII_INTERNET
14906
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14907
#endif
14908
#ifdef _SC_PII_INTERNET_DGRAM
14909
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14910
#endif
14911
#ifdef _SC_PII_INTERNET_STREAM
14912
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14913
#endif
14914
#ifdef _SC_PII_OSI
14915
    {"SC_PII_OSI",      _SC_PII_OSI},
14916
#endif
14917
#ifdef _SC_PII_OSI_CLTS
14918
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14919
#endif
14920
#ifdef _SC_PII_OSI_COTS
14921
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14922
#endif
14923
#ifdef _SC_PII_OSI_M
14924
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14925
#endif
14926
#ifdef _SC_PII_SOCKET
14927
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14928
#endif
14929
#ifdef _SC_PII_XTI
14930
    {"SC_PII_XTI",      _SC_PII_XTI},
14931
#endif
14932
#ifdef _SC_POLL
14933
    {"SC_POLL", _SC_POLL},
14934
#endif
14935
#ifdef _SC_PRIORITIZED_IO
14936
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14937
#endif
14938
#ifdef _SC_PRIORITY_SCHEDULING
14939
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14940
#endif
14941
#ifdef _SC_REALTIME_SIGNALS
14942
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14943
#endif
14944
#ifdef _SC_RE_DUP_MAX
14945
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14946
#endif
14947
#ifdef _SC_RTSIG_MAX
14948
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14949
#endif
14950
#ifdef _SC_SAVED_IDS
14951
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14952
#endif
14953
#ifdef _SC_SCHAR_MAX
14954
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14955
#endif
14956
#ifdef _SC_SCHAR_MIN
14957
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14958
#endif
14959
#ifdef _SC_SELECT
14960
    {"SC_SELECT",       _SC_SELECT},
14961
#endif
14962
#ifdef _SC_SEMAPHORES
14963
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14964
#endif
14965
#ifdef _SC_SEM_NSEMS_MAX
14966
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14967
#endif
14968
#ifdef _SC_SEM_VALUE_MAX
14969
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14970
#endif
14971
#ifdef _SC_SHARED_MEMORY_OBJECTS
14972
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14973
#endif
14974
#ifdef _SC_SHRT_MAX
14975
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14976
#endif
14977
#ifdef _SC_SHRT_MIN
14978
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14979
#endif
14980
#ifdef _SC_SIGQUEUE_MAX
14981
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14982
#endif
14983
#ifdef _SC_SIGRT_MAX
14984
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14985
#endif
14986
#ifdef _SC_SIGRT_MIN
14987
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14988
#endif
14989
#ifdef _SC_SOFTPOWER
14990
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14991
#endif
14992
#ifdef _SC_SPLIT_CACHE
14993
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14994
#endif
14995
#ifdef _SC_SSIZE_MAX
14996
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14997
#endif
14998
#ifdef _SC_STACK_PROT
14999
    {"SC_STACK_PROT",   _SC_STACK_PROT},
15000
#endif
15001
#ifdef _SC_STREAM_MAX
15002
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
15003
#endif
15004
#ifdef _SC_SYNCHRONIZED_IO
15005
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
15006
#endif
15007
#ifdef _SC_THREADS
15008
    {"SC_THREADS",      _SC_THREADS},
15009
#endif
15010
#ifdef _SC_THREAD_ATTR_STACKADDR
15011
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
15012
#endif
15013
#ifdef _SC_THREAD_ATTR_STACKSIZE
15014
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
15015
#endif
15016
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
15017
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
15018
#endif
15019
#ifdef _SC_THREAD_KEYS_MAX
15020
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
15021
#endif
15022
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
15023
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
15024
#endif
15025
#ifdef _SC_THREAD_PRIO_INHERIT
15026
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
15027
#endif
15028
#ifdef _SC_THREAD_PRIO_PROTECT
15029
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
15030
#endif
15031
#ifdef _SC_THREAD_PROCESS_SHARED
15032
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
15033
#endif
15034
#ifdef _SC_THREAD_SAFE_FUNCTIONS
15035
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
15036
#endif
15037
#ifdef _SC_THREAD_STACK_MIN
15038
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
15039
#endif
15040
#ifdef _SC_THREAD_THREADS_MAX
15041
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
15042
#endif
15043
#ifdef _SC_TIMERS
15044
    {"SC_TIMERS",       _SC_TIMERS},
15045
#endif
15046
#ifdef _SC_TIMER_MAX
15047
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
15048
#endif
15049
#ifdef _SC_TTY_NAME_MAX
15050
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
15051
#endif
15052
#ifdef _SC_TZNAME_MAX
15053
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
15054
#endif
15055
#ifdef _SC_T_IOV_MAX
15056
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
15057
#endif
15058
#ifdef _SC_UCHAR_MAX
15059
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
15060
#endif
15061
#ifdef _SC_UINT_MAX
15062
    {"SC_UINT_MAX",     _SC_UINT_MAX},
15063
#endif
15064
#ifdef _SC_UIO_MAXIOV
15065
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
15066
#endif
15067
#ifdef _SC_ULONG_MAX
15068
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
15069
#endif
15070
#ifdef _SC_USHRT_MAX
15071
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
15072
#endif
15073
#ifdef _SC_VERSION
15074
    {"SC_VERSION",      _SC_VERSION},
15075
#endif
15076
#ifdef _SC_WORD_BIT
15077
    {"SC_WORD_BIT",     _SC_WORD_BIT},
15078
#endif
15079
#ifdef _SC_XBS5_ILP32_OFF32
15080
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15081
#endif
15082
#ifdef _SC_XBS5_ILP32_OFFBIG
15083
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15084
#endif
15085
#ifdef _SC_XBS5_LP64_OFF64
15086
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15087
#endif
15088
#ifdef _SC_XBS5_LPBIG_OFFBIG
15089
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15090
#endif
15091
#ifdef _SC_XOPEN_CRYPT
15092
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15093
#endif
15094
#ifdef _SC_XOPEN_ENH_I18N
15095
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15096
#endif
15097
#ifdef _SC_XOPEN_LEGACY
15098
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15099
#endif
15100
#ifdef _SC_XOPEN_REALTIME
15101
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15102
#endif
15103
#ifdef _SC_XOPEN_REALTIME_THREADS
15104
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15105
#endif
15106
#ifdef _SC_XOPEN_SHM
15107
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15108
#endif
15109
#ifdef _SC_XOPEN_UNIX
15110
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15111
#endif
15112
#ifdef _SC_XOPEN_VERSION
15113
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15114
#endif
15115
#ifdef _SC_XOPEN_XCU_VERSION
15116
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15117
#endif
15118
#ifdef _SC_XOPEN_XPG2
15119
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15120
#endif
15121
#ifdef _SC_XOPEN_XPG3
15122
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15123
#endif
15124
#ifdef _SC_XOPEN_XPG4
15125
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15126
#endif
15127
#ifdef _SC_MINSIGSTKSZ
15128
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15129
#endif
15130
};
15131
15132
15133
/*[clinic input]
15134
os.sysconf -> long
15135
    name: confname(table="sysconf_names")
15136
    /
15137
15138
Return an integer-valued system configuration variable.
15139
[clinic start generated code]*/
15140
15141
static long
15142
os_sysconf_impl(PyObject *module, int name)
15143
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15144
0
{
15145
0
    long value;
15146
15147
0
    errno = 0;
15148
0
    value = sysconf(name);
15149
0
    if (value == -1 && errno != 0)
15150
0
        posix_error();
15151
0
    return value;
15152
0
}
15153
#endif /* HAVE_SYSCONF */
15154
15155
15156
static int
15157
setup_confname_table(struct constdef *table, size_t tablesize,
15158
                     const char *tablename, PyObject *module)
15159
108
{
15160
108
    PyObject *d = PyDict_New();
15161
108
    if (d == NULL)
15162
0
        return -1;
15163
15164
6.62k
    for (size_t i=0; i < tablesize; ++i) {
15165
6.51k
        PyObject *o = PyLong_FromLong(table[i].value);
15166
6.51k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15167
0
            Py_XDECREF(o);
15168
0
            Py_DECREF(d);
15169
0
            return -1;
15170
0
        }
15171
6.51k
        Py_DECREF(o);
15172
6.51k
    }
15173
108
    return PyModule_Add(module, tablename, d);
15174
108
}
15175
15176
/* Return -1 on failure, 0 on success. */
15177
static int
15178
setup_confname_tables(PyObject *module)
15179
36
{
15180
36
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15181
36
    if (setup_confname_table(posix_constants_pathconf,
15182
36
                             sizeof(posix_constants_pathconf)
15183
36
                               / sizeof(struct constdef),
15184
36
                             "pathconf_names", module))
15185
0
        return -1;
15186
36
#endif
15187
36
#ifdef HAVE_CONFSTR
15188
36
    if (setup_confname_table(posix_constants_confstr,
15189
36
                             sizeof(posix_constants_confstr)
15190
36
                               / sizeof(struct constdef),
15191
36
                             "confstr_names", module))
15192
0
        return -1;
15193
36
#endif
15194
36
#ifdef HAVE_SYSCONF
15195
36
    if (setup_confname_table(posix_constants_sysconf,
15196
36
                             sizeof(posix_constants_sysconf)
15197
36
                               / sizeof(struct constdef),
15198
36
                             "sysconf_names", module))
15199
0
        return -1;
15200
36
#endif
15201
36
    return 0;
15202
36
}
15203
15204
15205
/*[clinic input]
15206
os.abort
15207
15208
Abort the interpreter immediately.
15209
15210
This function 'dumps core' or otherwise fails in the hardest way
15211
possible on the hosting operating system.  This function never returns.
15212
[clinic start generated code]*/
15213
15214
static PyObject *
15215
os_abort_impl(PyObject *module)
15216
/*[clinic end generated code: output=dcf52586dad2467c input=ee8bd0ed690440ab]*/
15217
0
{
15218
0
    abort();
15219
    /*NOTREACHED*/
15220
#ifndef __clang__
15221
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15222
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15223
       is smarter and emits a warning on the return. */
15224
    Py_FatalError("abort() called from Python code didn't abort!");
15225
    return NULL;
15226
#endif
15227
0
}
15228
15229
#ifdef MS_WINDOWS
15230
/* Grab ShellExecute dynamically from shell32 */
15231
static int has_ShellExecute = -1;
15232
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15233
                                              LPCWSTR, INT);
15234
static int
15235
check_ShellExecute(void)
15236
{
15237
    HINSTANCE hShell32;
15238
15239
    /* only recheck */
15240
    if (-1 == has_ShellExecute) {
15241
        Py_BEGIN_ALLOW_THREADS
15242
        /* Security note: this call is not vulnerable to "DLL hijacking".
15243
           SHELL32 is part of "KnownDLLs" and so Windows always load
15244
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15245
           in the DLL search path. */
15246
        hShell32 = LoadLibraryW(L"SHELL32");
15247
        if (hShell32) {
15248
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15249
                                            "ShellExecuteW");
15250
            has_ShellExecute = Py_ShellExecuteW != NULL;
15251
        } else {
15252
            has_ShellExecute = 0;
15253
        }
15254
        Py_END_ALLOW_THREADS
15255
    }
15256
    return has_ShellExecute;
15257
}
15258
15259
15260
/*[clinic input]
15261
os.startfile
15262
    filepath: path_t
15263
    operation: Py_UNICODE = NULL
15264
    arguments: Py_UNICODE = NULL
15265
    cwd: path_t(nullable=True) = None
15266
    show_cmd: int = 1
15267
15268
Start a file with its associated application.
15269
15270
When "operation" is not specified or "open", this acts like
15271
double-clicking the file in Explorer, or giving the file name as an
15272
argument to the DOS "start" command: the file is opened with whatever
15273
application (if any) its extension is associated.
15274
When another "operation" is given, it specifies what should be done with
15275
the file.  A typical operation is "print".
15276
15277
"arguments" is passed to the application, but should be omitted if the
15278
file is a document.
15279
15280
"cwd" is the working directory for the operation. If "filepath" is
15281
relative, it will be resolved against this directory. This argument
15282
should usually be an absolute path.
15283
15284
"show_cmd" can be used to override the recommended visibility option.
15285
See the Windows ShellExecute documentation for values.
15286
15287
startfile returns as soon as the associated application is launched.
15288
There is no option to wait for the application to close, and no way
15289
to retrieve the application's exit status.
15290
15291
The filepath is relative to the current directory.  If you want to use
15292
an absolute path, make sure the first character is not a slash ("/");
15293
the underlying Win32 ShellExecute function doesn't work if it is.
15294
[clinic start generated code]*/
15295
15296
static PyObject *
15297
os_startfile_impl(PyObject *module, path_t *filepath,
15298
                  const wchar_t *operation, const wchar_t *arguments,
15299
                  path_t *cwd, int show_cmd)
15300
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15301
{
15302
    HINSTANCE rc;
15303
15304
    if(!check_ShellExecute()) {
15305
        /* If the OS doesn't have ShellExecute, return a
15306
           NotImplementedError. */
15307
        return PyErr_Format(PyExc_NotImplementedError,
15308
            "startfile not available on this platform");
15309
    }
15310
15311
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15312
        return NULL;
15313
    }
15314
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15315
                    arguments, cwd->object ? cwd->object : Py_None,
15316
                    show_cmd) < 0) {
15317
        return NULL;
15318
    }
15319
15320
    Py_BEGIN_ALLOW_THREADS
15321
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15322
                          arguments, cwd->wide, show_cmd);
15323
    Py_END_ALLOW_THREADS
15324
15325
    if (rc <= (HINSTANCE)32) {
15326
        win32_error_object("startfile", filepath->object);
15327
        return NULL;
15328
    }
15329
    Py_RETURN_NONE;
15330
}
15331
#endif /* MS_WINDOWS */
15332
15333
15334
#ifdef HAVE_GETLOADAVG
15335
/*[clinic input]
15336
os.getloadavg
15337
15338
Return average recent system load information.
15339
15340
Return the number of processes in the system run queue averaged over
15341
the last 1, 5, and 15 minutes as a tuple of three floats.
15342
Raises OSError if the load average was unobtainable.
15343
[clinic start generated code]*/
15344
15345
static PyObject *
15346
os_getloadavg_impl(PyObject *module)
15347
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15348
0
{
15349
0
    double loadavg[3];
15350
0
    if (getloadavg(loadavg, 3)!=3) {
15351
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15352
0
        return NULL;
15353
0
    } else
15354
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15355
0
}
15356
#endif /* HAVE_GETLOADAVG */
15357
15358
15359
/*[clinic input]
15360
os.device_encoding
15361
    fd: int
15362
15363
Return a string describing the encoding of a terminal's file descriptor.
15364
15365
The file descriptor must be attached to a terminal.
15366
If the device is not a terminal, return None.
15367
[clinic start generated code]*/
15368
15369
static PyObject *
15370
os_device_encoding_impl(PyObject *module, int fd)
15371
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15372
0
{
15373
0
    return _Py_device_encoding(fd);
15374
0
}
15375
15376
15377
#ifdef HAVE_SETRESUID
15378
/*[clinic input]
15379
os.setresuid
15380
15381
    ruid: uid_t
15382
    euid: uid_t
15383
    suid: uid_t
15384
    /
15385
15386
Set the current process's real, effective, and saved user ids.
15387
[clinic start generated code]*/
15388
15389
static PyObject *
15390
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15391
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15392
0
{
15393
0
    if (setresuid(ruid, euid, suid) < 0)
15394
0
        return posix_error();
15395
0
    Py_RETURN_NONE;
15396
0
}
15397
#endif /* HAVE_SETRESUID */
15398
15399
15400
#ifdef HAVE_SETRESGID
15401
/*[clinic input]
15402
os.setresgid
15403
15404
    rgid: gid_t
15405
    egid: gid_t
15406
    sgid: gid_t
15407
    /
15408
15409
Set the current process's real, effective, and saved group ids.
15410
[clinic start generated code]*/
15411
15412
static PyObject *
15413
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15414
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15415
0
{
15416
0
    if (setresgid(rgid, egid, sgid) < 0)
15417
0
        return posix_error();
15418
0
    Py_RETURN_NONE;
15419
0
}
15420
#endif /* HAVE_SETRESGID */
15421
15422
15423
#ifdef HAVE_GETRESUID
15424
/*[clinic input]
15425
@permit_long_summary
15426
os.getresuid
15427
15428
Return a tuple of the current process's real, effective, and saved user ids.
15429
[clinic start generated code]*/
15430
15431
static PyObject *
15432
os_getresuid_impl(PyObject *module)
15433
/*[clinic end generated code: output=8e0becff5dece5bf input=ddf95881f492cb97]*/
15434
0
{
15435
0
    uid_t ruid, euid, suid;
15436
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15437
0
        return posix_error();
15438
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15439
0
                                  _PyLong_FromUid(euid),
15440
0
                                  _PyLong_FromUid(suid));
15441
0
}
15442
#endif /* HAVE_GETRESUID */
15443
15444
15445
#ifdef HAVE_GETRESGID
15446
/*[clinic input]
15447
@permit_long_summary
15448
os.getresgid
15449
15450
Return a tuple of the current process's real, effective, and saved group ids.
15451
[clinic start generated code]*/
15452
15453
static PyObject *
15454
os_getresgid_impl(PyObject *module)
15455
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15456
0
{
15457
0
    gid_t rgid, egid, sgid;
15458
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15459
0
        return posix_error();
15460
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15461
0
                                  _PyLong_FromGid(egid),
15462
0
                                  _PyLong_FromGid(sgid));
15463
0
}
15464
#endif /* HAVE_GETRESGID */
15465
15466
15467
#ifdef USE_XATTRS
15468
/*[clinic input]
15469
os.getxattr
15470
15471
    path: path_t(allow_fd=True)
15472
    attribute: path_t
15473
    *
15474
    follow_symlinks: bool = True
15475
15476
Return the value of extended attribute attribute on path.
15477
15478
path may be either a string, a path-like object, or an open file
15479
descriptor.
15480
If follow_symlinks is False, and the last element of the path is
15481
a symbolic link, getxattr will examine the symbolic link itself
15482
instead of the file the link points to.
15483
15484
[clinic start generated code]*/
15485
15486
static PyObject *
15487
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15488
                 int follow_symlinks)
15489
/*[clinic end generated code: output=5f2f44200a43cff2 input=db1021ed738d9754]*/
15490
0
{
15491
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
15492
0
        return NULL;
15493
15494
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15495
0
        return NULL;
15496
0
    }
15497
15498
0
    for (Py_ssize_t i = 0; ; i++) {
15499
0
        ssize_t result;
15500
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15501
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15502
0
        if (!buffer_size) {
15503
0
            path_error(path);
15504
0
            return NULL;
15505
0
        }
15506
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15507
0
        if (writer == NULL) {
15508
0
            return NULL;
15509
0
        }
15510
0
        void *ptr = PyBytesWriter_GetData(writer);
15511
15512
0
        Py_BEGIN_ALLOW_THREADS;
15513
0
        if (path->is_fd)
15514
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15515
0
        else if (follow_symlinks)
15516
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15517
0
        else
15518
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15519
0
        Py_END_ALLOW_THREADS;
15520
15521
0
        if (result < 0) {
15522
0
            PyBytesWriter_Discard(writer);
15523
0
            if (errno == ERANGE) {
15524
0
                continue;
15525
0
            }
15526
0
            path_error(path);
15527
0
            return NULL;
15528
0
        }
15529
15530
0
        return PyBytesWriter_FinishWithSize(writer, result);
15531
0
    }
15532
0
}
15533
15534
15535
/*[clinic input]
15536
os.setxattr
15537
15538
    path: path_t(allow_fd=True)
15539
    attribute: path_t
15540
    value: Py_buffer
15541
    flags: int = 0
15542
    *
15543
    follow_symlinks: bool = True
15544
15545
Set extended attribute attribute on path to value.
15546
15547
path may be either a string, a path-like object,  or an open file
15548
descriptor.
15549
If follow_symlinks is False, and the last element of the path is
15550
a symbolic link, setxattr will modify the symbolic link itself instead
15551
of the file the link points to.
15552
15553
[clinic start generated code]*/
15554
15555
static PyObject *
15556
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15557
                 Py_buffer *value, int flags, int follow_symlinks)
15558
/*[clinic end generated code: output=98b83f63fdde26bb input=6c4ee6724e8947a4]*/
15559
0
{
15560
0
    ssize_t result;
15561
15562
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
15563
0
        return NULL;
15564
15565
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15566
0
                    value->buf, value->len, flags) < 0) {
15567
0
        return NULL;
15568
0
    }
15569
15570
0
    Py_BEGIN_ALLOW_THREADS;
15571
0
    if (path->is_fd)
15572
0
        result = fsetxattr(path->fd, attribute->narrow,
15573
0
                           value->buf, value->len, flags);
15574
0
    else if (follow_symlinks)
15575
0
        result = setxattr(path->narrow, attribute->narrow,
15576
0
                           value->buf, value->len, flags);
15577
0
    else
15578
0
        result = lsetxattr(path->narrow, attribute->narrow,
15579
0
                           value->buf, value->len, flags);
15580
0
    Py_END_ALLOW_THREADS;
15581
15582
0
    if (result) {
15583
0
        path_error(path);
15584
0
        return NULL;
15585
0
    }
15586
15587
0
    Py_RETURN_NONE;
15588
0
}
15589
15590
15591
/*[clinic input]
15592
os.removexattr
15593
15594
    path: path_t(allow_fd=True)
15595
    attribute: path_t
15596
    *
15597
    follow_symlinks: bool = True
15598
15599
Remove extended attribute attribute on path.
15600
15601
path may be either a string, a path-like object, or an open file
15602
descriptor.
15603
If follow_symlinks is False, and the last element of the path is
15604
a symbolic link, removexattr will modify the symbolic link itself
15605
instead of the file the link points to.
15606
15607
[clinic start generated code]*/
15608
15609
static PyObject *
15610
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15611
                    int follow_symlinks)
15612
/*[clinic end generated code: output=521a51817980cda6 input=a7ec62a86aa83f01]*/
15613
0
{
15614
0
    ssize_t result;
15615
15616
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
15617
0
        return NULL;
15618
15619
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15620
0
        return NULL;
15621
0
    }
15622
15623
0
    Py_BEGIN_ALLOW_THREADS;
15624
0
    if (path->is_fd)
15625
0
        result = fremovexattr(path->fd, attribute->narrow);
15626
0
    else if (follow_symlinks)
15627
0
        result = removexattr(path->narrow, attribute->narrow);
15628
0
    else
15629
0
        result = lremovexattr(path->narrow, attribute->narrow);
15630
0
    Py_END_ALLOW_THREADS;
15631
15632
0
    if (result) {
15633
0
        return path_error(path);
15634
0
    }
15635
15636
0
    Py_RETURN_NONE;
15637
0
}
15638
15639
15640
/*[clinic input]
15641
os.listxattr
15642
15643
    path: path_t(allow_fd=True, nullable=True) = None
15644
    *
15645
    follow_symlinks: bool = True
15646
15647
Return a list of extended attributes on path.
15648
15649
path may be either None, a string, a path-like object, or an open file
15650
descriptor.  If path is None, listxattr will examine the current
15651
directory.
15652
If follow_symlinks is False, and the last element of the path is
15653
a symbolic link, listxattr will examine the symbolic link itself instead
15654
of the file the link points to.
15655
[clinic start generated code]*/
15656
15657
static PyObject *
15658
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15659
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=cb4a6414afaa99bd]*/
15660
0
{
15661
0
    Py_ssize_t i;
15662
0
    PyObject *result = NULL;
15663
0
    const char *name;
15664
0
    char *buffer = NULL;
15665
15666
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
15667
0
        goto exit;
15668
15669
0
    if (PySys_Audit("os.listxattr", "(O)",
15670
0
                    path->object ? path->object : Py_None) < 0) {
15671
0
        return NULL;
15672
0
    }
15673
15674
0
    name = path->narrow ? path->narrow : ".";
15675
15676
0
    for (i = 0; ; i++) {
15677
0
        const char *start, *trace, *end;
15678
0
        ssize_t length;
15679
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15680
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15681
0
        if (!buffer_size) {
15682
            /* ERANGE */
15683
0
            path_error(path);
15684
0
            break;
15685
0
        }
15686
0
        buffer = PyMem_Malloc(buffer_size);
15687
0
        if (!buffer) {
15688
0
            PyErr_NoMemory();
15689
0
            break;
15690
0
        }
15691
15692
0
        Py_BEGIN_ALLOW_THREADS;
15693
0
        if (path->is_fd)
15694
0
            length = flistxattr(path->fd, buffer, buffer_size);
15695
0
        else if (follow_symlinks)
15696
0
            length = listxattr(name, buffer, buffer_size);
15697
0
        else
15698
0
            length = llistxattr(name, buffer, buffer_size);
15699
0
        Py_END_ALLOW_THREADS;
15700
15701
0
        if (length < 0) {
15702
0
            if (errno == ERANGE) {
15703
0
                PyMem_Free(buffer);
15704
0
                buffer = NULL;
15705
0
                continue;
15706
0
            }
15707
0
            path_error(path);
15708
0
            break;
15709
0
        }
15710
15711
0
        result = PyList_New(0);
15712
0
        if (!result) {
15713
0
            goto exit;
15714
0
        }
15715
15716
0
        end = buffer + length;
15717
0
        for (trace = start = buffer; trace != end; trace++) {
15718
0
            if (!*trace) {
15719
0
                int error;
15720
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15721
0
                                                                 trace - start);
15722
0
                if (!attribute) {
15723
0
                    Py_SETREF(result, NULL);
15724
0
                    goto exit;
15725
0
                }
15726
0
                error = PyList_Append(result, attribute);
15727
0
                Py_DECREF(attribute);
15728
0
                if (error) {
15729
0
                    Py_SETREF(result, NULL);
15730
0
                    goto exit;
15731
0
                }
15732
0
                start = trace + 1;
15733
0
            }
15734
0
        }
15735
0
    break;
15736
0
    }
15737
0
exit:
15738
0
    if (buffer)
15739
0
        PyMem_Free(buffer);
15740
0
    return result;
15741
0
}
15742
#endif /* USE_XATTRS */
15743
15744
15745
/*[clinic input]
15746
@permit_long_summary
15747
os.urandom
15748
15749
    size: Py_ssize_t(allow_negative=False)
15750
    /
15751
15752
Return a bytes object containing random bytes suitable for cryptographic use.
15753
[clinic start generated code]*/
15754
15755
static PyObject *
15756
os_urandom_impl(PyObject *module, Py_ssize_t size)
15757
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15758
0
{
15759
0
    if (size < 0) {
15760
0
        return PyErr_Format(PyExc_ValueError,
15761
0
                            "negative argument not allowed");
15762
0
    }
15763
15764
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15765
0
    if (writer == NULL) {
15766
0
        return NULL;
15767
0
    }
15768
15769
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15770
0
    if (result == -1) {
15771
0
        PyBytesWriter_Discard(writer);
15772
0
        return NULL;
15773
0
    }
15774
0
    return PyBytesWriter_Finish(writer);
15775
0
}
15776
15777
#ifdef HAVE_MEMFD_CREATE
15778
/*[clinic input]
15779
os.memfd_create
15780
15781
    name: unicode_fs_encoded
15782
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15783
15784
[clinic start generated code]*/
15785
15786
static PyObject *
15787
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15788
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15789
0
{
15790
0
    int fd;
15791
0
    const char *bytes = PyBytes_AS_STRING(name);
15792
0
    Py_BEGIN_ALLOW_THREADS
15793
0
    fd = memfd_create(bytes, flags);
15794
0
    Py_END_ALLOW_THREADS
15795
0
    if (fd == -1) {
15796
0
        return PyErr_SetFromErrno(PyExc_OSError);
15797
0
    }
15798
0
    return PyLong_FromLong(fd);
15799
0
}
15800
#endif
15801
15802
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15803
/*[clinic input]
15804
os.eventfd
15805
15806
    initval: unsigned_int
15807
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15808
15809
Creates and returns an event notification file descriptor.
15810
[clinic start generated code]*/
15811
15812
static PyObject *
15813
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15814
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15815
15816
0
{
15817
    /* initval is limited to uint32_t, internal counter is uint64_t */
15818
0
    int fd;
15819
0
    Py_BEGIN_ALLOW_THREADS
15820
0
    fd = eventfd(initval, flags);
15821
0
    Py_END_ALLOW_THREADS
15822
0
    if (fd == -1) {
15823
0
        return PyErr_SetFromErrno(PyExc_OSError);
15824
0
    }
15825
0
    return PyLong_FromLong(fd);
15826
0
}
15827
15828
/*[clinic input]
15829
os.eventfd_read
15830
15831
    fd: fildes
15832
15833
Read eventfd value
15834
[clinic start generated code]*/
15835
15836
static PyObject *
15837
os_eventfd_read_impl(PyObject *module, int fd)
15838
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15839
0
{
15840
0
    eventfd_t value;
15841
0
    int result;
15842
0
    Py_BEGIN_ALLOW_THREADS
15843
0
    result = eventfd_read(fd, &value);
15844
0
    Py_END_ALLOW_THREADS
15845
0
    if (result == -1) {
15846
0
        return PyErr_SetFromErrno(PyExc_OSError);
15847
0
    }
15848
0
    return PyLong_FromUnsignedLongLong(value);
15849
0
}
15850
15851
/*[clinic input]
15852
os.eventfd_write
15853
15854
    fd: fildes
15855
    value: unsigned_long_long
15856
15857
Write eventfd value.
15858
[clinic start generated code]*/
15859
15860
static PyObject *
15861
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15862
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15863
0
{
15864
0
    int result;
15865
0
    Py_BEGIN_ALLOW_THREADS
15866
0
    result = eventfd_write(fd, value);
15867
0
    Py_END_ALLOW_THREADS
15868
0
    if (result == -1) {
15869
0
        return PyErr_SetFromErrno(PyExc_OSError);
15870
0
    }
15871
0
    Py_RETURN_NONE;
15872
0
}
15873
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15874
15875
/* Terminal size querying */
15876
15877
PyDoc_STRVAR(TerminalSize_docstring,
15878
    "A tuple of (columns, lines) for holding terminal window size");
15879
15880
static PyStructSequence_Field TerminalSize_fields[] = {
15881
    {"columns", "width of the terminal window in characters"},
15882
    {"lines", "height of the terminal window in characters"},
15883
    {NULL, NULL}
15884
};
15885
15886
static PyStructSequence_Desc TerminalSize_desc = {
15887
    "os.terminal_size",
15888
    TerminalSize_docstring,
15889
    TerminalSize_fields,
15890
    2,
15891
};
15892
15893
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15894
/*[clinic input]
15895
os.get_terminal_size
15896
15897
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15898
    /
15899
15900
Return the size of the terminal window as (columns, lines).
15901
15902
The optional argument fd (default standard output) specifies
15903
which file descriptor should be queried.
15904
15905
If the file descriptor is not connected to a terminal, an OSError
15906
is thrown.
15907
15908
This function will only be defined if an implementation is
15909
available for this system.
15910
15911
shutil.get_terminal_size is the high-level function which should
15912
normally be used, os.get_terminal_size is the low-level implementation.
15913
[clinic start generated code]*/
15914
15915
static PyObject *
15916
os_get_terminal_size_impl(PyObject *module, int fd)
15917
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15918
0
{
15919
0
    int columns, lines;
15920
0
    PyObject *termsize;
15921
15922
    /* Under some conditions stdout may not be connected and
15923
     * fileno(stdout) may point to an invalid file descriptor. For example
15924
     * GUI apps don't have valid standard streams by default.
15925
     *
15926
     * If this happens, and the optional fd argument is not present,
15927
     * the ioctl below will fail returning EBADF. This is what we want.
15928
     */
15929
15930
0
#ifdef TERMSIZE_USE_IOCTL
15931
0
    {
15932
0
        struct winsize w;
15933
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15934
0
            return PyErr_SetFromErrno(PyExc_OSError);
15935
0
        columns = w.ws_col;
15936
0
        lines = w.ws_row;
15937
0
    }
15938
0
#endif /* TERMSIZE_USE_IOCTL */
15939
15940
#ifdef TERMSIZE_USE_CONIO
15941
    {
15942
        HANDLE handle;
15943
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15944
        handle = _Py_get_osfhandle(fd);
15945
        if (handle == INVALID_HANDLE_VALUE)
15946
            return NULL;
15947
15948
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15949
            return PyErr_SetFromWindowsErr(0);
15950
15951
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15952
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15953
    }
15954
#endif /* TERMSIZE_USE_CONIO */
15955
15956
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15957
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15958
0
    if (termsize == NULL)
15959
0
        return NULL;
15960
15961
0
    int pos = 0;
15962
15963
0
#define SET_TERMSIZE(CALL)                                   \
15964
0
    do {                                                     \
15965
0
        PyObject *item = (CALL);                             \
15966
0
        if (item == NULL) {                                  \
15967
0
            Py_DECREF(termsize);                             \
15968
0
            return NULL;                                     \
15969
0
        }                                                    \
15970
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15971
0
    } while(0)
15972
15973
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15974
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15975
0
#undef SET_TERMSIZE
15976
15977
0
    return termsize;
15978
0
}
15979
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15980
15981
/*[clinic input]
15982
os.cpu_count
15983
15984
Return the number of logical CPUs in the system.
15985
15986
Return None if indeterminable.
15987
[clinic start generated code]*/
15988
15989
static PyObject *
15990
os_cpu_count_impl(PyObject *module)
15991
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15992
0
{
15993
0
    const PyConfig *config = _Py_GetConfig();
15994
0
    if (config->cpu_count > 0) {
15995
0
        return PyLong_FromLong(config->cpu_count);
15996
0
    }
15997
15998
0
    int ncpu = 0;
15999
#ifdef MS_WINDOWS
16000
# ifdef MS_WINDOWS_DESKTOP
16001
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
16002
# else
16003
    ncpu = 0;
16004
# endif
16005
16006
#elif defined(__hpux)
16007
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
16008
16009
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
16010
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
16011
16012
#elif defined(__VXWORKS__)
16013
    ncpu = _Py_popcount32(vxCpuEnabledGet());
16014
16015
#elif defined(__DragonFly__) || \
16016
      defined(__OpenBSD__)   || \
16017
      defined(__FreeBSD__)   || \
16018
      defined(__NetBSD__)    || \
16019
      defined(__APPLE__)
16020
    ncpu = 0;
16021
    size_t len = sizeof(ncpu);
16022
    int mib[2] = {CTL_HW, HW_NCPU};
16023
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
16024
        ncpu = 0;
16025
    }
16026
#endif
16027
16028
0
    if (ncpu < 1) {
16029
0
        Py_RETURN_NONE;
16030
0
    }
16031
0
    return PyLong_FromLong(ncpu);
16032
0
}
16033
16034
16035
/*[clinic input]
16036
os.get_inheritable -> bool
16037
16038
    fd: int
16039
    /
16040
16041
Get the close-on-exe flag of the specified file descriptor.
16042
[clinic start generated code]*/
16043
16044
static int
16045
os_get_inheritable_impl(PyObject *module, int fd)
16046
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
16047
0
{
16048
0
    int return_value;
16049
0
    _Py_BEGIN_SUPPRESS_IPH
16050
0
    return_value = _Py_get_inheritable(fd);
16051
0
    _Py_END_SUPPRESS_IPH
16052
0
    return return_value;
16053
0
}
16054
16055
16056
/*[clinic input]
16057
os.set_inheritable
16058
    fd: int
16059
    inheritable: int
16060
    /
16061
16062
Set the inheritable flag of the specified file descriptor.
16063
[clinic start generated code]*/
16064
16065
static PyObject *
16066
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
16067
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
16068
0
{
16069
0
    int result;
16070
16071
0
    _Py_BEGIN_SUPPRESS_IPH
16072
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
16073
0
    _Py_END_SUPPRESS_IPH
16074
0
    if (result < 0)
16075
0
        return NULL;
16076
0
    Py_RETURN_NONE;
16077
0
}
16078
16079
16080
#ifdef MS_WINDOWS
16081
#ifndef HANDLE_FLAG_INHERIT
16082
#define HANDLE_FLAG_INHERIT 0x00000001
16083
#endif
16084
16085
/*[clinic input]
16086
os.get_handle_inheritable -> bool
16087
    handle: intptr_t
16088
    /
16089
16090
Get the close-on-exe flag of the specified file descriptor.
16091
[clinic start generated code]*/
16092
16093
static int
16094
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16095
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16096
{
16097
    DWORD flags;
16098
16099
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16100
        PyErr_SetFromWindowsErr(0);
16101
        return -1;
16102
    }
16103
16104
    return flags & HANDLE_FLAG_INHERIT;
16105
}
16106
16107
16108
/*[clinic input]
16109
os.set_handle_inheritable
16110
    handle: intptr_t
16111
    inheritable: bool
16112
    /
16113
16114
Set the inheritable flag of the specified handle.
16115
[clinic start generated code]*/
16116
16117
static PyObject *
16118
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16119
                               int inheritable)
16120
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16121
{
16122
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16123
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16124
        PyErr_SetFromWindowsErr(0);
16125
        return NULL;
16126
    }
16127
    Py_RETURN_NONE;
16128
}
16129
#endif /* MS_WINDOWS */
16130
16131
/*[clinic input]
16132
os.get_blocking -> bool
16133
    fd: int
16134
    /
16135
16136
Get the blocking mode of the file descriptor.
16137
16138
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16139
[clinic start generated code]*/
16140
16141
static int
16142
os_get_blocking_impl(PyObject *module, int fd)
16143
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16144
0
{
16145
0
    int blocking;
16146
16147
0
    _Py_BEGIN_SUPPRESS_IPH
16148
0
    blocking = _Py_get_blocking(fd);
16149
0
    _Py_END_SUPPRESS_IPH
16150
0
    return blocking;
16151
0
}
16152
16153
/*[clinic input]
16154
os.set_blocking
16155
    fd: int
16156
    blocking: bool
16157
    /
16158
16159
Set the blocking mode of the specified file descriptor.
16160
16161
Set the O_NONBLOCK flag if blocking is False,
16162
clear the O_NONBLOCK flag otherwise.
16163
[clinic start generated code]*/
16164
16165
static PyObject *
16166
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16167
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16168
0
{
16169
0
    int result;
16170
16171
0
    _Py_BEGIN_SUPPRESS_IPH
16172
0
    result = _Py_set_blocking(fd, blocking);
16173
0
    _Py_END_SUPPRESS_IPH
16174
0
    if (result < 0)
16175
0
        return NULL;
16176
0
    Py_RETURN_NONE;
16177
0
}
16178
16179
16180
/*[clinic input]
16181
class os.DirEntry "DirEntry *" "DirEntryType"
16182
[clinic start generated code]*/
16183
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16184
16185
typedef struct {
16186
    PyObject_HEAD
16187
    PyObject *name;
16188
    PyObject *path;
16189
    PyObject *stat;
16190
    PyObject *lstat;
16191
#ifdef MS_WINDOWS
16192
    struct _Py_stat_struct win32_lstat;
16193
    uint64_t win32_file_index;
16194
    uint64_t win32_file_index_high;
16195
    int got_file_index;
16196
#else /* POSIX */
16197
#ifdef HAVE_DIRENT_D_TYPE
16198
    unsigned char d_type;
16199
#endif
16200
    ino_t d_ino;
16201
    int dir_fd;
16202
#endif
16203
} DirEntry;
16204
16205
104k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16206
16207
static void
16208
DirEntry_dealloc(PyObject *op)
16209
104k
{
16210
104k
    DirEntry *entry = DirEntry_CAST(op);
16211
104k
    PyTypeObject *tp = Py_TYPE(entry);
16212
104k
    Py_XDECREF(entry->name);
16213
104k
    Py_XDECREF(entry->path);
16214
104k
    Py_XDECREF(entry->stat);
16215
104k
    Py_XDECREF(entry->lstat);
16216
104k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16217
104k
    free_func(entry);
16218
104k
    Py_DECREF(tp);
16219
104k
}
16220
16221
/* Forward reference */
16222
static int
16223
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16224
                   int follow_symlinks, unsigned short mode_bits);
16225
16226
/*[clinic input]
16227
os.DirEntry.is_symlink -> bool
16228
    defining_class: defining_class
16229
    /
16230
16231
Return True if the entry is a symbolic link; cached per entry.
16232
[clinic start generated code]*/
16233
16234
static int
16235
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16236
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16237
0
{
16238
#ifdef MS_WINDOWS
16239
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16240
#elif defined(HAVE_DIRENT_D_TYPE)
16241
    /* POSIX */
16242
0
    if (self->d_type != DT_UNKNOWN)
16243
0
        return self->d_type == DT_LNK;
16244
0
    else
16245
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16246
#else
16247
    /* POSIX without d_type */
16248
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16249
#endif
16250
0
}
16251
16252
/*[clinic input]
16253
os.DirEntry.is_junction -> bool
16254
16255
Return True if the entry is a junction; cached per entry.
16256
[clinic start generated code]*/
16257
16258
static int
16259
os_DirEntry_is_junction_impl(DirEntry *self)
16260
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16261
0
{
16262
#ifdef MS_WINDOWS
16263
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16264
#else
16265
0
    return 0;
16266
0
#endif
16267
0
}
16268
16269
static PyObject *
16270
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16271
86.8k
{
16272
86.8k
    int result;
16273
86.8k
    STRUCT_STAT st;
16274
86.8k
    PyObject *ub;
16275
16276
#ifdef MS_WINDOWS
16277
    if (!PyUnicode_FSDecoder(self->path, &ub))
16278
        return NULL;
16279
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16280
    Py_DECREF(ub);
16281
#else /* POSIX */
16282
86.8k
    if (!PyUnicode_FSConverter(self->path, &ub))
16283
0
        return NULL;
16284
86.8k
    const char *path = PyBytes_AS_STRING(ub);
16285
86.8k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16286
86.8k
#ifdef HAVE_FSTATAT
16287
86.8k
      if (HAVE_FSTATAT_RUNTIME) {
16288
86.8k
        Py_BEGIN_ALLOW_THREADS
16289
86.8k
        result = fstatat(self->dir_fd, path, &st,
16290
86.8k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16291
86.8k
        Py_END_ALLOW_THREADS
16292
86.8k
      } else
16293
16294
0
#endif /* HAVE_FSTATAT */
16295
0
      {
16296
0
        Py_DECREF(ub);
16297
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16298
0
        return NULL;
16299
0
      }
16300
86.8k
    }
16301
0
    else
16302
0
#endif
16303
0
    {
16304
0
        Py_BEGIN_ALLOW_THREADS
16305
0
        if (follow_symlinks) {
16306
0
            result = STAT(path, &st);
16307
0
        }
16308
0
        else {
16309
0
            result = LSTAT(path, &st);
16310
0
        }
16311
0
        Py_END_ALLOW_THREADS
16312
0
    }
16313
16314
86.8k
    int saved_errno = errno;
16315
#if defined(MS_WINDOWS)
16316
    PyMem_Free(path);
16317
#else
16318
86.8k
    Py_DECREF(ub);
16319
86.8k
#endif
16320
16321
86.8k
    if (result != 0) {
16322
0
        errno = saved_errno;
16323
0
        path_object_error(self->path);
16324
0
        return NULL;
16325
0
    }
16326
16327
86.8k
    return _pystat_fromstructstat(module, &st);
16328
86.8k
}
16329
16330
static PyObject *
16331
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16332
86.8k
{
16333
86.8k
    if (!self->lstat) {
16334
86.8k
        PyObject *module = PyType_GetModule(defining_class);
16335
#ifdef MS_WINDOWS
16336
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16337
#else /* POSIX */
16338
86.8k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16339
86.8k
#endif
16340
86.8k
    }
16341
86.8k
    return Py_XNewRef(self->lstat);
16342
86.8k
}
16343
16344
/*[clinic input]
16345
os.DirEntry.stat
16346
    defining_class: defining_class
16347
    /
16348
    *
16349
    follow_symlinks: bool = True
16350
16351
Return stat_result object for the entry; cached per entry.
16352
[clinic start generated code]*/
16353
16354
static PyObject *
16355
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16356
                      int follow_symlinks)
16357
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16358
86.8k
{
16359
86.8k
    if (!follow_symlinks) {
16360
86.8k
        return DirEntry_get_lstat(defining_class, self);
16361
86.8k
    }
16362
16363
0
    if (!self->stat) {
16364
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16365
0
        if (result == -1) {
16366
0
            return NULL;
16367
0
        }
16368
0
        if (result) {
16369
0
            PyObject *module = PyType_GetModule(defining_class);
16370
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16371
0
        }
16372
0
        else {
16373
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16374
0
        }
16375
0
    }
16376
16377
0
    return Py_XNewRef(self->stat);
16378
0
}
16379
16380
/* Set exception and return -1 on error, 0 for False, 1 for True */
16381
static int
16382
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16383
                   int follow_symlinks, unsigned short mode_bits)
16384
104k
{
16385
104k
    PyObject *stat = NULL;
16386
104k
    PyObject *st_mode = NULL;
16387
104k
    long mode;
16388
104k
    int result;
16389
104k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16390
104k
    int is_symlink;
16391
104k
    int need_stat;
16392
104k
#endif
16393
#ifdef MS_WINDOWS
16394
    unsigned long dir_bits;
16395
#endif
16396
16397
#ifdef MS_WINDOWS
16398
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16399
    need_stat = follow_symlinks && is_symlink;
16400
#elif defined(HAVE_DIRENT_D_TYPE)
16401
104k
    is_symlink = self->d_type == DT_LNK;
16402
104k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16403
104k
#endif
16404
16405
104k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16406
104k
    if (need_stat) {
16407
0
#endif
16408
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16409
0
        if (!stat) {
16410
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16411
                /* If file doesn't exist (anymore), then return False
16412
                   (i.e., say it's not a file/directory) */
16413
0
                PyErr_Clear();
16414
0
                return 0;
16415
0
            }
16416
0
            goto error;
16417
0
        }
16418
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16419
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16420
0
        if (!st_mode)
16421
0
            goto error;
16422
16423
0
        mode = PyLong_AsLong(st_mode);
16424
0
        if (mode == -1 && PyErr_Occurred())
16425
0
            goto error;
16426
0
        Py_CLEAR(st_mode);
16427
0
        Py_CLEAR(stat);
16428
0
        result = (mode & S_IFMT) == mode_bits;
16429
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16430
0
    }
16431
104k
    else if (is_symlink) {
16432
0
        assert(mode_bits != S_IFLNK);
16433
0
        result = 0;
16434
0
    }
16435
104k
    else {
16436
104k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16437
#ifdef MS_WINDOWS
16438
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16439
        if (mode_bits == S_IFDIR)
16440
            result = dir_bits != 0;
16441
        else
16442
            result = dir_bits == 0;
16443
#else /* POSIX */
16444
104k
        if (mode_bits == S_IFDIR)
16445
104k
            result = self->d_type == DT_DIR;
16446
0
        else
16447
0
            result = self->d_type == DT_REG;
16448
104k
#endif
16449
104k
    }
16450
104k
#endif
16451
16452
104k
    return result;
16453
16454
0
error:
16455
0
    Py_XDECREF(st_mode);
16456
0
    Py_XDECREF(stat);
16457
0
    return -1;
16458
104k
}
16459
16460
/*[clinic input]
16461
os.DirEntry.is_dir -> bool
16462
    defining_class: defining_class
16463
    /
16464
    *
16465
    follow_symlinks: bool = True
16466
16467
Return True if the entry is a directory; cached per entry.
16468
[clinic start generated code]*/
16469
16470
static int
16471
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16472
                        int follow_symlinks)
16473
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16474
104k
{
16475
104k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16476
104k
}
16477
16478
/*[clinic input]
16479
os.DirEntry.is_file -> bool
16480
    defining_class: defining_class
16481
    /
16482
    *
16483
    follow_symlinks: bool = True
16484
16485
Return True if the entry is a file; cached per entry.
16486
[clinic start generated code]*/
16487
16488
static int
16489
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16490
                         int follow_symlinks)
16491
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16492
0
{
16493
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16494
0
}
16495
16496
/*[clinic input]
16497
os.DirEntry.inode
16498
16499
Return inode of the entry; cached per entry.
16500
[clinic start generated code]*/
16501
16502
static PyObject *
16503
os_DirEntry_inode_impl(DirEntry *self)
16504
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16505
0
{
16506
#ifdef MS_WINDOWS
16507
    if (!self->got_file_index) {
16508
        PyObject *unicode;
16509
        STRUCT_STAT stat;
16510
        int result;
16511
16512
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16513
            return NULL;
16514
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16515
        Py_DECREF(unicode);
16516
        result = LSTAT(path, &stat);
16517
16518
        int saved_errno = errno;
16519
        PyMem_Free(path);
16520
16521
        if (result != 0) {
16522
            errno = saved_errno;
16523
            return path_object_error(self->path);
16524
        }
16525
16526
        self->win32_file_index = stat.st_ino;
16527
        self->win32_file_index_high = stat.st_ino_high;
16528
        self->got_file_index = 1;
16529
    }
16530
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16531
#else /* POSIX */
16532
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16533
0
                  "DirEntry.d_ino is larger than unsigned long long");
16534
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16535
0
#endif
16536
0
}
16537
16538
static PyObject *
16539
DirEntry_repr(PyObject *op)
16540
0
{
16541
0
    DirEntry *self = DirEntry_CAST(op);
16542
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16543
0
}
16544
16545
/*[clinic input]
16546
os.DirEntry.__fspath__
16547
16548
Returns the path for the entry.
16549
[clinic start generated code]*/
16550
16551
static PyObject *
16552
os_DirEntry___fspath___impl(DirEntry *self)
16553
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16554
0
{
16555
0
    return Py_NewRef(self->path);
16556
0
}
16557
16558
static PyMemberDef DirEntry_members[] = {
16559
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16560
     "the entry's base filename, relative to scandir() \"path\" argument"},
16561
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16562
     "the entry's full path name; equivalent to\nos.path.join(scandir_path, entry.name)"},
16563
    {NULL}
16564
};
16565
16566
#include "clinic/posixmodule.c.h"
16567
16568
static PyMethodDef DirEntry_methods[] = {
16569
    OS_DIRENTRY_IS_DIR_METHODDEF
16570
    OS_DIRENTRY_IS_FILE_METHODDEF
16571
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16572
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16573
    OS_DIRENTRY_STAT_METHODDEF
16574
    OS_DIRENTRY_INODE_METHODDEF
16575
    OS_DIRENTRY___FSPATH___METHODDEF
16576
    {"__class_getitem__",       Py_GenericAlias,
16577
    METH_O|METH_CLASS,          PyDoc_STR("DirEntry is generic over the type of the path (str or bytes)")},
16578
    {NULL}
16579
};
16580
16581
static PyType_Slot DirEntryType_slots[] = {
16582
    {Py_tp_dealloc, DirEntry_dealloc},
16583
    {Py_tp_repr, DirEntry_repr},
16584
    {Py_tp_methods, DirEntry_methods},
16585
    {Py_tp_members, DirEntry_members},
16586
    {0, 0},
16587
};
16588
16589
static PyType_Spec DirEntryType_spec = {
16590
    .name = MODNAME ".DirEntry",
16591
    .basicsize = sizeof(DirEntry),
16592
    .flags = (
16593
        Py_TPFLAGS_DEFAULT
16594
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16595
        | Py_TPFLAGS_IMMUTABLETYPE
16596
    ),
16597
    .slots = DirEntryType_slots
16598
};
16599
16600
16601
#ifdef MS_WINDOWS
16602
16603
static int
16604
is_extended_path(const wchar_t *path)
16605
{
16606
    return wcsncmp(path, L"\\\\?\\", 4) == 0;
16607
}
16608
16609
static wchar_t *
16610
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,
16611
                    int normalize)
16612
{
16613
    Py_ssize_t path_len;
16614
    wchar_t *result;
16615
    wchar_t *path_allocated = NULL;
16616
16617
    if (!path_wide) { /* Default arg: "." */
16618
        path_wide = L".";
16619
        path_len = 1;
16620
    }
16621
    else {
16622
        path_len = wcslen(path_wide);
16623
    }
16624
16625
    if (path_len == 0) {
16626
        result = PyMem_New(wchar_t, 1);
16627
        if (result == NULL) {
16628
            PyErr_NoMemory();
16629
            return NULL;
16630
        }
16631
        result[0] = L'\0';
16632
        return result;
16633
    }
16634
16635
    if (normalize && !is_extended_path(path_wide)) {
16636
        int err = _PyOS_getfullpathname(path_wide, &path_allocated);
16637
        if (err < 0) {
16638
            PyErr_SetFromWindowsErr(0);
16639
            return NULL;
16640
        }
16641
        if (path_allocated == NULL) {
16642
            PyErr_NoMemory();
16643
            return NULL;
16644
        }
16645
        path_wide = path_allocated;
16646
        path_len = wcslen(path_wide);
16647
    }
16648
16649
    size_t size = (size_t)path_len + 1 + wcslen(filename) + 1;
16650
    result = PyMem_New(wchar_t, size);
16651
    if (result == NULL) {
16652
        PyMem_RawFree(path_allocated);
16653
        PyErr_NoMemory();
16654
        return NULL;
16655
    }
16656
    wcscpy(result, path_wide);
16657
    wchar_t ch = result[path_len - 1];
16658
    if (ch != SEP && ch != ALTSEP && ch != L':') {
16659
        result[path_len++] = SEP;
16660
    }
16661
    wcscpy(result + path_len, filename);
16662
    PyMem_RawFree(path_allocated);
16663
    return result;
16664
}
16665
16666
static PyObject *
16667
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16668
{
16669
    DirEntry *entry;
16670
    BY_HANDLE_FILE_INFORMATION file_info;
16671
    ULONG reparse_tag;
16672
    wchar_t *joined_path;
16673
16674
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16675
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16676
    if (!entry)
16677
        return NULL;
16678
    entry->name = NULL;
16679
    entry->path = NULL;
16680
    entry->stat = NULL;
16681
    entry->lstat = NULL;
16682
    entry->got_file_index = 0;
16683
16684
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16685
    if (!entry->name)
16686
        goto error;
16687
    int return_bytes = path->wide && PyBytes_Check(path->object);
16688
    if (return_bytes) {
16689
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16690
        if (!entry->name)
16691
            goto error;
16692
    }
16693
16694
    joined_path = join_path_filenameW(path->wide, dataW->cFileName, 0);
16695
    if (!joined_path)
16696
        goto error;
16697
16698
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16699
    PyMem_Free(joined_path);
16700
    if (!entry->path)
16701
        goto error;
16702
    if (return_bytes) {
16703
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16704
        if (!entry->path)
16705
            goto error;
16706
    }
16707
16708
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16709
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16710
16711
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16712
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16713
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16714
16715
    return (PyObject *)entry;
16716
16717
error:
16718
    Py_DECREF(entry);
16719
    return NULL;
16720
}
16721
16722
#else /* POSIX */
16723
16724
static char *
16725
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16726
0
{
16727
0
    Py_ssize_t path_len;
16728
0
    Py_ssize_t size;
16729
0
    char *result;
16730
16731
0
    if (!path_narrow) { /* Default arg: "." */
16732
0
        path_narrow = ".";
16733
0
        path_len = 1;
16734
0
    }
16735
0
    else {
16736
0
        path_len = strlen(path_narrow);
16737
0
    }
16738
16739
0
    if (filename_len == -1)
16740
0
        filename_len = strlen(filename);
16741
16742
    /* The +1's are for the path separator and the NUL */
16743
0
    size = path_len + 1 + filename_len + 1;
16744
0
    result = PyMem_New(char, size);
16745
0
    if (!result) {
16746
0
        PyErr_NoMemory();
16747
0
        return NULL;
16748
0
    }
16749
0
    strcpy(result, path_narrow);
16750
0
    if (path_len > 0 && result[path_len - 1] != '/')
16751
0
        result[path_len++] = '/';
16752
0
    strcpy(result + path_len, filename);
16753
0
    return result;
16754
0
}
16755
16756
static PyObject *
16757
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16758
                         Py_ssize_t name_len, ino_t d_ino
16759
#ifdef HAVE_DIRENT_D_TYPE
16760
                         , unsigned char d_type
16761
#endif
16762
                         )
16763
104k
{
16764
104k
    DirEntry *entry;
16765
104k
    char *joined_path;
16766
16767
104k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16768
104k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16769
104k
    if (!entry)
16770
0
        return NULL;
16771
104k
    entry->name = NULL;
16772
104k
    entry->path = NULL;
16773
104k
    entry->stat = NULL;
16774
104k
    entry->lstat = NULL;
16775
16776
104k
    if (path->is_fd) {
16777
104k
        entry->dir_fd = path->fd;
16778
104k
        joined_path = NULL;
16779
104k
    }
16780
0
    else {
16781
0
        entry->dir_fd = DEFAULT_DIR_FD;
16782
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16783
0
        if (!joined_path)
16784
0
            goto error;
16785
0
    }
16786
16787
104k
    if (!path->narrow || !PyBytes_Check(path->object)) {
16788
104k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16789
104k
        if (joined_path)
16790
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16791
104k
    }
16792
0
    else {
16793
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16794
0
        if (joined_path)
16795
0
            entry->path = PyBytes_FromString(joined_path);
16796
0
    }
16797
104k
    PyMem_Free(joined_path);
16798
104k
    if (!entry->name)
16799
0
        goto error;
16800
16801
104k
    if (path->is_fd) {
16802
104k
        entry->path = Py_NewRef(entry->name);
16803
104k
    }
16804
0
    else if (!entry->path)
16805
0
        goto error;
16806
16807
104k
#ifdef HAVE_DIRENT_D_TYPE
16808
104k
    entry->d_type = d_type;
16809
104k
#endif
16810
104k
    entry->d_ino = d_ino;
16811
16812
104k
    return (PyObject *)entry;
16813
16814
0
error:
16815
0
    Py_XDECREF(entry);
16816
0
    return NULL;
16817
104k
}
16818
16819
#endif
16820
16821
16822
typedef struct {
16823
    PyObject_HEAD
16824
    path_t path;
16825
#ifdef MS_WINDOWS
16826
    HANDLE handle;
16827
    WIN32_FIND_DATAW file_data;
16828
    int first_time;
16829
#else /* POSIX */
16830
    DIR *dirp;
16831
#endif
16832
#ifdef HAVE_FDOPENDIR
16833
    int fd;
16834
#endif
16835
} ScandirIterator;
16836
16837
378k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16838
16839
#ifdef MS_WINDOWS
16840
16841
static int
16842
ScandirIterator_is_closed(ScandirIterator *iterator)
16843
{
16844
    return iterator->handle == INVALID_HANDLE_VALUE;
16845
}
16846
16847
static void
16848
ScandirIterator_closedir(ScandirIterator *iterator)
16849
{
16850
    HANDLE handle = iterator->handle;
16851
16852
    if (handle == INVALID_HANDLE_VALUE)
16853
        return;
16854
16855
    iterator->handle = INVALID_HANDLE_VALUE;
16856
    Py_BEGIN_ALLOW_THREADS
16857
    FindClose(handle);
16858
    Py_END_ALLOW_THREADS
16859
}
16860
16861
static PyObject *
16862
ScandirIterator_iternext(PyObject *op)
16863
{
16864
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16865
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16866
    BOOL success;
16867
    PyObject *entry;
16868
16869
    /* Happens if the iterator is iterated twice, or closed explicitly */
16870
    if (iterator->handle == INVALID_HANDLE_VALUE)
16871
        return NULL;
16872
16873
    while (1) {
16874
        if (!iterator->first_time) {
16875
            Py_BEGIN_ALLOW_THREADS
16876
            success = FindNextFileW(iterator->handle, file_data);
16877
            Py_END_ALLOW_THREADS
16878
            if (!success) {
16879
                /* Error or no more files */
16880
                if (GetLastError() != ERROR_NO_MORE_FILES)
16881
                    path_error(&iterator->path);
16882
                break;
16883
            }
16884
        }
16885
        iterator->first_time = 0;
16886
16887
        /* Skip over . and .. */
16888
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16889
            wcscmp(file_data->cFileName, L"..") != 0)
16890
        {
16891
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16892
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16893
            if (!entry)
16894
                break;
16895
            return entry;
16896
        }
16897
16898
        /* Loop till we get a non-dot directory or finish iterating */
16899
    }
16900
16901
    /* Error or no more files */
16902
    ScandirIterator_closedir(iterator);
16903
    return NULL;
16904
}
16905
16906
#else /* POSIX */
16907
16908
static int
16909
ScandirIterator_is_closed(ScandirIterator *iterator)
16910
91.1k
{
16911
91.1k
    return !iterator->dirp;
16912
91.1k
}
16913
16914
static void
16915
ScandirIterator_closedir(ScandirIterator *iterator)
16916
182k
{
16917
182k
    DIR *dirp = iterator->dirp;
16918
16919
182k
    if (!dirp)
16920
91.1k
        return;
16921
16922
91.1k
    iterator->dirp = NULL;
16923
91.1k
    Py_BEGIN_ALLOW_THREADS
16924
91.1k
#ifdef HAVE_FDOPENDIR
16925
91.1k
    if (iterator->path.is_fd) {
16926
91.1k
        rewinddir(dirp);
16927
91.1k
    }
16928
91.1k
#endif
16929
91.1k
    closedir(dirp);
16930
91.1k
    Py_END_ALLOW_THREADS
16931
91.1k
    return;
16932
182k
}
16933
16934
static PyObject *
16935
ScandirIterator_iternext(PyObject *op)
16936
196k
{
16937
196k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16938
196k
    struct dirent *direntp;
16939
196k
    Py_ssize_t name_len;
16940
196k
    int is_dot;
16941
196k
    PyObject *entry;
16942
16943
    /* Happens if the iterator is iterated twice, or closed explicitly */
16944
196k
    if (!iterator->dirp)
16945
0
        return NULL;
16946
16947
378k
    while (1) {
16948
378k
        errno = 0;
16949
378k
        Py_BEGIN_ALLOW_THREADS
16950
378k
        direntp = readdir(iterator->dirp);
16951
378k
        Py_END_ALLOW_THREADS
16952
16953
378k
        if (!direntp) {
16954
            /* Error or no more files */
16955
91.1k
            if (errno != 0)
16956
0
                path_error(&iterator->path);
16957
91.1k
            break;
16958
91.1k
        }
16959
16960
        /* Skip over . and .. */
16961
287k
        name_len = NAMLEN(direntp);
16962
287k
        is_dot = direntp->d_name[0] == '.' &&
16963
183k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16964
287k
        if (!is_dot) {
16965
104k
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16966
104k
            entry = DirEntry_from_posix_info(module,
16967
104k
                                             &iterator->path, direntp->d_name,
16968
104k
                                             name_len, direntp->d_ino
16969
104k
#ifdef HAVE_DIRENT_D_TYPE
16970
104k
                                             , direntp->d_type
16971
104k
#endif
16972
104k
                                            );
16973
104k
            if (!entry)
16974
0
                break;
16975
104k
            return entry;
16976
104k
        }
16977
16978
        /* Loop till we get a non-dot directory or finish iterating */
16979
287k
    }
16980
16981
    /* Error or no more files */
16982
91.1k
    ScandirIterator_closedir(iterator);
16983
91.1k
    return NULL;
16984
196k
}
16985
16986
#endif
16987
16988
static PyObject *
16989
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16990
0
{
16991
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16992
0
    ScandirIterator_closedir(self);
16993
0
    Py_RETURN_NONE;
16994
0
}
16995
16996
static PyObject *
16997
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16998
91.1k
{
16999
91.1k
    return Py_NewRef(self);
17000
91.1k
}
17001
17002
static PyObject *
17003
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
17004
91.1k
{
17005
91.1k
    ScandirIterator *self = ScandirIterator_CAST(op);
17006
91.1k
    ScandirIterator_closedir(self);
17007
91.1k
    Py_RETURN_NONE;
17008
91.1k
}
17009
17010
static void
17011
ScandirIterator_finalize(PyObject *op)
17012
91.1k
{
17013
91.1k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
17014
    /* Save the current exception, if any. */
17015
91.1k
    PyObject *exc = PyErr_GetRaisedException();
17016
17017
91.1k
    if (!ScandirIterator_is_closed(iterator)) {
17018
0
        ScandirIterator_closedir(iterator);
17019
17020
0
        if (PyErr_ResourceWarning(op, 1,
17021
0
                                  "unclosed scandir iterator %R", iterator))
17022
0
        {
17023
            /* Spurious errors can appear at shutdown */
17024
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
17025
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
17026
0
                                       "scandir iterator %R", iterator);
17027
0
            }
17028
0
        }
17029
0
    }
17030
17031
91.1k
    path_cleanup(&iterator->path);
17032
17033
    /* Restore the saved exception. */
17034
91.1k
    PyErr_SetRaisedException(exc);
17035
91.1k
}
17036
17037
static void
17038
ScandirIterator_dealloc(PyObject *op)
17039
91.1k
{
17040
91.1k
    PyTypeObject *tp = Py_TYPE(op);
17041
91.1k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
17042
0
        return;
17043
17044
91.1k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
17045
91.1k
    free_func(op);
17046
91.1k
    Py_DECREF(tp);
17047
91.1k
}
17048
17049
static PyMethodDef ScandirIterator_methods[] = {
17050
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
17051
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
17052
    {"close", ScandirIterator_close, METH_NOARGS},
17053
    {NULL}
17054
};
17055
17056
static PyType_Slot ScandirIteratorType_slots[] = {
17057
    {Py_tp_dealloc, ScandirIterator_dealloc},
17058
    {Py_tp_finalize, ScandirIterator_finalize},
17059
    {Py_tp_iter, PyObject_SelfIter},
17060
    {Py_tp_iternext, ScandirIterator_iternext},
17061
    {Py_tp_methods, ScandirIterator_methods},
17062
    {0, 0},
17063
};
17064
17065
static PyType_Spec ScandirIteratorType_spec = {
17066
    .name = MODNAME ".ScandirIterator",
17067
    .basicsize = sizeof(ScandirIterator),
17068
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
17069
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
17070
    .flags = (
17071
        Py_TPFLAGS_DEFAULT
17072
        | Py_TPFLAGS_HAVE_FINALIZE
17073
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
17074
        | Py_TPFLAGS_IMMUTABLETYPE
17075
    ),
17076
    .slots = ScandirIteratorType_slots
17077
};
17078
17079
/*[clinic input]
17080
os.scandir
17081
17082
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
17083
17084
Return an iterator of DirEntry objects for given path.
17085
17086
path can be specified as either str, bytes, or a path-like object.  If
17087
path is bytes, the names of yielded DirEntry objects will also be bytes;
17088
in all other circumstances they will be str.
17089
17090
If path is None, uses the path='.'.
17091
[clinic start generated code]*/
17092
17093
static PyObject *
17094
os_scandir_impl(PyObject *module, path_t *path)
17095
/*[clinic end generated code: output=6eb2668b675ca89e input=6ab9600993f51577]*/
17096
91.1k
{
17097
91.1k
    ScandirIterator *iterator;
17098
#ifdef MS_WINDOWS
17099
    wchar_t *path_strW;
17100
#else
17101
91.1k
    const char *path_str;
17102
91.1k
#ifdef HAVE_FDOPENDIR
17103
91.1k
    int fd = -1;
17104
91.1k
#endif
17105
91.1k
#endif
17106
17107
91.1k
    if (PySys_Audit("os.scandir", "O",
17108
91.1k
                    path->object ? path->object : Py_None) < 0) {
17109
0
        return NULL;
17110
0
    }
17111
17112
91.1k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
17113
91.1k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
17114
91.1k
    if (!iterator)
17115
0
        return NULL;
17116
17117
#ifdef MS_WINDOWS
17118
    iterator->handle = INVALID_HANDLE_VALUE;
17119
#else
17120
91.1k
    iterator->dirp = NULL;
17121
91.1k
#endif
17122
17123
    /* Move the ownership to iterator->path */
17124
91.1k
    memcpy(&iterator->path, path, sizeof(path_t));
17125
91.1k
    memset(path, 0, sizeof(path_t));
17126
17127
#ifdef MS_WINDOWS
17128
    iterator->first_time = 1;
17129
17130
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*", 1);
17131
    if (!path_strW)
17132
        goto error;
17133
17134
    Py_BEGIN_ALLOW_THREADS
17135
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17136
    Py_END_ALLOW_THREADS
17137
17138
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17139
        path_error(&iterator->path);
17140
        PyMem_Free(path_strW);
17141
        goto error;
17142
    }
17143
    PyMem_Free(path_strW);
17144
#else /* POSIX */
17145
91.1k
    errno = 0;
17146
91.1k
#ifdef HAVE_FDOPENDIR
17147
91.1k
    if (iterator->path.is_fd) {
17148
91.1k
      if (HAVE_FDOPENDIR_RUNTIME) {
17149
        /* closedir() closes the FD, so we duplicate it */
17150
91.1k
        fd = _Py_dup(iterator->path.fd);
17151
91.1k
        if (fd == -1)
17152
0
            goto error;
17153
17154
91.1k
        Py_BEGIN_ALLOW_THREADS
17155
91.1k
        iterator->dirp = fdopendir(fd);
17156
91.1k
        Py_END_ALLOW_THREADS
17157
91.1k
      } else {
17158
0
        PyErr_SetString(PyExc_TypeError,
17159
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17160
0
        return NULL;
17161
0
      }
17162
91.1k
    }
17163
0
    else
17164
0
#endif
17165
0
    {
17166
0
        if (iterator->path.narrow)
17167
0
            path_str = iterator->path.narrow;
17168
0
        else
17169
0
            path_str = ".";
17170
17171
0
        Py_BEGIN_ALLOW_THREADS
17172
0
        iterator->dirp = opendir(path_str);
17173
0
        Py_END_ALLOW_THREADS
17174
0
    }
17175
17176
91.1k
    if (!iterator->dirp) {
17177
0
        path_error(&iterator->path);
17178
0
#ifdef HAVE_FDOPENDIR
17179
0
        if (fd != -1) {
17180
0
            Py_BEGIN_ALLOW_THREADS
17181
0
            close(fd);
17182
0
            Py_END_ALLOW_THREADS
17183
0
        }
17184
0
#endif
17185
0
        goto error;
17186
0
    }
17187
91.1k
#endif
17188
17189
91.1k
    return (PyObject *)iterator;
17190
17191
0
error:
17192
0
    Py_DECREF(iterator);
17193
0
    return NULL;
17194
91.1k
}
17195
17196
/*
17197
    Return the file system path representation of the object.
17198
17199
    If the object is str or bytes, then allow it to pass through with
17200
    an incremented refcount. If the object defines __fspath__(), then
17201
    return the result of that method. All other types raise a TypeError.
17202
*/
17203
PyObject *
17204
PyOS_FSPath(PyObject *path)
17205
1.00M
{
17206
    /* For error message reasons, this function is manually inlined in
17207
       path_converter(). */
17208
1.00M
    PyObject *func = NULL;
17209
1.00M
    PyObject *path_repr = NULL;
17210
17211
1.00M
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17212
1.00M
        return Py_NewRef(path);
17213
1.00M
    }
17214
17215
422
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17216
422
    if ((NULL == func) || (func == Py_None)) {
17217
0
        return PyErr_Format(PyExc_TypeError,
17218
0
                            "expected str, bytes or os.PathLike object, "
17219
0
                            "not %.200s",
17220
0
                            _PyType_Name(Py_TYPE(path)));
17221
0
    }
17222
17223
422
    path_repr = _PyObject_CallNoArgs(func);
17224
422
    Py_DECREF(func);
17225
422
    if (NULL == path_repr) {
17226
0
        return NULL;
17227
0
    }
17228
17229
422
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17230
0
        PyErr_Format(PyExc_TypeError,
17231
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17232
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17233
0
                     _PyType_Name(Py_TYPE(path_repr)));
17234
0
        Py_DECREF(path_repr);
17235
0
        return NULL;
17236
0
    }
17237
17238
422
    return path_repr;
17239
422
}
17240
17241
/*[clinic input]
17242
os.fspath
17243
17244
    path: object
17245
17246
Return the file system path representation of the object.
17247
17248
If the object is str or bytes, then allow it to pass through as-is.  If
17249
the object defines __fspath__(), then return the result of that method.
17250
All other types raise a TypeError.
17251
[clinic start generated code]*/
17252
17253
static PyObject *
17254
os_fspath_impl(PyObject *module, PyObject *path)
17255
/*[clinic end generated code: output=c3c3b78ecff2914f input=d3c54404240d5da0]*/
17256
675k
{
17257
675k
    return PyOS_FSPath(path);
17258
675k
}
17259
17260
#ifdef HAVE_GETRANDOM_SYSCALL
17261
/*[clinic input]
17262
os.getrandom
17263
17264
    size: Py_ssize_t
17265
    flags: int=0
17266
17267
Obtain a series of random bytes.
17268
[clinic start generated code]*/
17269
17270
static PyObject *
17271
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17272
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17273
0
{
17274
0
    if (size < 0) {
17275
0
        errno = EINVAL;
17276
0
        return posix_error();
17277
0
    }
17278
17279
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17280
0
    if (writer == NULL) {
17281
0
        return NULL;
17282
0
    }
17283
0
    void *data = PyBytesWriter_GetData(writer);
17284
17285
0
    Py_ssize_t n;
17286
0
    while (1) {
17287
0
        n = syscall(SYS_getrandom, data, size, flags);
17288
0
        if (n < 0 && errno == EINTR) {
17289
0
            if (PyErr_CheckSignals() < 0) {
17290
0
                goto error;
17291
0
            }
17292
17293
            /* getrandom() was interrupted by a signal: retry */
17294
0
            continue;
17295
0
        }
17296
0
        break;
17297
0
    }
17298
17299
0
    if (n < 0) {
17300
0
        PyErr_SetFromErrno(PyExc_OSError);
17301
0
        goto error;
17302
0
    }
17303
17304
0
    _Py_MSAN_UNPOISON(data, size);
17305
17306
0
    return PyBytesWriter_FinishWithSize(writer, n);
17307
17308
0
error:
17309
0
    PyBytesWriter_Discard(writer);
17310
0
    return NULL;
17311
0
}
17312
#endif   /* HAVE_GETRANDOM_SYSCALL */
17313
17314
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17315
17316
/* bpo-36085: Helper functions for managing DLL search directories
17317
 * on win32
17318
 */
17319
17320
/*[clinic input]
17321
os._add_dll_directory
17322
17323
    path: path_t
17324
17325
Add a path to the DLL search path.
17326
17327
This search path is used when resolving dependencies for imported
17328
extension modules (the module itself is resolved through sys.path),
17329
and also by ctypes.
17330
17331
Returns an opaque value that may be passed to os.remove_dll_directory
17332
to remove this directory from the search path.
17333
[clinic start generated code]*/
17334
17335
static PyObject *
17336
os__add_dll_directory_impl(PyObject *module, path_t *path)
17337
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17338
{
17339
    DLL_DIRECTORY_COOKIE cookie = 0;
17340
    DWORD err = 0;
17341
17342
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17343
        return NULL;
17344
    }
17345
17346
    Py_BEGIN_ALLOW_THREADS
17347
    if (!(cookie = AddDllDirectory(path->wide))) {
17348
        err = GetLastError();
17349
    }
17350
    Py_END_ALLOW_THREADS
17351
17352
    if (err) {
17353
        return win32_error_object_err("add_dll_directory",
17354
                                      path->object, err);
17355
    }
17356
17357
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17358
}
17359
17360
/*[clinic input]
17361
os._remove_dll_directory
17362
17363
    cookie: object
17364
17365
Removes a path from the DLL search path.
17366
17367
The parameter is an opaque value that was returned from
17368
os.add_dll_directory. You can only remove directories that you added
17369
yourself.
17370
[clinic start generated code]*/
17371
17372
static PyObject *
17373
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17374
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17375
{
17376
    DLL_DIRECTORY_COOKIE cookieValue;
17377
    DWORD err = 0;
17378
17379
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17380
        PyErr_SetString(PyExc_TypeError,
17381
            "Provided cookie was not returned from os.add_dll_directory");
17382
        return NULL;
17383
    }
17384
17385
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17386
        cookie, "DLL directory cookie");
17387
17388
    Py_BEGIN_ALLOW_THREADS
17389
    if (!RemoveDllDirectory(cookieValue)) {
17390
        err = GetLastError();
17391
    }
17392
    Py_END_ALLOW_THREADS
17393
17394
    if (err) {
17395
        return win32_error_object_err("remove_dll_directory",
17396
                                      NULL, err);
17397
    }
17398
17399
    if (PyCapsule_SetName(cookie, NULL)) {
17400
        return NULL;
17401
    }
17402
17403
    Py_RETURN_NONE;
17404
}
17405
17406
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17407
17408
17409
/* Only check if WIFEXITED is available: expect that it comes
17410
   with WEXITSTATUS, WIFSIGNALED, etc.
17411
17412
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17413
   subprocess can safely call it during late Python finalization without
17414
   risking that used os attributes were set to None by finalize_modules(). */
17415
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17416
/*[clinic input]
17417
os.waitstatus_to_exitcode
17418
17419
    status as status_obj: object
17420
17421
Convert a wait status to an exit code.
17422
17423
On Unix:
17424
17425
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17426
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17427
* Otherwise, raise a ValueError.
17428
17429
On Windows, return status shifted right by 8 bits.
17430
17431
On Unix, if the process is being traced or if waitpid() was called with
17432
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is
17433
true.  This function must not be called if WIFSTOPPED(status) is true.
17434
[clinic start generated code]*/
17435
17436
static PyObject *
17437
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17438
/*[clinic end generated code: output=db50b1b0ba3c7153 input=3b44a23f5090006c]*/
17439
0
{
17440
0
#ifndef MS_WINDOWS
17441
0
    int status = PyLong_AsInt(status_obj);
17442
0
    if (status == -1 && PyErr_Occurred()) {
17443
0
        return NULL;
17444
0
    }
17445
17446
0
    WAIT_TYPE wait_status;
17447
0
    WAIT_STATUS_INT(wait_status) = status;
17448
0
    int exitcode;
17449
0
    if (WIFEXITED(wait_status)) {
17450
0
        exitcode = WEXITSTATUS(wait_status);
17451
        /* Sanity check to provide warranty on the function behavior.
17452
           It should not occur in practice */
17453
0
        if (exitcode < 0) {
17454
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17455
0
            return NULL;
17456
0
        }
17457
0
    }
17458
0
    else if (WIFSIGNALED(wait_status)) {
17459
0
        int signum = WTERMSIG(wait_status);
17460
        /* Sanity check to provide warranty on the function behavior.
17461
           It should not occurs in practice */
17462
0
        if (signum <= 0) {
17463
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17464
0
            return NULL;
17465
0
        }
17466
0
        exitcode = -signum;
17467
0
    } else if (WIFSTOPPED(wait_status)) {
17468
        /* Status only received if the process is being traced
17469
           or if waitpid() was called with WUNTRACED option. */
17470
0
        int signum = WSTOPSIG(wait_status);
17471
0
        PyErr_Format(PyExc_ValueError,
17472
0
                     "process stopped by delivery of signal %i",
17473
0
                     signum);
17474
0
        return NULL;
17475
0
    }
17476
0
    else {
17477
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17478
0
        return NULL;
17479
0
    }
17480
0
    return PyLong_FromLong(exitcode);
17481
#else
17482
    /* Windows implementation: see os.waitpid() implementation
17483
       which uses _cwait(). */
17484
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17485
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17486
        return NULL;
17487
    }
17488
17489
    unsigned long long exitcode = (status >> 8);
17490
    /* ExitProcess() accepts an UINT type:
17491
       reject exit code which doesn't fit in an UINT */
17492
    if (exitcode > UINT_MAX) {
17493
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17494
        return NULL;
17495
    }
17496
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17497
#endif
17498
0
}
17499
#endif
17500
17501
#if defined(MS_WINDOWS)
17502
/*[clinic input]
17503
os._supports_virtual_terminal
17504
17505
Checks if virtual terminal is supported in windows
17506
[clinic start generated code]*/
17507
17508
static PyObject *
17509
os__supports_virtual_terminal_impl(PyObject *module)
17510
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17511
{
17512
#ifdef HAVE_WINDOWS_CONSOLE_IO
17513
    DWORD mode = 0;
17514
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17515
    if (!GetConsoleMode(handle, &mode)) {
17516
        Py_RETURN_FALSE;
17517
    }
17518
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17519
#else
17520
    Py_RETURN_FALSE;
17521
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17522
}
17523
#endif
17524
17525
/*[clinic input]
17526
os._inputhook
17527
17528
Calls PyOS_InputHook dropping the GIL first
17529
[clinic start generated code]*/
17530
17531
static PyObject *
17532
os__inputhook_impl(PyObject *module)
17533
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17534
0
{
17535
0
     int result = 0;
17536
0
     if (PyOS_InputHook) {
17537
0
         Py_BEGIN_ALLOW_THREADS;
17538
0
         result = PyOS_InputHook();
17539
0
         Py_END_ALLOW_THREADS;
17540
0
     }
17541
0
     return PyLong_FromLong(result);
17542
0
}
17543
17544
/*[clinic input]
17545
os._is_inputhook_installed
17546
17547
Checks if PyOS_InputHook is set
17548
[clinic start generated code]*/
17549
17550
static PyObject *
17551
os__is_inputhook_installed_impl(PyObject *module)
17552
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17553
0
{
17554
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17555
0
}
17556
17557
/*[clinic input]
17558
os._create_environ
17559
17560
Create the environment dictionary.
17561
[clinic start generated code]*/
17562
17563
static PyObject *
17564
os__create_environ_impl(PyObject *module)
17565
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17566
0
{
17567
0
    return convertenviron();
17568
0
}
17569
17570
17571
#ifdef __EMSCRIPTEN__
17572
/*[clinic input]
17573
os._emscripten_debugger
17574
17575
Create a breakpoint for the JavaScript debugger. Emscripten only.
17576
[clinic start generated code]*/
17577
17578
static PyObject *
17579
os__emscripten_debugger_impl(PyObject *module)
17580
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17581
{
17582
    emscripten_debugger();
17583
    Py_RETURN_NONE;
17584
}
17585
17586
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17587
    console.warn(UTF8ToString(arg));
17588
});
17589
17590
/*[clinic input]
17591
os._emscripten_log
17592
   arg: str
17593
17594
Log something to the JS console. Emscripten only.
17595
[clinic start generated code]*/
17596
17597
static PyObject *
17598
os__emscripten_log_impl(PyObject *module, const char *arg)
17599
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17600
{
17601
    emscripten_log_impl_js(arg);
17602
    Py_RETURN_NONE;
17603
}
17604
#endif /* __EMSCRIPTEN__ */
17605
17606
17607
static PyMethodDef posix_methods[] = {
17608
    OS_STAT_METHODDEF
17609
    OS_STATX_METHODDEF
17610
    OS_ACCESS_METHODDEF
17611
    OS_TTYNAME_METHODDEF
17612
    OS_CHDIR_METHODDEF
17613
    OS_CHFLAGS_METHODDEF
17614
    OS_CHMOD_METHODDEF
17615
    OS_FCHMOD_METHODDEF
17616
    OS_LCHMOD_METHODDEF
17617
    OS_CHOWN_METHODDEF
17618
    OS_FCHOWN_METHODDEF
17619
    OS_LCHOWN_METHODDEF
17620
    OS_LCHFLAGS_METHODDEF
17621
    OS_CHROOT_METHODDEF
17622
    OS_CTERMID_METHODDEF
17623
    OS_GETCWD_METHODDEF
17624
    OS_GETCWDB_METHODDEF
17625
    OS_LINK_METHODDEF
17626
    OS_LISTDIR_METHODDEF
17627
    OS_LISTDRIVES_METHODDEF
17628
    OS_LISTMOUNTS_METHODDEF
17629
    OS_LISTVOLUMES_METHODDEF
17630
    OS_LSTAT_METHODDEF
17631
    OS_MKDIR_METHODDEF
17632
    OS_NICE_METHODDEF
17633
    OS_GETPRIORITY_METHODDEF
17634
    OS_SETPRIORITY_METHODDEF
17635
    OS_POSIX_SPAWN_METHODDEF
17636
    OS_POSIX_SPAWNP_METHODDEF
17637
    OS_READLINK_METHODDEF
17638
    OS_COPY_FILE_RANGE_METHODDEF
17639
    OS_SPLICE_METHODDEF
17640
    OS_RENAME_METHODDEF
17641
    OS_REPLACE_METHODDEF
17642
    OS_RMDIR_METHODDEF
17643
    OS_SYMLINK_METHODDEF
17644
    OS_SYSTEM_METHODDEF
17645
    OS_UMASK_METHODDEF
17646
    OS_UNAME_METHODDEF
17647
    OS_UNLINK_METHODDEF
17648
    OS_REMOVE_METHODDEF
17649
    OS_UTIME_METHODDEF
17650
    OS_TIMES_METHODDEF
17651
    OS__EXIT_METHODDEF
17652
    OS__FCOPYFILE_METHODDEF
17653
    OS_EXECV_METHODDEF
17654
    OS_EXECVE_METHODDEF
17655
    OS_SPAWNV_METHODDEF
17656
    OS_SPAWNVE_METHODDEF
17657
    OS_FORK1_METHODDEF
17658
    OS_FORK_METHODDEF
17659
    OS_REGISTER_AT_FORK_METHODDEF
17660
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17661
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17662
    OS_SCHED_GETPARAM_METHODDEF
17663
    OS_SCHED_GETSCHEDULER_METHODDEF
17664
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17665
    OS_SCHED_SETPARAM_METHODDEF
17666
    OS_SCHED_SETSCHEDULER_METHODDEF
17667
    OS_SCHED_YIELD_METHODDEF
17668
    OS_SCHED_SETAFFINITY_METHODDEF
17669
    OS_SCHED_GETAFFINITY_METHODDEF
17670
    OS_POSIX_OPENPT_METHODDEF
17671
    OS_GRANTPT_METHODDEF
17672
    OS_UNLOCKPT_METHODDEF
17673
    OS_PTSNAME_METHODDEF
17674
    OS_OPENPTY_METHODDEF
17675
    OS_LOGIN_TTY_METHODDEF
17676
    OS_FORKPTY_METHODDEF
17677
    OS_GETEGID_METHODDEF
17678
    OS_GETEUID_METHODDEF
17679
    OS_GETGID_METHODDEF
17680
    OS_GETGROUPLIST_METHODDEF
17681
    OS_GETGROUPS_METHODDEF
17682
    OS_GETPID_METHODDEF
17683
    OS_GETPGRP_METHODDEF
17684
    OS_GETPPID_METHODDEF
17685
    OS_GETUID_METHODDEF
17686
    OS_GETLOGIN_METHODDEF
17687
    OS_KILL_METHODDEF
17688
    OS_KILLPG_METHODDEF
17689
    OS_PLOCK_METHODDEF
17690
    OS_STARTFILE_METHODDEF
17691
    OS_SETUID_METHODDEF
17692
    OS_SETEUID_METHODDEF
17693
    OS_SETREUID_METHODDEF
17694
    OS_SETGID_METHODDEF
17695
    OS_SETEGID_METHODDEF
17696
    OS_SETREGID_METHODDEF
17697
    OS_SETGROUPS_METHODDEF
17698
    OS_INITGROUPS_METHODDEF
17699
    OS_GETPGID_METHODDEF
17700
    OS_SETPGRP_METHODDEF
17701
    OS_WAIT_METHODDEF
17702
    OS_WAIT3_METHODDEF
17703
    OS_WAIT4_METHODDEF
17704
    OS_WAITID_METHODDEF
17705
    OS_WAITPID_METHODDEF
17706
    OS_PIDFD_OPEN_METHODDEF
17707
    OS_PIDFD_GETFD_METHODDEF
17708
    OS_GETSID_METHODDEF
17709
    OS_SETSID_METHODDEF
17710
    OS_SETPGID_METHODDEF
17711
    OS_TCGETPGRP_METHODDEF
17712
    OS_TCSETPGRP_METHODDEF
17713
    OS_OPEN_METHODDEF
17714
    OS_CLOSE_METHODDEF
17715
    OS_CLOSERANGE_METHODDEF
17716
    OS_DEVICE_ENCODING_METHODDEF
17717
    OS_DUP_METHODDEF
17718
    OS_DUP2_METHODDEF
17719
    OS_LOCKF_METHODDEF
17720
    OS_LSEEK_METHODDEF
17721
    OS_READ_METHODDEF
17722
    OS_READINTO_METHODDEF
17723
    OS_READV_METHODDEF
17724
    OS_PREAD_METHODDEF
17725
    OS_PREADV_METHODDEF
17726
    OS_WRITE_METHODDEF
17727
    OS_WRITEV_METHODDEF
17728
    OS_PWRITE_METHODDEF
17729
    OS_PWRITEV_METHODDEF
17730
    OS_SENDFILE_METHODDEF
17731
    OS_FSTAT_METHODDEF
17732
    OS_ISATTY_METHODDEF
17733
    OS_PIPE_METHODDEF
17734
    OS_PIPE2_METHODDEF
17735
    OS_MKFIFO_METHODDEF
17736
    OS_MKNOD_METHODDEF
17737
    OS_MAJOR_METHODDEF
17738
    OS_MINOR_METHODDEF
17739
    OS_MAKEDEV_METHODDEF
17740
    OS_FTRUNCATE_METHODDEF
17741
    OS_TRUNCATE_METHODDEF
17742
    OS_POSIX_FALLOCATE_METHODDEF
17743
    OS_POSIX_FADVISE_METHODDEF
17744
    OS_PUTENV_METHODDEF
17745
    OS_UNSETENV_METHODDEF
17746
    OS__CLEARENV_METHODDEF
17747
    OS_STRERROR_METHODDEF
17748
    OS_FCHDIR_METHODDEF
17749
    OS_FSYNC_METHODDEF
17750
    OS_SYNC_METHODDEF
17751
    OS_FDATASYNC_METHODDEF
17752
    OS_WCOREDUMP_METHODDEF
17753
    OS_WIFCONTINUED_METHODDEF
17754
    OS_WIFSTOPPED_METHODDEF
17755
    OS_WIFSIGNALED_METHODDEF
17756
    OS_WIFEXITED_METHODDEF
17757
    OS_WEXITSTATUS_METHODDEF
17758
    OS_WTERMSIG_METHODDEF
17759
    OS_WSTOPSIG_METHODDEF
17760
    OS_FSTATVFS_METHODDEF
17761
    OS_STATVFS_METHODDEF
17762
    OS_CONFSTR_METHODDEF
17763
    OS_SYSCONF_METHODDEF
17764
    OS_FPATHCONF_METHODDEF
17765
    OS_PATHCONF_METHODDEF
17766
    OS_ABORT_METHODDEF
17767
    OS__GETFULLPATHNAME_METHODDEF
17768
    OS__GETDISKUSAGE_METHODDEF
17769
    OS__GETFINALPATHNAME_METHODDEF
17770
    OS__FINDFIRSTFILE_METHODDEF
17771
    OS__GETVOLUMEPATHNAME_METHODDEF
17772
    OS__PATH_SPLITROOT_METHODDEF
17773
    OS__PATH_SPLITROOT_EX_METHODDEF
17774
    OS__PATH_NORMPATH_METHODDEF
17775
    OS_GETLOADAVG_METHODDEF
17776
    OS_URANDOM_METHODDEF
17777
    OS_SETRESUID_METHODDEF
17778
    OS_SETRESGID_METHODDEF
17779
    OS_GETRESUID_METHODDEF
17780
    OS_GETRESGID_METHODDEF
17781
17782
    OS_GETXATTR_METHODDEF
17783
    OS_SETXATTR_METHODDEF
17784
    OS_REMOVEXATTR_METHODDEF
17785
    OS_LISTXATTR_METHODDEF
17786
17787
    OS_GET_TERMINAL_SIZE_METHODDEF
17788
    OS_CPU_COUNT_METHODDEF
17789
    OS_GET_INHERITABLE_METHODDEF
17790
    OS_SET_INHERITABLE_METHODDEF
17791
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17792
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17793
    OS_GET_BLOCKING_METHODDEF
17794
    OS_SET_BLOCKING_METHODDEF
17795
    OS_SCANDIR_METHODDEF
17796
    OS_FSPATH_METHODDEF
17797
    OS_GETRANDOM_METHODDEF
17798
    OS_MEMFD_CREATE_METHODDEF
17799
    OS_EVENTFD_METHODDEF
17800
    OS_EVENTFD_READ_METHODDEF
17801
    OS_EVENTFD_WRITE_METHODDEF
17802
    OS__ADD_DLL_DIRECTORY_METHODDEF
17803
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17804
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17805
    OS_SETNS_METHODDEF
17806
    OS_UNSHARE_METHODDEF
17807
    OS_TIMERFD_CREATE_METHODDEF
17808
    OS_TIMERFD_SETTIME_METHODDEF
17809
    OS_TIMERFD_SETTIME_NS_METHODDEF
17810
    OS_TIMERFD_GETTIME_METHODDEF
17811
    OS_TIMERFD_GETTIME_NS_METHODDEF
17812
17813
    OS__PATH_ISDEVDRIVE_METHODDEF
17814
    OS__PATH_ISDIR_METHODDEF
17815
    OS__PATH_ISFILE_METHODDEF
17816
    OS__PATH_ISLINK_METHODDEF
17817
    OS__PATH_ISJUNCTION_METHODDEF
17818
    OS__PATH_EXISTS_METHODDEF
17819
    OS__PATH_LEXISTS_METHODDEF
17820
17821
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17822
    OS__INPUTHOOK_METHODDEF
17823
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17824
    OS__CREATE_ENVIRON_METHODDEF
17825
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17826
    OS__EMSCRIPTEN_LOG_METHODDEF
17827
    {NULL,              NULL}            /* Sentinel */
17828
};
17829
17830
static int
17831
all_ins(PyObject *m)
17832
36
{
17833
36
#ifdef F_OK
17834
36
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17835
36
#endif
17836
36
#ifdef R_OK
17837
36
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17838
36
#endif
17839
36
#ifdef W_OK
17840
36
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17841
36
#endif
17842
36
#ifdef X_OK
17843
36
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17844
36
#endif
17845
36
#ifdef NGROUPS_MAX
17846
36
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17847
36
#endif
17848
36
#ifdef TMP_MAX
17849
36
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17850
36
#endif
17851
36
#ifdef WCONTINUED
17852
36
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17853
36
#endif
17854
36
#ifdef WNOHANG
17855
36
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17856
36
#endif
17857
36
#ifdef WUNTRACED
17858
36
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17859
36
#endif
17860
36
#ifdef O_RDONLY
17861
36
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17862
36
#endif
17863
36
#ifdef O_WRONLY
17864
36
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17865
36
#endif
17866
36
#ifdef O_RDWR
17867
36
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17868
36
#endif
17869
36
#ifdef O_NDELAY
17870
36
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17871
36
#endif
17872
36
#ifdef O_NONBLOCK
17873
36
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17874
36
#endif
17875
36
#ifdef O_APPEND
17876
36
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17877
36
#endif
17878
36
#ifdef O_DSYNC
17879
36
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17880
36
#endif
17881
36
#ifdef O_RSYNC
17882
36
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17883
36
#endif
17884
36
#ifdef O_SYNC
17885
36
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17886
36
#endif
17887
36
#ifdef O_NOCTTY
17888
36
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17889
36
#endif
17890
36
#ifdef O_CREAT
17891
36
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17892
36
#endif
17893
36
#ifdef O_EXCL
17894
36
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17895
36
#endif
17896
36
#ifdef O_TRUNC
17897
36
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17898
36
#endif
17899
#ifdef O_BINARY
17900
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17901
#endif
17902
#ifdef O_TEXT
17903
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17904
#endif
17905
#ifdef O_XATTR
17906
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17907
#endif
17908
36
#ifdef O_LARGEFILE
17909
36
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17910
36
#endif
17911
36
#ifndef __GNU__
17912
#ifdef O_SHLOCK
17913
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17914
#endif
17915
#ifdef O_EXLOCK
17916
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17917
#endif
17918
36
#endif
17919
#ifdef O_EXEC
17920
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17921
#endif
17922
#ifdef O_SEARCH
17923
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17924
#endif
17925
36
#ifdef O_PATH
17926
36
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17927
36
#endif
17928
#ifdef O_TTY_INIT
17929
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17930
#endif
17931
36
#ifdef O_TMPFILE
17932
36
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17933
36
#endif
17934
36
#ifdef PRIO_PROCESS
17935
36
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17936
36
#endif
17937
36
#ifdef PRIO_PGRP
17938
36
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17939
36
#endif
17940
36
#ifdef PRIO_USER
17941
36
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17942
36
#endif
17943
#ifdef PRIO_DARWIN_THREAD
17944
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17945
#endif
17946
#ifdef PRIO_DARWIN_PROCESS
17947
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17948
#endif
17949
#ifdef PRIO_DARWIN_BG
17950
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17951
#endif
17952
#ifdef PRIO_DARWIN_NONUI
17953
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17954
#endif
17955
36
#ifdef O_CLOEXEC
17956
36
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17957
36
#endif
17958
36
#ifdef O_ACCMODE
17959
36
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17960
36
#endif
17961
#ifdef O_EVTONLY
17962
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17963
#endif
17964
36
#ifdef O_FSYNC
17965
36
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17966
36
#endif
17967
#ifdef O_SYMLINK
17968
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17969
#endif
17970
17971
36
#ifdef SEEK_HOLE
17972
36
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17973
36
#endif
17974
36
#ifdef SEEK_DATA
17975
36
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17976
36
#endif
17977
17978
/* MS Windows */
17979
#ifdef O_NOINHERIT
17980
    /* Don't inherit in child processes. */
17981
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17982
#endif
17983
#ifdef _O_SHORT_LIVED
17984
    /* Optimize for short life (keep in memory). */
17985
    /* MS forgot to define this one with a non-underscore form too. */
17986
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17987
#endif
17988
#ifdef O_TEMPORARY
17989
    /* Automatically delete when last handle is closed. */
17990
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17991
#endif
17992
#ifdef O_RANDOM
17993
    /* Optimize for random access. */
17994
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17995
#endif
17996
#ifdef O_SEQUENTIAL
17997
    /* Optimize for sequential access. */
17998
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17999
#endif
18000
18001
/* GNU extensions. */
18002
36
#ifdef O_ASYNC
18003
    /* Send a SIGIO signal whenever input or output
18004
       becomes available on file descriptor */
18005
36
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
18006
36
#endif
18007
36
#ifdef O_DIRECT
18008
    /* Direct disk access. */
18009
36
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
18010
36
#endif
18011
36
#ifdef O_DIRECTORY
18012
    /* Must be a directory.      */
18013
36
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
18014
36
#endif
18015
36
#ifdef O_NOFOLLOW
18016
    /* Do not follow links.      */
18017
36
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
18018
36
#endif
18019
#ifdef O_NOFOLLOW_ANY
18020
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
18021
#endif
18022
#ifdef O_NOLINKS
18023
    /* Fails if link count of the named file is greater than 1 */
18024
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
18025
#endif
18026
36
#ifdef O_NOATIME
18027
    /* Do not update the access time. */
18028
36
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
18029
36
#endif
18030
18031
    /* These come from sysexits.h */
18032
36
#ifdef EX_OK
18033
36
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
18034
36
#endif /* EX_OK */
18035
36
#ifdef EX_USAGE
18036
36
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
18037
36
#endif /* EX_USAGE */
18038
36
#ifdef EX_DATAERR
18039
36
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
18040
36
#endif /* EX_DATAERR */
18041
36
#ifdef EX_NOINPUT
18042
36
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
18043
36
#endif /* EX_NOINPUT */
18044
36
#ifdef EX_NOUSER
18045
36
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
18046
36
#endif /* EX_NOUSER */
18047
36
#ifdef EX_NOHOST
18048
36
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
18049
36
#endif /* EX_NOHOST */
18050
36
#ifdef EX_UNAVAILABLE
18051
36
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
18052
36
#endif /* EX_UNAVAILABLE */
18053
36
#ifdef EX_SOFTWARE
18054
36
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
18055
36
#endif /* EX_SOFTWARE */
18056
36
#ifdef EX_OSERR
18057
36
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
18058
36
#endif /* EX_OSERR */
18059
36
#ifdef EX_OSFILE
18060
36
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
18061
36
#endif /* EX_OSFILE */
18062
36
#ifdef EX_CANTCREAT
18063
36
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
18064
36
#endif /* EX_CANTCREAT */
18065
36
#ifdef EX_IOERR
18066
36
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
18067
36
#endif /* EX_IOERR */
18068
36
#ifdef EX_TEMPFAIL
18069
36
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
18070
36
#endif /* EX_TEMPFAIL */
18071
36
#ifdef EX_PROTOCOL
18072
36
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
18073
36
#endif /* EX_PROTOCOL */
18074
36
#ifdef EX_NOPERM
18075
36
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
18076
36
#endif /* EX_NOPERM */
18077
36
#ifdef EX_CONFIG
18078
36
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
18079
36
#endif /* EX_CONFIG */
18080
#ifdef EX_NOTFOUND
18081
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
18082
#endif /* EX_NOTFOUND */
18083
18084
    /* statvfs */
18085
36
#ifdef ST_RDONLY
18086
36
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
18087
36
#endif /* ST_RDONLY */
18088
36
#ifdef ST_NOSUID
18089
36
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
18090
36
#endif /* ST_NOSUID */
18091
18092
       /* GNU extensions */
18093
36
#ifdef ST_NODEV
18094
36
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
18095
36
#endif /* ST_NODEV */
18096
36
#ifdef ST_NOEXEC
18097
36
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
18098
36
#endif /* ST_NOEXEC */
18099
36
#ifdef ST_SYNCHRONOUS
18100
36
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
18101
36
#endif /* ST_SYNCHRONOUS */
18102
36
#ifdef ST_MANDLOCK
18103
36
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
18104
36
#endif /* ST_MANDLOCK */
18105
36
#ifdef ST_WRITE
18106
36
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
18107
36
#endif /* ST_WRITE */
18108
36
#ifdef ST_APPEND
18109
36
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
18110
36
#endif /* ST_APPEND */
18111
36
#ifdef ST_NOATIME
18112
36
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
18113
36
#endif /* ST_NOATIME */
18114
36
#ifdef ST_NODIRATIME
18115
36
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
18116
36
#endif /* ST_NODIRATIME */
18117
36
#ifdef ST_RELATIME
18118
36
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18119
36
#endif /* ST_RELATIME */
18120
18121
    /* FreeBSD sendfile() constants */
18122
#ifdef SF_NODISKIO
18123
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18124
#endif
18125
    /* is obsolete since the 11.x release */
18126
#ifdef SF_MNOWAIT
18127
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18128
#endif
18129
#ifdef SF_SYNC
18130
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18131
#endif
18132
#ifdef SF_NOCACHE
18133
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18134
#endif
18135
18136
36
#ifdef TFD_NONBLOCK
18137
36
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18138
36
#endif
18139
36
#ifdef TFD_CLOEXEC
18140
36
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18141
36
#endif
18142
36
#ifdef TFD_TIMER_ABSTIME
18143
36
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18144
36
#endif
18145
36
#ifdef TFD_TIMER_CANCEL_ON_SET
18146
36
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18147
36
#endif
18148
18149
    /* constants for posix_fadvise */
18150
36
#ifdef POSIX_FADV_NORMAL
18151
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18152
36
#endif
18153
36
#ifdef POSIX_FADV_SEQUENTIAL
18154
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18155
36
#endif
18156
36
#ifdef POSIX_FADV_RANDOM
18157
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18158
36
#endif
18159
36
#ifdef POSIX_FADV_NOREUSE
18160
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18161
36
#endif
18162
36
#ifdef POSIX_FADV_WILLNEED
18163
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18164
36
#endif
18165
36
#ifdef POSIX_FADV_DONTNEED
18166
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18167
36
#endif
18168
18169
    /* constants for waitid */
18170
36
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18171
36
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18172
36
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18173
36
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18174
36
#ifdef P_PIDFD
18175
36
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18176
36
#endif
18177
#ifdef PIDFD_NONBLOCK
18178
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18179
#endif
18180
36
#endif
18181
36
#ifdef WEXITED
18182
36
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18183
36
#endif
18184
36
#ifdef WNOWAIT
18185
36
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18186
36
#endif
18187
36
#ifdef WSTOPPED
18188
36
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18189
36
#endif
18190
36
#ifdef CLD_EXITED
18191
36
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18192
36
#endif
18193
36
#ifdef CLD_KILLED
18194
36
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18195
36
#endif
18196
36
#ifdef CLD_DUMPED
18197
36
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18198
36
#endif
18199
36
#ifdef CLD_TRAPPED
18200
36
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18201
36
#endif
18202
36
#ifdef CLD_STOPPED
18203
36
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18204
36
#endif
18205
36
#ifdef CLD_CONTINUED
18206
36
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18207
36
#endif
18208
18209
    /* constants for lockf */
18210
36
#ifdef F_LOCK
18211
36
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18212
36
#endif
18213
36
#ifdef F_TLOCK
18214
36
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18215
36
#endif
18216
36
#ifdef F_ULOCK
18217
36
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18218
36
#endif
18219
36
#ifdef F_TEST
18220
36
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18221
36
#endif
18222
18223
36
#ifdef RWF_DSYNC
18224
36
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18225
36
#endif
18226
36
#ifdef RWF_HIPRI
18227
36
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18228
36
#endif
18229
36
#ifdef RWF_SYNC
18230
36
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18231
36
#endif
18232
36
#ifdef RWF_NOWAIT
18233
36
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18234
36
#endif
18235
#ifdef RWF_DONTCACHE
18236
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18237
#endif
18238
#ifdef RWF_ATOMIC
18239
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18240
#endif
18241
36
#ifdef RWF_APPEND
18242
36
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18243
36
#endif
18244
18245
/* constants for splice */
18246
36
#if defined(HAVE_SPLICE) && defined(__linux__)
18247
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18248
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18249
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18250
36
#endif
18251
18252
/* constants for posix_spawn */
18253
36
#ifdef HAVE_POSIX_SPAWN
18254
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18255
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18256
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18257
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18258
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18259
#endif
18260
36
#endif
18261
18262
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18263
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18264
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18265
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18266
#endif
18267
#ifdef HAVE_SPAWNV
18268
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18269
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18270
#endif
18271
18272
36
#ifdef HAVE_SCHED_H
18273
36
#ifdef SCHED_OTHER
18274
36
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18275
36
#endif
18276
36
#ifdef SCHED_DEADLINE
18277
36
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18278
36
#endif
18279
36
#ifdef SCHED_FIFO
18280
36
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18281
36
#endif
18282
36
#ifdef SCHED_NORMAL
18283
36
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18284
36
#endif
18285
36
#ifdef SCHED_RR
18286
36
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18287
36
#endif
18288
#ifdef SCHED_SPORADIC
18289
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18290
#endif
18291
36
#ifdef SCHED_BATCH
18292
36
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18293
36
#endif
18294
36
#ifdef SCHED_IDLE
18295
36
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18296
36
#endif
18297
36
#ifdef SCHED_RESET_ON_FORK
18298
36
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18299
36
#endif
18300
#ifdef SCHED_SYS
18301
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18302
#endif
18303
#ifdef SCHED_IA
18304
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18305
#endif
18306
#ifdef SCHED_FSS
18307
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18308
#endif
18309
#ifdef SCHED_FX
18310
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18311
#endif
18312
18313
/* constants for namespaces */
18314
36
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18315
36
#ifdef CLONE_FS
18316
36
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18317
36
#endif
18318
36
#ifdef CLONE_FILES
18319
36
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18320
36
#endif
18321
36
#ifdef CLONE_NEWNS
18322
36
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18323
36
#endif
18324
36
#ifdef CLONE_NEWCGROUP
18325
36
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18326
36
#endif
18327
36
#ifdef CLONE_NEWUTS
18328
36
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18329
36
#endif
18330
36
#ifdef CLONE_NEWIPC
18331
36
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18332
36
#endif
18333
36
#ifdef CLONE_NEWUSER
18334
36
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18335
36
#endif
18336
36
#ifdef CLONE_NEWPID
18337
36
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18338
36
#endif
18339
36
#ifdef CLONE_NEWNET
18340
36
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18341
36
#endif
18342
#ifdef CLONE_NEWTIME
18343
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18344
#endif
18345
36
#ifdef CLONE_SYSVSEM
18346
36
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18347
36
#endif
18348
36
#ifdef CLONE_THREAD
18349
36
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18350
36
#endif
18351
36
#ifdef CLONE_SIGHAND
18352
36
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18353
36
#endif
18354
36
#ifdef CLONE_VM
18355
36
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18356
36
#endif
18357
36
#endif
18358
18359
36
#endif
18360
18361
36
#ifdef USE_XATTRS
18362
36
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18363
36
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18364
36
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18365
36
#endif
18366
18367
36
#if HAVE_DECL_RTLD_LAZY
18368
36
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18369
36
#endif
18370
36
#if HAVE_DECL_RTLD_NOW
18371
36
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18372
36
#endif
18373
36
#if HAVE_DECL_RTLD_GLOBAL
18374
36
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18375
36
#endif
18376
36
#if HAVE_DECL_RTLD_LOCAL
18377
36
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18378
36
#endif
18379
36
#if HAVE_DECL_RTLD_NODELETE
18380
36
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18381
36
#endif
18382
36
#if HAVE_DECL_RTLD_NOLOAD
18383
36
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18384
36
#endif
18385
36
#if HAVE_DECL_RTLD_DEEPBIND
18386
36
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18387
36
#endif
18388
#if HAVE_DECL_RTLD_MEMBER
18389
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18390
#endif
18391
18392
36
#ifdef HAVE_GETRANDOM_SYSCALL
18393
36
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18394
36
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18395
36
#endif
18396
36
#ifdef HAVE_MEMFD_CREATE
18397
36
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18398
36
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18399
36
#ifdef MFD_HUGETLB
18400
36
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18401
36
#endif
18402
36
#ifdef MFD_HUGE_SHIFT
18403
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18404
36
#endif
18405
36
#ifdef MFD_HUGE_MASK
18406
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18407
36
#endif
18408
36
#ifdef MFD_HUGE_64KB
18409
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18410
36
#endif
18411
36
#ifdef MFD_HUGE_512KB
18412
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18413
36
#endif
18414
36
#ifdef MFD_HUGE_1MB
18415
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18416
36
#endif
18417
36
#ifdef MFD_HUGE_2MB
18418
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18419
36
#endif
18420
36
#ifdef MFD_HUGE_8MB
18421
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18422
36
#endif
18423
36
#ifdef MFD_HUGE_16MB
18424
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18425
36
#endif
18426
36
#ifdef MFD_HUGE_32MB
18427
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18428
36
#endif
18429
36
#ifdef MFD_HUGE_256MB
18430
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18431
36
#endif
18432
36
#ifdef MFD_HUGE_512MB
18433
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18434
36
#endif
18435
36
#ifdef MFD_HUGE_1GB
18436
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18437
36
#endif
18438
36
#ifdef MFD_HUGE_2GB
18439
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18440
36
#endif
18441
36
#ifdef MFD_HUGE_16GB
18442
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18443
36
#endif
18444
36
#endif /* HAVE_MEMFD_CREATE */
18445
18446
36
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18447
36
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18448
36
#ifdef EFD_NONBLOCK
18449
36
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18450
36
#endif
18451
36
#ifdef EFD_SEMAPHORE
18452
36
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18453
36
#endif
18454
36
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18455
18456
36
#ifdef NODEV
18457
36
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18458
36
#endif
18459
18460
36
#ifdef AT_NO_AUTOMOUNT
18461
36
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18462
36
#endif
18463
18464
36
#ifdef HAVE_STATX
18465
36
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18466
36
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18467
36
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18468
36
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18469
36
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18470
36
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18471
36
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18472
36
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18473
36
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18474
36
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18475
36
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18476
36
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18477
36
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18478
#ifdef STATX_MNT_ID
18479
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18480
#endif
18481
#ifdef STATX_DIOALIGN
18482
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18483
#endif
18484
#ifdef STATX_MNT_ID_UNIQUE
18485
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18486
#endif
18487
#ifdef STATX_SUBVOL
18488
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18489
#endif
18490
#ifdef STATX_WRITE_ATOMIC
18491
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18492
#endif
18493
#ifdef STATX_DIO_READ_ALIGN
18494
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18495
#endif
18496
    /* STATX_ALL intentionally omitted because it is deprecated */
18497
36
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18498
36
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18499
36
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18500
    /* STATX_ATTR_* constants are in the stat module */
18501
36
#endif /* HAVE_STATX */
18502
18503
#if defined(__APPLE__)
18504
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18505
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18506
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18507
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18508
#endif
18509
18510
#ifdef MS_WINDOWS
18511
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18512
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18513
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18514
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18515
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18516
#endif
18517
18518
36
    return 0;
18519
36
}
18520
18521
18522
18523
#define PROBE(name, test) \
18524
   static int name(void)  \
18525
612
   {                      \
18526
612
      if (test) {        \
18527
612
          return 1;       \
18528
612
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
612
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_futimens
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_linkat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_openat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_renameat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18525
36
   {                      \
18526
36
      if (test) {        \
18527
36
          return 1;       \
18528
36
      } else {            \
18529
0
          return 0;       \
18530
0
      }                   \
18531
36
   }
18532
18533
#ifdef HAVE_FSTATAT
18534
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18535
#endif
18536
18537
#ifdef HAVE_FACCESSAT
18538
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18539
#endif
18540
18541
#ifdef HAVE_FCHMODAT
18542
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18543
#endif
18544
18545
#ifdef HAVE_FCHOWNAT
18546
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18547
#endif
18548
18549
#ifdef HAVE_LINKAT
18550
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18551
#endif
18552
18553
#ifdef HAVE_FDOPENDIR
18554
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18555
#endif
18556
18557
#ifdef HAVE_MKDIRAT
18558
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18559
#endif
18560
18561
#ifdef HAVE_MKFIFOAT
18562
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18563
#endif
18564
18565
#ifdef HAVE_MKNODAT
18566
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18567
#endif
18568
18569
#ifdef HAVE_RENAMEAT
18570
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18571
#endif
18572
18573
#ifdef HAVE_UNLINKAT
18574
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18575
#endif
18576
18577
#ifdef HAVE_OPENAT
18578
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18579
#endif
18580
18581
#ifdef HAVE_READLINKAT
18582
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18583
#endif
18584
18585
#ifdef HAVE_SYMLINKAT
18586
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18587
#endif
18588
18589
#ifdef HAVE_FUTIMENS
18590
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18591
#endif
18592
18593
#ifdef HAVE_UTIMENSAT
18594
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18595
#endif
18596
18597
#ifdef HAVE_PTSNAME_R
18598
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18599
#endif
18600
18601
18602
18603
static const struct have_function {
18604
    const char * const label;
18605
    int (*probe)(void);
18606
} have_functions[] = {
18607
18608
#ifdef HAVE_EVENTFD
18609
    {"HAVE_EVENTFD", NULL},
18610
#endif
18611
18612
#ifdef HAVE_TIMERFD_CREATE
18613
    {"HAVE_TIMERFD_CREATE", NULL},
18614
#endif
18615
18616
#ifdef HAVE_FACCESSAT
18617
    { "HAVE_FACCESSAT", probe_faccessat },
18618
#endif
18619
18620
#ifdef HAVE_FCHDIR
18621
    { "HAVE_FCHDIR", NULL },
18622
#endif
18623
18624
#ifdef HAVE_FCHMOD
18625
    { "HAVE_FCHMOD", NULL },
18626
#endif
18627
18628
#ifdef HAVE_FCHMODAT
18629
    { "HAVE_FCHMODAT", probe_fchmodat },
18630
#endif
18631
18632
#ifdef HAVE_FCHOWN
18633
    { "HAVE_FCHOWN", NULL },
18634
#endif
18635
18636
#ifdef HAVE_FCHOWNAT
18637
    { "HAVE_FCHOWNAT", probe_fchownat },
18638
#endif
18639
18640
#ifdef HAVE_FEXECVE
18641
    { "HAVE_FEXECVE", NULL },
18642
#endif
18643
18644
#ifdef HAVE_FDOPENDIR
18645
    { "HAVE_FDOPENDIR", probe_fdopendir },
18646
#endif
18647
18648
#ifdef HAVE_FPATHCONF
18649
    { "HAVE_FPATHCONF", NULL },
18650
#endif
18651
18652
#ifdef HAVE_FSTATAT
18653
    { "HAVE_FSTATAT", probe_fstatat },
18654
#endif
18655
18656
#ifdef HAVE_FSTATVFS
18657
    { "HAVE_FSTATVFS", NULL },
18658
#endif
18659
18660
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18661
    { "HAVE_FTRUNCATE", NULL },
18662
#endif
18663
18664
#ifdef HAVE_FUTIMENS
18665
    { "HAVE_FUTIMENS", probe_futimens },
18666
#endif
18667
18668
#ifdef HAVE_FUTIMES
18669
    { "HAVE_FUTIMES", NULL },
18670
#endif
18671
18672
#ifdef HAVE_FUTIMESAT
18673
    { "HAVE_FUTIMESAT", NULL },
18674
#endif
18675
18676
#ifdef HAVE_LINKAT
18677
    { "HAVE_LINKAT", probe_linkat },
18678
#endif
18679
18680
#ifdef HAVE_LCHFLAGS
18681
    { "HAVE_LCHFLAGS", NULL },
18682
#endif
18683
18684
#ifdef HAVE_LCHMOD
18685
    { "HAVE_LCHMOD", NULL },
18686
#endif
18687
18688
#ifdef HAVE_LCHOWN
18689
    { "HAVE_LCHOWN", NULL },
18690
#endif
18691
18692
#ifdef HAVE_LSTAT
18693
    { "HAVE_LSTAT", NULL },
18694
#endif
18695
18696
#ifdef HAVE_LUTIMES
18697
    { "HAVE_LUTIMES", NULL },
18698
#endif
18699
18700
#ifdef HAVE_MEMFD_CREATE
18701
    { "HAVE_MEMFD_CREATE", NULL },
18702
#endif
18703
18704
#ifdef HAVE_MKDIRAT
18705
    { "HAVE_MKDIRAT", probe_mkdirat },
18706
#endif
18707
18708
#ifdef HAVE_MKFIFOAT
18709
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18710
#endif
18711
18712
#ifdef HAVE_MKNODAT
18713
    { "HAVE_MKNODAT", probe_mknodat },
18714
#endif
18715
18716
#ifdef HAVE_OPENAT
18717
    { "HAVE_OPENAT", probe_openat },
18718
#endif
18719
18720
#ifdef HAVE_READLINKAT
18721
    { "HAVE_READLINKAT", probe_readlinkat },
18722
#endif
18723
18724
#ifdef HAVE_RENAMEAT
18725
    { "HAVE_RENAMEAT", probe_renameat },
18726
#endif
18727
18728
#ifdef HAVE_SYMLINKAT
18729
    { "HAVE_SYMLINKAT", probe_symlinkat },
18730
#endif
18731
18732
#ifdef HAVE_UNLINKAT
18733
    { "HAVE_UNLINKAT", probe_unlinkat },
18734
#endif
18735
18736
#ifdef HAVE_UTIMENSAT
18737
    { "HAVE_UTIMENSAT", probe_utimensat },
18738
#endif
18739
18740
#ifdef HAVE_PTSNAME_R
18741
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18742
#endif
18743
18744
#ifdef MS_WINDOWS
18745
    { "MS_WINDOWS", NULL },
18746
#endif
18747
18748
    { NULL, NULL }
18749
};
18750
18751
18752
static int
18753
posixmodule_exec(PyObject *m)
18754
36
{
18755
36
    _posixstate *state = get_posix_state(m);
18756
18757
36
#if defined(HAVE_PWRITEV)
18758
36
    if (HAVE_PWRITEV_RUNTIME) {} else {
18759
0
        PyObject* dct = PyModule_GetDict(m);
18760
18761
0
        if (dct == NULL) {
18762
0
            return -1;
18763
0
        }
18764
18765
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18766
0
            return -1;
18767
0
        }
18768
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18769
0
            return -1;
18770
0
        }
18771
0
    }
18772
36
#endif
18773
18774
36
#ifdef HAVE_STATX
18775
36
    if (statx == NULL) {
18776
0
        PyObject* dct = PyModule_GetDict(m);
18777
0
        if (dct == NULL) {
18778
0
            return -1;
18779
0
        }
18780
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18781
0
            return -1;
18782
0
        }
18783
0
    }
18784
36
    else {
18785
36
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18786
36
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18787
0
            return -1;
18788
0
        }
18789
36
    }
18790
36
#endif
18791
18792
    /* Initialize environ dictionary */
18793
36
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18794
0
        return -1;
18795
0
    }
18796
18797
36
    if (all_ins(m))
18798
0
        return -1;
18799
18800
36
    if (setup_confname_tables(m))
18801
0
        return -1;
18802
18803
36
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18804
0
        return -1;
18805
0
    }
18806
18807
36
#if defined(HAVE_WAITID)
18808
36
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18809
36
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18810
0
        return -1;
18811
0
    }
18812
36
#endif
18813
18814
36
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18815
36
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18816
36
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18817
36
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18818
36
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18819
0
        return -1;
18820
0
    }
18821
36
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18822
36
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18823
18824
36
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18825
36
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18826
0
        return -1;
18827
0
    }
18828
18829
36
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18830
36
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18831
36
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18832
0
        return -1;
18833
0
    }
18834
36
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18835
36
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18836
36
                          &os_sched_param_reduce_method) < 0)
18837
0
    {
18838
0
        return -1;
18839
0
    }
18840
36
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18841
36
#endif
18842
18843
    /* initialize TerminalSize_info */
18844
36
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18845
36
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18846
0
        return -1;
18847
0
    }
18848
18849
    /* initialize scandir types */
18850
36
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18851
36
    if (ScandirIteratorType == NULL) {
18852
0
        return -1;
18853
0
    }
18854
36
    state->ScandirIteratorType = ScandirIteratorType;
18855
18856
36
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18857
36
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18858
0
        return -1;
18859
0
    }
18860
18861
36
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18862
36
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18863
0
        return -1;
18864
0
    }
18865
18866
36
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18867
36
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18868
0
        return -1;
18869
0
    }
18870
18871
36
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18872
0
        return -1;
18873
36
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18874
36
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18875
36
    if (state->struct_rusage == NULL)
18876
0
        return -1;
18877
36
#endif
18878
36
    state->st_mode = PyUnicode_InternFromString("st_mode");
18879
36
    if (state->st_mode == NULL)
18880
0
        return -1;
18881
18882
    /* suppress "function not used" warnings */
18883
36
    {
18884
36
    int ignored;
18885
36
    fd_specified("", -1);
18886
36
    follow_symlinks_specified("", 1);
18887
36
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18888
36
    dir_fd_converter(Py_None, &ignored);
18889
36
    dir_fd_unavailable(Py_None, &ignored);
18890
36
    }
18891
18892
    /*
18893
     * provide list of locally available functions
18894
     * so os.py can populate support_* lists
18895
     */
18896
36
    PyObject *list = PyList_New(0);
18897
36
    if (!list) {
18898
0
        return -1;
18899
0
    }
18900
1.18k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18901
1.15k
        PyObject *unicode;
18902
1.15k
        if (trace->probe && !trace->probe()) continue;
18903
1.15k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18904
1.15k
        if (!unicode)
18905
0
            return -1;
18906
1.15k
        if (PyList_Append(list, unicode))
18907
0
            return -1;
18908
1.15k
        Py_DECREF(unicode);
18909
1.15k
    }
18910
18911
36
#ifndef MS_WINDOWS
18912
36
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18913
0
        PyErr_SetString(PyExc_RuntimeError,
18914
0
                        "cannot read ticks_per_second");
18915
0
        return -1;
18916
0
    }
18917
36
    assert(state->ticks_per_second >= 1);
18918
36
#endif
18919
18920
36
    return PyModule_Add(m, "_have_functions", list);
18921
36
}
18922
18923
18924
static PyModuleDef_Slot posixmodile_slots[] = {
18925
    _Py_ABI_SLOT,
18926
    {Py_mod_exec, posixmodule_exec},
18927
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18928
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18929
    {0, NULL}
18930
};
18931
18932
static struct PyModuleDef posixmodule = {
18933
    PyModuleDef_HEAD_INIT,
18934
    .m_name = MODNAME,
18935
    .m_doc = posix__doc__,
18936
    .m_size = sizeof(_posixstate),
18937
    .m_methods = posix_methods,
18938
    .m_slots = posixmodile_slots,
18939
    .m_traverse = _posix_traverse,
18940
    .m_clear = _posix_clear,
18941
    .m_free = _posix_free,
18942
};
18943
18944
PyMODINIT_FUNC
18945
INITFUNC(void)
18946
36
{
18947
36
    return PyModuleDef_Init(&posixmodule);
18948
36
}