Coverage Report

Created: 2026-05-16 06:46

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
411k
#  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
307k
#  define STAT stat
409
11.4k
#  define LSTAT lstat
410
124k
#  define FSTAT fstat
411
563k
#  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
119k
#  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
124k
#  define HAVE_FDOPENDIR_RUNTIME 1
610
0
#  define HAVE_MKDIRAT_RUNTIME 1
611
0
#  define HAVE_RENAMEAT_RUNTIME 1
612
142k
#  define HAVE_UNLINKAT_RUNTIME 1
613
119k
#  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
37
#  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
84
{
807
84
    if (func == NULL)  /* nothing to register? do nothing. */
808
48
        return 0;
809
36
    if (*lst == NULL) {
810
18
        *lst = PyList_New(0);
811
18
        if (*lst == NULL)
812
0
            return -1;
813
18
    }
814
36
    return PyList_Append(*lst, func);
815
36
}
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
318k
{
844
318k
    if (uid == (uid_t)-1)
845
0
        return PyLong_FromLong(-1);
846
318k
    return PyLong_FromUnsignedLong(uid);
847
318k
}
848
849
PyObject *
850
_PyLong_FromGid(gid_t gid)
851
318k
{
852
318k
    if (gid == (gid_t)-1)
853
0
        return PyLong_FromLong(-1);
854
318k
    return PyLong_FromUnsignedLong(gid);
855
318k
}
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
636k
{
1075
636k
#ifdef NODEV
1076
636k
    if (dev == NODEV) {
1077
37
        return PyLong_FromLongLong((long long)dev);
1078
37
    }
1079
636k
#endif
1080
636k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1081
636k
}
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
2.48M
#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
387k
{
1146
387k
    int overflow;
1147
387k
    long long_value;
1148
1149
387k
    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
387k
    PyObject *index = _PyNumber_Index(o);
1157
387k
    if (index == NULL) {
1158
0
        return 0;
1159
0
    }
1160
1161
387k
    assert(PyLong_Check(index));
1162
387k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1163
387k
    Py_DECREF(index);
1164
387k
    assert(!PyErr_Occurred());
1165
387k
    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
387k
    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
387k
    *p = (int)long_value;
1177
387k
    return 1;
1178
387k
}
1179
1180
static int
1181
dir_fd_converter(PyObject *o, void *p)
1182
281k
{
1183
281k
    if (o == Py_None) {
1184
19.1k
        *(int *)p = DEFAULT_DIR_FD;
1185
19.1k
        return 1;
1186
19.1k
    }
1187
262k
    else if (PyIndex_Check(o)) {
1188
262k
        return _fd_converter(o, (int *)p);
1189
262k
    }
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
281k
}
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
586k
{
1231
586k
    void *state = _PyModule_GetState(module);
1232
586k
    assert(state != NULL);
1233
586k
    return (_posixstate *)state;
1234
586k
}
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
1.04M
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1356
1.04M
     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
841k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1366
841k
                      suppress_value_error, allow_fd)
1367
#endif
1368
1369
static void
1370
path_cleanup(path_t *path)
1371
1.17M
{
1372
1.17M
    wchar_t *wide = (wchar_t *)path->wide;
1373
1.17M
    path->wide = NULL;
1374
1.17M
    PyMem_Free(wide);
1375
1.17M
    Py_CLEAR(path->object);
1376
1.17M
    Py_CLEAR(path->cleanup);
1377
1.17M
}
1378
1379
static int
1380
path_converter(PyObject *o, void *p)
1381
1.04M
{
1382
1.04M
    path_t *path = (path_t *)p;
1383
1.04M
    PyObject *bytes = NULL;
1384
1.04M
    Py_ssize_t length = 0;
1385
1.04M
    int is_index, is_bytes, is_unicode;
1386
1.04M
    const char *narrow;
1387
1.04M
    PyObject *wo = NULL;
1388
1.04M
    wchar_t *wide = NULL;
1389
1390
1.04M
#define FORMAT_EXCEPTION(exc, fmt) \
1391
1.04M
    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
1.04M
    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
1.04M
    path->object = path->cleanup = NULL;
1404
    /* path->object owns a reference to the original object */
1405
1.04M
    Py_INCREF(o);
1406
1407
1.04M
    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
1.04M
    is_index = path->allow_fd && PyIndex_Check(o);
1417
1.04M
    is_bytes = PyBytes_Check(o);
1418
1.04M
    is_unicode = PyUnicode_Check(o);
1419
1420
1.04M
    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
1.04M
    if (is_unicode) {
1453
924k
        if (path->make_wide) {
1454
207k
            wide = PyUnicode_AsWideCharString(o, &length);
1455
207k
            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
207k
            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
207k
            path->wide = wide;
1471
207k
            path->narrow = NULL;
1472
207k
            path->fd = -1;
1473
207k
            wide = NULL;
1474
207k
            goto success_exit;
1475
207k
        }
1476
716k
        bytes = PyUnicode_EncodeFSDefault(o);
1477
716k
        if (!bytes) {
1478
0
            goto error_exit;
1479
0
        }
1480
716k
    }
1481
124k
    else if (is_bytes) {
1482
0
        bytes = Py_NewRef(o);
1483
0
    }
1484
124k
    else if (is_index) {
1485
124k
        if (!_fd_converter(o, &path->fd)) {
1486
0
            goto error_exit;
1487
0
        }
1488
124k
        path->wide = NULL;
1489
124k
        path->narrow = NULL;
1490
124k
        path->is_fd = true;
1491
124k
        goto success_exit;
1492
124k
    }
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
716k
    length = PyBytes_GET_SIZE(bytes);
1509
716k
    narrow = PyBytes_AS_STRING(bytes);
1510
716k
    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
716k
    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
716k
    else {
1543
716k
        path->wide = NULL;
1544
716k
        path->narrow = narrow;
1545
716k
        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
716k
        else {
1551
716k
            path->cleanup = bytes;
1552
716k
        }
1553
716k
    }
1554
716k
    path->fd = -1;
1555
1556
1.04M
 success_exit:
1557
1.04M
    path->value_error = 0;
1558
1.04M
    path->length = length;
1559
1.04M
    path->object = o;
1560
1.04M
    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
37
{
1594
37
    int dir_fd;
1595
37
    if (!dir_fd_converter(o, &dir_fd))
1596
0
        return 0;
1597
37
    if (dir_fd != DEFAULT_DIR_FD) {
1598
0
        argument_unavailable_error(NULL, "dir_fd");
1599
0
        return 0;
1600
0
    }
1601
37
    *(int *)p = dir_fd;
1602
37
    return 1;
1603
37
}
1604
1605
static int
1606
fd_specified(const char *function_name, int fd)
1607
37
{
1608
37
    if (fd == -1)
1609
37
        return 0;
1610
1611
0
    argument_unavailable_error(function_name, "fd");
1612
0
    return 1;
1613
37
}
1614
1615
static int
1616
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1617
37
{
1618
37
    if (follow_symlinks)
1619
37
        return 0;
1620
1621
0
    argument_unavailable_error(function_name, "follow_symlinks");
1622
0
    return 1;
1623
37
}
1624
1625
static int
1626
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1627
318k
{
1628
318k
    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
318k
    return 0;
1635
318k
}
1636
1637
static int
1638
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1639
318k
{
1640
318k
    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
318k
    return 0;
1647
318k
}
1648
1649
static int
1650
fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
1651
                               int follow_symlinks)
1652
318k
{
1653
318k
    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
318k
    return 0;
1660
318k
}
1661
1662
static int
1663
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1664
                                   int follow_symlinks)
1665
37
{
1666
37
    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
37
    return 0;
1673
37
}
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
37
{
1793
37
    PyObject *d;
1794
#ifdef MS_WINDOWS
1795
    wchar_t **e;
1796
#else
1797
37
    char **e;
1798
37
#endif
1799
1800
37
    d = PyDict_New();
1801
37
    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
37
    e = environ;
1815
37
#endif
1816
37
    if (e == NULL)
1817
0
        return d;
1818
1.29k
    for (; *e != NULL; e++) {
1819
1.25k
        PyObject *k;
1820
1.25k
        PyObject *v;
1821
#ifdef MS_WINDOWS
1822
        const wchar_t *p = wcschr(*e, L'=');
1823
#else
1824
1.25k
        const char *p = strchr(*e, '=');
1825
1.25k
#endif
1826
1.25k
        if (p == NULL)
1827
0
            continue;
1828
#ifdef MS_WINDOWS
1829
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1830
#else
1831
1.25k
        k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
1832
1.25k
#endif
1833
1.25k
        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.25k
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1841
1.25k
#endif
1842
1.25k
        if (v == NULL) {
1843
0
            Py_DECREF(k);
1844
0
            Py_DECREF(d);
1845
0
            return NULL;
1846
0
        }
1847
1.25k
        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.25k
        Py_DECREF(k);
1854
1.25k
        Py_DECREF(v);
1855
1.25k
    }
1856
37
    return d;
1857
37
}
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
245k
{
1908
245k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1909
245k
}
1910
1911
static PyObject *
1912
path_object_error(PyObject *path)
1913
245k
{
1914
#ifdef MS_WINDOWS
1915
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1916
                PyExc_OSError, 0, path);
1917
#else
1918
245k
    return posix_path_object_error(path);
1919
245k
#endif
1920
245k
}
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
245k
{
1936
245k
    return path_object_error(path->object);
1937
245k
}
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, st_uid, 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.33k
{
2614
1.33k
    _posixstate *state = get_posix_state(module);
2615
1.33k
    Py_VISIT(state->billion);
2616
1.33k
    Py_VISIT(state->DirEntryType);
2617
1.33k
    Py_VISIT(state->ScandirIteratorType);
2618
1.33k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2619
1.33k
    Py_VISIT(state->SchedParamType);
2620
1.33k
#endif
2621
1.33k
    Py_VISIT(state->StatResultType);
2622
1.33k
#ifdef HAVE_STATX
2623
1.33k
    Py_VISIT(state->StatxResultType);
2624
1.33k
#endif
2625
1.33k
    Py_VISIT(state->StatVFSResultType);
2626
1.33k
    Py_VISIT(state->TerminalSizeType);
2627
1.33k
    Py_VISIT(state->TimesResultType);
2628
1.33k
    Py_VISIT(state->UnameResultType);
2629
1.33k
#if defined(HAVE_WAITID)
2630
1.33k
    Py_VISIT(state->WaitidResultType);
2631
1.33k
#endif
2632
1.33k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2633
1.33k
    Py_VISIT(state->struct_rusage);
2634
1.33k
#endif
2635
1.33k
    Py_VISIT(state->st_mode);
2636
1.33k
    return 0;
2637
1.33k
}
2638
2639
static void
2640
_posix_free(void *module)
2641
0
{
2642
0
   _posix_clear((PyObject *)module);
2643
0
}
2644
2645
2646
2.86M
#define SEC_TO_NS (1000000000LL)
2647
static PyObject *
2648
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2649
954k
{
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
954k
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2655
954k
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2656
954k
    }
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
954k
#endif
2681
954k
}
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
954k
{
2687
954k
    assert(!PyErr_Occurred());
2688
954k
    assert(nsec < SEC_TO_NS);
2689
2690
954k
    if (s_index >= 0) {
2691
954k
        PyObject *s = _PyLong_FromTime_t(sec);
2692
954k
        if (s == NULL) {
2693
0
            return -1;
2694
0
        }
2695
954k
        PyStructSequence_SET_ITEM(v, s_index, s);
2696
954k
    }
2697
2698
954k
    if (f_index >= 0) {
2699
954k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2700
954k
        if (float_s == NULL) {
2701
0
            return -1;
2702
0
        }
2703
954k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2704
954k
    }
2705
2706
954k
    if (ns_index >= 0) {
2707
954k
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2708
954k
        if (ns_total == NULL) {
2709
0
            return -1;
2710
0
        }
2711
954k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2712
954k
    }
2713
2714
954k
    assert(!PyErr_Occurred());
2715
954k
    return 0;
2716
954k
}
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
318k
{
2751
318k
    assert(!PyErr_Occurred());
2752
2753
318k
    _posixstate *state = get_posix_state(module);
2754
318k
    PyObject *StatResultType = state->StatResultType;
2755
318k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2756
318k
    if (v == NULL) {
2757
0
        return NULL;
2758
0
    }
2759
2760
318k
#define SET_ITEM(pos, expr) \
2761
3.18M
    do { \
2762
3.18M
        PyObject *obj = (expr); \
2763
3.18M
        if (obj == NULL) { \
2764
0
            goto error; \
2765
0
        } \
2766
3.18M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2767
3.18M
    } while (0)
2768
2769
318k
    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
318k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2775
318k
                  "stat.st_ino is larger than unsigned long long");
2776
318k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2777
318k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2778
318k
#endif
2779
318k
    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
318k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2785
318k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2786
318k
#endif
2787
318k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2788
318k
                  "stat.st_size is larger than long long");
2789
318k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2790
2791
    // Set st_atime, st_mtime and st_ctime
2792
318k
    unsigned long ansec, mnsec, cnsec;
2793
318k
#if defined(HAVE_STAT_TV_NSEC)
2794
318k
    ansec = st->st_atim.tv_nsec;
2795
318k
    mnsec = st->st_mtim.tv_nsec;
2796
318k
    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
318k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2809
0
        goto error;
2810
0
    }
2811
318k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2812
0
        goto error;
2813
0
    }
2814
318k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2815
0
        goto error;
2816
0
    }
2817
2818
318k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2819
318k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2820
318k
#endif
2821
318k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2822
318k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2823
318k
#endif
2824
318k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2825
318k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2826
318k
#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
318k
    assert(!PyErr_Occurred());
2862
318k
    return v;
2863
2864
0
error:
2865
0
    Py_DECREF(v);
2866
0
    return NULL;
2867
2868
318k
#undef SET_ITEM
2869
318k
}
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
318k
{
2878
318k
    STRUCT_STAT st;
2879
318k
    int result;
2880
2881
318k
#ifdef HAVE_FSTATAT
2882
318k
    int fstatat_unavailable = 0;
2883
318k
#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
318k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2891
318k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2892
318k
        fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
2893
0
        return NULL;
2894
2895
318k
    Py_BEGIN_ALLOW_THREADS
2896
318k
    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
318k
    else
2906
318k
#if defined(HAVE_LSTAT)
2907
318k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2908
11.4k
        result = LSTAT(path->narrow, &st);
2909
307k
    else
2910
307k
#endif /* HAVE_LSTAT */
2911
307k
#ifdef HAVE_FSTATAT
2912
307k
    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
307k
#endif /* HAVE_FSTATAT */
2922
307k
        result = STAT(path->narrow, &st);
2923
318k
#endif /* MS_WINDOWS */
2924
318k
    Py_END_ALLOW_THREADS
2925
2926
318k
#ifdef HAVE_FSTATAT
2927
318k
    if (fstatat_unavailable) {
2928
0
        argument_unavailable_error("stat", "dir_fd");
2929
0
        return NULL;
2930
0
    }
2931
318k
#endif
2932
2933
318k
    if (result != 0) {
2934
244k
        return path_error(path);
2935
244k
    }
2936
2937
73.5k
    return _pystat_fromstructstat(module, &st);
2938
318k
}
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
9.55k
    #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
124k
    #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
147k
    #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=d58f18bdf3bd3565]*/
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
307k
{
3306
307k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3307
307k
}
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.4k
{
3330
11.4k
    int follow_symlinks = 0;
3331
11.4k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3332
11.4k
}
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.
3929
On some platforms, path may also be specified as an open file descriptor.
3930
If this functionality is 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=a74ceab5d72adf74]*/
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 a path-like object.
4049
        On some platforms, path may also be specified as an open file descriptor.
4050
        If this functionality is unavailable, using it raises an exception.
4051
4052
    mode: int
4053
        Operating-system mode bitfield.
4054
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4055
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4056
        Python.
4057
4058
    *
4059
4060
    dir_fd : dir_fd(requires='fchmodat') = None
4061
        If not None, it should be a file descriptor open to a directory,
4062
        and path should be relative; path will then be relative to that
4063
        directory.
4064
4065
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4066
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4067
        If False, and the last element of the path is a symbolic link,
4068
        chmod will modify the symbolic link itself instead of the file
4069
        the link points to.
4070
4071
Change the access permissions of a file.
4072
4073
It is an error to use dir_fd or follow_symlinks when specifying path as
4074
  an open file descriptor.
4075
dir_fd and follow_symlinks may not be implemented on your platform.
4076
  If they are unavailable, using them will raise a NotImplementedError.
4077
4078
[clinic start generated code]*/
4079
4080
static PyObject *
4081
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4082
              int follow_symlinks)
4083
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
4084
0
{
4085
0
    int result;
4086
4087
0
#ifdef HAVE_FCHMODAT
4088
0
    int fchmodat_nofollow_unsupported = 0;
4089
0
    int fchmodat_unsupported = 0;
4090
0
#endif
4091
4092
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4093
    if (follow_symlinks_specified("chmod", follow_symlinks))
4094
        return NULL;
4095
#endif
4096
4097
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4098
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4099
0
        return NULL;
4100
0
    }
4101
4102
#ifdef MS_WINDOWS
4103
    result = 0;
4104
    Py_BEGIN_ALLOW_THREADS
4105
    if (path->is_fd) {
4106
        result = win32_fchmod(path->fd, mode);
4107
    }
4108
    else if (follow_symlinks) {
4109
        HANDLE hfile = CreateFileW(path->wide,
4110
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4111
                                   0, NULL,
4112
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4113
        if (hfile != INVALID_HANDLE_VALUE) {
4114
            result = win32_hchmod(hfile, mode);
4115
            (void)CloseHandle(hfile);
4116
        }
4117
    }
4118
    else {
4119
        result = win32_lchmod(path->wide, mode);
4120
    }
4121
    Py_END_ALLOW_THREADS
4122
    if (!result) {
4123
        return path_error(path);
4124
    }
4125
#else /* MS_WINDOWS */
4126
0
    Py_BEGIN_ALLOW_THREADS
4127
0
#ifdef HAVE_FCHMOD
4128
0
    if (path->is_fd) {
4129
0
        result = fchmod(path->fd, mode);
4130
0
    }
4131
0
    else
4132
0
#endif /* HAVE_CHMOD */
4133
#ifdef HAVE_LCHMOD
4134
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4135
        result = lchmod(path->narrow, mode);
4136
    else
4137
#endif /* HAVE_LCHMOD */
4138
0
#ifdef HAVE_FCHMODAT
4139
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4140
0
        if (HAVE_FCHMODAT_RUNTIME) {
4141
            /*
4142
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4143
             * The documentation specifically shows how to use it,
4144
             * and then says it isn't implemented yet.
4145
             * (true on linux with glibc 2.15, and openindiana 3.x)
4146
             *
4147
             * Once it is supported, os.chmod will automatically
4148
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4149
             * Until then, we need to be careful what exception we raise.
4150
             */
4151
0
            result = fchmodat(dir_fd, path->narrow, mode,
4152
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4153
            /*
4154
             * But wait!  We can't throw the exception without allowing threads,
4155
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4156
             */
4157
0
            fchmodat_nofollow_unsupported =
4158
0
                             result &&
4159
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4160
0
                             !follow_symlinks;
4161
0
        } else {
4162
0
            fchmodat_unsupported = 1;
4163
0
            fchmodat_nofollow_unsupported = 1;
4164
4165
0
            result = -1;
4166
0
        }
4167
0
    }
4168
0
    else
4169
0
#endif /* HAVE_FHCMODAT */
4170
0
    {
4171
0
#ifdef HAVE_CHMOD
4172
0
        result = chmod(path->narrow, mode);
4173
#elif defined(__wasi__)
4174
        // WASI SDK 15.0 does not support chmod.
4175
        // Ignore missing syscall for now.
4176
        result = 0;
4177
#else
4178
        result = -1;
4179
        errno = ENOSYS;
4180
#endif
4181
0
    }
4182
0
    Py_END_ALLOW_THREADS
4183
4184
0
    if (result) {
4185
0
#ifdef HAVE_FCHMODAT
4186
0
        if (fchmodat_unsupported) {
4187
0
            if (dir_fd != DEFAULT_DIR_FD) {
4188
0
                argument_unavailable_error("chmod", "dir_fd");
4189
0
                return NULL;
4190
0
            }
4191
0
        }
4192
4193
0
        if (fchmodat_nofollow_unsupported) {
4194
0
            if (dir_fd != DEFAULT_DIR_FD)
4195
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4196
0
                                                   dir_fd, follow_symlinks);
4197
0
            else
4198
0
                follow_symlinks_specified("chmod", follow_symlinks);
4199
0
            return NULL;
4200
0
        }
4201
0
        else
4202
0
#endif /* HAVE_FCHMODAT */
4203
0
        return path_error(path);
4204
0
    }
4205
0
#endif /* MS_WINDOWS */
4206
4207
0
    Py_RETURN_NONE;
4208
0
}
4209
4210
4211
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4212
/*[clinic input]
4213
os.fchmod
4214
4215
    fd: int
4216
        The file descriptor of the file to be modified.
4217
    mode: int
4218
        Operating-system mode bitfield.
4219
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4220
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4221
        Python.
4222
4223
Change the access permissions of the file given by file descriptor fd.
4224
4225
Equivalent to os.chmod(fd, mode).
4226
[clinic start generated code]*/
4227
4228
static PyObject *
4229
os_fchmod_impl(PyObject *module, int fd, int mode)
4230
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
4231
0
{
4232
0
    int res;
4233
4234
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4235
0
        return NULL;
4236
0
    }
4237
4238
#ifdef MS_WINDOWS
4239
    res = 0;
4240
    Py_BEGIN_ALLOW_THREADS
4241
    res = win32_fchmod(fd, mode);
4242
    Py_END_ALLOW_THREADS
4243
    if (!res) {
4244
        return PyErr_SetFromWindowsErr(0);
4245
    }
4246
#else /* MS_WINDOWS */
4247
0
    int async_err = 0;
4248
0
    do {
4249
0
        Py_BEGIN_ALLOW_THREADS
4250
0
        res = fchmod(fd, mode);
4251
0
        Py_END_ALLOW_THREADS
4252
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4253
0
    if (res != 0)
4254
0
        return (!async_err) ? posix_error() : NULL;
4255
0
#endif /* MS_WINDOWS */
4256
4257
0
    Py_RETURN_NONE;
4258
0
}
4259
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4260
4261
4262
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4263
/*[clinic input]
4264
os.lchmod
4265
4266
    path: path_t
4267
    mode: int
4268
4269
Change the access permissions of a file, without following symbolic links.
4270
4271
If path is a symlink, this affects the link itself rather than the target.
4272
Equivalent to chmod(path, mode, follow_symlinks=False)."
4273
[clinic start generated code]*/
4274
4275
static PyObject *
4276
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4277
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
4278
{
4279
    int res;
4280
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4281
        return NULL;
4282
    }
4283
#ifdef MS_WINDOWS
4284
    Py_BEGIN_ALLOW_THREADS
4285
    res = win32_lchmod(path->wide, mode);
4286
    Py_END_ALLOW_THREADS
4287
    if (!res) {
4288
        path_error(path);
4289
        return NULL;
4290
    }
4291
#else /* MS_WINDOWS */
4292
    Py_BEGIN_ALLOW_THREADS
4293
    res = lchmod(path->narrow, mode);
4294
    Py_END_ALLOW_THREADS
4295
    if (res < 0) {
4296
        path_error(path);
4297
        return NULL;
4298
    }
4299
#endif /* MS_WINDOWS */
4300
    Py_RETURN_NONE;
4301
}
4302
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4303
4304
4305
#ifdef HAVE_CHFLAGS
4306
/*[clinic input]
4307
os.chflags
4308
4309
    path: path_t
4310
    flags: unsigned_long(bitwise=True)
4311
    follow_symlinks: bool=True
4312
4313
Set file flags.
4314
4315
If follow_symlinks is False, and the last element of the path is a symbolic
4316
  link, chflags will change flags on the symbolic link itself instead of the
4317
  file the link points to.
4318
follow_symlinks may not be implemented on your platform.  If it is
4319
unavailable, using it will raise a NotImplementedError.
4320
4321
[clinic start generated code]*/
4322
4323
static PyObject *
4324
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4325
                int follow_symlinks)
4326
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
4327
{
4328
    int result;
4329
4330
#ifndef HAVE_LCHFLAGS
4331
    if (follow_symlinks_specified("chflags", follow_symlinks))
4332
        return NULL;
4333
#endif
4334
4335
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4336
        return NULL;
4337
    }
4338
4339
    Py_BEGIN_ALLOW_THREADS
4340
#ifdef HAVE_LCHFLAGS
4341
    if (!follow_symlinks)
4342
        result = lchflags(path->narrow, flags);
4343
    else
4344
#endif
4345
        result = chflags(path->narrow, flags);
4346
    Py_END_ALLOW_THREADS
4347
4348
    if (result)
4349
        return path_error(path);
4350
4351
    Py_RETURN_NONE;
4352
}
4353
#endif /* HAVE_CHFLAGS */
4354
4355
4356
#ifdef HAVE_LCHFLAGS
4357
/*[clinic input]
4358
os.lchflags
4359
4360
    path: path_t
4361
    flags: unsigned_long(bitwise=True)
4362
4363
Set file flags.
4364
4365
This function will not follow symbolic links.
4366
Equivalent to chflags(path, flags, follow_symlinks=False).
4367
[clinic start generated code]*/
4368
4369
static PyObject *
4370
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4371
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4372
{
4373
    int res;
4374
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4375
        return NULL;
4376
    }
4377
    Py_BEGIN_ALLOW_THREADS
4378
    res = lchflags(path->narrow, flags);
4379
    Py_END_ALLOW_THREADS
4380
    if (res < 0) {
4381
        return path_error(path);
4382
    }
4383
    Py_RETURN_NONE;
4384
}
4385
#endif /* HAVE_LCHFLAGS */
4386
4387
4388
#ifdef HAVE_CHROOT
4389
/*[clinic input]
4390
os.chroot
4391
    path: path_t
4392
4393
Change root directory to path.
4394
4395
[clinic start generated code]*/
4396
4397
static PyObject *
4398
os_chroot_impl(PyObject *module, path_t *path)
4399
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4400
0
{
4401
0
    int res;
4402
0
    Py_BEGIN_ALLOW_THREADS
4403
0
    res = chroot(path->narrow);
4404
0
    Py_END_ALLOW_THREADS
4405
0
    if (res < 0)
4406
0
        return path_error(path);
4407
0
    Py_RETURN_NONE;
4408
0
}
4409
#endif /* HAVE_CHROOT */
4410
4411
4412
#ifdef HAVE_FSYNC
4413
/*[clinic input]
4414
os.fsync
4415
4416
    fd: fildes
4417
4418
Force write of fd to disk.
4419
[clinic start generated code]*/
4420
4421
static PyObject *
4422
os_fsync_impl(PyObject *module, int fd)
4423
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4424
0
{
4425
0
    return posix_fildes_fd(fd, fsync);
4426
0
}
4427
#endif /* HAVE_FSYNC */
4428
4429
4430
#ifdef HAVE_SYNC
4431
/*[clinic input]
4432
os.sync
4433
4434
Force write of everything to disk.
4435
[clinic start generated code]*/
4436
4437
static PyObject *
4438
os_sync_impl(PyObject *module)
4439
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4440
0
{
4441
0
    Py_BEGIN_ALLOW_THREADS
4442
0
    sync();
4443
0
    Py_END_ALLOW_THREADS
4444
0
    Py_RETURN_NONE;
4445
0
}
4446
#endif /* HAVE_SYNC */
4447
4448
4449
#ifdef HAVE_FDATASYNC
4450
#ifdef __hpux
4451
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4452
#endif
4453
4454
/*[clinic input]
4455
os.fdatasync
4456
4457
    fd: fildes
4458
4459
Force write of fd to disk without forcing update of metadata.
4460
[clinic start generated code]*/
4461
4462
static PyObject *
4463
os_fdatasync_impl(PyObject *module, int fd)
4464
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4465
0
{
4466
0
    return posix_fildes_fd(fd, fdatasync);
4467
0
}
4468
#endif /* HAVE_FDATASYNC */
4469
4470
4471
#ifdef HAVE_CHOWN
4472
/*[clinic input]
4473
os.chown
4474
4475
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4476
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4477
4478
    uid: uid_t
4479
4480
    gid: gid_t
4481
4482
    *
4483
4484
    dir_fd : dir_fd(requires='fchownat') = None
4485
        If not None, it should be a file descriptor open to a directory,
4486
        and path should be relative; path will then be relative to that
4487
        directory.
4488
4489
    follow_symlinks: bool = True
4490
        If False, and the last element of the path is a symbolic link,
4491
        stat will examine the symbolic link itself instead of the file
4492
        the link points to.
4493
4494
Change the owner and group id of path to the numeric uid and gid.\
4495
4496
path may always be specified as a string.
4497
On some platforms, path may also be specified as an open file descriptor.
4498
  If this functionality is unavailable, using it raises an exception.
4499
If dir_fd is not None, it should be a file descriptor open to a directory,
4500
  and path should be relative; path will then be relative to that directory.
4501
If follow_symlinks is False, and the last element of the path is a symbolic
4502
  link, chown will modify the symbolic link itself instead of the file the
4503
  link points to.
4504
It is an error to use dir_fd or follow_symlinks when specifying path as
4505
  an open file descriptor.
4506
dir_fd and follow_symlinks may not be implemented on your platform.
4507
  If they are unavailable, using them will raise a NotImplementedError.
4508
4509
[clinic start generated code]*/
4510
4511
static PyObject *
4512
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4513
              int dir_fd, int follow_symlinks)
4514
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4515
0
{
4516
0
    int result;
4517
4518
0
#if defined(HAVE_FCHOWNAT)
4519
0
    int fchownat_unsupported = 0;
4520
0
#endif
4521
4522
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4523
    if (follow_symlinks_specified("chown", follow_symlinks))
4524
        return NULL;
4525
#endif
4526
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4527
0
        fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
4528
0
        return NULL;
4529
4530
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4531
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4532
0
        return NULL;
4533
0
    }
4534
4535
0
    Py_BEGIN_ALLOW_THREADS
4536
0
#ifdef HAVE_FCHOWN
4537
0
    if (path->is_fd)
4538
0
        result = fchown(path->fd, uid, gid);
4539
0
    else
4540
0
#endif
4541
0
#ifdef HAVE_LCHOWN
4542
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4543
0
        result = lchown(path->narrow, uid, gid);
4544
0
    else
4545
0
#endif
4546
0
#ifdef HAVE_FCHOWNAT
4547
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4548
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4549
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4550
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4551
0
      } else {
4552
0
         fchownat_unsupported = 1;
4553
0
      }
4554
0
    } else
4555
0
#endif
4556
0
        result = chown(path->narrow, uid, gid);
4557
0
    Py_END_ALLOW_THREADS
4558
4559
0
#ifdef HAVE_FCHOWNAT
4560
0
    if (fchownat_unsupported) {
4561
        /* This would be incorrect if the current platform
4562
         * doesn't support lchown.
4563
         */
4564
0
        argument_unavailable_error(NULL, "dir_fd");
4565
0
        return NULL;
4566
0
    }
4567
0
#endif
4568
4569
0
    if (result)
4570
0
        return path_error(path);
4571
4572
0
    Py_RETURN_NONE;
4573
0
}
4574
#endif /* HAVE_CHOWN */
4575
4576
4577
#ifdef HAVE_FCHOWN
4578
/*[clinic input]
4579
os.fchown
4580
4581
    fd: int
4582
    uid: uid_t
4583
    gid: gid_t
4584
4585
Change the owner and group id of the file specified by file descriptor.
4586
4587
Equivalent to os.chown(fd, uid, gid).
4588
4589
[clinic start generated code]*/
4590
4591
static PyObject *
4592
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4593
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4594
0
{
4595
0
    int res;
4596
0
    int async_err = 0;
4597
4598
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4599
0
        return NULL;
4600
0
    }
4601
4602
0
    do {
4603
0
        Py_BEGIN_ALLOW_THREADS
4604
0
        res = fchown(fd, uid, gid);
4605
0
        Py_END_ALLOW_THREADS
4606
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4607
0
    if (res != 0)
4608
0
        return (!async_err) ? posix_error() : NULL;
4609
4610
0
    Py_RETURN_NONE;
4611
0
}
4612
#endif /* HAVE_FCHOWN */
4613
4614
4615
#ifdef HAVE_LCHOWN
4616
/*[clinic input]
4617
os.lchown
4618
4619
    path : path_t
4620
    uid: uid_t
4621
    gid: gid_t
4622
4623
Change the owner and group id of path to the numeric uid and gid.
4624
4625
This function will not follow symbolic links.
4626
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4627
[clinic start generated code]*/
4628
4629
static PyObject *
4630
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4631
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4632
0
{
4633
0
    int res;
4634
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4635
0
        return NULL;
4636
0
    }
4637
0
    Py_BEGIN_ALLOW_THREADS
4638
0
    res = lchown(path->narrow, uid, gid);
4639
0
    Py_END_ALLOW_THREADS
4640
0
    if (res < 0) {
4641
0
        return path_error(path);
4642
0
    }
4643
0
    Py_RETURN_NONE;
4644
0
}
4645
#endif /* HAVE_LCHOWN */
4646
4647
4648
static PyObject *
4649
posix_getcwd(int use_bytes)
4650
6
{
4651
#ifdef MS_WINDOWS
4652
    wchar_t wbuf[MAXPATHLEN];
4653
    wchar_t *wbuf2 = wbuf;
4654
    DWORD len;
4655
4656
    Py_BEGIN_ALLOW_THREADS
4657
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4658
    /* If the buffer is large enough, len does not include the
4659
       terminating \0. If the buffer is too small, len includes
4660
       the space needed for the terminator. */
4661
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4662
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4663
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4664
        }
4665
        else {
4666
            wbuf2 = NULL;
4667
        }
4668
        if (wbuf2) {
4669
            len = GetCurrentDirectoryW(len, wbuf2);
4670
        }
4671
    }
4672
    Py_END_ALLOW_THREADS
4673
4674
    if (!wbuf2) {
4675
        PyErr_NoMemory();
4676
        return NULL;
4677
    }
4678
    if (!len) {
4679
        PyErr_SetFromWindowsErr(0);
4680
        if (wbuf2 != wbuf)
4681
            PyMem_RawFree(wbuf2);
4682
        return NULL;
4683
    }
4684
4685
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4686
    if (wbuf2 != wbuf) {
4687
        PyMem_RawFree(wbuf2);
4688
    }
4689
4690
    if (use_bytes) {
4691
        if (resobj == NULL) {
4692
            return NULL;
4693
        }
4694
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4695
    }
4696
4697
    return resobj;
4698
#else
4699
6
    const size_t chunk = 1024;
4700
4701
6
    char *buf = NULL;
4702
6
    char *cwd = NULL;
4703
6
    size_t buflen = 0;
4704
4705
6
    Py_BEGIN_ALLOW_THREADS
4706
6
    do {
4707
6
        char *newbuf;
4708
6
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4709
6
            buflen += chunk;
4710
6
            newbuf = PyMem_RawRealloc(buf, buflen);
4711
6
        }
4712
0
        else {
4713
0
            newbuf = NULL;
4714
0
        }
4715
6
        if (newbuf == NULL) {
4716
0
            PyMem_RawFree(buf);
4717
0
            buf = NULL;
4718
0
            break;
4719
0
        }
4720
6
        buf = newbuf;
4721
4722
6
        cwd = getcwd(buf, buflen);
4723
6
    } while (cwd == NULL && errno == ERANGE);
4724
6
    Py_END_ALLOW_THREADS
4725
4726
6
    if (buf == NULL) {
4727
0
        return PyErr_NoMemory();
4728
0
    }
4729
6
    if (cwd == NULL) {
4730
0
        posix_error();
4731
0
        PyMem_RawFree(buf);
4732
0
        return NULL;
4733
0
    }
4734
4735
6
    PyObject *obj;
4736
6
    if (use_bytes) {
4737
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4738
0
    }
4739
6
    else {
4740
6
        obj = PyUnicode_DecodeFSDefault(buf);
4741
6
    }
4742
6
#ifdef __linux__
4743
6
    if (buf[0] != '/') {
4744
        /*
4745
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4746
         * relative pathname starting with '(unreachable)'. We detect this
4747
         * and fail with ENOENT, matching newer glibc behaviour.
4748
         */
4749
0
        errno = ENOENT;
4750
0
        path_object_error(obj);
4751
0
        PyMem_RawFree(buf);
4752
0
        return NULL;
4753
0
    }
4754
6
#endif
4755
6
    assert(buf[0] == '/');
4756
6
    PyMem_RawFree(buf);
4757
4758
6
    return obj;
4759
6
#endif   /* !MS_WINDOWS */
4760
6
}
4761
4762
4763
/*[clinic input]
4764
os.getcwd
4765
4766
Return a unicode string representing the current working directory.
4767
[clinic start generated code]*/
4768
4769
static PyObject *
4770
os_getcwd_impl(PyObject *module)
4771
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4772
6
{
4773
6
    return posix_getcwd(0);
4774
6
}
4775
4776
4777
/*[clinic input]
4778
os.getcwdb
4779
4780
Return a bytes string representing the current working directory.
4781
[clinic start generated code]*/
4782
4783
static PyObject *
4784
os_getcwdb_impl(PyObject *module)
4785
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4786
0
{
4787
0
    return posix_getcwd(1);
4788
0
}
4789
4790
4791
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4792
#define HAVE_LINK 1
4793
#endif
4794
4795
#ifdef HAVE_LINK
4796
/*[clinic input]
4797
4798
@permit_long_docstring_body
4799
os.link
4800
4801
    src : path_t
4802
    dst : path_t
4803
    *
4804
    src_dir_fd : dir_fd = None
4805
    dst_dir_fd : dir_fd = None
4806
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4807
4808
Create a hard link to a file.
4809
4810
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4811
  descriptor open to a directory, and the respective path string (src or dst)
4812
  should be relative; the path will then be relative to that directory.
4813
If follow_symlinks is False, and the last element of src is a symbolic
4814
  link, link will create a link to the symbolic link itself instead of the
4815
  file the link points to.
4816
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4817
  platform.  If they are unavailable, using them will raise a
4818
  NotImplementedError.
4819
[clinic start generated code]*/
4820
4821
static PyObject *
4822
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4823
             int dst_dir_fd, int follow_symlinks)
4824
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4825
0
{
4826
#ifdef MS_WINDOWS
4827
    BOOL result = FALSE;
4828
#else
4829
0
    int result;
4830
0
#endif
4831
4832
0
#ifdef HAVE_LINKAT
4833
0
    if (HAVE_LINKAT_RUNTIME) {
4834
0
        if (follow_symlinks < 0) {
4835
0
            follow_symlinks = 1;
4836
0
        }
4837
0
    }
4838
0
    else
4839
0
#endif
4840
0
    {
4841
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4842
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4843
0
            return NULL;
4844
0
        }
4845
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4846
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4847
0
#if defined(MS_WINDOWS) || defined(__linux__)
4848
0
        if (follow_symlinks == 1) {
4849
0
            argument_unavailable_error("link", "follow_symlinks=True");
4850
0
            return NULL;
4851
0
        }
4852
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4853
        if (follow_symlinks == 0) {
4854
            argument_unavailable_error("link", "follow_symlinks=False");
4855
            return NULL;
4856
        }
4857
#else
4858
        if (follow_symlinks >= 0) {
4859
            argument_unavailable_error("link", "follow_symlinks");
4860
            return NULL;
4861
        }
4862
#endif
4863
0
    }
4864
4865
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4866
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4867
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4868
0
        return NULL;
4869
0
    }
4870
4871
#ifdef MS_WINDOWS
4872
    Py_BEGIN_ALLOW_THREADS
4873
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4874
    Py_END_ALLOW_THREADS
4875
4876
    if (!result)
4877
        return path_error2(src, dst);
4878
#else
4879
0
    Py_BEGIN_ALLOW_THREADS
4880
0
#ifdef HAVE_LINKAT
4881
0
    if (HAVE_LINKAT_RUNTIME) {
4882
0
        result = linkat(src_dir_fd, src->narrow,
4883
0
            dst_dir_fd, dst->narrow,
4884
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4885
0
    }
4886
0
    else
4887
0
#endif
4888
0
    {
4889
        /* linkat not available */
4890
0
        result = link(src->narrow, dst->narrow);
4891
0
    }
4892
0
    Py_END_ALLOW_THREADS
4893
4894
0
    if (result)
4895
0
        return path_error2(src, dst);
4896
0
#endif /* MS_WINDOWS */
4897
4898
0
    Py_RETURN_NONE;
4899
0
}
4900
#endif
4901
4902
4903
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4904
static PyObject *
4905
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4906
{
4907
    PyObject *v;
4908
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4909
    BOOL result, return_bytes;
4910
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4911
    /* only claim to have space for MAX_PATH */
4912
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4913
    wchar_t *wnamebuf = NULL;
4914
4915
    WIN32_FIND_DATAW wFileData;
4916
    const wchar_t *po_wchars;
4917
4918
    if (!path->wide) { /* Default arg: "." */
4919
        po_wchars = L".";
4920
        len = 1;
4921
        return_bytes = 0;
4922
    } else {
4923
        po_wchars = path->wide;
4924
        len = wcslen(path->wide);
4925
        return_bytes = PyBytes_Check(path->object);
4926
    }
4927
    /* The +5 is so we can append "\\*.*\0" */
4928
    wnamebuf = PyMem_New(wchar_t, len + 5);
4929
    if (!wnamebuf) {
4930
        PyErr_NoMemory();
4931
        goto exit;
4932
    }
4933
    wcscpy(wnamebuf, po_wchars);
4934
    if (len > 0) {
4935
        wchar_t wch = wnamebuf[len-1];
4936
        if (wch != SEP && wch != ALTSEP && wch != L':')
4937
            wnamebuf[len++] = SEP;
4938
        wcscpy(wnamebuf + len, L"*.*");
4939
    }
4940
    if ((list = PyList_New(0)) == NULL) {
4941
        goto exit;
4942
    }
4943
    Py_BEGIN_ALLOW_THREADS
4944
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4945
    Py_END_ALLOW_THREADS
4946
    if (hFindFile == INVALID_HANDLE_VALUE) {
4947
        int error = GetLastError();
4948
        if (error == ERROR_FILE_NOT_FOUND)
4949
            goto exit;
4950
        path_error(path);
4951
        Py_CLEAR(list);
4952
        goto exit;
4953
    }
4954
    do {
4955
        /* Skip over . and .. */
4956
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4957
            wcscmp(wFileData.cFileName, L"..") != 0) {
4958
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4959
                                       wcslen(wFileData.cFileName));
4960
            if (return_bytes && v) {
4961
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4962
            }
4963
            if (v == NULL) {
4964
                Py_CLEAR(list);
4965
                break;
4966
            }
4967
            if (PyList_Append(list, v) != 0) {
4968
                Py_DECREF(v);
4969
                Py_CLEAR(list);
4970
                break;
4971
            }
4972
            Py_DECREF(v);
4973
        }
4974
        Py_BEGIN_ALLOW_THREADS
4975
        result = FindNextFileW(hFindFile, &wFileData);
4976
        Py_END_ALLOW_THREADS
4977
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4978
           it got to the end of the directory. */
4979
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4980
            path_error(path);
4981
            Py_CLEAR(list);
4982
            goto exit;
4983
        }
4984
    } while (result == TRUE);
4985
4986
exit:
4987
    if (hFindFile != INVALID_HANDLE_VALUE) {
4988
        if (FindClose(hFindFile) == FALSE) {
4989
            if (list != NULL) {
4990
                path_error(path);
4991
                Py_CLEAR(list);
4992
            }
4993
        }
4994
    }
4995
    PyMem_Free(wnamebuf);
4996
4997
    return list;
4998
}  /* end of _listdir_windows_no_opendir */
4999
5000
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
5001
5002
static PyObject *
5003
_posix_listdir(path_t *path, PyObject *list)
5004
397
{
5005
397
    PyObject *v;
5006
397
    DIR *dirp = NULL;
5007
397
    struct dirent *ep;
5008
397
    int return_str; /* if false, return bytes */
5009
397
#ifdef HAVE_FDOPENDIR
5010
397
    int fd = -1;
5011
397
#endif
5012
5013
397
    errno = 0;
5014
397
#ifdef HAVE_FDOPENDIR
5015
397
    if (path->is_fd) {
5016
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5017
        /* closedir() closes the FD, so we duplicate it */
5018
0
        fd = _Py_dup(path->fd);
5019
0
        if (fd == -1)
5020
0
            return NULL;
5021
5022
0
        return_str = 1;
5023
5024
0
        Py_BEGIN_ALLOW_THREADS
5025
0
        dirp = fdopendir(fd);
5026
0
        Py_END_ALLOW_THREADS
5027
0
      } else {
5028
0
        PyErr_SetString(PyExc_TypeError,
5029
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5030
0
        return NULL;
5031
0
      }
5032
0
    }
5033
397
    else
5034
397
#endif
5035
397
    {
5036
397
        const char *name;
5037
397
        if (path->narrow) {
5038
397
            name = path->narrow;
5039
            /* only return bytes if they specified a bytes object */
5040
397
            return_str = !PyBytes_Check(path->object);
5041
397
        }
5042
0
        else {
5043
0
            name = ".";
5044
0
            return_str = 1;
5045
0
        }
5046
5047
397
        Py_BEGIN_ALLOW_THREADS
5048
397
        dirp = opendir(name);
5049
397
        Py_END_ALLOW_THREADS
5050
397
    }
5051
5052
397
    if (dirp == NULL) {
5053
4
        path_error(path);
5054
4
        list = NULL;
5055
4
#ifdef HAVE_FDOPENDIR
5056
4
        if (fd != -1) {
5057
0
            Py_BEGIN_ALLOW_THREADS
5058
0
            close(fd);
5059
0
            Py_END_ALLOW_THREADS
5060
0
        }
5061
4
#endif
5062
4
        goto exit;
5063
4
    }
5064
393
    if ((list = PyList_New(0)) == NULL) {
5065
0
        goto exit;
5066
0
    }
5067
19.7k
    for (;;) {
5068
19.7k
        errno = 0;
5069
19.7k
        Py_BEGIN_ALLOW_THREADS
5070
19.7k
        ep = readdir(dirp);
5071
19.7k
        Py_END_ALLOW_THREADS
5072
19.7k
        if (ep == NULL) {
5073
393
            if (errno == 0) {
5074
393
                break;
5075
393
            } else {
5076
0
                path_error(path);
5077
0
                Py_CLEAR(list);
5078
0
                goto exit;
5079
0
            }
5080
393
        }
5081
19.3k
        if (ep->d_name[0] == '.' &&
5082
824
            (NAMLEN(ep) == 1 ||
5083
431
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5084
786
            continue;
5085
18.5k
        if (return_str)
5086
18.5k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5087
0
        else
5088
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5089
18.5k
        if (v == NULL) {
5090
0
            Py_CLEAR(list);
5091
0
            break;
5092
0
        }
5093
18.5k
        if (PyList_Append(list, v) != 0) {
5094
0
            Py_DECREF(v);
5095
0
            Py_CLEAR(list);
5096
0
            break;
5097
0
        }
5098
18.5k
        Py_DECREF(v);
5099
18.5k
    }
5100
5101
397
exit:
5102
397
    if (dirp != NULL) {
5103
393
        Py_BEGIN_ALLOW_THREADS
5104
393
#ifdef HAVE_FDOPENDIR
5105
393
        if (fd > -1)
5106
0
            rewinddir(dirp);
5107
393
#endif
5108
393
        closedir(dirp);
5109
393
        Py_END_ALLOW_THREADS
5110
393
    }
5111
5112
397
    return list;
5113
393
}  /* end of _posix_listdir */
5114
#endif  /* which OS */
5115
5116
5117
/*[clinic input]
5118
@permit_long_docstring_body
5119
os.listdir
5120
5121
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5122
5123
Return a list containing the names of the files in the directory.
5124
5125
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
5126
  the filenames returned will also be bytes; in all other circumstances
5127
  the filenames returned will be str.
5128
If path is None, uses the path='.'.
5129
On some platforms, path may also be specified as an open file descriptor;\
5130
  the file descriptor must refer to a directory.
5131
  If this functionality is unavailable, using it raises NotImplementedError.
5132
5133
The list is in arbitrary order.  It does not include the special
5134
entries '.' and '..' even if they are present in the directory.
5135
5136
5137
[clinic start generated code]*/
5138
5139
static PyObject *
5140
os_listdir_impl(PyObject *module, path_t *path)
5141
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
5142
397
{
5143
397
    if (PySys_Audit("os.listdir", "O",
5144
397
                    path->object ? path->object : Py_None) < 0) {
5145
0
        return NULL;
5146
0
    }
5147
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5148
    return _listdir_windows_no_opendir(path, NULL);
5149
#else
5150
397
    return _posix_listdir(path, NULL);
5151
397
#endif
5152
397
}
5153
5154
5155
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5156
5157
/*[clinic input]
5158
os.listdrives
5159
5160
Return a list containing the names of drives in the system.
5161
5162
A drive name typically looks like 'C:\\'.
5163
5164
[clinic start generated code]*/
5165
5166
static PyObject *
5167
os_listdrives_impl(PyObject *module)
5168
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5169
{
5170
    /* Number of possible drives is limited, so 256 should always be enough.
5171
       On the day when it is not, listmounts() will have to be used. */
5172
    wchar_t buffer[256];
5173
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5174
    PyObject *result = NULL;
5175
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5176
        return NULL;
5177
    }
5178
5179
    Py_BEGIN_ALLOW_THREADS;
5180
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5181
    Py_END_ALLOW_THREADS;
5182
5183
    if (!buflen) {
5184
        PyErr_SetFromWindowsErr(0);
5185
        return NULL;
5186
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5187
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5188
        return NULL;
5189
    }
5190
5191
    /* buflen includes a null terminator, so remove it */
5192
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5193
    if (str) {
5194
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5195
        if (nullchar) {
5196
            result = PyUnicode_Split(str, nullchar, -1);
5197
            Py_DECREF(nullchar);
5198
        }
5199
        Py_DECREF(str);
5200
    }
5201
    return result;
5202
}
5203
5204
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5205
5206
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5207
5208
/*[clinic input]
5209
os.listvolumes
5210
5211
Return a list containing the volumes in the system.
5212
5213
Volumes are typically represented as a GUID path.
5214
5215
[clinic start generated code]*/
5216
5217
static PyObject *
5218
os_listvolumes_impl(PyObject *module)
5219
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5220
{
5221
    PyObject *result = PyList_New(0);
5222
    HANDLE find = INVALID_HANDLE_VALUE;
5223
    wchar_t buffer[MAX_PATH + 1];
5224
    if (!result) {
5225
        return NULL;
5226
    }
5227
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5228
        Py_DECREF(result);
5229
        return NULL;
5230
    }
5231
5232
    int err = 0;
5233
    Py_BEGIN_ALLOW_THREADS;
5234
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5235
    if (find == INVALID_HANDLE_VALUE) {
5236
        err = GetLastError();
5237
    }
5238
    Py_END_ALLOW_THREADS;
5239
5240
    while (!err) {
5241
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5242
        if (!s || PyList_Append(result, s) < 0) {
5243
            Py_XDECREF(s);
5244
            Py_CLEAR(result);
5245
            break;
5246
        }
5247
        Py_DECREF(s);
5248
5249
        Py_BEGIN_ALLOW_THREADS;
5250
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5251
            err = GetLastError();
5252
        }
5253
        Py_END_ALLOW_THREADS;
5254
    }
5255
5256
    if (find != INVALID_HANDLE_VALUE) {
5257
        Py_BEGIN_ALLOW_THREADS;
5258
        FindVolumeClose(find);
5259
        Py_END_ALLOW_THREADS;
5260
    }
5261
    if (err && err != ERROR_NO_MORE_FILES) {
5262
        PyErr_SetFromWindowsErr(err);
5263
        Py_XDECREF(result);
5264
        result = NULL;
5265
    }
5266
    return result;
5267
}
5268
5269
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5270
5271
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5272
5273
/*[clinic input]
5274
os.listmounts
5275
5276
    volume: path_t
5277
5278
Return a list containing mount points for a particular volume.
5279
5280
'volume' should be a GUID path as returned from os.listvolumes.
5281
5282
[clinic start generated code]*/
5283
5284
static PyObject *
5285
os_listmounts_impl(PyObject *module, path_t *volume)
5286
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5287
{
5288
    wchar_t default_buffer[MAX_PATH + 1];
5289
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5290
    LPWSTR buffer = default_buffer;
5291
    DWORD attributes;
5292
    PyObject *str = NULL;
5293
    PyObject *nullchar = NULL;
5294
    PyObject *result = NULL;
5295
5296
    /* Ensure we have a valid volume path before continuing */
5297
    Py_BEGIN_ALLOW_THREADS
5298
    attributes = GetFileAttributesW(volume->wide);
5299
    Py_END_ALLOW_THREADS
5300
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5301
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5302
    {
5303
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5304
    }
5305
5306
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5307
        return NULL;
5308
    }
5309
5310
    while (1) {
5311
        BOOL success;
5312
        Py_BEGIN_ALLOW_THREADS
5313
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5314
                                                   buflen, &buflen);
5315
        Py_END_ALLOW_THREADS
5316
        if (success) {
5317
            break;
5318
        }
5319
        if (GetLastError() != ERROR_MORE_DATA) {
5320
            PyErr_SetFromWindowsErr(0);
5321
            goto exit;
5322
        }
5323
        if (buffer != default_buffer) {
5324
            PyMem_Free((void *)buffer);
5325
        }
5326
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5327
        if (!buffer) {
5328
            PyErr_NoMemory();
5329
            goto exit;
5330
        }
5331
    }
5332
    if (buflen < 2) {
5333
        result = PyList_New(0);
5334
        goto exit;
5335
    }
5336
    // buflen includes two null terminators, one for the last string
5337
    // and one for the array of strings.
5338
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5339
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5340
    if (str && nullchar) {
5341
        result = PyUnicode_Split(str, nullchar, -1);
5342
    }
5343
exit:
5344
    if (buffer != default_buffer) {
5345
        PyMem_Free(buffer);
5346
    }
5347
    Py_XDECREF(nullchar);
5348
    Py_XDECREF(str);
5349
    return result;
5350
}
5351
5352
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5353
5354
#ifdef MS_WINDOWS
5355
5356
/*[clinic input]
5357
os._path_isdevdrive
5358
5359
    path: path_t
5360
5361
Determines whether the specified path is on a Windows Dev Drive.
5362
5363
[clinic start generated code]*/
5364
5365
static PyObject *
5366
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5367
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5368
{
5369
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5370
    /* This flag will be documented at
5371
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5372
       after release, and will be available in the latest WinSDK.
5373
       We include the flag to avoid a specific version dependency
5374
       on the latest WinSDK. */
5375
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5376
#endif
5377
    int err = 0;
5378
    PyObject *r = NULL;
5379
    wchar_t volume[MAX_PATH];
5380
5381
    Py_BEGIN_ALLOW_THREADS
5382
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5383
        /* invalid path of some kind */
5384
        /* Note that this also includes the case where a volume is mounted
5385
           in a path longer than 260 characters. This is likely to be rare
5386
           and problematic for other reasons, so a (soft) failure in this
5387
           check seems okay. */
5388
        err = GetLastError();
5389
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5390
        /* only care about local dev drives */
5391
        r = Py_False;
5392
    } else {
5393
        HANDLE hVolume = CreateFileW(
5394
            volume,
5395
            FILE_READ_ATTRIBUTES,
5396
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5397
            NULL,
5398
            OPEN_EXISTING,
5399
            FILE_FLAG_BACKUP_SEMANTICS,
5400
            NULL
5401
        );
5402
        if (hVolume == INVALID_HANDLE_VALUE) {
5403
            err = GetLastError();
5404
        } else {
5405
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5406
            volumeState.Version = 1;
5407
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5408
            if (!DeviceIoControl(
5409
                hVolume,
5410
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5411
                &volumeState,
5412
                sizeof(volumeState),
5413
                &volumeState,
5414
                sizeof(volumeState),
5415
                NULL,
5416
                NULL
5417
            )) {
5418
                err = GetLastError();
5419
            }
5420
            CloseHandle(hVolume);
5421
            if (err == ERROR_INVALID_PARAMETER) {
5422
                /* not supported on this platform */
5423
                r = Py_False;
5424
            } else if (!err) {
5425
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5426
                    ? Py_True : Py_False;
5427
            }
5428
        }
5429
    }
5430
    Py_END_ALLOW_THREADS
5431
5432
    if (err) {
5433
        PyErr_SetFromWindowsErr(err);
5434
        return NULL;
5435
    }
5436
5437
    if (r) {
5438
        return Py_NewRef(r);
5439
    }
5440
5441
    return NULL;
5442
}
5443
5444
5445
int
5446
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5447
{
5448
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5449
    DWORD result;
5450
5451
    result = GetFullPathNameW(path,
5452
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5453
                              NULL);
5454
    if (!result) {
5455
        return -1;
5456
    }
5457
5458
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5459
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5460
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5461
        }
5462
        else {
5463
            woutbufp = NULL;
5464
        }
5465
        if (!woutbufp) {
5466
            *abspath_p = NULL;
5467
            return 0;
5468
        }
5469
5470
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5471
        if (!result) {
5472
            PyMem_RawFree(woutbufp);
5473
            return -1;
5474
        }
5475
    }
5476
5477
    if (woutbufp != woutbuf) {
5478
        *abspath_p = woutbufp;
5479
        return 0;
5480
    }
5481
5482
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5483
    return 0;
5484
}
5485
5486
5487
/* A helper function for abspath on win32 */
5488
/*[clinic input]
5489
os._getfullpathname
5490
5491
    path: path_t
5492
    /
5493
5494
[clinic start generated code]*/
5495
5496
static PyObject *
5497
os__getfullpathname_impl(PyObject *module, path_t *path)
5498
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5499
{
5500
    wchar_t *abspath;
5501
5502
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5503
        return win32_error_object("GetFullPathNameW", path->object);
5504
    }
5505
    if (abspath == NULL) {
5506
        return PyErr_NoMemory();
5507
    }
5508
5509
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5510
    PyMem_RawFree(abspath);
5511
    if (str == NULL) {
5512
        return NULL;
5513
    }
5514
    if (PyBytes_Check(path->object)) {
5515
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5516
    }
5517
    return str;
5518
}
5519
5520
5521
/*[clinic input]
5522
os._getfinalpathname
5523
5524
    path: path_t
5525
    /
5526
5527
A helper function for samepath on windows.
5528
[clinic start generated code]*/
5529
5530
static PyObject *
5531
os__getfinalpathname_impl(PyObject *module, path_t *path)
5532
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5533
{
5534
    HANDLE hFile;
5535
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5536
    int buf_size = Py_ARRAY_LENGTH(buf);
5537
    int result_length;
5538
    PyObject *result;
5539
5540
    Py_BEGIN_ALLOW_THREADS
5541
    hFile = CreateFileW(
5542
        path->wide,
5543
        0, /* desired access */
5544
        0, /* share mode */
5545
        NULL, /* security attributes */
5546
        OPEN_EXISTING,
5547
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5548
        FILE_FLAG_BACKUP_SEMANTICS,
5549
        NULL);
5550
    Py_END_ALLOW_THREADS
5551
5552
    if (hFile == INVALID_HANDLE_VALUE) {
5553
        return win32_error_object("CreateFileW", path->object);
5554
    }
5555
5556
    /* We have a good handle to the target, use it to determine the
5557
       target path name. */
5558
    while (1) {
5559
        Py_BEGIN_ALLOW_THREADS
5560
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5561
                                                  buf_size, VOLUME_NAME_DOS);
5562
        Py_END_ALLOW_THREADS
5563
5564
        if (!result_length) {
5565
            result = win32_error_object("GetFinalPathNameByHandleW",
5566
                                         path->object);
5567
            goto cleanup;
5568
        }
5569
5570
        if (result_length < buf_size) {
5571
            break;
5572
        }
5573
5574
        wchar_t *tmp;
5575
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5576
                            result_length * sizeof(*tmp));
5577
        if (!tmp) {
5578
            result = PyErr_NoMemory();
5579
            goto cleanup;
5580
        }
5581
5582
        buf_size = result_length;
5583
        target_path = tmp;
5584
    }
5585
5586
    result = PyUnicode_FromWideChar(target_path, result_length);
5587
    if (result && PyBytes_Check(path->object)) {
5588
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5589
    }
5590
5591
cleanup:
5592
    if (target_path != buf) {
5593
        PyMem_Free(target_path);
5594
    }
5595
    CloseHandle(hFile);
5596
    return result;
5597
}
5598
5599
/*[clinic input]
5600
os._findfirstfile
5601
    path: path_t
5602
    /
5603
A function to get the real file name without accessing the file in Windows.
5604
[clinic start generated code]*/
5605
5606
static PyObject *
5607
os__findfirstfile_impl(PyObject *module, path_t *path)
5608
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5609
{
5610
    PyObject *result;
5611
    HANDLE hFindFile;
5612
    WIN32_FIND_DATAW wFileData;
5613
    WCHAR *wRealFileName;
5614
5615
    Py_BEGIN_ALLOW_THREADS
5616
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5617
    Py_END_ALLOW_THREADS
5618
5619
    if (hFindFile == INVALID_HANDLE_VALUE) {
5620
        path_error(path);
5621
        return NULL;
5622
    }
5623
5624
    wRealFileName = wFileData.cFileName;
5625
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5626
    FindClose(hFindFile);
5627
    return result;
5628
}
5629
5630
5631
/*[clinic input]
5632
os._getvolumepathname
5633
5634
    path: path_t
5635
5636
A helper function for ismount on Win32.
5637
[clinic start generated code]*/
5638
5639
static PyObject *
5640
os__getvolumepathname_impl(PyObject *module, path_t *path)
5641
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5642
{
5643
    PyObject *result;
5644
    wchar_t *mountpath=NULL;
5645
    size_t buflen;
5646
    BOOL ret;
5647
5648
    /* Volume path should be shorter than entire path */
5649
    buflen = Py_MAX(path->length, MAX_PATH);
5650
5651
    if (buflen > PY_DWORD_MAX) {
5652
        PyErr_SetString(PyExc_OverflowError, "path too long");
5653
        return NULL;
5654
    }
5655
5656
    mountpath = PyMem_New(wchar_t, buflen);
5657
    if (mountpath == NULL)
5658
        return PyErr_NoMemory();
5659
5660
    Py_BEGIN_ALLOW_THREADS
5661
    ret = GetVolumePathNameW(path->wide, mountpath,
5662
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5663
    Py_END_ALLOW_THREADS
5664
5665
    if (!ret) {
5666
        result = win32_error_object("_getvolumepathname", path->object);
5667
        goto exit;
5668
    }
5669
    result = PyUnicode_FromWideChar(mountpath, -1);
5670
    if (PyBytes_Check(path->object))
5671
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5672
5673
exit:
5674
    PyMem_Free(mountpath);
5675
    return result;
5676
}
5677
5678
5679
/*[clinic input]
5680
os._path_splitroot
5681
5682
    path: path_t
5683
    /
5684
5685
Removes everything after the root on Win32.
5686
[clinic start generated code]*/
5687
5688
static PyObject *
5689
os__path_splitroot_impl(PyObject *module, path_t *path)
5690
/*[clinic end generated code: output=ab7f1a88b654581c input=d356de1edb6050a2]*/
5691
{
5692
    wchar_t *buffer;
5693
    wchar_t *end;
5694
    PyObject *result = NULL;
5695
    HRESULT ret;
5696
5697
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5698
    if (!buffer) {
5699
        return NULL;
5700
    }
5701
    wcscpy(buffer, path->wide);
5702
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5703
        *p = L'\\';
5704
    }
5705
5706
    Py_BEGIN_ALLOW_THREADS
5707
    ret = PathCchSkipRoot(buffer, &end);
5708
    Py_END_ALLOW_THREADS
5709
    if (FAILED(ret)) {
5710
        result = Py_BuildValue("sO", "", path->object);
5711
    } else if (end != buffer) {
5712
        size_t rootLen = (size_t)(end - buffer);
5713
        result = Py_BuildValue("NN",
5714
            PyUnicode_FromWideChar(path->wide, rootLen),
5715
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5716
        );
5717
    } else {
5718
        result = Py_BuildValue("Os", path->object, "");
5719
    }
5720
    PyMem_Free(buffer);
5721
5722
    return result;
5723
}
5724
5725
5726
#define PY_IFREG  1 // Regular file
5727
#define PY_IFDIR  2 // Directory
5728
#define PY_IFLNK  4 // Symlink
5729
#define PY_IFMNT  8 // Mount Point (junction)
5730
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5731
#define PY_IFRRP 32 // Regular Reparse Point
5732
5733
static inline BOOL
5734
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5735
{
5736
    switch (testedType) {
5737
    case PY_IFREG:
5738
        return diskDevice && attributes &&
5739
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5740
    case PY_IFDIR:
5741
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5742
    case PY_IFLNK:
5743
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5744
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5745
    case PY_IFMNT:
5746
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5747
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5748
    case PY_IFLRP:
5749
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5750
               IsReparseTagNameSurrogate(reparseTag);
5751
    case PY_IFRRP:
5752
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5753
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5754
    }
5755
5756
    return FALSE;
5757
}
5758
5759
static BOOL
5760
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5761
{
5762
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5763
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5764
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5765
5766
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5767
    if (diskOnly && !diskDevice) {
5768
        return FALSE;
5769
    }
5770
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5771
        FILE_ATTRIBUTE_TAG_INFO info;
5772
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5773
                                            sizeof(info)) &&
5774
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5775
                         testedType);
5776
    }
5777
    FILE_BASIC_INFO info;
5778
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5779
                                        sizeof(info)) &&
5780
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5781
}
5782
5783
static BOOL
5784
_testFileTypeByName(LPCWSTR path, int testedType)
5785
{
5786
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5787
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5788
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5789
5790
    FILE_STAT_BASIC_INFORMATION info;
5791
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5792
                                     sizeof(info)))
5793
    {
5794
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5795
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5796
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5797
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5798
                                diskDevice, testedType);
5799
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5800
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5801
        {
5802
            return result;
5803
        }
5804
    }
5805
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5806
                GetLastError()))
5807
    {
5808
        return FALSE;
5809
    }
5810
5811
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5812
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5813
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5814
    }
5815
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5816
                               OPEN_EXISTING, flags, NULL);
5817
    if (hfile != INVALID_HANDLE_VALUE) {
5818
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5819
        CloseHandle(hfile);
5820
        return result;
5821
    }
5822
5823
    switch (GetLastError()) {
5824
    case ERROR_ACCESS_DENIED:
5825
    case ERROR_SHARING_VIOLATION:
5826
    case ERROR_CANT_ACCESS_FILE:
5827
    case ERROR_INVALID_PARAMETER:
5828
        int rc;
5829
        STRUCT_STAT st;
5830
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5831
            rc = STAT(path, &st);
5832
        }
5833
        else {
5834
            // PY_IFRRP is not generally supported in this case, except for
5835
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5836
            rc = LSTAT(path, &st);
5837
        }
5838
        if (!rc) {
5839
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5840
                             st.st_mode & S_IFREG, testedType);
5841
        }
5842
    }
5843
5844
    return FALSE;
5845
}
5846
5847
5848
static BOOL
5849
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5850
{
5851
    FILE_STAT_BASIC_INFORMATION info;
5852
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5853
                                     sizeof(info)))
5854
    {
5855
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5856
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5857
        {
5858
            return TRUE;
5859
        }
5860
    }
5861
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5862
                    GetLastError()))
5863
    {
5864
        return FALSE;
5865
    }
5866
5867
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5868
    if (!followLinks) {
5869
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5870
    }
5871
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5872
                               OPEN_EXISTING, flags, NULL);
5873
    if (hfile != INVALID_HANDLE_VALUE) {
5874
        if (followLinks) {
5875
            CloseHandle(hfile);
5876
            return TRUE;
5877
        }
5878
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5879
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5880
        CloseHandle(hfile);
5881
        if (!result) {
5882
            return TRUE;
5883
        }
5884
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5885
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5886
        if (hfile != INVALID_HANDLE_VALUE) {
5887
            CloseHandle(hfile);
5888
            return TRUE;
5889
        }
5890
    }
5891
5892
    switch (GetLastError()) {
5893
    case ERROR_ACCESS_DENIED:
5894
    case ERROR_SHARING_VIOLATION:
5895
    case ERROR_CANT_ACCESS_FILE:
5896
    case ERROR_INVALID_PARAMETER:
5897
        STRUCT_STAT _st;
5898
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5899
    }
5900
5901
    return FALSE;
5902
}
5903
5904
5905
static BOOL
5906
_testFileExists(path_t *path, BOOL followLinks)
5907
{
5908
    BOOL result = FALSE;
5909
    if (path->value_error) {
5910
        return FALSE;
5911
    }
5912
5913
    Py_BEGIN_ALLOW_THREADS
5914
    if (path->is_fd) {
5915
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5916
        if (hfile != INVALID_HANDLE_VALUE) {
5917
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5918
                result = TRUE;
5919
            }
5920
        }
5921
    }
5922
    else if (path->wide) {
5923
        result = _testFileExistsByName(path->wide, followLinks);
5924
    }
5925
    Py_END_ALLOW_THREADS
5926
5927
    return result;
5928
}
5929
5930
5931
static BOOL
5932
_testFileType(path_t *path, int testedType)
5933
{
5934
    BOOL result = FALSE;
5935
    if (path->value_error) {
5936
        return FALSE;
5937
    }
5938
5939
    Py_BEGIN_ALLOW_THREADS
5940
    if (path->is_fd) {
5941
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5942
        if (hfile != INVALID_HANDLE_VALUE) {
5943
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5944
        }
5945
    }
5946
    else if (path->wide) {
5947
        result = _testFileTypeByName(path->wide, testedType);
5948
    }
5949
    Py_END_ALLOW_THREADS
5950
5951
    return result;
5952
}
5953
5954
5955
/*[clinic input]
5956
os._path_exists -> bool
5957
5958
    path: path_t(allow_fd=True, suppress_value_error=True)
5959
5960
Test whether a path exists.  Returns False for broken symbolic links.
5961
5962
[clinic start generated code]*/
5963
5964
static int
5965
os__path_exists_impl(PyObject *module, path_t *path)
5966
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5967
{
5968
    return _testFileExists(path, TRUE);
5969
}
5970
5971
5972
/*[clinic input]
5973
os._path_lexists -> bool
5974
5975
    path: path_t(allow_fd=True, suppress_value_error=True)
5976
5977
Test whether a path exists.  Returns True for broken symbolic links.
5978
5979
[clinic start generated code]*/
5980
5981
static int
5982
os__path_lexists_impl(PyObject *module, path_t *path)
5983
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5984
{
5985
    return _testFileExists(path, FALSE);
5986
}
5987
5988
5989
/*[clinic input]
5990
os._path_isdir -> bool
5991
5992
    path: path_t(allow_fd=True, suppress_value_error=True)
5993
    /
5994
5995
Return true if the pathname refers to an existing directory.
5996
5997
[clinic start generated code]*/
5998
5999
static int
6000
os__path_isdir_impl(PyObject *module, path_t *path)
6001
/*[clinic end generated code: output=d5786196f9e2fa7a input=b15f9b697a7a759f]*/
6002
{
6003
    return _testFileType(path, PY_IFDIR);
6004
}
6005
6006
6007
/*[clinic input]
6008
os._path_isfile -> bool
6009
6010
    path: path_t(allow_fd=True, suppress_value_error=True)
6011
6012
Test whether a path is a regular file
6013
6014
[clinic start generated code]*/
6015
6016
static int
6017
os__path_isfile_impl(PyObject *module, path_t *path)
6018
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6019
{
6020
    return _testFileType(path, PY_IFREG);
6021
}
6022
6023
6024
/*[clinic input]
6025
os._path_islink -> bool
6026
6027
    path: path_t(allow_fd=True, suppress_value_error=True)
6028
6029
Test whether a path is a symbolic link
6030
6031
[clinic start generated code]*/
6032
6033
static int
6034
os__path_islink_impl(PyObject *module, path_t *path)
6035
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6036
{
6037
    return _testFileType(path, PY_IFLNK);
6038
}
6039
6040
6041
/*[clinic input]
6042
os._path_isjunction -> bool
6043
6044
    path: path_t(allow_fd=True, suppress_value_error=True)
6045
6046
Test whether a path is a junction
6047
6048
[clinic start generated code]*/
6049
6050
static int
6051
os__path_isjunction_impl(PyObject *module, path_t *path)
6052
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6053
{
6054
    return _testFileType(path, PY_IFMNT);
6055
}
6056
6057
#undef PY_IFREG
6058
#undef PY_IFDIR
6059
#undef PY_IFLNK
6060
#undef PY_IFMNT
6061
#undef PY_IFLRP
6062
#undef PY_IFRRP
6063
6064
#endif /* MS_WINDOWS */
6065
6066
6067
/*[clinic input]
6068
os._path_splitroot_ex
6069
6070
    path: path_t(make_wide=True, nonstrict=True)
6071
    /
6072
6073
Split a pathname into drive, root and tail.
6074
6075
The tail contains anything after the root.
6076
[clinic start generated code]*/
6077
6078
static PyObject *
6079
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6080
/*[clinic end generated code: output=4b0072b6cdf4b611 input=012fbfad14888b2b]*/
6081
175k
{
6082
175k
    Py_ssize_t drvsize, rootsize;
6083
175k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6084
6085
175k
    const wchar_t *buffer = path->wide;
6086
175k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6087
175k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6088
175k
    if (drv == NULL) {
6089
0
        goto exit;
6090
0
    }
6091
175k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6092
175k
    if (root == NULL) {
6093
0
        goto exit;
6094
0
    }
6095
175k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6096
175k
                                  path->length - drvsize - rootsize);
6097
175k
    if (tail == NULL) {
6098
0
        goto exit;
6099
0
    }
6100
175k
    if (PyBytes_Check(path->object)) {
6101
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6102
0
        if (drv == NULL) {
6103
0
            goto exit;
6104
0
        }
6105
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6106
0
        if (root == NULL) {
6107
0
            goto exit;
6108
0
        }
6109
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6110
0
        if (tail == NULL) {
6111
0
            goto exit;
6112
0
        }
6113
0
    }
6114
175k
    result = PyTuple_Pack(3, drv, root, tail);
6115
175k
exit:
6116
175k
    Py_XDECREF(drv);
6117
175k
    Py_XDECREF(root);
6118
175k
    Py_XDECREF(tail);
6119
175k
    return result;
6120
175k
}
6121
6122
6123
/*[clinic input]
6124
os._path_normpath
6125
6126
    path: path_t(make_wide=True, nonstrict=True)
6127
6128
Normalize path, eliminating double slashes, etc.
6129
[clinic start generated code]*/
6130
6131
static PyObject *
6132
os__path_normpath_impl(PyObject *module, path_t *path)
6133
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6134
32.3k
{
6135
32.3k
    PyObject *result;
6136
32.3k
    Py_ssize_t norm_len;
6137
32.3k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6138
32.3k
                                               path->length, &norm_len);
6139
32.3k
    if (!norm_len) {
6140
0
        result = PyUnicode_FromOrdinal('.');
6141
0
    }
6142
32.3k
    else {
6143
32.3k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6144
32.3k
    }
6145
32.3k
    if (PyBytes_Check(path->object)) {
6146
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6147
0
    }
6148
32.3k
    return result;
6149
32.3k
}
6150
6151
/*[clinic input]
6152
os.mkdir
6153
6154
    path : path_t
6155
6156
    mode: int = 0o777
6157
6158
    *
6159
6160
    dir_fd : dir_fd(requires='mkdirat') = None
6161
6162
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
6163
6164
Create a directory.
6165
6166
If dir_fd is not None, it should be a file descriptor open to a directory,
6167
  and path should be relative; path will then be relative to that directory.
6168
dir_fd may not be implemented on your platform.
6169
  If it is unavailable, using it will raise a NotImplementedError.
6170
6171
The mode argument is ignored on Windows. Where it is used, the current umask
6172
value is first masked out.
6173
[clinic start generated code]*/
6174
6175
static PyObject *
6176
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6177
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
6178
125k
{
6179
125k
    int result;
6180
#ifdef MS_WINDOWS
6181
    int error = 0;
6182
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6183
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6184
#endif
6185
125k
#ifdef HAVE_MKDIRAT
6186
125k
    int mkdirat_unavailable = 0;
6187
125k
#endif
6188
6189
125k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6190
125k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6191
0
        return NULL;
6192
0
    }
6193
6194
#ifdef MS_WINDOWS
6195
    Py_BEGIN_ALLOW_THREADS
6196
    // For API sets that don't support these APIs, we have no choice
6197
    // but to silently create a directory with default ACL.
6198
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6199
    if (mode == 0700 /* 0o700 */) {
6200
        ULONG sdSize;
6201
        pSecAttr = &secAttr;
6202
        // Set a discretionary ACL (D) that is protected (P) and includes
6203
        // inheritable (OICI) entries that allow (A) full control (FA) to
6204
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6205
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6206
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6207
            SDDL_REVISION_1,
6208
            &secAttr.lpSecurityDescriptor,
6209
            &sdSize
6210
        )) {
6211
            error = GetLastError();
6212
        }
6213
    }
6214
#endif
6215
    if (!error) {
6216
        result = CreateDirectoryW(path->wide, pSecAttr);
6217
        if (secAttr.lpSecurityDescriptor &&
6218
            // uncommonly, LocalFree returns non-zero on error, but still uses
6219
            // GetLastError() to see what the error code is
6220
            LocalFree(secAttr.lpSecurityDescriptor)) {
6221
            error = GetLastError();
6222
        }
6223
    }
6224
    Py_END_ALLOW_THREADS
6225
6226
    if (error) {
6227
        return PyErr_SetFromWindowsErr(error);
6228
    }
6229
    if (!result) {
6230
        return path_error(path);
6231
    }
6232
#else
6233
125k
    Py_BEGIN_ALLOW_THREADS
6234
125k
#if HAVE_MKDIRAT
6235
125k
    if (dir_fd != DEFAULT_DIR_FD) {
6236
0
      if (HAVE_MKDIRAT_RUNTIME) {
6237
0
        result = mkdirat(dir_fd, path->narrow, mode);
6238
6239
0
      } else {
6240
0
        mkdirat_unavailable = 1;
6241
0
      }
6242
0
    } else
6243
125k
#endif
6244
#if defined(__WATCOMC__) && !defined(__QNX__)
6245
        result = mkdir(path->narrow);
6246
#else
6247
125k
        result = mkdir(path->narrow, mode);
6248
125k
#endif
6249
125k
    Py_END_ALLOW_THREADS
6250
6251
125k
#if HAVE_MKDIRAT
6252
125k
    if (mkdirat_unavailable) {
6253
0
        argument_unavailable_error(NULL, "dir_fd");
6254
0
        return NULL;
6255
0
    }
6256
125k
#endif
6257
6258
125k
    if (result < 0)
6259
368
        return path_error(path);
6260
124k
#endif /* MS_WINDOWS */
6261
125k
    Py_RETURN_NONE;
6262
125k
}
6263
6264
6265
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6266
#if defined(HAVE_SYS_RESOURCE_H)
6267
#include <sys/resource.h>
6268
#endif
6269
6270
6271
#ifdef HAVE_NICE
6272
/*[clinic input]
6273
os.nice
6274
6275
    increment: int
6276
    /
6277
6278
Add increment to the priority of process and return the new priority.
6279
[clinic start generated code]*/
6280
6281
static PyObject *
6282
os_nice_impl(PyObject *module, int increment)
6283
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6284
0
{
6285
0
    int value;
6286
6287
    /* There are two flavours of 'nice': one that returns the new
6288
       priority (as required by almost all standards out there) and the
6289
       Linux/FreeBSD one, which returns '0' on success and advices
6290
       the use of getpriority() to get the new priority.
6291
6292
       If we are of the nice family that returns the new priority, we
6293
       need to clear errno before the call, and check if errno is filled
6294
       before calling posix_error() on a returnvalue of -1, because the
6295
       -1 may be the actual new priority! */
6296
6297
0
    errno = 0;
6298
0
    value = nice(increment);
6299
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6300
    if (value == 0)
6301
        value = getpriority(PRIO_PROCESS, 0);
6302
#endif
6303
0
    if (value == -1 && errno != 0)
6304
        /* either nice() or getpriority() returned an error */
6305
0
        return posix_error();
6306
0
    return PyLong_FromLong((long) value);
6307
0
}
6308
#endif /* HAVE_NICE */
6309
6310
6311
#ifdef HAVE_GETPRIORITY
6312
/*[clinic input]
6313
os.getpriority
6314
6315
    which: int
6316
    who: int
6317
6318
Return program scheduling priority.
6319
[clinic start generated code]*/
6320
6321
static PyObject *
6322
os_getpriority_impl(PyObject *module, int which, int who)
6323
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6324
0
{
6325
0
    int retval;
6326
6327
0
    errno = 0;
6328
0
    retval = getpriority(which, who);
6329
0
    if (errno != 0)
6330
0
        return posix_error();
6331
0
    return PyLong_FromLong((long)retval);
6332
0
}
6333
#endif /* HAVE_GETPRIORITY */
6334
6335
6336
#ifdef HAVE_SETPRIORITY
6337
/*[clinic input]
6338
os.setpriority
6339
6340
    which: int
6341
    who: int
6342
    priority: int
6343
6344
Set program scheduling priority.
6345
[clinic start generated code]*/
6346
6347
static PyObject *
6348
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6349
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6350
0
{
6351
0
    int retval;
6352
6353
0
    retval = setpriority(which, who, priority);
6354
0
    if (retval == -1)
6355
0
        return posix_error();
6356
0
    Py_RETURN_NONE;
6357
0
}
6358
#endif /* HAVE_SETPRIORITY */
6359
6360
6361
static PyObject *
6362
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6363
178
{
6364
178
    const char *function_name = is_replace ? "replace" : "rename";
6365
178
    int dir_fd_specified;
6366
6367
178
#ifdef HAVE_RENAMEAT
6368
178
    int renameat_unavailable = 0;
6369
178
#endif
6370
6371
#ifdef MS_WINDOWS
6372
    BOOL result;
6373
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6374
#else
6375
178
    int result;
6376
178
#endif
6377
6378
178
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6379
178
                       (dst_dir_fd != DEFAULT_DIR_FD);
6380
#ifndef HAVE_RENAMEAT
6381
    if (dir_fd_specified) {
6382
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6383
        return NULL;
6384
    }
6385
#endif
6386
6387
178
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6388
178
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6389
178
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6390
0
        return NULL;
6391
0
    }
6392
6393
#ifdef MS_WINDOWS
6394
    Py_BEGIN_ALLOW_THREADS
6395
    result = MoveFileExW(src->wide, dst->wide, flags);
6396
    Py_END_ALLOW_THREADS
6397
6398
    if (!result)
6399
        return path_error2(src, dst);
6400
6401
#else
6402
178
    Py_BEGIN_ALLOW_THREADS
6403
178
#ifdef HAVE_RENAMEAT
6404
178
    if (dir_fd_specified) {
6405
0
        if (HAVE_RENAMEAT_RUNTIME) {
6406
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6407
0
        } else {
6408
0
            renameat_unavailable = 1;
6409
0
        }
6410
0
    } else
6411
178
#endif
6412
178
    result = rename(src->narrow, dst->narrow);
6413
178
    Py_END_ALLOW_THREADS
6414
6415
6416
178
#ifdef HAVE_RENAMEAT
6417
178
    if (renameat_unavailable) {
6418
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6419
0
        return NULL;
6420
0
    }
6421
178
#endif
6422
6423
178
    if (result)
6424
0
        return path_error2(src, dst);
6425
178
#endif
6426
178
    Py_RETURN_NONE;
6427
178
}
6428
6429
6430
/*[clinic input]
6431
@permit_long_docstring_body
6432
os.rename
6433
6434
    src : path_t
6435
    dst : path_t
6436
    *
6437
    src_dir_fd : dir_fd = None
6438
    dst_dir_fd : dir_fd = None
6439
6440
Rename a file or directory.
6441
6442
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6443
  descriptor open to a directory, and the respective path string (src or dst)
6444
  should be relative; the path will then be relative to that directory.
6445
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6446
  If they are unavailable, using them will raise a NotImplementedError.
6447
[clinic start generated code]*/
6448
6449
static PyObject *
6450
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6451
               int dst_dir_fd)
6452
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6453
5
{
6454
5
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6455
5
}
6456
6457
6458
/*[clinic input]
6459
@permit_long_docstring_body
6460
os.replace = os.rename
6461
6462
Rename a file or directory, overwriting the destination.
6463
6464
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6465
  descriptor open to a directory, and the respective path string (src or dst)
6466
  should be relative; the path will then be relative to that directory.
6467
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6468
  If they are unavailable, using them will raise a NotImplementedError.
6469
[clinic start generated code]*/
6470
6471
static PyObject *
6472
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6473
                int dst_dir_fd)
6474
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6475
173
{
6476
173
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6477
173
}
6478
6479
6480
/*[clinic input]
6481
os.rmdir
6482
6483
    path: path_t
6484
    *
6485
    dir_fd: dir_fd(requires='unlinkat') = None
6486
6487
Remove a directory.
6488
6489
If dir_fd is not None, it should be a file descriptor open to a directory,
6490
  and path should be relative; path will then be relative to that directory.
6491
dir_fd may not be implemented on your platform.
6492
  If it is unavailable, using it will raise a NotImplementedError.
6493
[clinic start generated code]*/
6494
6495
static PyObject *
6496
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6497
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6498
124k
{
6499
124k
    int result;
6500
124k
#ifdef HAVE_UNLINKAT
6501
124k
    int unlinkat_unavailable = 0;
6502
124k
#endif
6503
6504
124k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6505
124k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6506
0
        return NULL;
6507
0
    }
6508
6509
124k
    Py_BEGIN_ALLOW_THREADS
6510
#ifdef MS_WINDOWS
6511
    /* Windows, success=1, UNIX, success=0 */
6512
    result = !RemoveDirectoryW(path->wide);
6513
#else
6514
124k
#ifdef HAVE_UNLINKAT
6515
124k
    if (dir_fd != DEFAULT_DIR_FD) {
6516
119k
      if (HAVE_UNLINKAT_RUNTIME) {
6517
119k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6518
119k
      } else {
6519
0
        unlinkat_unavailable = 1;
6520
0
        result = -1;
6521
0
      }
6522
119k
    } else
6523
4.78k
#endif
6524
4.78k
        result = rmdir(path->narrow);
6525
124k
#endif
6526
124k
    Py_END_ALLOW_THREADS
6527
6528
124k
#ifdef HAVE_UNLINKAT
6529
124k
    if (unlinkat_unavailable) {
6530
0
        argument_unavailable_error("rmdir", "dir_fd");
6531
0
        return NULL;
6532
0
    }
6533
124k
#endif
6534
6535
124k
    if (result)
6536
5
        return path_error(path);
6537
6538
124k
    Py_RETURN_NONE;
6539
124k
}
6540
6541
6542
#ifdef HAVE_SYSTEM
6543
#ifdef MS_WINDOWS
6544
/*[clinic input]
6545
os.system -> long
6546
6547
    command: Py_UNICODE
6548
6549
Execute the command in a subshell.
6550
[clinic start generated code]*/
6551
6552
static long
6553
os_system_impl(PyObject *module, const wchar_t *command)
6554
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6555
{
6556
    long result;
6557
6558
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6559
        return -1;
6560
    }
6561
6562
    Py_BEGIN_ALLOW_THREADS
6563
    _Py_BEGIN_SUPPRESS_IPH
6564
    result = _wsystem(command);
6565
    _Py_END_SUPPRESS_IPH
6566
    Py_END_ALLOW_THREADS
6567
    return result;
6568
}
6569
#else /* MS_WINDOWS */
6570
/*[clinic input]
6571
os.system -> long
6572
6573
    command: unicode_fs_encoded
6574
6575
Execute the command in a subshell.
6576
[clinic start generated code]*/
6577
6578
static long
6579
os_system_impl(PyObject *module, PyObject *command)
6580
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6581
0
{
6582
0
    long result;
6583
0
    const char *bytes = PyBytes_AsString(command);
6584
6585
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6586
0
        return -1;
6587
0
    }
6588
6589
0
    Py_BEGIN_ALLOW_THREADS
6590
0
    result = system(bytes);
6591
0
    Py_END_ALLOW_THREADS
6592
0
    return result;
6593
0
}
6594
#endif
6595
#endif /* HAVE_SYSTEM */
6596
6597
6598
#ifdef HAVE_UMASK
6599
/*[clinic input]
6600
os.umask
6601
6602
    mask: int
6603
    /
6604
6605
Set the current numeric umask and return the previous umask.
6606
[clinic start generated code]*/
6607
6608
static PyObject *
6609
os_umask_impl(PyObject *module, int mask)
6610
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6611
0
{
6612
0
    int i = (int)umask(mask);
6613
0
    if (i < 0)
6614
0
        return posix_error();
6615
0
    return PyLong_FromLong((long)i);
6616
0
}
6617
#endif
6618
6619
#ifdef MS_WINDOWS
6620
6621
/* override the default DeleteFileW behavior so that directory
6622
symlinks can be removed with this function, the same as with
6623
Unix symlinks */
6624
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6625
{
6626
    WIN32_FILE_ATTRIBUTE_DATA info;
6627
    WIN32_FIND_DATAW find_data;
6628
    HANDLE find_data_handle;
6629
    int is_directory = 0;
6630
    int is_link = 0;
6631
6632
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6633
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6634
6635
        /* Get WIN32_FIND_DATA structure for the path to determine if
6636
           it is a symlink */
6637
        if(is_directory &&
6638
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6639
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6640
6641
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6642
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6643
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6644
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6645
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6646
                FindClose(find_data_handle);
6647
            }
6648
        }
6649
    }
6650
6651
    if (is_directory && is_link)
6652
        return RemoveDirectoryW(lpFileName);
6653
6654
    return DeleteFileW(lpFileName);
6655
}
6656
#endif /* MS_WINDOWS */
6657
6658
6659
/*[clinic input]
6660
os.unlink
6661
6662
    path: path_t
6663
    *
6664
    dir_fd: dir_fd(requires='unlinkat')=None
6665
6666
Remove a file (same as remove()).
6667
6668
If dir_fd is not None, it should be a file descriptor open to a directory,
6669
  and path should be relative; path will then be relative to that directory.
6670
dir_fd may not be implemented on your platform.
6671
  If it is unavailable, using it will raise a NotImplementedError.
6672
6673
[clinic start generated code]*/
6674
6675
static PyObject *
6676
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6677
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6678
22.9k
{
6679
22.9k
    int result;
6680
22.9k
#ifdef HAVE_UNLINKAT
6681
22.9k
    int unlinkat_unavailable = 0;
6682
22.9k
#endif
6683
6684
22.9k
    if (PySys_Audit("os.remove", "Oi", path->object,
6685
22.9k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6686
0
        return NULL;
6687
0
    }
6688
6689
22.9k
    Py_BEGIN_ALLOW_THREADS
6690
22.9k
    _Py_BEGIN_SUPPRESS_IPH
6691
#ifdef MS_WINDOWS
6692
    /* Windows, success=1, UNIX, success=0 */
6693
    result = !Py_DeleteFileW(path->wide);
6694
#else
6695
22.9k
#ifdef HAVE_UNLINKAT
6696
22.9k
    if (dir_fd != DEFAULT_DIR_FD) {
6697
22.9k
      if (HAVE_UNLINKAT_RUNTIME) {
6698
6699
22.9k
        result = unlinkat(dir_fd, path->narrow, 0);
6700
22.9k
      } else {
6701
0
        unlinkat_unavailable = 1;
6702
0
      }
6703
22.9k
    } else
6704
2
#endif /* HAVE_UNLINKAT */
6705
2
        result = unlink(path->narrow);
6706
22.9k
#endif
6707
22.9k
    _Py_END_SUPPRESS_IPH
6708
22.9k
    Py_END_ALLOW_THREADS
6709
6710
22.9k
#ifdef HAVE_UNLINKAT
6711
22.9k
    if (unlinkat_unavailable) {
6712
0
        argument_unavailable_error(NULL, "dir_fd");
6713
0
        return NULL;
6714
0
    }
6715
22.9k
#endif
6716
6717
22.9k
    if (result)
6718
0
        return path_error(path);
6719
6720
22.9k
    Py_RETURN_NONE;
6721
22.9k
}
6722
6723
6724
/*[clinic input]
6725
os.remove = os.unlink
6726
6727
Remove a file (same as unlink()).
6728
6729
If dir_fd is not None, it should be a file descriptor open to a directory,
6730
  and path should be relative; path will then be relative 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=e05c5ab55cd30983]*/
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
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
7060
7061
Set the access and modified time of path.
7062
7063
path may always be specified as a string.
7064
On some platforms, path may also be specified as an open file descriptor.
7065
  If this functionality is unavailable, using it raises an exception.
7066
7067
If times is not None, it must be a tuple (atime, mtime);
7068
    atime and mtime should be expressed as float seconds since the epoch.
7069
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7070
    atime_ns and mtime_ns should be expressed as integer nanoseconds
7071
    since the epoch.
7072
If times is None and ns is unspecified, utime uses the current time.
7073
Specifying tuples for both times and ns is an error.
7074
7075
If dir_fd is not None, it should be a file descriptor open to a directory,
7076
  and path should be relative; path will then be relative to that directory.
7077
If follow_symlinks is False, and the last element of the path is a symbolic
7078
  link, utime will modify the symbolic link itself instead of the file the
7079
  link points to.
7080
It is an error to use dir_fd or follow_symlinks when specifying path
7081
  as an open file descriptor.
7082
dir_fd and follow_symlinks may not be available on your platform.
7083
  If they are unavailable, using them will raise a NotImplementedError.
7084
7085
[clinic start generated code]*/
7086
7087
static PyObject *
7088
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7089
              int dir_fd, int follow_symlinks)
7090
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
7091
0
{
7092
#ifdef MS_WINDOWS
7093
    HANDLE hFile;
7094
    FILETIME atime, mtime;
7095
#else
7096
0
    int result;
7097
0
#endif
7098
7099
0
    utime_t utime;
7100
7101
0
    memset(&utime, 0, sizeof(utime_t));
7102
7103
0
    if (times != Py_None && ns) {
7104
0
        PyErr_SetString(PyExc_ValueError,
7105
0
                     "utime: you may specify either 'times'"
7106
0
                     " or 'ns' but not both");
7107
0
        return NULL;
7108
0
    }
7109
7110
0
    if (times != Py_None) {
7111
0
        time_t a_sec, m_sec;
7112
0
        long a_nsec, m_nsec;
7113
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7114
0
            PyErr_SetString(PyExc_TypeError,
7115
0
                         "utime: 'times' must be either"
7116
0
                         " a tuple of two numbers or None");
7117
0
            return NULL;
7118
0
        }
7119
0
        utime.now = 0;
7120
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7121
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7122
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7123
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7124
0
            return NULL;
7125
0
        }
7126
0
        utime.atime_s = a_sec;
7127
0
        utime.atime_ns = a_nsec;
7128
0
        utime.mtime_s = m_sec;
7129
0
        utime.mtime_ns = m_nsec;
7130
0
    }
7131
0
    else if (ns) {
7132
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7133
0
            PyErr_SetString(PyExc_TypeError,
7134
0
                         "utime: 'ns' must be a tuple of two ints");
7135
0
            return NULL;
7136
0
        }
7137
0
        utime.now = 0;
7138
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7139
0
                                      &utime.atime_s, &utime.atime_ns) ||
7140
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7141
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7142
0
            return NULL;
7143
0
        }
7144
0
    }
7145
0
    else {
7146
        /* times and ns are both None/unspecified. use "now". */
7147
0
        utime.now = 1;
7148
0
    }
7149
7150
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7151
    if (follow_symlinks_specified("utime", follow_symlinks))
7152
        return NULL;
7153
#endif
7154
7155
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7156
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7157
0
        fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
7158
0
        return NULL;
7159
7160
#if !defined(HAVE_UTIMENSAT)
7161
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7162
        PyErr_SetString(PyExc_ValueError,
7163
                     "utime: cannot use dir_fd and follow_symlinks "
7164
                     "together on this platform");
7165
        return NULL;
7166
    }
7167
#endif
7168
7169
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7170
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7171
0
        return NULL;
7172
0
    }
7173
7174
#ifdef MS_WINDOWS
7175
    Py_BEGIN_ALLOW_THREADS
7176
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7177
                        NULL, OPEN_EXISTING,
7178
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7179
    Py_END_ALLOW_THREADS
7180
    if (hFile == INVALID_HANDLE_VALUE) {
7181
        path_error(path);
7182
        return NULL;
7183
    }
7184
7185
    if (utime.now) {
7186
        GetSystemTimeAsFileTime(&mtime);
7187
        atime = mtime;
7188
    }
7189
    else {
7190
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7191
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7192
    }
7193
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7194
        path_error(path);
7195
        CloseHandle(hFile);
7196
        return NULL;
7197
    }
7198
    CloseHandle(hFile);
7199
#else /* MS_WINDOWS */
7200
0
    Py_BEGIN_ALLOW_THREADS
7201
7202
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7203
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7204
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7205
0
    else
7206
0
#endif
7207
7208
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7209
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7210
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7211
7212
0
    } else
7213
0
#endif
7214
7215
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7216
0
    if (path->is_fd)
7217
0
        result = utime_fd(&utime, path->fd);
7218
0
    else
7219
0
#endif
7220
7221
0
    result = utime_default(&utime, path->narrow);
7222
7223
0
    Py_END_ALLOW_THREADS
7224
7225
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7226
    /* See utime_dir_fd implementation */
7227
    if (result == -1 && errno == ENOSYS) {
7228
        argument_unavailable_error(NULL, "dir_fd");
7229
        return NULL;
7230
    }
7231
#endif
7232
7233
0
    if (result < 0) {
7234
0
        path_error(path);
7235
0
        return NULL;
7236
0
    }
7237
7238
0
#endif /* MS_WINDOWS */
7239
7240
0
    Py_RETURN_NONE;
7241
0
}
7242
7243
/* Process operations */
7244
7245
7246
/*[clinic input]
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=5e6d57556b0c4a62]*/
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 will be activated.
8061
    setsigmask: object(c_default='NULL') = ()
8062
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8063
    setsigdef: object(c_default='NULL') = ()
8064
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8065
    scheduler: object(c_default='NULL') = None
8066
        A tuple with the scheduler policy (optional) and parameters.
8067
8068
Execute the program specified by path in a new process.
8069
[clinic start generated code]*/
8070
8071
static PyObject *
8072
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8073
                    PyObject *env, PyObject *file_actions,
8074
                    PyObject *setpgroup, int resetids, int setsid,
8075
                    PyObject *setsigmask, PyObject *setsigdef,
8076
                    PyObject *scheduler)
8077
/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/
8078
0
{
8079
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8080
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8081
0
                          scheduler);
8082
0
}
8083
 #endif /* HAVE_POSIX_SPAWN */
8084
8085
8086
8087
#ifdef HAVE_POSIX_SPAWNP
8088
/*[clinic input]
8089
8090
os.posix_spawnp
8091
    path: path_t
8092
        Path of executable file.
8093
    argv: object
8094
        Tuple or list of strings.
8095
    env: object
8096
        Dictionary of strings mapping to strings.
8097
    /
8098
    *
8099
    file_actions: object(c_default='NULL') = ()
8100
        A sequence of file action tuples.
8101
    setpgroup: object(c_default='NULL') = None
8102
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8103
    resetids: bool = False
8104
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8105
    setsid: bool = False
8106
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8107
    setsigmask: object(c_default='NULL') = ()
8108
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8109
    setsigdef: object(c_default='NULL') = ()
8110
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8111
    scheduler: object(c_default='NULL') = None
8112
        A tuple with the scheduler policy (optional) and parameters.
8113
8114
Execute the program specified by path in a new process.
8115
[clinic start generated code]*/
8116
8117
static PyObject *
8118
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8119
                     PyObject *env, PyObject *file_actions,
8120
                     PyObject *setpgroup, int resetids, int setsid,
8121
                     PyObject *setsigmask, PyObject *setsigdef,
8122
                     PyObject *scheduler)
8123
/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/
8124
0
{
8125
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8126
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8127
0
                          scheduler);
8128
0
}
8129
#endif /* HAVE_POSIX_SPAWNP */
8130
8131
#ifdef HAVE_RTPSPAWN
8132
static intptr_t
8133
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8134
               const char  *envp[])
8135
{
8136
     RTP_ID rtpid;
8137
     int status;
8138
     pid_t res;
8139
     int async_err = 0;
8140
8141
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8142
        uStackSize=0 cannot be used, the default stack size is too small for
8143
        Python. */
8144
     if (envp) {
8145
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8146
                          100, 0x1000000, 0, VX_FP_TASK);
8147
     }
8148
     else {
8149
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8150
                          100, 0x1000000, 0, VX_FP_TASK);
8151
     }
8152
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8153
         do {
8154
             res = waitpid((pid_t)rtpid, &status, 0);
8155
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8156
8157
         if (res < 0)
8158
             return RTP_ID_ERROR;
8159
         return ((intptr_t)status);
8160
     }
8161
     return ((intptr_t)rtpid);
8162
}
8163
#endif
8164
8165
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8166
/*[clinic input]
8167
os.spawnv
8168
8169
    mode: int
8170
        Mode of process creation.
8171
    path: path_t
8172
        Path of executable file.
8173
    argv: object
8174
        Tuple or list of strings.
8175
    /
8176
8177
Execute the program specified by path in a new process.
8178
[clinic start generated code]*/
8179
8180
static PyObject *
8181
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8182
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8183
{
8184
    EXECV_CHAR **argvlist;
8185
    int i;
8186
    Py_ssize_t argc;
8187
    intptr_t spawnval;
8188
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8189
8190
    /* spawnv has three arguments: (mode, path, argv), where
8191
       argv is a list or tuple of strings. */
8192
8193
    if (PyList_Check(argv)) {
8194
        argc = PyList_Size(argv);
8195
        getitem = PyList_GetItem;
8196
    }
8197
    else if (PyTuple_Check(argv)) {
8198
        argc = PyTuple_Size(argv);
8199
        getitem = PyTuple_GetItem;
8200
    }
8201
    else {
8202
        PyErr_SetString(PyExc_TypeError,
8203
                        "spawnv() arg 2 must be a tuple or list");
8204
        return NULL;
8205
    }
8206
    if (argc == 0) {
8207
        PyErr_SetString(PyExc_ValueError,
8208
            "spawnv() arg 2 cannot be empty");
8209
        return NULL;
8210
    }
8211
8212
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8213
    if (argvlist == NULL) {
8214
        return PyErr_NoMemory();
8215
    }
8216
    for (i = 0; i < argc; i++) {
8217
        if (!fsconvert_strdup((*getitem)(argv, i),
8218
                              &argvlist[i])) {
8219
            free_string_array(argvlist, i);
8220
            PyErr_SetString(
8221
                PyExc_TypeError,
8222
                "spawnv() arg 2 must contain only strings");
8223
            return NULL;
8224
        }
8225
        if (i == 0 && !argvlist[0][0]) {
8226
            free_string_array(argvlist, i + 1);
8227
            PyErr_SetString(
8228
                PyExc_ValueError,
8229
                "spawnv() arg 2 first element cannot be empty");
8230
            return NULL;
8231
        }
8232
    }
8233
    argvlist[argc] = NULL;
8234
8235
#if !defined(HAVE_RTPSPAWN)
8236
    if (mode == _OLD_P_OVERLAY)
8237
        mode = _P_OVERLAY;
8238
#endif
8239
8240
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8241
                    Py_None) < 0) {
8242
        free_string_array(argvlist, argc);
8243
        return NULL;
8244
    }
8245
8246
    Py_BEGIN_ALLOW_THREADS
8247
    _Py_BEGIN_SUPPRESS_IPH
8248
#ifdef HAVE_WSPAWNV
8249
    spawnval = _wspawnv(mode, path->wide, argvlist);
8250
#elif defined(HAVE_RTPSPAWN)
8251
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8252
#else
8253
    spawnval = _spawnv(mode, path->narrow, argvlist);
8254
#endif
8255
    _Py_END_SUPPRESS_IPH
8256
    Py_END_ALLOW_THREADS
8257
8258
    int saved_errno = errno;
8259
    free_string_array(argvlist, argc);
8260
8261
    if (spawnval == -1) {
8262
        errno = saved_errno;
8263
        posix_error();
8264
        return NULL;
8265
    }
8266
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8267
}
8268
8269
/*[clinic input]
8270
os.spawnve
8271
8272
    mode: int
8273
        Mode of process creation.
8274
    path: path_t
8275
        Path of executable file.
8276
    argv: object
8277
        Tuple or list of strings.
8278
    env: object
8279
        Dictionary of strings mapping to strings.
8280
    /
8281
8282
Execute the program specified by path in a new process.
8283
[clinic start generated code]*/
8284
8285
static PyObject *
8286
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8287
                PyObject *env)
8288
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8289
{
8290
    EXECV_CHAR **argvlist;
8291
    EXECV_CHAR **envlist;
8292
    PyObject *res = NULL;
8293
    Py_ssize_t argc, i, envc;
8294
    intptr_t spawnval;
8295
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8296
    Py_ssize_t lastarg = 0;
8297
8298
    /* spawnve has four arguments: (mode, path, argv, env), where
8299
       argv is a list or tuple of strings and env is a dictionary
8300
       like posix.environ. */
8301
8302
    if (PyList_Check(argv)) {
8303
        argc = PyList_Size(argv);
8304
        getitem = PyList_GetItem;
8305
    }
8306
    else if (PyTuple_Check(argv)) {
8307
        argc = PyTuple_Size(argv);
8308
        getitem = PyTuple_GetItem;
8309
    }
8310
    else {
8311
        PyErr_SetString(PyExc_TypeError,
8312
                        "spawnve() arg 2 must be a tuple or list");
8313
        goto fail_0;
8314
    }
8315
    if (argc == 0) {
8316
        PyErr_SetString(PyExc_ValueError,
8317
            "spawnve() arg 2 cannot be empty");
8318
        goto fail_0;
8319
    }
8320
    if (!PyMapping_Check(env)) {
8321
        PyErr_SetString(PyExc_TypeError,
8322
                        "spawnve() arg 3 must be a mapping object");
8323
        goto fail_0;
8324
    }
8325
8326
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8327
    if (argvlist == NULL) {
8328
        PyErr_NoMemory();
8329
        goto fail_0;
8330
    }
8331
    for (i = 0; i < argc; i++) {
8332
        if (!fsconvert_strdup((*getitem)(argv, i),
8333
                              &argvlist[i]))
8334
        {
8335
            lastarg = i;
8336
            goto fail_1;
8337
        }
8338
        if (i == 0 && !argvlist[0][0]) {
8339
            lastarg = i + 1;
8340
            PyErr_SetString(
8341
                PyExc_ValueError,
8342
                "spawnv() arg 2 first element cannot be empty");
8343
            goto fail_1;
8344
        }
8345
    }
8346
    lastarg = argc;
8347
    argvlist[argc] = NULL;
8348
8349
    envlist = parse_envlist(env, &envc);
8350
    if (envlist == NULL)
8351
        goto fail_1;
8352
8353
#if !defined(HAVE_RTPSPAWN)
8354
    if (mode == _OLD_P_OVERLAY)
8355
        mode = _P_OVERLAY;
8356
#endif
8357
8358
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8359
        goto fail_2;
8360
    }
8361
8362
    Py_BEGIN_ALLOW_THREADS
8363
    _Py_BEGIN_SUPPRESS_IPH
8364
#ifdef HAVE_WSPAWNV
8365
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8366
#elif defined(HAVE_RTPSPAWN)
8367
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8368
                           (const char **)envlist);
8369
#else
8370
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8371
#endif
8372
    _Py_END_SUPPRESS_IPH
8373
    Py_END_ALLOW_THREADS
8374
8375
    if (spawnval == -1)
8376
        (void) posix_error();
8377
    else
8378
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8379
8380
  fail_2:
8381
    while (--envc >= 0) {
8382
        PyMem_Free(envlist[envc]);
8383
    }
8384
    PyMem_Free(envlist);
8385
  fail_1:
8386
    free_string_array(argvlist, lastarg);
8387
  fail_0:
8388
    return res;
8389
}
8390
8391
#endif /* HAVE_SPAWNV */
8392
8393
#ifdef HAVE_FORK
8394
8395
/* Helper function to validate arguments.
8396
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8397
   If obj is non-NULL it must be callable.  */
8398
static int
8399
check_null_or_callable(PyObject *obj, const char* obj_name)
8400
84
{
8401
84
    if (obj && !PyCallable_Check(obj)) {
8402
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8403
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8404
0
        return -1;
8405
0
    }
8406
84
    return 0;
8407
84
}
8408
8409
/*[clinic input]
8410
os.register_at_fork
8411
8412
    *
8413
    before: object=NULL
8414
        A callable to be called in the parent before the fork() syscall.
8415
    after_in_child: object=NULL
8416
        A callable to be called in the child after fork().
8417
    after_in_parent: object=NULL
8418
        A callable to be called in the parent after fork().
8419
8420
Register callables to be called when forking a new process.
8421
8422
'before' callbacks are called in reverse order.
8423
'after_in_child' and 'after_in_parent' callbacks are called in order.
8424
8425
[clinic start generated code]*/
8426
8427
static PyObject *
8428
os_register_at_fork_impl(PyObject *module, PyObject *before,
8429
                         PyObject *after_in_child, PyObject *after_in_parent)
8430
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8431
28
{
8432
28
    PyInterpreterState *interp;
8433
8434
28
    if (!before && !after_in_child && !after_in_parent) {
8435
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8436
0
        return NULL;
8437
0
    }
8438
28
    if (check_null_or_callable(before, "before") ||
8439
28
        check_null_or_callable(after_in_child, "after_in_child") ||
8440
28
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8441
0
        return NULL;
8442
0
    }
8443
28
    interp = _PyInterpreterState_GET();
8444
8445
28
    if (register_at_forker(&interp->before_forkers, before)) {
8446
0
        return NULL;
8447
0
    }
8448
28
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8449
0
        return NULL;
8450
0
    }
8451
28
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8452
0
        return NULL;
8453
0
    }
8454
28
    Py_RETURN_NONE;
8455
28
}
8456
#endif /* HAVE_FORK */
8457
8458
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8459
// Common code to raise a warning if we detect there is more than one thread
8460
// running in the process. Best effort, silent if unable to count threads.
8461
// Constraint: Quick. Never overcounts. Never leaves an error set.
8462
//
8463
// This MUST only be called from the parent process after
8464
// PyOS_AfterFork_Parent().
8465
static int
8466
warn_about_fork_with_threads(
8467
    const char* name,  // Name of the API to use in the warning message.
8468
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8469
)
8470
0
{
8471
    // It's not safe to issue the warning while the world is stopped, because
8472
    // other threads might be holding locks that we need, which would deadlock.
8473
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8474
8475
0
    Py_ssize_t num_python_threads = num_os_threads;
8476
0
    if (num_python_threads <= 0) {
8477
        // Fall back to just the number our threading module knows about.
8478
        // An incomplete view of the world, but better than nothing.
8479
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8480
0
        if (!threading) {
8481
0
            PyErr_Clear();
8482
0
            return 0;
8483
0
        }
8484
0
        PyObject *threading_active =
8485
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8486
0
        if (!threading_active) {
8487
0
            PyErr_Clear();
8488
0
            Py_DECREF(threading);
8489
0
            return 0;
8490
0
        }
8491
0
        PyObject *threading_limbo =
8492
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8493
0
        if (!threading_limbo) {
8494
0
            PyErr_Clear();
8495
0
            Py_DECREF(threading);
8496
0
            Py_DECREF(threading_active);
8497
0
            return 0;
8498
0
        }
8499
0
        Py_DECREF(threading);
8500
        // Duplicating what threading.active_count() does but without holding
8501
        // threading._active_limbo_lock so our count could be inaccurate if
8502
        // these dicts are mid-update from another thread.  Not a big deal.
8503
        // Worst case if someone replaced threading._active or threading._limbo
8504
        // with non-dicts, we get -1 from *Length() below and undercount.
8505
        // Nobody should, but we're best effort so we clear errors and move on.
8506
0
        num_python_threads = (PyMapping_Length(threading_active)
8507
0
                              + PyMapping_Length(threading_limbo));
8508
0
        PyErr_Clear();
8509
0
        Py_DECREF(threading_active);
8510
0
        Py_DECREF(threading_limbo);
8511
0
    }
8512
0
    if (num_python_threads > 1) {
8513
0
        return PyErr_WarnFormat(
8514
0
                PyExc_DeprecationWarning, 1,
8515
0
#ifdef HAVE_GETPID
8516
0
                "This process (pid=%d) is multi-threaded, "
8517
#else
8518
                "This process is multi-threaded, "
8519
#endif
8520
0
                "use of %s() may lead to deadlocks in the child.",
8521
0
#ifdef HAVE_GETPID
8522
0
                getpid(),
8523
0
#endif
8524
0
                name);
8525
0
    }
8526
0
    return 0;
8527
0
}
8528
8529
// If this returns <= 0, we were unable to successfully use any OS APIs.
8530
// Returns a positive number of threads otherwise.
8531
static Py_ssize_t get_number_of_os_threads(void)
8532
0
{
8533
    // TODO: Consider making an `os` module API to return the current number
8534
    // of threads in the process. That'd presumably use this platform code but
8535
    // raise an error rather than using the inaccurate fallback.
8536
0
    Py_ssize_t num_python_threads = 0;
8537
#if defined(__APPLE__) && defined(HAVE_GETPID)
8538
    mach_port_t macos_self = mach_task_self();
8539
    mach_port_t macos_task;
8540
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8541
        thread_array_t macos_threads;
8542
        mach_msg_type_number_t macos_n_threads;
8543
        if (task_threads(macos_task, &macos_threads,
8544
                         &macos_n_threads) == KERN_SUCCESS) {
8545
            num_python_threads = macos_n_threads;
8546
        }
8547
    }
8548
#elif defined(__linux__)
8549
    // Linux /proc/self/stat 20th field is the number of threads.
8550
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8551
0
    if (proc_stat) {
8552
0
        size_t n;
8553
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8554
        // observed on the author's workstation.
8555
0
        char stat_line[160];
8556
0
        n = fread(&stat_line, 1, 159, proc_stat);
8557
0
        stat_line[n] = '\0';
8558
0
        fclose(proc_stat);
8559
8560
0
        char *saveptr = NULL;
8561
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8562
0
        unsigned int idx;
8563
0
        for (idx = 19; idx && field; --idx) {
8564
0
            field = strtok_r(NULL, " ", &saveptr);
8565
0
        }
8566
0
        if (idx == 0 && field) {  // found the 20th field
8567
0
            num_python_threads = atoi(field);  // 0 on error
8568
0
        }
8569
0
    }
8570
0
#endif
8571
0
    return num_python_threads;
8572
0
}
8573
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8574
8575
#ifdef HAVE_FORK1
8576
/*[clinic input]
8577
os.fork1
8578
8579
Fork a child process with a single multiplexed (i.e., not bound) thread.
8580
8581
Return 0 to child process and PID of child to parent process.
8582
[clinic start generated code]*/
8583
8584
static PyObject *
8585
os_fork1_impl(PyObject *module)
8586
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8587
{
8588
    pid_t pid;
8589
8590
    PyInterpreterState *interp = _PyInterpreterState_GET();
8591
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8592
        PyErr_SetString(PyExc_PythonFinalizationError,
8593
                        "can't fork at interpreter shutdown");
8594
        return NULL;
8595
    }
8596
    if (!_Py_IsMainInterpreter(interp)) {
8597
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8598
        return NULL;
8599
    }
8600
    PyOS_BeforeFork();
8601
    pid = fork1();
8602
    int saved_errno = errno;
8603
    if (pid == 0) {
8604
        /* child: this clobbers and resets the import lock. */
8605
        PyOS_AfterFork_Child();
8606
    } else {
8607
        // Called before AfterFork_Parent in case those hooks start threads.
8608
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8609
        /* parent: release the import lock. */
8610
        PyOS_AfterFork_Parent();
8611
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8612
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8613
            return NULL;
8614
        }
8615
    }
8616
    if (pid == -1) {
8617
        errno = saved_errno;
8618
        return posix_error();
8619
    }
8620
    return PyLong_FromPid(pid);
8621
}
8622
#endif /* HAVE_FORK1 */
8623
8624
8625
#ifdef HAVE_FORK
8626
/*[clinic input]
8627
os.fork
8628
8629
Fork a child process.
8630
8631
Return 0 to child process and PID of child to parent process.
8632
[clinic start generated code]*/
8633
8634
static PyObject *
8635
os_fork_impl(PyObject *module)
8636
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8637
0
{
8638
0
    pid_t pid;
8639
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8640
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8641
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8642
0
                        "can't fork at interpreter shutdown");
8643
0
        return NULL;
8644
0
    }
8645
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8646
0
        PyErr_SetString(PyExc_RuntimeError,
8647
0
                        "fork not supported for isolated subinterpreters");
8648
0
        return NULL;
8649
0
    }
8650
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8651
0
        return NULL;
8652
0
    }
8653
0
    PyOS_BeforeFork();
8654
0
    pid = fork();
8655
0
    int saved_errno = errno;
8656
0
    if (pid == 0) {
8657
        /* child: this clobbers and resets the import lock. */
8658
0
        PyOS_AfterFork_Child();
8659
0
    } else {
8660
        // Called before AfterFork_Parent in case those hooks start threads.
8661
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8662
        /* parent: release the import lock. */
8663
0
        PyOS_AfterFork_Parent();
8664
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8665
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8666
0
            return NULL;
8667
0
    }
8668
0
    if (pid == -1) {
8669
0
        errno = saved_errno;
8670
0
        return posix_error();
8671
0
    }
8672
0
    return PyLong_FromPid(pid);
8673
0
}
8674
#endif /* HAVE_FORK */
8675
8676
8677
#ifdef HAVE_SCHED_H
8678
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8679
/*[clinic input]
8680
os.sched_get_priority_max
8681
8682
    policy: int
8683
8684
Get the maximum scheduling priority for policy.
8685
[clinic start generated code]*/
8686
8687
static PyObject *
8688
os_sched_get_priority_max_impl(PyObject *module, int policy)
8689
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8690
0
{
8691
    /* make sure that errno is cleared before the call */
8692
0
    errno = 0;
8693
0
    int max = sched_get_priority_max(policy);
8694
0
    if (max == -1 && errno)
8695
0
        return posix_error();
8696
0
    return PyLong_FromLong(max);
8697
0
}
8698
8699
8700
/*[clinic input]
8701
os.sched_get_priority_min
8702
8703
    policy: int
8704
8705
Get the minimum scheduling priority for policy.
8706
[clinic start generated code]*/
8707
8708
static PyObject *
8709
os_sched_get_priority_min_impl(PyObject *module, int policy)
8710
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8711
0
{
8712
    /* make sure that errno is cleared before the call */
8713
0
    errno = 0;
8714
0
    int min = sched_get_priority_min(policy);
8715
0
    if (min == -1 && errno)
8716
0
        return posix_error();
8717
0
    return PyLong_FromLong(min);
8718
0
}
8719
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8720
8721
8722
#ifdef HAVE_SCHED_SETSCHEDULER
8723
/*[clinic input]
8724
os.sched_getscheduler
8725
    pid: pid_t
8726
    /
8727
8728
Get the scheduling policy for the process identified by pid.
8729
8730
Passing 0 for pid returns the scheduling policy for the calling process.
8731
[clinic start generated code]*/
8732
8733
static PyObject *
8734
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8735
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8736
0
{
8737
0
    int policy;
8738
8739
0
    policy = sched_getscheduler(pid);
8740
0
    if (policy < 0)
8741
0
        return posix_error();
8742
0
    return PyLong_FromLong(policy);
8743
0
}
8744
#endif /* HAVE_SCHED_SETSCHEDULER */
8745
8746
8747
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8748
/*[clinic input]
8749
class os.sched_param "PyObject *" "SchedParamType"
8750
8751
@classmethod
8752
os.sched_param.__new__
8753
8754
    sched_priority: object
8755
        A scheduling parameter.
8756
8757
Currently has only one field: sched_priority
8758
[clinic start generated code]*/
8759
8760
static PyObject *
8761
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8762
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8763
0
{
8764
0
    PyObject *res;
8765
8766
0
    res = PyStructSequence_New(type);
8767
0
    if (!res)
8768
0
        return NULL;
8769
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8770
0
    return res;
8771
0
}
8772
8773
static PyObject *
8774
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8775
0
{
8776
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8777
0
}
8778
8779
static PyMethodDef os_sched_param_reduce_method = {
8780
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8781
};
8782
8783
PyDoc_VAR(os_sched_param__doc__);
8784
8785
static PyStructSequence_Field sched_param_fields[] = {
8786
    {"sched_priority", "the scheduling priority"},
8787
    {0}
8788
};
8789
8790
static PyStructSequence_Desc sched_param_desc = {
8791
    MODNAME ".sched_param", /* name */
8792
    os_sched_param__doc__, /* doc */
8793
    sched_param_fields,
8794
    1
8795
};
8796
8797
static int
8798
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8799
0
{
8800
0
    long priority;
8801
8802
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8803
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8804
0
        return 0;
8805
0
    }
8806
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8807
0
    if (priority == -1 && PyErr_Occurred())
8808
0
        return 0;
8809
0
    if (priority > INT_MAX || priority < INT_MIN) {
8810
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8811
0
        return 0;
8812
0
    }
8813
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8814
0
    return 1;
8815
0
}
8816
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8817
8818
8819
#ifdef HAVE_SCHED_SETSCHEDULER
8820
/*[clinic input]
8821
os.sched_setscheduler
8822
8823
    pid: pid_t
8824
    policy: int
8825
    param as param_obj: object
8826
    /
8827
8828
Set the scheduling policy for the process identified by pid.
8829
8830
If pid is 0, the calling process is changed.
8831
param is an instance of sched_param.
8832
[clinic start generated code]*/
8833
8834
static PyObject *
8835
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8836
                           PyObject *param_obj)
8837
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8838
0
{
8839
0
    struct sched_param param;
8840
0
    if (!convert_sched_param(module, param_obj, &param)) {
8841
0
        return NULL;
8842
0
    }
8843
8844
    /*
8845
    ** sched_setscheduler() returns 0 in Linux, but the previous
8846
    ** scheduling policy under Solaris/Illumos, and others.
8847
    ** On error, -1 is returned in all Operating Systems.
8848
    */
8849
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8850
0
        return posix_error();
8851
0
    Py_RETURN_NONE;
8852
0
}
8853
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8854
8855
8856
#ifdef HAVE_SCHED_SETPARAM
8857
/*[clinic input]
8858
os.sched_getparam
8859
    pid: pid_t
8860
    /
8861
8862
Returns scheduling parameters for the process identified by pid.
8863
8864
If pid is 0, returns parameters for the calling process.
8865
Return value is an instance of sched_param.
8866
[clinic start generated code]*/
8867
8868
static PyObject *
8869
os_sched_getparam_impl(PyObject *module, pid_t pid)
8870
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8871
0
{
8872
0
    struct sched_param param;
8873
0
    PyObject *result;
8874
0
    PyObject *priority;
8875
8876
0
    if (sched_getparam(pid, &param))
8877
0
        return posix_error();
8878
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8879
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8880
0
    if (!result)
8881
0
        return NULL;
8882
0
    priority = PyLong_FromLong(param.sched_priority);
8883
0
    if (!priority) {
8884
0
        Py_DECREF(result);
8885
0
        return NULL;
8886
0
    }
8887
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8888
0
    return result;
8889
0
}
8890
8891
8892
/*[clinic input]
8893
os.sched_setparam
8894
    pid: pid_t
8895
    param as param_obj: object
8896
    /
8897
8898
Set scheduling parameters for the process identified by pid.
8899
8900
If pid is 0, sets parameters for the calling process.
8901
param should be an instance of sched_param.
8902
[clinic start generated code]*/
8903
8904
static PyObject *
8905
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8906
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8907
0
{
8908
0
    struct sched_param param;
8909
0
    if (!convert_sched_param(module, param_obj, &param)) {
8910
0
        return NULL;
8911
0
    }
8912
8913
0
    if (sched_setparam(pid, &param))
8914
0
        return posix_error();
8915
0
    Py_RETURN_NONE;
8916
0
}
8917
#endif /* HAVE_SCHED_SETPARAM */
8918
8919
8920
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8921
/*[clinic input]
8922
@permit_long_summary
8923
os.sched_rr_get_interval -> double
8924
    pid: pid_t
8925
    /
8926
8927
Return the round-robin quantum for the process identified by pid, in seconds.
8928
8929
Value returned is a float.
8930
[clinic start generated code]*/
8931
8932
static double
8933
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8934
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8935
0
{
8936
0
    struct timespec interval;
8937
0
    if (sched_rr_get_interval(pid, &interval)) {
8938
0
        posix_error();
8939
0
        return -1.0;
8940
0
    }
8941
#ifdef _Py_MEMORY_SANITIZER
8942
    __msan_unpoison(&interval, sizeof(interval));
8943
#endif
8944
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8945
0
}
8946
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8947
8948
8949
/*[clinic input]
8950
os.sched_yield
8951
8952
Voluntarily relinquish the CPU.
8953
[clinic start generated code]*/
8954
8955
static PyObject *
8956
os_sched_yield_impl(PyObject *module)
8957
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8958
0
{
8959
0
    int result;
8960
0
    Py_BEGIN_ALLOW_THREADS
8961
0
    result = sched_yield();
8962
0
    Py_END_ALLOW_THREADS
8963
0
    if (result < 0) {
8964
0
        return posix_error();
8965
0
    }
8966
0
    Py_RETURN_NONE;
8967
0
}
8968
8969
#ifdef HAVE_SCHED_SETAFFINITY
8970
/* The minimum number of CPUs allocated in a cpu_set_t */
8971
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8972
8973
/*[clinic input]
8974
os.sched_setaffinity
8975
    pid: pid_t
8976
    mask : object
8977
    /
8978
8979
Set the CPU affinity of the process identified by pid to mask.
8980
8981
mask should be an iterable of integers identifying CPUs.
8982
[clinic start generated code]*/
8983
8984
static PyObject *
8985
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8986
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8987
0
{
8988
0
    int ncpus;
8989
0
    size_t setsize;
8990
0
    cpu_set_t *cpu_set = NULL;
8991
0
    PyObject *iterator = NULL, *item;
8992
8993
0
    iterator = PyObject_GetIter(mask);
8994
0
    if (iterator == NULL)
8995
0
        return NULL;
8996
8997
0
    ncpus = NCPUS_START;
8998
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8999
0
    cpu_set = CPU_ALLOC(ncpus);
9000
0
    if (cpu_set == NULL) {
9001
0
        PyErr_NoMemory();
9002
0
        goto error;
9003
0
    }
9004
0
    CPU_ZERO_S(setsize, cpu_set);
9005
9006
0
    while ((item = PyIter_Next(iterator))) {
9007
0
        long cpu;
9008
0
        if (!PyIndex_Check(item)) {
9009
0
            PyErr_Format(PyExc_TypeError,
9010
0
                        "expected an iterator of ints, "
9011
0
                        "but iterator yielded %R",
9012
0
                        Py_TYPE(item));
9013
0
            Py_DECREF(item);
9014
0
            goto error;
9015
0
        }
9016
0
        cpu = PyLong_AsLong(item);
9017
0
        Py_DECREF(item);
9018
0
        if (cpu < 0) {
9019
0
            if (!PyErr_Occurred())
9020
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9021
0
            goto error;
9022
0
        }
9023
0
        if (cpu > INT_MAX - 1) {
9024
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9025
0
            goto error;
9026
0
        }
9027
0
        if (cpu >= ncpus) {
9028
            /* Grow CPU mask to fit the CPU number */
9029
0
            int newncpus = ncpus;
9030
0
            cpu_set_t *newmask;
9031
0
            size_t newsetsize;
9032
0
            while (newncpus <= cpu) {
9033
0
                if (newncpus > INT_MAX / 2)
9034
0
                    newncpus = cpu + 1;
9035
0
                else
9036
0
                    newncpus = newncpus * 2;
9037
0
            }
9038
0
            newmask = CPU_ALLOC(newncpus);
9039
0
            if (newmask == NULL) {
9040
0
                PyErr_NoMemory();
9041
0
                goto error;
9042
0
            }
9043
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9044
0
            CPU_ZERO_S(newsetsize, newmask);
9045
0
            memcpy(newmask, cpu_set, setsize);
9046
0
            CPU_FREE(cpu_set);
9047
0
            setsize = newsetsize;
9048
0
            cpu_set = newmask;
9049
0
            ncpus = newncpus;
9050
0
        }
9051
0
        CPU_SET_S(cpu, setsize, cpu_set);
9052
0
    }
9053
0
    if (PyErr_Occurred()) {
9054
0
        goto error;
9055
0
    }
9056
0
    Py_CLEAR(iterator);
9057
9058
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9059
0
        posix_error();
9060
0
        goto error;
9061
0
    }
9062
0
    CPU_FREE(cpu_set);
9063
0
    Py_RETURN_NONE;
9064
9065
0
error:
9066
0
    if (cpu_set)
9067
0
        CPU_FREE(cpu_set);
9068
0
    Py_XDECREF(iterator);
9069
0
    return NULL;
9070
0
}
9071
9072
9073
/*[clinic input]
9074
@permit_long_summary
9075
os.sched_getaffinity
9076
    pid: pid_t
9077
    /
9078
9079
Return the affinity of the process identified by pid (or the current process if zero).
9080
9081
The affinity is returned as a set of CPU identifiers.
9082
[clinic start generated code]*/
9083
9084
static PyObject *
9085
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9086
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9087
0
{
9088
0
    int ncpus = NCPUS_START;
9089
0
    size_t setsize;
9090
0
    cpu_set_t *mask;
9091
9092
0
    while (1) {
9093
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9094
0
        mask = CPU_ALLOC(ncpus);
9095
0
        if (mask == NULL) {
9096
0
            return PyErr_NoMemory();
9097
0
        }
9098
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9099
0
            break;
9100
0
        }
9101
0
        CPU_FREE(mask);
9102
0
        if (errno != EINVAL) {
9103
0
            return posix_error();
9104
0
        }
9105
0
        if (ncpus > INT_MAX / 2) {
9106
0
            PyErr_SetString(PyExc_OverflowError,
9107
0
                            "could not allocate a large enough CPU set");
9108
0
            return NULL;
9109
0
        }
9110
0
        ncpus *= 2;
9111
0
    }
9112
9113
0
    PyObject *res = PySet_New(NULL);
9114
0
    if (res == NULL) {
9115
0
        goto error;
9116
0
    }
9117
9118
0
    int cpu = 0;
9119
0
    int count = CPU_COUNT_S(setsize, mask);
9120
0
    for (; count; cpu++) {
9121
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9122
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9123
0
            --count;
9124
0
            if (cpu_num == NULL) {
9125
0
                goto error;
9126
0
            }
9127
0
            if (PySet_Add(res, cpu_num)) {
9128
0
                Py_DECREF(cpu_num);
9129
0
                goto error;
9130
0
            }
9131
0
            Py_DECREF(cpu_num);
9132
0
        }
9133
0
    }
9134
0
    CPU_FREE(mask);
9135
0
    return res;
9136
9137
0
error:
9138
0
    if (mask) {
9139
0
        CPU_FREE(mask);
9140
0
    }
9141
0
    Py_XDECREF(res);
9142
0
    return NULL;
9143
0
}
9144
#endif /* HAVE_SCHED_SETAFFINITY */
9145
9146
#endif /* HAVE_SCHED_H */
9147
9148
9149
#ifdef HAVE_POSIX_OPENPT
9150
/*[clinic input]
9151
os.posix_openpt -> int
9152
9153
    oflag: int
9154
    /
9155
9156
Open and return a file descriptor for a master pseudo-terminal device.
9157
9158
Performs a posix_openpt() C function call. The oflag argument is used to
9159
set file status flags and file access modes as specified in the manual page
9160
of posix_openpt() of your system.
9161
[clinic start generated code]*/
9162
9163
static int
9164
os_posix_openpt_impl(PyObject *module, int oflag)
9165
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
9166
0
{
9167
0
    int fd;
9168
9169
0
#if defined(O_CLOEXEC)
9170
0
    oflag |= O_CLOEXEC;
9171
0
#endif
9172
9173
0
    fd = posix_openpt(oflag);
9174
0
    if (fd == -1) {
9175
0
        posix_error();
9176
0
        return -1;
9177
0
    }
9178
9179
    // Just in case, likely a no-op given O_CLOEXEC above.
9180
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9181
0
        close(fd);
9182
0
        return -1;
9183
0
    }
9184
9185
0
    return fd;
9186
0
}
9187
#endif /* HAVE_POSIX_OPENPT */
9188
9189
#ifdef HAVE_GRANTPT
9190
/*[clinic input]
9191
os.grantpt
9192
9193
    fd: fildes
9194
        File descriptor of a master pseudo-terminal device.
9195
    /
9196
9197
Grant access to the slave pseudo-terminal device.
9198
9199
Performs a grantpt() C function call.
9200
[clinic start generated code]*/
9201
9202
static PyObject *
9203
os_grantpt_impl(PyObject *module, int fd)
9204
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9205
0
{
9206
0
    int ret;
9207
0
    int saved_errno;
9208
0
    PyOS_sighandler_t sig_saved;
9209
9210
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9211
9212
0
    ret = grantpt(fd);
9213
0
    if (ret == -1)
9214
0
        saved_errno = errno;
9215
9216
0
    PyOS_setsig(SIGCHLD, sig_saved);
9217
9218
0
    if (ret == -1) {
9219
0
        errno = saved_errno;
9220
0
        return posix_error();
9221
0
    }
9222
9223
0
    Py_RETURN_NONE;
9224
0
}
9225
#endif /* HAVE_GRANTPT */
9226
9227
#ifdef HAVE_UNLOCKPT
9228
/*[clinic input]
9229
os.unlockpt
9230
9231
    fd: fildes
9232
        File descriptor of a master pseudo-terminal device.
9233
    /
9234
9235
Unlock a pseudo-terminal master/slave pair.
9236
9237
Performs an unlockpt() C function call.
9238
[clinic start generated code]*/
9239
9240
static PyObject *
9241
os_unlockpt_impl(PyObject *module, int fd)
9242
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9243
0
{
9244
0
    if (unlockpt(fd) == -1)
9245
0
        return posix_error();
9246
9247
0
    Py_RETURN_NONE;
9248
0
}
9249
#endif /* HAVE_UNLOCKPT */
9250
9251
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9252
static PyObject *
9253
py_ptsname(int fd)
9254
0
{
9255
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9256
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9257
0
    errno = 0;
9258
0
    char *name = ptsname(fd);
9259
0
    if (name == NULL) {
9260
0
        return posix_error();
9261
0
    }
9262
0
    return PyUnicode_DecodeFSDefault(name);
9263
0
}
9264
9265
/*[clinic input]
9266
os.ptsname
9267
9268
    fd: fildes
9269
        File descriptor of a master pseudo-terminal device.
9270
    /
9271
9272
Return the name of the slave pseudo-terminal device.
9273
9274
If the ptsname_r() C function is available, it is called;
9275
otherwise, performs a ptsname() C function call.
9276
[clinic start generated code]*/
9277
9278
static PyObject *
9279
os_ptsname_impl(PyObject *module, int fd)
9280
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9281
0
{
9282
0
#ifdef HAVE_PTSNAME_R
9283
0
    int ret;
9284
0
    char name[MAXPATHLEN+1];
9285
9286
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9287
0
        ret = ptsname_r(fd, name, sizeof(name));
9288
0
    }
9289
0
    else {
9290
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9291
0
        return py_ptsname(fd);
9292
0
    }
9293
0
    if (ret != 0) {
9294
0
        errno = ret;
9295
0
        return posix_error();
9296
0
    }
9297
9298
0
    return PyUnicode_DecodeFSDefault(name);
9299
#else
9300
    return py_ptsname(fd);
9301
#endif /* HAVE_PTSNAME_R */
9302
0
}
9303
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9304
9305
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9306
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9307
#  define DEV_PTY_FILE "/dev/ptc"
9308
#  define HAVE_DEV_PTMX
9309
#else
9310
#  define DEV_PTY_FILE "/dev/ptmx"
9311
#endif
9312
9313
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9314
#ifdef HAVE_PTY_H
9315
#include <pty.h>
9316
#elif defined(HAVE_LIBUTIL_H)
9317
#include <libutil.h>
9318
#elif defined(HAVE_UTIL_H)
9319
#include <util.h>
9320
#endif /* HAVE_PTY_H */
9321
#ifdef HAVE_UTMP_H
9322
#include <utmp.h>
9323
#endif /* HAVE_UTMP_H */
9324
#ifdef HAVE_STROPTS_H
9325
#include <stropts.h>
9326
#endif
9327
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9328
9329
9330
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9331
/*[clinic input]
9332
os.openpty
9333
9334
Open a pseudo-terminal.
9335
9336
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9337
for both the master and slave ends.
9338
[clinic start generated code]*/
9339
9340
static PyObject *
9341
os_openpty_impl(PyObject *module)
9342
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9343
0
{
9344
0
    int master_fd = -1, slave_fd = -1;
9345
#ifndef HAVE_OPENPTY
9346
    char * slave_name;
9347
#endif
9348
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9349
    PyOS_sighandler_t sig_saved;
9350
#if defined(__sun) && defined(__SVR4)
9351
    extern char *ptsname(int fildes);
9352
#endif
9353
#endif
9354
9355
0
#ifdef HAVE_OPENPTY
9356
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9357
0
        goto posix_error;
9358
9359
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9360
0
        goto error;
9361
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9362
0
        goto error;
9363
9364
#elif defined(HAVE__GETPTY)
9365
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9366
    if (slave_name == NULL)
9367
        goto posix_error;
9368
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9369
        goto error;
9370
9371
    slave_fd = _Py_open(slave_name, O_RDWR);
9372
    if (slave_fd < 0)
9373
        goto error;
9374
9375
#else
9376
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9377
    if (master_fd < 0)
9378
        goto posix_error;
9379
9380
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9381
9382
    /* change permission of slave */
9383
    if (grantpt(master_fd) < 0) {
9384
        int saved_errno = errno;
9385
        PyOS_setsig(SIGCHLD, sig_saved);
9386
        errno = saved_errno;
9387
        goto posix_error;
9388
    }
9389
9390
    /* unlock slave */
9391
    if (unlockpt(master_fd) < 0) {
9392
        int saved_errno = errno;
9393
        PyOS_setsig(SIGCHLD, sig_saved);
9394
        errno = saved_errno;
9395
        goto posix_error;
9396
    }
9397
9398
    PyOS_setsig(SIGCHLD, sig_saved);
9399
9400
    slave_name = ptsname(master_fd); /* get name of slave */
9401
    if (slave_name == NULL)
9402
        goto posix_error;
9403
9404
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9405
    if (slave_fd == -1)
9406
        goto error;
9407
9408
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9409
        goto posix_error;
9410
9411
#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC)
9412
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9413
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9414
#ifndef __hpux
9415
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9416
#endif /* __hpux */
9417
#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
9418
#endif /* HAVE_OPENPTY */
9419
9420
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9421
9422
0
posix_error:
9423
0
    posix_error();
9424
0
error:
9425
0
    if (master_fd != -1)
9426
0
        close(master_fd);
9427
0
    if (slave_fd != -1)
9428
0
        close(slave_fd);
9429
0
    return NULL;
9430
0
}
9431
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9432
9433
9434
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9435
#define HAVE_FALLBACK_LOGIN_TTY 1
9436
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9437
9438
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9439
/*[clinic input]
9440
os.login_tty
9441
9442
    fd: fildes
9443
    /
9444
9445
Prepare the tty of which fd is a file descriptor for a new login session.
9446
9447
Make the calling process a session leader; make the tty the
9448
controlling tty, the stdin, the stdout, and the stderr of the
9449
calling process; close fd.
9450
[clinic start generated code]*/
9451
9452
static PyObject *
9453
os_login_tty_impl(PyObject *module, int fd)
9454
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
9455
0
{
9456
0
#ifdef HAVE_LOGIN_TTY
9457
0
    if (login_tty(fd) == -1) {
9458
0
        return posix_error();
9459
0
    }
9460
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9461
    /* Establish a new session. */
9462
    if (setsid() == -1) {
9463
        return posix_error();
9464
    }
9465
9466
    /* The tty becomes the controlling terminal. */
9467
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9468
        return posix_error();
9469
    }
9470
9471
    /* The tty becomes stdin/stdout/stderr */
9472
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9473
        return posix_error();
9474
    }
9475
    if (fd > 2) {
9476
        close(fd);
9477
    }
9478
#endif /* HAVE_LOGIN_TTY */
9479
0
    Py_RETURN_NONE;
9480
0
}
9481
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9482
9483
9484
#ifdef HAVE_FORKPTY
9485
/*[clinic input]
9486
os.forkpty
9487
9488
Fork a new process with a new pseudo-terminal as controlling tty.
9489
9490
Returns a tuple of (pid, master_fd).
9491
Like fork(), return pid of 0 to the child process,
9492
and pid of child to the parent process.
9493
To both, return fd of newly opened pseudo-terminal.
9494
The master_fd is non-inheritable.
9495
[clinic start generated code]*/
9496
9497
static PyObject *
9498
os_forkpty_impl(PyObject *module)
9499
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9500
0
{
9501
0
    int master_fd = -1;
9502
0
    pid_t pid;
9503
9504
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9505
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9506
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9507
0
                        "can't fork at interpreter shutdown");
9508
0
        return NULL;
9509
0
    }
9510
0
    if (!_Py_IsMainInterpreter(interp)) {
9511
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9512
0
        return NULL;
9513
0
    }
9514
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9515
0
        return NULL;
9516
0
    }
9517
0
    PyOS_BeforeFork();
9518
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9519
0
    if (pid == 0) {
9520
        /* child: this clobbers and resets the import lock. */
9521
0
        PyOS_AfterFork_Child();
9522
0
    } else {
9523
        // Called before AfterFork_Parent in case those hooks start threads.
9524
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9525
        /* parent: release the import lock. */
9526
0
        PyOS_AfterFork_Parent();
9527
        /* set O_CLOEXEC on master_fd */
9528
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9529
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9530
0
                                   "non-inheritable in forkpty()");
9531
0
        }
9532
9533
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9534
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9535
0
            return NULL;
9536
0
    }
9537
0
    if (pid == -1) {
9538
0
        return posix_error();
9539
0
    }
9540
9541
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9542
0
}
9543
#endif /* HAVE_FORKPTY */
9544
9545
9546
#ifdef HAVE_GETEGID
9547
/*[clinic input]
9548
os.getegid
9549
9550
Return the current process's effective group id.
9551
[clinic start generated code]*/
9552
9553
static PyObject *
9554
os_getegid_impl(PyObject *module)
9555
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9556
37
{
9557
37
    return _PyLong_FromGid(getegid());
9558
37
}
9559
#endif /* HAVE_GETEGID */
9560
9561
9562
#ifdef HAVE_GETEUID
9563
/*[clinic input]
9564
os.geteuid
9565
9566
Return the current process's effective user id.
9567
[clinic start generated code]*/
9568
9569
static PyObject *
9570
os_geteuid_impl(PyObject *module)
9571
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9572
37
{
9573
37
    return _PyLong_FromUid(geteuid());
9574
37
}
9575
#endif /* HAVE_GETEUID */
9576
9577
9578
#ifdef HAVE_GETGID
9579
/*[clinic input]
9580
os.getgid
9581
9582
Return the current process's group id.
9583
[clinic start generated code]*/
9584
9585
static PyObject *
9586
os_getgid_impl(PyObject *module)
9587
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9588
37
{
9589
37
    return _PyLong_FromGid(getgid());
9590
37
}
9591
#endif /* HAVE_GETGID */
9592
9593
9594
#if defined(HAVE_GETPID)
9595
/*[clinic input]
9596
os.getpid
9597
9598
Return the current process id.
9599
[clinic start generated code]*/
9600
9601
static PyObject *
9602
os_getpid_impl(PyObject *module)
9603
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9604
4.78k
{
9605
4.78k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9606
4.78k
    return PyLong_FromPid(getpid());
9607
#else
9608
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9609
#endif
9610
4.78k
}
9611
#endif /* defined(HAVE_GETPID) */
9612
9613
#ifdef NGROUPS_MAX
9614
0
#define MAX_GROUPS NGROUPS_MAX
9615
#else
9616
    /* defined to be 16 on Solaris7, so this should be a small number */
9617
#define MAX_GROUPS 64
9618
#endif
9619
9620
#ifdef HAVE_GETGROUPLIST
9621
9622
#ifdef __APPLE__
9623
/*[clinic input]
9624
os.getgrouplist
9625
9626
    user: str
9627
        username to lookup
9628
    group as basegid: int
9629
        base group id of the user
9630
    /
9631
9632
Returns a list of groups to which a user belongs.
9633
[clinic start generated code]*/
9634
9635
static PyObject *
9636
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9637
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9638
#else
9639
/*[clinic input]
9640
os.getgrouplist
9641
9642
    user: str
9643
        username to lookup
9644
    group as basegid: gid_t
9645
        base group id of the user
9646
    /
9647
9648
Returns a list of groups to which a user belongs.
9649
[clinic start generated code]*/
9650
9651
static PyObject *
9652
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9653
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9654
#endif
9655
0
{
9656
0
    int i, ngroups;
9657
0
    PyObject *list;
9658
#ifdef __APPLE__
9659
    int *groups;
9660
#else
9661
0
    gid_t *groups;
9662
0
#endif
9663
9664
    /*
9665
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9666
     * number of supplemental groups a users can belong to.
9667
     * We have to increment it by one because
9668
     * getgrouplist() returns both the supplemental groups
9669
     * and the primary group, i.e. all of the groups the
9670
     * user belongs to.
9671
     */
9672
0
    ngroups = 1 + MAX_GROUPS;
9673
9674
0
    while (1) {
9675
#ifdef __APPLE__
9676
        groups = PyMem_New(int, ngroups);
9677
#else
9678
0
        groups = PyMem_New(gid_t, ngroups);
9679
0
#endif
9680
0
        if (groups == NULL) {
9681
0
            return PyErr_NoMemory();
9682
0
        }
9683
9684
0
        int old_ngroups = ngroups;
9685
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9686
            /* Success */
9687
0
            break;
9688
0
        }
9689
9690
        /* getgrouplist() fails if the group list is too small */
9691
0
        PyMem_Free(groups);
9692
9693
0
        if (ngroups > old_ngroups) {
9694
            /* If the group list is too small, the glibc implementation of
9695
               getgrouplist() sets ngroups to the total number of groups and
9696
               returns -1. */
9697
0
        }
9698
0
        else {
9699
            /* Double the group list size */
9700
0
            if (ngroups > INT_MAX / 2) {
9701
0
                return PyErr_NoMemory();
9702
0
            }
9703
0
            ngroups *= 2;
9704
0
        }
9705
9706
        /* Retry getgrouplist() with a larger group list */
9707
0
    }
9708
9709
#ifdef _Py_MEMORY_SANITIZER
9710
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9711
    __msan_unpoison(&ngroups, sizeof(ngroups));
9712
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9713
#endif
9714
9715
0
    list = PyList_New(ngroups);
9716
0
    if (list == NULL) {
9717
0
        PyMem_Free(groups);
9718
0
        return NULL;
9719
0
    }
9720
9721
0
    for (i = 0; i < ngroups; i++) {
9722
#ifdef __APPLE__
9723
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9724
#else
9725
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9726
0
#endif
9727
0
        if (o == NULL) {
9728
0
            Py_DECREF(list);
9729
0
            PyMem_Free(groups);
9730
0
            return NULL;
9731
0
        }
9732
0
        PyList_SET_ITEM(list, i, o);
9733
0
    }
9734
9735
0
    PyMem_Free(groups);
9736
9737
0
    return list;
9738
0
}
9739
#endif /* HAVE_GETGROUPLIST */
9740
9741
9742
#ifdef HAVE_GETGROUPS
9743
/*[clinic input]
9744
os.getgroups
9745
9746
Return list of supplemental group IDs for the process.
9747
[clinic start generated code]*/
9748
9749
static PyObject *
9750
os_getgroups_impl(PyObject *module)
9751
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9752
0
{
9753
    // Call getgroups with length 0 to get the actual number of groups
9754
0
    int n = getgroups(0, NULL);
9755
0
    if (n < 0) {
9756
0
        return posix_error();
9757
0
    }
9758
9759
0
    if (n == 0) {
9760
0
        return PyList_New(0);
9761
0
    }
9762
9763
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9764
0
    if (grouplist == NULL) {
9765
0
        return PyErr_NoMemory();
9766
0
    }
9767
9768
0
    n = getgroups(n, grouplist);
9769
0
    if (n == -1) {
9770
0
        posix_error();
9771
0
        PyMem_Free(grouplist);
9772
0
        return NULL;
9773
0
    }
9774
9775
0
    PyObject *result = PyList_New(n);
9776
0
    if (result == NULL) {
9777
0
        goto error;
9778
0
    }
9779
9780
0
    for (int i = 0; i < n; ++i) {
9781
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9782
0
        if (group == NULL) {
9783
0
            goto error;
9784
0
        }
9785
0
        PyList_SET_ITEM(result, i, group);
9786
0
    }
9787
0
    PyMem_Free(grouplist);
9788
9789
0
    return result;
9790
9791
0
error:
9792
0
    PyMem_Free(grouplist);
9793
0
    Py_XDECREF(result);
9794
0
    return NULL;
9795
0
}
9796
#endif /* HAVE_GETGROUPS */
9797
9798
#ifdef HAVE_INITGROUPS
9799
#ifdef __APPLE__
9800
/*[clinic input]
9801
os.initgroups
9802
9803
    username as oname: unicode_fs_encoded
9804
    gid: int
9805
    /
9806
9807
Initialize the group access list.
9808
9809
Call the system initgroups() to initialize the group access list with all of
9810
the groups of which the specified username is a member, plus the specified
9811
group id.
9812
[clinic start generated code]*/
9813
9814
static PyObject *
9815
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9816
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9817
#else
9818
/*[clinic input]
9819
os.initgroups
9820
9821
    username as oname: unicode_fs_encoded
9822
    gid: gid_t
9823
    /
9824
9825
Initialize the group access list.
9826
9827
Call the system initgroups() to initialize the group access list with all of
9828
the groups of which the specified username is a member, plus the specified
9829
group id.
9830
[clinic start generated code]*/
9831
9832
static PyObject *
9833
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9834
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9835
#endif
9836
0
{
9837
0
    const char *username = PyBytes_AS_STRING(oname);
9838
9839
0
    if (initgroups(username, gid) == -1)
9840
0
        return PyErr_SetFromErrno(PyExc_OSError);
9841
9842
0
    Py_RETURN_NONE;
9843
0
}
9844
#endif /* HAVE_INITGROUPS */
9845
9846
9847
#ifdef HAVE_GETPGID
9848
/*[clinic input]
9849
os.getpgid
9850
9851
    pid: pid_t
9852
9853
Call the system call getpgid(), and return the result.
9854
[clinic start generated code]*/
9855
9856
static PyObject *
9857
os_getpgid_impl(PyObject *module, pid_t pid)
9858
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9859
0
{
9860
0
    pid_t pgid = getpgid(pid);
9861
0
    if (pgid < 0)
9862
0
        return posix_error();
9863
0
    return PyLong_FromPid(pgid);
9864
0
}
9865
#endif /* HAVE_GETPGID */
9866
9867
9868
#ifdef HAVE_GETPGRP
9869
/*[clinic input]
9870
os.getpgrp
9871
9872
Return the current process group id.
9873
[clinic start generated code]*/
9874
9875
static PyObject *
9876
os_getpgrp_impl(PyObject *module)
9877
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9878
0
{
9879
#ifdef GETPGRP_HAVE_ARG
9880
    return PyLong_FromPid(getpgrp(0));
9881
#else /* GETPGRP_HAVE_ARG */
9882
0
    return PyLong_FromPid(getpgrp());
9883
0
#endif /* GETPGRP_HAVE_ARG */
9884
0
}
9885
#endif /* HAVE_GETPGRP */
9886
9887
9888
#ifdef HAVE_SETPGRP
9889
/*[clinic input]
9890
os.setpgrp
9891
9892
Make the current process the leader of its process group.
9893
[clinic start generated code]*/
9894
9895
static PyObject *
9896
os_setpgrp_impl(PyObject *module)
9897
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9898
0
{
9899
#ifdef SETPGRP_HAVE_ARG
9900
    if (setpgrp(0, 0) < 0)
9901
#else /* SETPGRP_HAVE_ARG */
9902
0
    if (setpgrp() < 0)
9903
0
#endif /* SETPGRP_HAVE_ARG */
9904
0
        return posix_error();
9905
0
    Py_RETURN_NONE;
9906
0
}
9907
#endif /* HAVE_SETPGRP */
9908
9909
#ifdef HAVE_GETPPID
9910
9911
#ifdef MS_WINDOWS
9912
#include <winternl.h>
9913
#include <ProcessSnapshot.h>
9914
9915
// The structure definition in winternl.h may be incomplete.
9916
// This structure is the full version from the MSDN documentation.
9917
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9918
    NTSTATUS ExitStatus;
9919
    PVOID PebBaseAddress;
9920
    ULONG_PTR AffinityMask;
9921
    LONG BasePriority;
9922
    ULONG_PTR UniqueProcessId;
9923
    ULONG_PTR InheritedFromUniqueProcessId;
9924
} PROCESS_BASIC_INFORMATION_FULL;
9925
9926
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9927
    IN    HANDLE           ProcessHandle,
9928
    IN    PROCESSINFOCLASS ProcessInformationClass,
9929
    OUT   PVOID            ProcessInformation,
9930
    IN    ULONG            ProcessInformationLength,
9931
    OUT   PULONG           ReturnLength OPTIONAL);
9932
9933
// This function returns the process ID of the parent process.
9934
// Returns 0 on failure.
9935
static ULONG
9936
win32_getppid_fast(void)
9937
{
9938
    NTSTATUS status;
9939
    HMODULE ntdll;
9940
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9941
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9942
    static ULONG cached_ppid = 0;
9943
9944
    if (cached_ppid) {
9945
        // No need to query the kernel again.
9946
        return cached_ppid;
9947
    }
9948
9949
    ntdll = GetModuleHandleW(L"ntdll.dll");
9950
    if (!ntdll) {
9951
        return 0;
9952
    }
9953
9954
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9955
    if (!pNtQueryInformationProcess) {
9956
        return 0;
9957
    }
9958
9959
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9960
                                        ProcessBasicInformation,
9961
                                        &basic_information,
9962
                                        sizeof(basic_information),
9963
                                        NULL);
9964
9965
    if (!NT_SUCCESS(status)) {
9966
        return 0;
9967
    }
9968
9969
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9970
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9971
    // zero and (ULONG) -1.
9972
9973
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9974
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9975
    {
9976
        return 0;
9977
    }
9978
9979
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9980
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9981
    // process. This process ID will be correctly returned even if the parent process has
9982
    // exited or been terminated.
9983
9984
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9985
    return cached_ppid;
9986
}
9987
9988
static PyObject*
9989
win32_getppid(void)
9990
{
9991
    DWORD error;
9992
    PyObject* result = NULL;
9993
    HANDLE process = GetCurrentProcess();
9994
    HPSS snapshot = NULL;
9995
    ULONG pid;
9996
9997
    pid = win32_getppid_fast();
9998
    if (pid != 0) {
9999
        return PyLong_FromUnsignedLong(pid);
10000
    }
10001
10002
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
10003
10004
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
10005
    if (error != ERROR_SUCCESS) {
10006
        return PyErr_SetFromWindowsErr(error);
10007
    }
10008
10009
    PSS_PROCESS_INFORMATION info;
10010
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
10011
                             sizeof(info));
10012
    if (error == ERROR_SUCCESS) {
10013
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
10014
    }
10015
    else {
10016
        result = PyErr_SetFromWindowsErr(error);
10017
    }
10018
10019
    PssFreeSnapshot(process, snapshot);
10020
    return result;
10021
}
10022
#endif /*MS_WINDOWS*/
10023
10024
10025
/*[clinic input]
10026
os.getppid
10027
10028
Return the parent's process id.
10029
10030
If the parent process has already exited, Windows machines will still
10031
return its id; others systems will return the id of the 'init' process (1).
10032
[clinic start generated code]*/
10033
10034
static PyObject *
10035
os_getppid_impl(PyObject *module)
10036
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
10037
0
{
10038
#ifdef MS_WINDOWS
10039
    return win32_getppid();
10040
#else
10041
0
    return PyLong_FromPid(getppid());
10042
0
#endif
10043
0
}
10044
#endif /* HAVE_GETPPID */
10045
10046
10047
#ifdef HAVE_GETLOGIN
10048
/*[clinic input]
10049
os.getlogin
10050
10051
Return the actual login name.
10052
[clinic start generated code]*/
10053
10054
static PyObject *
10055
os_getlogin_impl(PyObject *module)
10056
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10057
0
{
10058
0
    PyObject *result = NULL;
10059
#ifdef MS_WINDOWS
10060
    wchar_t user_name[UNLEN + 1];
10061
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10062
10063
    if (GetUserNameW(user_name, &num_chars)) {
10064
        /* num_chars is the number of unicode chars plus null terminator */
10065
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10066
    }
10067
    else
10068
        result = PyErr_SetFromWindowsErr(GetLastError());
10069
#elif defined (HAVE_GETLOGIN_R)
10070
# if defined (HAVE_MAXLOGNAME)
10071
    char name[MAXLOGNAME + 1];
10072
# elif defined (HAVE_UT_NAMESIZE)
10073
    char name[UT_NAMESIZE + 1];
10074
# else
10075
    char name[256];
10076
# endif
10077
0
    int err = getlogin_r(name, sizeof(name));
10078
0
    if (err) {
10079
0
        int old_errno = errno;
10080
0
        errno = err;
10081
0
        posix_error();
10082
0
        errno = old_errno;
10083
0
    }
10084
0
    else {
10085
0
        result = PyUnicode_DecodeFSDefault(name);
10086
0
    }
10087
#else
10088
    char *name;
10089
    int old_errno = errno;
10090
10091
    errno = 0;
10092
    name = getlogin();
10093
    if (name == NULL) {
10094
        if (errno)
10095
            posix_error();
10096
        else
10097
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10098
    }
10099
    else
10100
        result = PyUnicode_DecodeFSDefault(name);
10101
    errno = old_errno;
10102
#endif
10103
0
    return result;
10104
0
}
10105
#endif /* HAVE_GETLOGIN */
10106
10107
10108
#ifdef HAVE_GETUID
10109
/*[clinic input]
10110
os.getuid
10111
10112
Return the current process's user id.
10113
[clinic start generated code]*/
10114
10115
static PyObject *
10116
os_getuid_impl(PyObject *module)
10117
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10118
37
{
10119
37
    return _PyLong_FromUid(getuid());
10120
37
}
10121
#endif /* HAVE_GETUID */
10122
10123
10124
#ifdef MS_WINDOWS
10125
#define HAVE_KILL
10126
#endif /* MS_WINDOWS */
10127
10128
#ifdef HAVE_KILL
10129
/*[clinic input]
10130
os.kill
10131
10132
    pid: pid_t
10133
    signal: Py_ssize_t
10134
    /
10135
10136
Kill a process with a signal.
10137
[clinic start generated code]*/
10138
10139
static PyObject *
10140
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10141
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10142
0
{
10143
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10144
0
        return NULL;
10145
0
    }
10146
0
#ifndef MS_WINDOWS
10147
0
    if (kill(pid, (int)signal) == -1) {
10148
0
        return posix_error();
10149
0
    }
10150
10151
    // Check immediately if the signal was sent to the current process.
10152
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10153
    // is cheap.
10154
0
    if (PyErr_CheckSignals()) {
10155
0
        return NULL;
10156
0
    }
10157
10158
0
    Py_RETURN_NONE;
10159
#else /* !MS_WINDOWS */
10160
    DWORD sig = (DWORD)signal;
10161
10162
#ifdef HAVE_WINDOWS_CONSOLE_IO
10163
    /* Console processes which share a common console can be sent CTRL+C or
10164
       CTRL+BREAK events, provided they handle said events. */
10165
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10166
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10167
            return PyErr_SetFromWindowsErr(0);
10168
        }
10169
        Py_RETURN_NONE;
10170
    }
10171
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10172
10173
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10174
       attempt to open and terminate the process. */
10175
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10176
    if (handle == NULL) {
10177
        return PyErr_SetFromWindowsErr(0);
10178
    }
10179
10180
    BOOL res = TerminateProcess(handle, sig);
10181
    CloseHandle(handle);
10182
    if (res == 0) {
10183
        return PyErr_SetFromWindowsErr(0);
10184
    }
10185
10186
    Py_RETURN_NONE;
10187
#endif /* !MS_WINDOWS */
10188
0
}
10189
#endif /* HAVE_KILL */
10190
10191
10192
#ifdef HAVE_KILLPG
10193
/*[clinic input]
10194
os.killpg
10195
10196
    pgid: pid_t
10197
    signal: int
10198
    /
10199
10200
Kill a process group with a signal.
10201
[clinic start generated code]*/
10202
10203
static PyObject *
10204
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10205
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10206
0
{
10207
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10208
0
        return NULL;
10209
0
    }
10210
    /* XXX some man pages make the `pgid` parameter an int, others
10211
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10212
       take the same type. Moreover, pid_t is always at least as wide as
10213
       int (else compilation of this module fails), which is safe. */
10214
0
    if (killpg(pgid, signal) == -1)
10215
0
        return posix_error();
10216
0
    Py_RETURN_NONE;
10217
0
}
10218
#endif /* HAVE_KILLPG */
10219
10220
10221
#ifdef HAVE_PLOCK
10222
#ifdef HAVE_SYS_LOCK_H
10223
#include <sys/lock.h>
10224
#endif
10225
10226
/*[clinic input]
10227
os.plock
10228
    op: int
10229
    /
10230
10231
Lock program segments into memory.");
10232
[clinic start generated code]*/
10233
10234
static PyObject *
10235
os_plock_impl(PyObject *module, int op)
10236
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10237
{
10238
    if (plock(op) == -1)
10239
        return posix_error();
10240
    Py_RETURN_NONE;
10241
}
10242
#endif /* HAVE_PLOCK */
10243
10244
10245
#ifdef HAVE_SETUID
10246
/*[clinic input]
10247
os.setuid
10248
10249
    uid: uid_t
10250
    /
10251
10252
Set the current process's user id.
10253
[clinic start generated code]*/
10254
10255
static PyObject *
10256
os_setuid_impl(PyObject *module, uid_t uid)
10257
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10258
0
{
10259
0
    if (setuid(uid) < 0)
10260
0
        return posix_error();
10261
0
    Py_RETURN_NONE;
10262
0
}
10263
#endif /* HAVE_SETUID */
10264
10265
10266
#ifdef HAVE_SETEUID
10267
/*[clinic input]
10268
os.seteuid
10269
10270
    euid: uid_t
10271
    /
10272
10273
Set the current process's effective user id.
10274
[clinic start generated code]*/
10275
10276
static PyObject *
10277
os_seteuid_impl(PyObject *module, uid_t euid)
10278
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10279
0
{
10280
0
    if (seteuid(euid) < 0)
10281
0
        return posix_error();
10282
0
    Py_RETURN_NONE;
10283
0
}
10284
#endif /* HAVE_SETEUID */
10285
10286
10287
#ifdef HAVE_SETEGID
10288
/*[clinic input]
10289
os.setegid
10290
10291
    egid: gid_t
10292
    /
10293
10294
Set the current process's effective group id.
10295
[clinic start generated code]*/
10296
10297
static PyObject *
10298
os_setegid_impl(PyObject *module, gid_t egid)
10299
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10300
0
{
10301
0
    if (setegid(egid) < 0)
10302
0
        return posix_error();
10303
0
    Py_RETURN_NONE;
10304
0
}
10305
#endif /* HAVE_SETEGID */
10306
10307
10308
#ifdef HAVE_SETREUID
10309
/*[clinic input]
10310
os.setreuid
10311
10312
    ruid: uid_t
10313
    euid: uid_t
10314
    /
10315
10316
Set the current process's real and effective user ids.
10317
[clinic start generated code]*/
10318
10319
static PyObject *
10320
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10321
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10322
0
{
10323
0
    if (setreuid(ruid, euid) < 0) {
10324
0
        return posix_error();
10325
0
    } else {
10326
0
        Py_RETURN_NONE;
10327
0
    }
10328
0
}
10329
#endif /* HAVE_SETREUID */
10330
10331
10332
#ifdef HAVE_SETREGID
10333
/*[clinic input]
10334
os.setregid
10335
10336
    rgid: gid_t
10337
    egid: gid_t
10338
    /
10339
10340
Set the current process's real and effective group ids.
10341
[clinic start generated code]*/
10342
10343
static PyObject *
10344
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10345
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10346
0
{
10347
0
    if (setregid(rgid, egid) < 0)
10348
0
        return posix_error();
10349
0
    Py_RETURN_NONE;
10350
0
}
10351
#endif /* HAVE_SETREGID */
10352
10353
10354
#ifdef HAVE_SETGID
10355
/*[clinic input]
10356
os.setgid
10357
    gid: gid_t
10358
    /
10359
10360
Set the current process's group id.
10361
[clinic start generated code]*/
10362
10363
static PyObject *
10364
os_setgid_impl(PyObject *module, gid_t gid)
10365
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10366
0
{
10367
0
    if (setgid(gid) < 0)
10368
0
        return posix_error();
10369
0
    Py_RETURN_NONE;
10370
0
}
10371
#endif /* HAVE_SETGID */
10372
10373
10374
#ifdef HAVE_SETGROUPS
10375
/*[clinic input]
10376
os.setgroups
10377
10378
    groups: object
10379
    /
10380
10381
Set the groups of the current process to list.
10382
[clinic start generated code]*/
10383
10384
static PyObject *
10385
os_setgroups(PyObject *module, PyObject *groups)
10386
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10387
0
{
10388
0
    if (!PySequence_Check(groups)) {
10389
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10390
0
        return NULL;
10391
0
    }
10392
0
    Py_ssize_t len = PySequence_Size(groups);
10393
0
    if (len < 0) {
10394
0
        return NULL;
10395
0
    }
10396
0
    if (len > MAX_GROUPS) {
10397
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10398
0
        return NULL;
10399
0
    }
10400
10401
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10402
0
    if (grouplist == NULL) {
10403
0
        PyErr_NoMemory();
10404
0
        return NULL;
10405
0
    }
10406
0
    for (Py_ssize_t i = 0; i < len; i++) {
10407
0
        PyObject *elem;
10408
0
        elem = PySequence_GetItem(groups, i);
10409
0
        if (!elem) {
10410
0
            PyMem_Free(grouplist);
10411
0
            return NULL;
10412
0
        }
10413
0
        if (!PyIndex_Check(elem)) {
10414
0
            PyErr_SetString(PyExc_TypeError,
10415
0
                            "groups must be integers");
10416
0
            Py_DECREF(elem);
10417
0
            PyMem_Free(grouplist);
10418
0
            return NULL;
10419
0
        } else {
10420
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10421
0
                Py_DECREF(elem);
10422
0
                PyMem_Free(grouplist);
10423
0
                return NULL;
10424
0
            }
10425
0
        }
10426
0
        Py_DECREF(elem);
10427
0
    }
10428
10429
0
    if (setgroups(len, grouplist) < 0) {
10430
0
        posix_error();
10431
0
        PyMem_Free(grouplist);
10432
0
        return NULL;
10433
0
    }
10434
0
    PyMem_Free(grouplist);
10435
0
    Py_RETURN_NONE;
10436
0
}
10437
#endif /* HAVE_SETGROUPS */
10438
10439
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10440
static PyObject *
10441
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10442
0
{
10443
0
    PyObject *result;
10444
0
    PyObject *struct_rusage;
10445
10446
0
    if (pid == -1)
10447
0
        return posix_error();
10448
10449
    // If wait succeeded but no child was ready to report status, ru will not
10450
    // have been populated.
10451
0
    if (pid == 0) {
10452
0
        memset(ru, 0, sizeof(*ru));
10453
0
    }
10454
10455
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10456
0
    if (struct_rusage == NULL)
10457
0
        return NULL;
10458
10459
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10460
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10461
0
    Py_DECREF(struct_rusage);
10462
0
    if (!result)
10463
0
        return NULL;
10464
10465
0
    int pos = 0;
10466
10467
0
#ifndef doubletime
10468
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10469
0
#endif
10470
10471
0
#define SET_RESULT(CALL)                                     \
10472
0
    do {                                                     \
10473
0
        PyObject *item = (CALL);                             \
10474
0
        if (item == NULL) {                                  \
10475
0
            Py_DECREF(result);                               \
10476
0
            return NULL;                                     \
10477
0
        }                                                    \
10478
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10479
0
    } while(0)
10480
10481
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10482
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10483
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10484
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10485
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10486
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10487
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10488
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10489
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10490
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10491
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10492
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10493
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10494
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10495
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10496
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10497
0
#undef SET_RESULT
10498
10499
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10500
0
}
10501
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10502
10503
10504
#ifdef HAVE_WAIT3
10505
/*[clinic input]
10506
os.wait3
10507
10508
    options: int
10509
Wait for completion of a child process.
10510
10511
Returns a tuple of information about the child process:
10512
  (pid, status, rusage)
10513
[clinic start generated code]*/
10514
10515
static PyObject *
10516
os_wait3_impl(PyObject *module, int options)
10517
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10518
0
{
10519
0
    pid_t pid;
10520
0
    struct rusage ru;
10521
0
    int async_err = 0;
10522
0
    WAIT_TYPE status;
10523
0
    WAIT_STATUS_INT(status) = 0;
10524
10525
0
    do {
10526
0
        Py_BEGIN_ALLOW_THREADS
10527
0
        pid = wait3(&status, options, &ru);
10528
0
        Py_END_ALLOW_THREADS
10529
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10530
0
    if (pid < 0)
10531
0
        return (!async_err) ? posix_error() : NULL;
10532
10533
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10534
0
}
10535
#endif /* HAVE_WAIT3 */
10536
10537
10538
#ifdef HAVE_WAIT4
10539
/*[clinic input]
10540
10541
os.wait4
10542
10543
    pid: pid_t
10544
    options: int
10545
10546
Wait for completion of a specific child process.
10547
10548
Returns a tuple of information about the child process:
10549
  (pid, status, rusage)
10550
[clinic start generated code]*/
10551
10552
static PyObject *
10553
os_wait4_impl(PyObject *module, pid_t pid, int options)
10554
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10555
0
{
10556
0
    pid_t res;
10557
0
    struct rusage ru;
10558
0
    int async_err = 0;
10559
0
    WAIT_TYPE status;
10560
0
    WAIT_STATUS_INT(status) = 0;
10561
10562
0
    do {
10563
0
        Py_BEGIN_ALLOW_THREADS
10564
0
        res = wait4(pid, &status, options, &ru);
10565
0
        Py_END_ALLOW_THREADS
10566
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10567
0
    if (res < 0)
10568
0
        return (!async_err) ? posix_error() : NULL;
10569
10570
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10571
0
}
10572
#endif /* HAVE_WAIT4 */
10573
10574
10575
#if defined(HAVE_WAITID)
10576
/*[clinic input]
10577
os.waitid
10578
10579
    idtype: idtype_t
10580
        Must be one of be P_PID, P_PGID or P_ALL.
10581
    id: id_t
10582
        The id to wait on.
10583
    options: int
10584
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10585
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10586
    /
10587
10588
Returns the result of waiting for a process or processes.
10589
10590
Returns either waitid_result or None if WNOHANG is specified and there are
10591
no children in a waitable state.
10592
[clinic start generated code]*/
10593
10594
static PyObject *
10595
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10596
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10597
0
{
10598
0
    PyObject *result;
10599
0
    int res;
10600
0
    int async_err = 0;
10601
0
    siginfo_t si;
10602
0
    si.si_pid = 0;
10603
10604
0
    do {
10605
0
        Py_BEGIN_ALLOW_THREADS
10606
0
        res = waitid(idtype, id, &si, options);
10607
0
        Py_END_ALLOW_THREADS
10608
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10609
0
    if (res < 0)
10610
0
        return (!async_err) ? posix_error() : NULL;
10611
10612
0
    if (si.si_pid == 0)
10613
0
        Py_RETURN_NONE;
10614
10615
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10616
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10617
0
    if (!result)
10618
0
        return NULL;
10619
10620
0
    int pos = 0;
10621
10622
0
#define SET_RESULT(CALL)                                     \
10623
0
    do {                                                     \
10624
0
        PyObject *item = (CALL);                             \
10625
0
        if (item == NULL) {                                  \
10626
0
            Py_DECREF(result);                               \
10627
0
            return NULL;                                     \
10628
0
        }                                                    \
10629
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10630
0
    } while(0)
10631
10632
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10633
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10634
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10635
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10636
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10637
10638
0
#undef SET_RESULT
10639
10640
0
    return result;
10641
0
}
10642
#endif /* defined(HAVE_WAITID) */
10643
10644
10645
#if defined(HAVE_WAITPID)
10646
/*[clinic input]
10647
os.waitpid
10648
    pid: pid_t
10649
    options: int
10650
    /
10651
10652
Wait for completion of a given child process.
10653
10654
Returns a tuple of information regarding the child process:
10655
    (pid, status)
10656
10657
The options argument is ignored on Windows.
10658
[clinic start generated code]*/
10659
10660
static PyObject *
10661
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10662
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10663
0
{
10664
0
    pid_t res;
10665
0
    int async_err = 0;
10666
0
    WAIT_TYPE status;
10667
0
    WAIT_STATUS_INT(status) = 0;
10668
10669
0
    do {
10670
0
        Py_BEGIN_ALLOW_THREADS
10671
0
        res = waitpid(pid, &status, options);
10672
0
        Py_END_ALLOW_THREADS
10673
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10674
0
    if (res < 0)
10675
0
        return (!async_err) ? posix_error() : NULL;
10676
10677
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10678
0
}
10679
#elif defined(HAVE_CWAIT)
10680
/* MS C has a variant of waitpid() that's usable for most purposes. */
10681
/*[clinic input]
10682
os.waitpid
10683
    pid: intptr_t
10684
    options: int
10685
    /
10686
10687
Wait for completion of a given process.
10688
10689
Returns a tuple of information regarding the process:
10690
    (pid, status << 8)
10691
10692
The options argument is ignored on Windows.
10693
[clinic start generated code]*/
10694
10695
static PyObject *
10696
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10697
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10698
{
10699
    int status;
10700
    intptr_t res;
10701
    int async_err = 0;
10702
10703
    do {
10704
        Py_BEGIN_ALLOW_THREADS
10705
        _Py_BEGIN_SUPPRESS_IPH
10706
        res = _cwait(&status, pid, options);
10707
        _Py_END_SUPPRESS_IPH
10708
        Py_END_ALLOW_THREADS
10709
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10710
    if (res < 0)
10711
        return (!async_err) ? posix_error() : NULL;
10712
10713
    unsigned long long ustatus = (unsigned int)status;
10714
10715
    /* shift the status left a byte so this is more like the POSIX waitpid */
10716
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10717
}
10718
#endif
10719
10720
10721
#ifdef HAVE_WAIT
10722
/*[clinic input]
10723
os.wait
10724
10725
Wait for completion of a child process.
10726
10727
Returns a tuple of information about the child process:
10728
    (pid, status)
10729
[clinic start generated code]*/
10730
10731
static PyObject *
10732
os_wait_impl(PyObject *module)
10733
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10734
0
{
10735
0
    pid_t pid;
10736
0
    int async_err = 0;
10737
0
    WAIT_TYPE status;
10738
0
    WAIT_STATUS_INT(status) = 0;
10739
10740
0
    do {
10741
0
        Py_BEGIN_ALLOW_THREADS
10742
0
        pid = wait(&status);
10743
0
        Py_END_ALLOW_THREADS
10744
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10745
0
    if (pid < 0)
10746
0
        return (!async_err) ? posix_error() : NULL;
10747
10748
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10749
0
}
10750
#endif /* HAVE_WAIT */
10751
10752
10753
// This system call always crashes on older Android versions.
10754
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10755
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10756
/*[clinic input]
10757
os.pidfd_open
10758
  pid: pid_t
10759
  flags: unsigned_int = 0
10760
10761
Return a file descriptor referring to the process *pid*.
10762
10763
The descriptor can be used to perform process management without races and
10764
signals.
10765
[clinic start generated code]*/
10766
10767
static PyObject *
10768
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10769
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10770
4
{
10771
4
    int fd = syscall(__NR_pidfd_open, pid, flags);
10772
4
    if (fd < 0) {
10773
0
        return posix_error();
10774
0
    }
10775
4
    return PyLong_FromLong(fd);
10776
4
}
10777
#endif
10778
10779
10780
#ifdef HAVE_SETNS
10781
/*[clinic input]
10782
os.setns
10783
  fd: fildes
10784
    A file descriptor to a namespace.
10785
  nstype: int = 0
10786
    Type of namespace.
10787
10788
Move the calling thread into different namespaces.
10789
[clinic start generated code]*/
10790
10791
static PyObject *
10792
os_setns_impl(PyObject *module, int fd, int nstype)
10793
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10794
0
{
10795
0
    int res;
10796
10797
0
    Py_BEGIN_ALLOW_THREADS
10798
0
    res = setns(fd, nstype);
10799
0
    Py_END_ALLOW_THREADS
10800
10801
0
    if (res != 0) {
10802
0
        return posix_error();
10803
0
    }
10804
10805
0
    Py_RETURN_NONE;
10806
0
}
10807
#endif
10808
10809
10810
#ifdef HAVE_UNSHARE
10811
/*[clinic input]
10812
os.unshare
10813
  flags: int
10814
    Namespaces to be unshared.
10815
10816
Disassociate parts of a process (or thread) execution context.
10817
[clinic start generated code]*/
10818
10819
static PyObject *
10820
os_unshare_impl(PyObject *module, int flags)
10821
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10822
0
{
10823
0
    int res;
10824
10825
0
    Py_BEGIN_ALLOW_THREADS
10826
0
    res = unshare(flags);
10827
0
    Py_END_ALLOW_THREADS
10828
10829
0
    if (res != 0) {
10830
0
        return posix_error();
10831
0
    }
10832
10833
0
    Py_RETURN_NONE;
10834
0
}
10835
#endif
10836
10837
10838
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10839
/*[clinic input]
10840
os.readlink
10841
10842
    path: path_t
10843
    *
10844
    dir_fd: dir_fd(requires='readlinkat') = None
10845
10846
Return a string representing the path to which the symbolic link points.
10847
10848
If dir_fd is not None, it should be a file descriptor open to a directory,
10849
and path should be relative; path will then be relative to that directory.
10850
10851
dir_fd may not be implemented on your platform.  If it is unavailable,
10852
using it will raise a NotImplementedError.
10853
[clinic start generated code]*/
10854
10855
static PyObject *
10856
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10857
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10858
6
{
10859
6
#if defined(HAVE_READLINK)
10860
6
    char buffer[MAXPATHLEN+1];
10861
6
    ssize_t length;
10862
6
#ifdef HAVE_READLINKAT
10863
6
    int readlinkat_unavailable = 0;
10864
6
#endif
10865
10866
6
    Py_BEGIN_ALLOW_THREADS
10867
6
#ifdef HAVE_READLINKAT
10868
6
    if (dir_fd != DEFAULT_DIR_FD) {
10869
0
        if (HAVE_READLINKAT_RUNTIME) {
10870
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10871
0
        } else {
10872
0
            readlinkat_unavailable = 1;
10873
0
        }
10874
0
    } else
10875
6
#endif
10876
6
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10877
6
    Py_END_ALLOW_THREADS
10878
10879
6
#ifdef HAVE_READLINKAT
10880
6
    if (readlinkat_unavailable) {
10881
0
        argument_unavailable_error(NULL, "dir_fd");
10882
0
        return NULL;
10883
0
    }
10884
6
#endif
10885
10886
6
    if (length < 0) {
10887
0
        return path_error(path);
10888
0
    }
10889
6
    buffer[length] = '\0';
10890
10891
6
    if (PyUnicode_Check(path->object))
10892
6
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10893
0
    else
10894
0
        return PyBytes_FromStringAndSize(buffer, length);
10895
#elif defined(MS_WINDOWS)
10896
    DWORD n_bytes_returned;
10897
    DWORD io_result = 0;
10898
    HANDLE reparse_point_handle;
10899
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10900
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10901
    PyObject *result = NULL;
10902
10903
    /* First get a handle to the reparse point */
10904
    Py_BEGIN_ALLOW_THREADS
10905
    reparse_point_handle = CreateFileW(
10906
        path->wide,
10907
        0,
10908
        0,
10909
        0,
10910
        OPEN_EXISTING,
10911
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10912
        0);
10913
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10914
        /* New call DeviceIoControl to read the reparse point */
10915
        io_result = DeviceIoControl(
10916
            reparse_point_handle,
10917
            FSCTL_GET_REPARSE_POINT,
10918
            0, 0, /* in buffer */
10919
            target_buffer, sizeof(target_buffer),
10920
            &n_bytes_returned,
10921
            0 /* we're not using OVERLAPPED_IO */
10922
            );
10923
        CloseHandle(reparse_point_handle);
10924
    }
10925
    Py_END_ALLOW_THREADS
10926
10927
    if (io_result == 0) {
10928
        return path_error(path);
10929
    }
10930
10931
    wchar_t *name = NULL;
10932
    Py_ssize_t nameLen = 0;
10933
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10934
    {
10935
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10936
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10937
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10938
    }
10939
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10940
    {
10941
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10942
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10943
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10944
    }
10945
    else
10946
    {
10947
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10948
    }
10949
    if (name) {
10950
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10951
            /* Our buffer is mutable, so this is okay */
10952
            name[1] = L'\\';
10953
        }
10954
        result = PyUnicode_FromWideChar(name, nameLen);
10955
        if (result && PyBytes_Check(path->object)) {
10956
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10957
        }
10958
    }
10959
    return result;
10960
#endif
10961
6
}
10962
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10963
10964
#if defined(MS_WINDOWS)
10965
10966
/* Remove the last portion of the path - return 0 on success */
10967
static int
10968
_dirnameW(WCHAR *path)
10969
{
10970
    WCHAR *ptr;
10971
    size_t length = wcsnlen_s(path, MAX_PATH);
10972
    if (length == MAX_PATH) {
10973
        return -1;
10974
    }
10975
10976
    /* walk the path from the end until a backslash is encountered */
10977
    for(ptr = path + length; ptr != path; ptr--) {
10978
        if (*ptr == L'\\' || *ptr == L'/') {
10979
            break;
10980
        }
10981
    }
10982
    *ptr = 0;
10983
    return 0;
10984
}
10985
10986
#endif
10987
10988
#ifdef HAVE_SYMLINK
10989
10990
#if defined(MS_WINDOWS)
10991
10992
/* Is this path absolute? */
10993
static int
10994
_is_absW(const WCHAR *path)
10995
{
10996
    return path[0] == L'\\' || path[0] == L'/' ||
10997
        (path[0] && path[1] == L':');
10998
}
10999
11000
/* join root and rest with a backslash - return 0 on success */
11001
static int
11002
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
11003
{
11004
    if (_is_absW(rest)) {
11005
        return wcscpy_s(dest_path, MAX_PATH, rest);
11006
    }
11007
11008
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
11009
        return -1;
11010
    }
11011
11012
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
11013
        return -1;
11014
    }
11015
11016
    return wcscat_s(dest_path, MAX_PATH, rest);
11017
}
11018
11019
/* Return True if the path at src relative to dest is a directory */
11020
static int
11021
_check_dirW(LPCWSTR src, LPCWSTR dest)
11022
{
11023
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11024
    WCHAR dest_parent[MAX_PATH];
11025
    WCHAR src_resolved[MAX_PATH] = L"";
11026
11027
    /* dest_parent = os.path.dirname(dest) */
11028
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11029
        _dirnameW(dest_parent)) {
11030
        return 0;
11031
    }
11032
    /* src_resolved = os.path.join(dest_parent, src) */
11033
    if (_joinW(src_resolved, dest_parent, src)) {
11034
        return 0;
11035
    }
11036
    return (
11037
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11038
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11039
    );
11040
}
11041
#endif
11042
11043
11044
/*[clinic input]
11045
os.symlink
11046
    src: path_t
11047
    dst: path_t
11048
    target_is_directory: bool = False
11049
    *
11050
    dir_fd: dir_fd(requires='symlinkat')=None
11051
11052
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
11053
11054
Create a symbolic link pointing to src named dst.
11055
11056
target_is_directory is required on Windows if the target is to be
11057
  interpreted as a directory.  (On Windows, symlink requires
11058
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
11059
  target_is_directory is ignored on non-Windows platforms.
11060
11061
If dir_fd is not None, it should be a file descriptor open to a directory,
11062
  and path should be relative; path will then be relative to that directory.
11063
dir_fd may not be implemented on your platform.
11064
  If it is unavailable, using it will raise a NotImplementedError.
11065
11066
[clinic start generated code]*/
11067
11068
static PyObject *
11069
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11070
                int target_is_directory, int dir_fd)
11071
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
11072
0
{
11073
#ifdef MS_WINDOWS
11074
    DWORD result;
11075
    DWORD flags = 0;
11076
11077
    /* Assumed true, set to false if detected to not be available. */
11078
    static int windows_has_symlink_unprivileged_flag = TRUE;
11079
#else
11080
0
    int result;
11081
0
#ifdef HAVE_SYMLINKAT
11082
0
    int symlinkat_unavailable = 0;
11083
0
#endif
11084
0
#endif
11085
11086
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11087
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11088
0
        return NULL;
11089
0
    }
11090
11091
#ifdef MS_WINDOWS
11092
11093
    if (windows_has_symlink_unprivileged_flag) {
11094
        /* Allow non-admin symlinks if system allows it. */
11095
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11096
    }
11097
11098
    Py_BEGIN_ALLOW_THREADS
11099
    _Py_BEGIN_SUPPRESS_IPH
11100
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11101
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11102
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11103
    }
11104
11105
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11106
    _Py_END_SUPPRESS_IPH
11107
    Py_END_ALLOW_THREADS
11108
11109
    if (windows_has_symlink_unprivileged_flag && !result &&
11110
        ERROR_INVALID_PARAMETER == GetLastError()) {
11111
11112
        Py_BEGIN_ALLOW_THREADS
11113
        _Py_BEGIN_SUPPRESS_IPH
11114
        /* This error might be caused by
11115
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11116
        Try again, and update windows_has_symlink_unprivileged_flag if we
11117
        are successful this time.
11118
11119
        NOTE: There is a risk of a race condition here if there are other
11120
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11121
        another process (or thread) changes that condition in between our
11122
        calls to CreateSymbolicLink.
11123
        */
11124
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11125
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11126
        _Py_END_SUPPRESS_IPH
11127
        Py_END_ALLOW_THREADS
11128
11129
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11130
            windows_has_symlink_unprivileged_flag = FALSE;
11131
        }
11132
    }
11133
11134
    if (!result)
11135
        return path_error2(src, dst);
11136
11137
#else
11138
11139
0
    Py_BEGIN_ALLOW_THREADS
11140
0
#ifdef HAVE_SYMLINKAT
11141
0
    if (dir_fd != DEFAULT_DIR_FD) {
11142
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11143
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11144
0
        } else {
11145
0
            symlinkat_unavailable = 1;
11146
0
        }
11147
0
    } else
11148
0
#endif
11149
0
        result = symlink(src->narrow, dst->narrow);
11150
0
    Py_END_ALLOW_THREADS
11151
11152
0
#ifdef HAVE_SYMLINKAT
11153
0
    if (symlinkat_unavailable) {
11154
0
          argument_unavailable_error(NULL, "dir_fd");
11155
0
          return NULL;
11156
0
    }
11157
0
#endif
11158
11159
0
    if (result)
11160
0
        return path_error2(src, dst);
11161
0
#endif
11162
11163
0
    Py_RETURN_NONE;
11164
0
}
11165
#endif /* HAVE_SYMLINK */
11166
11167
11168
static PyStructSequence_Field times_result_fields[] = {
11169
    {"user",    "user time"},
11170
    {"system",   "system time"},
11171
    {"children_user",    "user time of children"},
11172
    {"children_system",    "system time of children"},
11173
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11174
    {NULL}
11175
};
11176
11177
PyDoc_STRVAR(times_result__doc__,
11178
"times_result: Result from os.times().\n\n\
11179
This object may be accessed either as a tuple of\n\
11180
  (user, system, children_user, children_system, elapsed),\n\
11181
or via the attributes user, system, children_user, children_system,\n\
11182
and elapsed.\n\
11183
\n\
11184
See os.times for more information.");
11185
11186
static PyStructSequence_Desc times_result_desc = {
11187
    MODNAME ".times_result", /* name */
11188
    times_result__doc__, /* doc */
11189
    times_result_fields,
11190
    5
11191
};
11192
11193
static PyObject *
11194
build_times_result(PyObject *module, double user, double system,
11195
    double children_user, double children_system,
11196
    double elapsed)
11197
0
{
11198
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11199
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11200
0
    if (value == NULL)
11201
0
        return NULL;
11202
11203
0
#define SET(i, field) \
11204
0
    { \
11205
0
    PyObject *o = PyFloat_FromDouble(field); \
11206
0
    if (!o) { \
11207
0
        Py_DECREF(value); \
11208
0
        return NULL; \
11209
0
    } \
11210
0
    PyStructSequence_SET_ITEM(value, i, o); \
11211
0
    } \
11212
0
11213
0
    SET(0, user);
11214
0
    SET(1, system);
11215
0
    SET(2, children_user);
11216
0
    SET(3, children_system);
11217
0
    SET(4, elapsed);
11218
11219
0
#undef SET
11220
11221
0
    return value;
11222
0
}
11223
11224
11225
/*[clinic input]
11226
os.times
11227
11228
Return a collection containing process timing information.
11229
11230
The object returned behaves like a named tuple with these fields:
11231
  (utime, stime, cutime, cstime, elapsed_time)
11232
All fields are floating-point numbers.
11233
[clinic start generated code]*/
11234
11235
static PyObject *
11236
os_times_impl(PyObject *module)
11237
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11238
0
{
11239
#ifdef MS_WINDOWS
11240
    FILETIME create, exit, kernel, user;
11241
    HANDLE hProc;
11242
    hProc = GetCurrentProcess();
11243
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11244
    /* The fields of a FILETIME structure are the hi and lo part
11245
       of a 64-bit value expressed in 100 nanosecond units.
11246
       1e7 is one second in such units; 1e-7 the inverse.
11247
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11248
    */
11249
    return build_times_result(module,
11250
        (double)(user.dwHighDateTime*429.4967296 +
11251
                 user.dwLowDateTime*1e-7),
11252
        (double)(kernel.dwHighDateTime*429.4967296 +
11253
                 kernel.dwLowDateTime*1e-7),
11254
        (double)0,
11255
        (double)0,
11256
        (double)0);
11257
#else /* MS_WINDOWS */
11258
0
    _posixstate *state = get_posix_state(module);
11259
0
    long ticks_per_second = state->ticks_per_second;
11260
11261
0
    struct tms process;
11262
0
    clock_t elapsed;
11263
0
    errno = 0;
11264
0
    elapsed = times(&process);
11265
0
    if (elapsed == (clock_t) -1) {
11266
0
        return posix_error();
11267
0
    }
11268
11269
0
    return build_times_result(module,
11270
0
        (double)process.tms_utime / ticks_per_second,
11271
0
        (double)process.tms_stime / ticks_per_second,
11272
0
        (double)process.tms_cutime / ticks_per_second,
11273
0
        (double)process.tms_cstime / ticks_per_second,
11274
0
        (double)elapsed / ticks_per_second);
11275
0
#endif /* MS_WINDOWS */
11276
0
}
11277
11278
11279
#if defined(HAVE_TIMERFD_CREATE)
11280
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11281
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11282
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11283
11284
static PyObject *
11285
build_itimerspec(const struct itimerspec* curr_value)
11286
0
{
11287
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11288
0
                                                          curr_value->it_value.tv_nsec);
11289
0
    PyObject *value = PyFloat_FromDouble(_value);
11290
0
    if (value == NULL) {
11291
0
        return NULL;
11292
0
    }
11293
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11294
0
                                                   curr_value->it_interval.tv_nsec);
11295
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11296
0
    if (interval == NULL) {
11297
0
        Py_DECREF(value);
11298
0
        return NULL;
11299
0
    }
11300
0
    return _PyTuple_FromPairSteal(value, interval);
11301
0
}
11302
11303
static PyObject *
11304
build_itimerspec_ns(const struct itimerspec* curr_value)
11305
0
{
11306
0
    PyTime_t value, interval;
11307
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11308
0
        return NULL;
11309
0
    }
11310
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11311
0
        return NULL;
11312
0
    }
11313
0
    return Py_BuildValue("LL", value, interval);
11314
0
}
11315
11316
/*[clinic input]
11317
os.timerfd_create
11318
11319
    clockid: int
11320
        A valid clock ID constant as timer file descriptor.
11321
11322
        time.CLOCK_REALTIME
11323
        time.CLOCK_MONOTONIC
11324
        time.CLOCK_BOOTTIME
11325
    /
11326
    *
11327
    flags: int = 0
11328
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11329
11330
        os.TFD_NONBLOCK
11331
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11332
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11333
11334
        os.TFD_CLOEXEC
11335
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11336
11337
Create and return a timer file descriptor.
11338
[clinic start generated code]*/
11339
11340
static PyObject *
11341
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11342
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11343
11344
0
{
11345
0
    int fd;
11346
0
    Py_BEGIN_ALLOW_THREADS
11347
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11348
0
    fd = timerfd_create(clockid, flags);
11349
0
    Py_END_ALLOW_THREADS
11350
0
    if (fd == -1) {
11351
0
        return PyErr_SetFromErrno(PyExc_OSError);
11352
0
    }
11353
0
    return PyLong_FromLong(fd);
11354
0
}
11355
11356
/*[clinic input]
11357
os.timerfd_settime
11358
11359
    fd: fildes
11360
        A timer file descriptor.
11361
    /
11362
    *
11363
    flags: int = 0
11364
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11365
    initial as initial_double: double = 0.0
11366
        The initial expiration time, in seconds.
11367
    interval as interval_double: double = 0.0
11368
        The timer's interval, in seconds.
11369
11370
Alter a timer file descriptor's internal timer in seconds.
11371
[clinic start generated code]*/
11372
11373
static PyObject *
11374
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11375
                        double initial_double, double interval_double)
11376
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11377
0
{
11378
0
    PyTime_t initial, interval;
11379
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11380
0
                                  &initial) < 0) {
11381
0
        return NULL;
11382
0
    }
11383
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11384
0
                                  &interval) < 0) {
11385
0
        return NULL;
11386
0
    }
11387
11388
0
    struct itimerspec new_value, old_value;
11389
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11390
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11391
0
        return NULL;
11392
0
    }
11393
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11394
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11395
0
        return NULL;
11396
0
    }
11397
11398
0
    int result;
11399
0
    Py_BEGIN_ALLOW_THREADS
11400
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11401
0
    Py_END_ALLOW_THREADS
11402
0
    if (result == -1) {
11403
0
        return PyErr_SetFromErrno(PyExc_OSError);
11404
0
    }
11405
0
    return build_itimerspec(&old_value);
11406
0
}
11407
11408
11409
/*[clinic input]
11410
os.timerfd_settime_ns
11411
11412
    fd: fildes
11413
        A timer file descriptor.
11414
    /
11415
    *
11416
    flags: int = 0
11417
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11418
    initial: long_long = 0
11419
        initial expiration timing in seconds.
11420
    interval: long_long = 0
11421
        interval for the timer in seconds.
11422
11423
Alter a timer file descriptor's internal timer in nanoseconds.
11424
[clinic start generated code]*/
11425
11426
static PyObject *
11427
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11428
                           long long initial, long long interval)
11429
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11430
0
{
11431
0
    struct itimerspec new_value;
11432
0
    struct itimerspec old_value;
11433
0
    int result;
11434
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11435
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11436
0
        return NULL;
11437
0
    }
11438
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11439
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11440
0
        return NULL;
11441
0
    }
11442
0
    Py_BEGIN_ALLOW_THREADS
11443
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11444
0
    Py_END_ALLOW_THREADS
11445
0
    if (result == -1) {
11446
0
        return PyErr_SetFromErrno(PyExc_OSError);
11447
0
    }
11448
0
    return build_itimerspec_ns(&old_value);
11449
0
}
11450
11451
/*[clinic input]
11452
@permit_long_summary
11453
os.timerfd_gettime
11454
11455
    fd: fildes
11456
        A timer file descriptor.
11457
    /
11458
11459
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11460
[clinic start generated code]*/
11461
11462
static PyObject *
11463
os_timerfd_gettime_impl(PyObject *module, int fd)
11464
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11465
0
{
11466
0
    struct itimerspec curr_value;
11467
0
    int result;
11468
0
    Py_BEGIN_ALLOW_THREADS
11469
0
    result = timerfd_gettime(fd, &curr_value);
11470
0
    Py_END_ALLOW_THREADS
11471
0
    if (result == -1) {
11472
0
        return PyErr_SetFromErrno(PyExc_OSError);
11473
0
    }
11474
0
    return build_itimerspec(&curr_value);
11475
0
}
11476
11477
11478
/*[clinic input]
11479
@permit_long_summary
11480
os.timerfd_gettime_ns
11481
11482
    fd: fildes
11483
        A timer file descriptor.
11484
    /
11485
11486
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11487
[clinic start generated code]*/
11488
11489
static PyObject *
11490
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11491
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11492
0
{
11493
0
    struct itimerspec curr_value;
11494
0
    int result;
11495
0
    Py_BEGIN_ALLOW_THREADS
11496
0
    result = timerfd_gettime(fd, &curr_value);
11497
0
    Py_END_ALLOW_THREADS
11498
0
    if (result == -1) {
11499
0
        return PyErr_SetFromErrno(PyExc_OSError);
11500
0
    }
11501
0
    return build_itimerspec_ns(&curr_value);
11502
0
}
11503
11504
#undef ONE_SECOND_IN_NS
11505
#undef EXTRACT_NSEC
11506
11507
#endif  /* HAVE_TIMERFD_CREATE */
11508
11509
#ifdef HAVE_GETSID
11510
/*[clinic input]
11511
os.getsid
11512
11513
    pid: pid_t
11514
    /
11515
11516
Call the system call getsid(pid) and return the result.
11517
[clinic start generated code]*/
11518
11519
static PyObject *
11520
os_getsid_impl(PyObject *module, pid_t pid)
11521
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11522
0
{
11523
0
    int sid;
11524
0
    sid = getsid(pid);
11525
0
    if (sid < 0)
11526
0
        return posix_error();
11527
0
    return PyLong_FromLong((long)sid);
11528
0
}
11529
#endif /* HAVE_GETSID */
11530
11531
11532
#ifdef HAVE_SETSID
11533
/*[clinic input]
11534
os.setsid
11535
11536
Call the system call setsid().
11537
[clinic start generated code]*/
11538
11539
static PyObject *
11540
os_setsid_impl(PyObject *module)
11541
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11542
0
{
11543
0
    if (setsid() < 0)
11544
0
        return posix_error();
11545
0
    Py_RETURN_NONE;
11546
0
}
11547
#endif /* HAVE_SETSID */
11548
11549
11550
#ifdef HAVE_SETPGID
11551
/*[clinic input]
11552
os.setpgid
11553
11554
    pid: pid_t
11555
    pgrp: pid_t
11556
    /
11557
11558
Call the system call setpgid(pid, pgrp).
11559
[clinic start generated code]*/
11560
11561
static PyObject *
11562
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11563
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11564
0
{
11565
0
    if (setpgid(pid, pgrp) < 0)
11566
0
        return posix_error();
11567
0
    Py_RETURN_NONE;
11568
0
}
11569
#endif /* HAVE_SETPGID */
11570
11571
11572
#ifdef HAVE_TCGETPGRP
11573
/*[clinic input]
11574
os.tcgetpgrp
11575
11576
    fd: int
11577
    /
11578
11579
Return the process group associated with the terminal specified by fd.
11580
[clinic start generated code]*/
11581
11582
static PyObject *
11583
os_tcgetpgrp_impl(PyObject *module, int fd)
11584
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11585
0
{
11586
0
    pid_t pgid = tcgetpgrp(fd);
11587
0
    if (pgid < 0)
11588
0
        return posix_error();
11589
0
    return PyLong_FromPid(pgid);
11590
0
}
11591
#endif /* HAVE_TCGETPGRP */
11592
11593
11594
#ifdef HAVE_TCSETPGRP
11595
/*[clinic input]
11596
os.tcsetpgrp
11597
11598
    fd: int
11599
    pgid: pid_t
11600
    /
11601
11602
Set the process group associated with the terminal specified by fd.
11603
[clinic start generated code]*/
11604
11605
static PyObject *
11606
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11607
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11608
0
{
11609
0
    if (tcsetpgrp(fd, pgid) < 0)
11610
0
        return posix_error();
11611
0
    Py_RETURN_NONE;
11612
0
}
11613
#endif /* HAVE_TCSETPGRP */
11614
11615
/* Functions acting on file descriptors */
11616
11617
#ifdef O_CLOEXEC
11618
extern int _Py_open_cloexec_works;
11619
#endif
11620
11621
11622
/*[clinic input]
11623
os.open -> int
11624
    path: path_t
11625
    flags: int
11626
    mode: int = 0o777
11627
    *
11628
    dir_fd: dir_fd(requires='openat') = None
11629
11630
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11631
11632
Open a file for low level IO.  Returns a file descriptor (integer).
11633
11634
If dir_fd is not None, it should be a file descriptor open to a directory,
11635
  and path should be relative; path will then be relative to that directory.
11636
dir_fd may not be implemented on your platform.
11637
  If it is unavailable, using it will raise a NotImplementedError.
11638
[clinic start generated code]*/
11639
11640
static int
11641
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11642
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11643
124k
{
11644
124k
    int fd;
11645
124k
    int async_err = 0;
11646
124k
#ifdef HAVE_OPENAT
11647
124k
    int openat_unavailable = 0;
11648
124k
#endif
11649
11650
124k
#ifdef O_CLOEXEC
11651
124k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11652
#elif !defined(MS_WINDOWS)
11653
    int *atomic_flag_works = NULL;
11654
#endif
11655
11656
#ifdef MS_WINDOWS
11657
    flags |= O_NOINHERIT;
11658
#elif defined(O_CLOEXEC)
11659
124k
    flags |= O_CLOEXEC;
11660
124k
#endif
11661
11662
124k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11663
0
        return -1;
11664
0
    }
11665
11666
124k
    _Py_BEGIN_SUPPRESS_IPH
11667
124k
    do {
11668
124k
        Py_BEGIN_ALLOW_THREADS
11669
#ifdef MS_WINDOWS
11670
        fd = _wopen(path->wide, flags, mode);
11671
#else
11672
124k
#ifdef HAVE_OPENAT
11673
124k
        if (dir_fd != DEFAULT_DIR_FD) {
11674
119k
            if (HAVE_OPENAT_RUNTIME) {
11675
119k
                fd = openat(dir_fd, path->narrow, flags, mode);
11676
11677
119k
            } else {
11678
0
                openat_unavailable = 1;
11679
0
                fd = -1;
11680
0
            }
11681
119k
        } else
11682
4.95k
#endif /* HAVE_OPENAT */
11683
4.95k
            fd = open(path->narrow, flags, mode);
11684
124k
#endif /* !MS_WINDOWS */
11685
124k
        Py_END_ALLOW_THREADS
11686
124k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11687
124k
    _Py_END_SUPPRESS_IPH
11688
11689
124k
#ifdef HAVE_OPENAT
11690
124k
    if (openat_unavailable) {
11691
0
        argument_unavailable_error(NULL, "dir_fd");
11692
0
        return -1;
11693
0
    }
11694
124k
#endif
11695
11696
124k
    if (fd < 0) {
11697
0
        if (!async_err)
11698
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11699
0
        return -1;
11700
0
    }
11701
11702
124k
#ifndef MS_WINDOWS
11703
124k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11704
0
        close(fd);
11705
0
        return -1;
11706
0
    }
11707
124k
#endif
11708
11709
124k
    return fd;
11710
124k
}
11711
11712
11713
/*[clinic input]
11714
os.close
11715
11716
    fd: int
11717
11718
Close a file descriptor.
11719
[clinic start generated code]*/
11720
11721
static PyObject *
11722
os_close_impl(PyObject *module, int fd)
11723
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11724
124k
{
11725
124k
    int res;
11726
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11727
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11728
     * for more details.
11729
     */
11730
124k
    Py_BEGIN_ALLOW_THREADS
11731
124k
    _Py_BEGIN_SUPPRESS_IPH
11732
124k
    res = close(fd);
11733
124k
    _Py_END_SUPPRESS_IPH
11734
124k
    Py_END_ALLOW_THREADS
11735
124k
    if (res < 0)
11736
0
        return posix_error();
11737
124k
    Py_RETURN_NONE;
11738
124k
}
11739
11740
/*[clinic input]
11741
os.closerange
11742
11743
    fd_low: int
11744
    fd_high: int
11745
    /
11746
11747
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11748
[clinic start generated code]*/
11749
11750
static PyObject *
11751
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11752
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11753
0
{
11754
0
    Py_BEGIN_ALLOW_THREADS
11755
0
    _Py_closerange(fd_low, fd_high - 1);
11756
0
    Py_END_ALLOW_THREADS
11757
0
    Py_RETURN_NONE;
11758
0
}
11759
11760
11761
/*[clinic input]
11762
os.dup -> int
11763
11764
    fd: int
11765
    /
11766
11767
Return a duplicate of a file descriptor.
11768
[clinic start generated code]*/
11769
11770
static int
11771
os_dup_impl(PyObject *module, int fd)
11772
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11773
0
{
11774
0
    return _Py_dup(fd);
11775
0
}
11776
11777
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11778
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11779
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11780
/*[clinic input]
11781
os.dup2 -> int
11782
    fd: int
11783
    fd2: int
11784
    inheritable: bool=True
11785
11786
Duplicate file descriptor.
11787
[clinic start generated code]*/
11788
11789
static int
11790
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11791
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11792
0
{
11793
0
    int res = 0;
11794
0
#if defined(HAVE_DUP3) && \
11795
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11796
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11797
0
    static int dup3_works = -1;
11798
0
#endif
11799
11800
    /* dup2() can fail with EINTR if the target FD is already open, because it
11801
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11802
     * upon close(), and therefore below.
11803
     */
11804
#ifdef MS_WINDOWS
11805
    Py_BEGIN_ALLOW_THREADS
11806
    _Py_BEGIN_SUPPRESS_IPH
11807
    res = dup2(fd, fd2);
11808
    _Py_END_SUPPRESS_IPH
11809
    Py_END_ALLOW_THREADS
11810
    if (res < 0) {
11811
        posix_error();
11812
        return -1;
11813
    }
11814
    res = fd2; // msvcrt dup2 returns 0 on success.
11815
11816
    /* Character files like console cannot be make non-inheritable */
11817
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11818
        close(fd2);
11819
        return -1;
11820
    }
11821
11822
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11823
    Py_BEGIN_ALLOW_THREADS
11824
    if (!inheritable)
11825
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11826
    else
11827
        res = dup2(fd, fd2);
11828
    Py_END_ALLOW_THREADS
11829
    if (res < 0) {
11830
        posix_error();
11831
        return -1;
11832
    }
11833
11834
#else
11835
11836
0
#ifdef HAVE_DUP3
11837
0
    if (!inheritable && dup3_works != 0) {
11838
0
        Py_BEGIN_ALLOW_THREADS
11839
0
        res = dup3(fd, fd2, O_CLOEXEC);
11840
0
        Py_END_ALLOW_THREADS
11841
0
        if (res < 0) {
11842
0
            if (dup3_works == -1)
11843
0
                dup3_works = (errno != ENOSYS);
11844
0
            if (dup3_works) {
11845
0
                posix_error();
11846
0
                return -1;
11847
0
            }
11848
0
        }
11849
0
    }
11850
11851
0
    if (inheritable || dup3_works == 0)
11852
0
    {
11853
0
#endif
11854
0
        Py_BEGIN_ALLOW_THREADS
11855
0
        res = dup2(fd, fd2);
11856
0
        Py_END_ALLOW_THREADS
11857
0
        if (res < 0) {
11858
0
            posix_error();
11859
0
            return -1;
11860
0
        }
11861
11862
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11863
0
            close(fd2);
11864
0
            return -1;
11865
0
        }
11866
0
#ifdef HAVE_DUP3
11867
0
    }
11868
0
#endif
11869
11870
0
#endif
11871
11872
0
    return res;
11873
0
}
11874
#endif
11875
11876
11877
#ifdef HAVE_LOCKF
11878
/*[clinic input]
11879
os.lockf
11880
11881
    fd: int
11882
        An open file descriptor.
11883
    command: int
11884
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11885
    length: Py_off_t
11886
        The number of bytes to lock, starting at the current position.
11887
    /
11888
11889
Apply, test or remove a POSIX lock on an open file descriptor.
11890
11891
[clinic start generated code]*/
11892
11893
static PyObject *
11894
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11895
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11896
0
{
11897
0
    int res;
11898
11899
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11900
0
        return NULL;
11901
0
    }
11902
11903
0
    Py_BEGIN_ALLOW_THREADS
11904
0
    res = lockf(fd, command, length);
11905
0
    Py_END_ALLOW_THREADS
11906
11907
0
    if (res < 0)
11908
0
        return posix_error();
11909
11910
0
    Py_RETURN_NONE;
11911
0
}
11912
#endif /* HAVE_LOCKF */
11913
11914
11915
/*[clinic input]
11916
@permit_long_docstring_body
11917
os.lseek -> Py_off_t
11918
11919
    fd: int
11920
        An open file descriptor, as returned by os.open().
11921
    position: Py_off_t
11922
        Position, interpreted relative to 'whence'.
11923
    whence as how: int
11924
        The relative position to seek from. Valid values are:
11925
        - SEEK_SET: seek from the start of the file.
11926
        - SEEK_CUR: seek from the current file position.
11927
        - SEEK_END: seek from the end of the file.
11928
    /
11929
11930
Set the position of a file descriptor.  Return the new position.
11931
11932
The return value is the number of bytes relative to the beginning of the file.
11933
[clinic start generated code]*/
11934
11935
static Py_off_t
11936
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11937
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11938
0
{
11939
0
    Py_off_t result;
11940
11941
0
#ifdef SEEK_SET
11942
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11943
0
    switch (how) {
11944
0
        case 0: how = SEEK_SET; break;
11945
0
        case 1: how = SEEK_CUR; break;
11946
0
        case 2: how = SEEK_END; break;
11947
0
    }
11948
0
#endif /* SEEK_END */
11949
11950
0
    Py_BEGIN_ALLOW_THREADS
11951
0
    _Py_BEGIN_SUPPRESS_IPH
11952
#ifdef MS_WINDOWS
11953
    result = _lseeki64(fd, position, how);
11954
#else
11955
0
    result = lseek(fd, position, how);
11956
0
#endif
11957
0
    _Py_END_SUPPRESS_IPH
11958
0
    Py_END_ALLOW_THREADS
11959
0
    if (result < 0)
11960
0
        posix_error();
11961
11962
0
    return result;
11963
0
}
11964
11965
11966
/*[clinic input]
11967
os.read
11968
    fd: int
11969
    length: Py_ssize_t
11970
    /
11971
11972
Read from a file descriptor.  Returns a bytes object.
11973
[clinic start generated code]*/
11974
11975
static PyObject *
11976
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11977
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11978
0
{
11979
0
    if (length < 0) {
11980
0
        errno = EINVAL;
11981
0
        return posix_error();
11982
0
    }
11983
11984
0
    length = Py_MIN(length, _PY_READ_MAX);
11985
11986
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11987
0
    if (writer == NULL) {
11988
0
        return NULL;
11989
0
    }
11990
11991
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11992
0
    if (n == -1) {
11993
0
        PyBytesWriter_Discard(writer);
11994
0
        return NULL;
11995
0
    }
11996
11997
0
    return PyBytesWriter_FinishWithSize(writer, n);
11998
0
}
11999
12000
/*[clinic input]
12001
@permit_long_docstring_body
12002
os.readinto -> Py_ssize_t
12003
    fd: int
12004
    buffer: Py_buffer(accept={rwbuffer})
12005
    /
12006
12007
Read into a buffer object from a file descriptor.
12008
12009
The buffer should be mutable and bytes-like. On success, returns the number of
12010
bytes read. Less bytes may be read than the size of the buffer. The underlying
12011
system call will be retried when interrupted by a signal, unless the signal
12012
handler raises an exception. Other errors will not be retried and an error will
12013
be raised.
12014
12015
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
12016
(which can be used to check for errors without reading data). Never returns
12017
negative.
12018
[clinic start generated code]*/
12019
12020
static Py_ssize_t
12021
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12022
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
12023
0
{
12024
0
    assert(buffer->len >= 0);
12025
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12026
    /* Ensure negative is never returned without an error. Simplifies calling
12027
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12028
        error. */
12029
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12030
0
    return result;
12031
0
}
12032
12033
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12034
                                || defined(__APPLE__))) \
12035
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12036
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12037
static int
12038
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12039
0
{
12040
0
    Py_ssize_t i, j;
12041
12042
0
    *iov = PyMem_New(struct iovec, cnt);
12043
0
    if (*iov == NULL) {
12044
0
        PyErr_NoMemory();
12045
0
        return -1;
12046
0
    }
12047
12048
0
    *buf = PyMem_New(Py_buffer, cnt);
12049
0
    if (*buf == NULL) {
12050
0
        PyMem_Free(*iov);
12051
0
        PyErr_NoMemory();
12052
0
        return -1;
12053
0
    }
12054
12055
0
    for (i = 0; i < cnt; i++) {
12056
0
        PyObject *item = PySequence_GetItem(seq, i);
12057
0
        if (item == NULL)
12058
0
            goto fail;
12059
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12060
0
            Py_DECREF(item);
12061
0
            goto fail;
12062
0
        }
12063
0
        Py_DECREF(item);
12064
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12065
0
        (*iov)[i].iov_len = (*buf)[i].len;
12066
0
    }
12067
0
    return 0;
12068
12069
0
fail:
12070
0
    PyMem_Free(*iov);
12071
0
    for (j = 0; j < i; j++) {
12072
0
        PyBuffer_Release(&(*buf)[j]);
12073
0
    }
12074
0
    PyMem_Free(*buf);
12075
0
    return -1;
12076
0
}
12077
12078
static void
12079
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12080
0
{
12081
0
    int i;
12082
0
    PyMem_Free(iov);
12083
0
    for (i = 0; i < cnt; i++) {
12084
0
        PyBuffer_Release(&buf[i]);
12085
0
    }
12086
0
    PyMem_Free(buf);
12087
0
}
12088
#endif
12089
12090
12091
#ifdef HAVE_READV
12092
/*[clinic input]
12093
os.readv -> Py_ssize_t
12094
12095
    fd: int
12096
    buffers: object
12097
    /
12098
12099
Read from a file descriptor fd into an iterable of buffers.
12100
12101
The buffers should be mutable buffers accepting bytes.
12102
readv will transfer data into each buffer until it is full
12103
and then move on to the next buffer in the sequence to hold
12104
the rest of the data.
12105
12106
readv returns the total number of bytes read,
12107
which may be less than the total capacity of all the buffers.
12108
[clinic start generated code]*/
12109
12110
static Py_ssize_t
12111
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12112
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12113
0
{
12114
0
    Py_ssize_t cnt, n;
12115
0
    int async_err = 0;
12116
0
    struct iovec *iov;
12117
0
    Py_buffer *buf;
12118
12119
0
    if (!PySequence_Check(buffers)) {
12120
0
        PyErr_SetString(PyExc_TypeError,
12121
0
            "readv() arg 2 must be a sequence");
12122
0
        return -1;
12123
0
    }
12124
12125
0
    cnt = PySequence_Size(buffers);
12126
0
    if (cnt < 0)
12127
0
        return -1;
12128
12129
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12130
0
        return -1;
12131
12132
0
    do {
12133
0
        Py_BEGIN_ALLOW_THREADS
12134
0
        n = readv(fd, iov, cnt);
12135
0
        Py_END_ALLOW_THREADS
12136
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12137
12138
0
    int saved_errno = errno;
12139
0
    iov_cleanup(iov, buf, cnt);
12140
0
    if (n < 0) {
12141
0
        if (!async_err) {
12142
0
            errno = saved_errno;
12143
0
            posix_error();
12144
0
        }
12145
0
        return -1;
12146
0
    }
12147
12148
0
    return n;
12149
0
}
12150
#endif /* HAVE_READV */
12151
12152
12153
#ifdef HAVE_PREAD
12154
/*[clinic input]
12155
@permit_long_summary
12156
os.pread
12157
12158
    fd: int
12159
    length: Py_ssize_t
12160
    offset: Py_off_t
12161
    /
12162
12163
Read a number of bytes from a file descriptor starting at a particular offset.
12164
12165
Read length bytes from file descriptor fd, starting at offset bytes from
12166
the beginning of the file.  The file offset remains unchanged.
12167
[clinic start generated code]*/
12168
12169
static PyObject *
12170
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12171
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12172
0
{
12173
0
    Py_ssize_t n;
12174
0
    int async_err = 0;
12175
12176
0
    if (length < 0) {
12177
0
        errno = EINVAL;
12178
0
        return posix_error();
12179
0
    }
12180
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12181
0
    if (writer == NULL) {
12182
0
        return NULL;
12183
0
    }
12184
12185
0
    do {
12186
0
        Py_BEGIN_ALLOW_THREADS
12187
0
        _Py_BEGIN_SUPPRESS_IPH
12188
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12189
0
        _Py_END_SUPPRESS_IPH
12190
0
        Py_END_ALLOW_THREADS
12191
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12192
12193
0
    if (n < 0) {
12194
0
        if (!async_err) {
12195
0
            posix_error();
12196
0
        }
12197
0
        PyBytesWriter_Discard(writer);
12198
0
        return NULL;
12199
0
    }
12200
0
    return PyBytesWriter_FinishWithSize(writer, n);
12201
0
}
12202
#endif /* HAVE_PREAD */
12203
12204
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12205
/*[clinic input]
12206
@permit_long_docstring_body
12207
os.preadv -> Py_ssize_t
12208
12209
    fd: int
12210
    buffers: object
12211
    offset: Py_off_t
12212
    flags: int = 0
12213
    /
12214
12215
Reads from a file descriptor into a number of mutable bytes-like objects.
12216
12217
Combines the functionality of readv() and pread(). As readv(), it will
12218
transfer data into each buffer until it is full and then move on to the next
12219
buffer in the sequence to hold the rest of the data. Its fourth argument,
12220
specifies the file offset at which the input operation is to be performed. It
12221
will return the total number of bytes read (which can be less than the total
12222
capacity of all the objects).
12223
12224
The flags argument contains a bitwise OR of zero or more of the following flags:
12225
12226
- RWF_HIPRI
12227
- RWF_NOWAIT
12228
- RWF_DONTCACHE
12229
12230
Using non-zero flags requires Linux 4.6 or newer.
12231
[clinic start generated code]*/
12232
12233
static Py_ssize_t
12234
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12235
               int flags)
12236
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
12237
0
{
12238
0
    Py_ssize_t cnt, n;
12239
0
    int async_err = 0;
12240
0
    struct iovec *iov;
12241
0
    Py_buffer *buf;
12242
12243
0
    if (!PySequence_Check(buffers)) {
12244
0
        PyErr_SetString(PyExc_TypeError,
12245
0
            "preadv2() arg 2 must be a sequence");
12246
0
        return -1;
12247
0
    }
12248
12249
0
    cnt = PySequence_Size(buffers);
12250
0
    if (cnt < 0) {
12251
0
        return -1;
12252
0
    }
12253
12254
#ifndef HAVE_PREADV2
12255
    if(flags != 0) {
12256
        argument_unavailable_error("preadv2", "flags");
12257
        return -1;
12258
    }
12259
#endif
12260
12261
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12262
0
        return -1;
12263
0
    }
12264
0
#ifdef HAVE_PREADV2
12265
0
    do {
12266
0
        Py_BEGIN_ALLOW_THREADS
12267
0
        _Py_BEGIN_SUPPRESS_IPH
12268
0
        n = preadv2(fd, iov, cnt, offset, flags);
12269
0
        _Py_END_SUPPRESS_IPH
12270
0
        Py_END_ALLOW_THREADS
12271
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12272
#else
12273
    do {
12274
#if defined(__APPLE__) && defined(__clang__)
12275
/* This entire function will be removed from the module dict when the API
12276
 * is not available.
12277
 */
12278
#pragma clang diagnostic push
12279
#pragma clang diagnostic ignored "-Wunguarded-availability"
12280
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12281
#endif
12282
        Py_BEGIN_ALLOW_THREADS
12283
        _Py_BEGIN_SUPPRESS_IPH
12284
        n = preadv(fd, iov, cnt, offset);
12285
        _Py_END_SUPPRESS_IPH
12286
        Py_END_ALLOW_THREADS
12287
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12288
12289
#if defined(__APPLE__) && defined(__clang__)
12290
#pragma clang diagnostic pop
12291
#endif
12292
12293
#endif
12294
12295
0
    int saved_errno = errno;
12296
0
    iov_cleanup(iov, buf, cnt);
12297
0
    if (n < 0) {
12298
0
        if (!async_err) {
12299
0
            errno = saved_errno;
12300
0
            posix_error();
12301
0
        }
12302
0
        return -1;
12303
0
    }
12304
12305
0
    return n;
12306
0
}
12307
#endif /* HAVE_PREADV */
12308
12309
12310
/*[clinic input]
12311
os.write -> Py_ssize_t
12312
12313
    fd: int
12314
    data: Py_buffer
12315
    /
12316
12317
Write a bytes object to a file descriptor.
12318
[clinic start generated code]*/
12319
12320
static Py_ssize_t
12321
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12322
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12323
2
{
12324
2
    return _Py_write(fd, data->buf, data->len);
12325
2
}
12326
12327
#ifdef HAVE_SENDFILE
12328
#ifdef __APPLE__
12329
/*[clinic input]
12330
os.sendfile
12331
12332
    out_fd: int
12333
    in_fd: int
12334
    offset: Py_off_t
12335
    count as sbytes: Py_off_t
12336
    headers: object(c_default="NULL") = ()
12337
    trailers: object(c_default="NULL") = ()
12338
    flags: int = 0
12339
12340
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12341
[clinic start generated code]*/
12342
12343
static PyObject *
12344
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12345
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12346
                 int flags)
12347
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12348
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12349
/*[clinic input]
12350
os.sendfile
12351
12352
    out_fd: int
12353
    in_fd: int
12354
    offset: Py_off_t
12355
    count: Py_ssize_t(allow_negative=False)
12356
    headers: object(c_default="NULL") = ()
12357
    trailers: object(c_default="NULL") = ()
12358
    flags: int = 0
12359
12360
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12361
[clinic start generated code]*/
12362
12363
static PyObject *
12364
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12365
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12366
                 int flags)
12367
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12368
#else
12369
/*[clinic input]
12370
os.sendfile
12371
12372
    out_fd: int
12373
    in_fd: int
12374
    offset as offobj: object
12375
    count: Py_ssize_t(allow_negative=False)
12376
12377
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12378
[clinic start generated code]*/
12379
12380
static PyObject *
12381
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12382
                 Py_ssize_t count)
12383
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12384
#endif
12385
0
{
12386
0
    Py_ssize_t ret;
12387
0
    int async_err = 0;
12388
12389
#ifdef __APPLE__
12390
    if(sbytes < 0) {
12391
        PyErr_SetString(PyExc_ValueError,
12392
                        "count cannot be negative");
12393
        return NULL;
12394
    }
12395
#else
12396
0
    assert(count >= 0);
12397
0
#endif
12398
12399
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12400
#ifndef __APPLE__
12401
    off_t sbytes;
12402
#endif
12403
    Py_buffer *hbuf, *tbuf;
12404
    struct sf_hdtr sf;
12405
12406
    sf.headers = NULL;
12407
    sf.trailers = NULL;
12408
12409
    if (headers != NULL) {
12410
        if (!PySequence_Check(headers)) {
12411
            PyErr_SetString(PyExc_TypeError,
12412
                "sendfile() headers must be a sequence");
12413
            return NULL;
12414
        } else {
12415
            Py_ssize_t i = PySequence_Size(headers);
12416
            if (i < 0)
12417
                return NULL;
12418
            if (i > INT_MAX) {
12419
                PyErr_SetString(PyExc_OverflowError,
12420
                    "sendfile() header is too large");
12421
                return NULL;
12422
            }
12423
            if (i > 0) {
12424
                sf.hdr_cnt = (int)i;
12425
                if (iov_setup(&(sf.headers), &hbuf,
12426
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12427
                    return NULL;
12428
#ifdef __APPLE__
12429
                for (i = 0; i < sf.hdr_cnt; i++) {
12430
                    Py_ssize_t blen = sf.headers[i].iov_len;
12431
# define OFF_T_MAX 0x7fffffffffffffff
12432
                    if (sbytes >= OFF_T_MAX - blen) {
12433
                        PyErr_SetString(PyExc_OverflowError,
12434
                            "sendfile() header is too large");
12435
                        return NULL;
12436
                    }
12437
                    sbytes += blen;
12438
                }
12439
#endif
12440
            }
12441
        }
12442
    }
12443
    if (trailers != NULL) {
12444
        if (!PySequence_Check(trailers)) {
12445
            PyErr_SetString(PyExc_TypeError,
12446
                "sendfile() trailers must be a sequence");
12447
            return NULL;
12448
        } else {
12449
            Py_ssize_t i = PySequence_Size(trailers);
12450
            if (i < 0)
12451
                return NULL;
12452
            if (i > INT_MAX) {
12453
                PyErr_SetString(PyExc_OverflowError,
12454
                    "sendfile() trailer is too large");
12455
                return NULL;
12456
            }
12457
            if (i > 0) {
12458
                sf.trl_cnt = (int)i;
12459
                if (iov_setup(&(sf.trailers), &tbuf,
12460
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12461
                    return NULL;
12462
            }
12463
        }
12464
    }
12465
12466
    _Py_BEGIN_SUPPRESS_IPH
12467
    do {
12468
        Py_BEGIN_ALLOW_THREADS
12469
#ifdef __APPLE__
12470
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12471
#else
12472
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12473
#endif
12474
        Py_END_ALLOW_THREADS
12475
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12476
    _Py_END_SUPPRESS_IPH
12477
12478
    int saved_errno = errno;
12479
    if (sf.headers != NULL)
12480
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12481
    if (sf.trailers != NULL)
12482
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12483
12484
    if (ret < 0) {
12485
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12486
            if (sbytes != 0) {
12487
                // some data has been sent
12488
                goto done;
12489
            }
12490
            // no data has been sent; upper application is supposed
12491
            // to retry on EAGAIN or EBUSY
12492
        }
12493
        if (!async_err) {
12494
            errno = saved_errno;
12495
            posix_error();
12496
        }
12497
        return NULL;
12498
    }
12499
    goto done;
12500
12501
done:
12502
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12503
        return PyLong_FromLong(sbytes);
12504
    #else
12505
        return PyLong_FromLongLong(sbytes);
12506
    #endif
12507
12508
#else
12509
0
#ifdef __linux__
12510
0
    if (offobj == Py_None) {
12511
0
        do {
12512
0
            Py_BEGIN_ALLOW_THREADS
12513
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12514
0
            Py_END_ALLOW_THREADS
12515
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12516
0
        if (ret < 0)
12517
0
            return (!async_err) ? posix_error() : NULL;
12518
0
        return PyLong_FromSsize_t(ret);
12519
0
    }
12520
0
#endif
12521
0
    off_t offset;
12522
0
    if (!Py_off_t_converter(offobj, &offset))
12523
0
        return NULL;
12524
12525
#if defined(__sun) && defined(__SVR4)
12526
    // On Solaris, sendfile raises EINVAL rather than returning 0
12527
    // when the offset is equal or bigger than the in_fd size.
12528
    struct stat st;
12529
12530
    do {
12531
        Py_BEGIN_ALLOW_THREADS
12532
        ret = fstat(in_fd, &st);
12533
        Py_END_ALLOW_THREADS
12534
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12535
    if (ret < 0)
12536
        return (!async_err) ? posix_error() : NULL;
12537
12538
    if (offset >= st.st_size) {
12539
        return PyLong_FromLong(0);
12540
    }
12541
12542
    // On illumos specifically sendfile() may perform a partial write but
12543
    // return -1/an error (in one confirmed case the destination socket
12544
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12545
    // code to check if the offset parameter was modified by sendfile().
12546
    //
12547
    // We need this variable to track said change.
12548
    off_t original_offset = offset;
12549
#endif
12550
12551
0
    do {
12552
0
        Py_BEGIN_ALLOW_THREADS
12553
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12554
#if defined(__sun) && defined(__SVR4)
12555
        // This handles illumos-specific sendfile() partial write behavior,
12556
        // see a comment above for more details.
12557
        if (ret < 0 && offset != original_offset) {
12558
            ret = offset - original_offset;
12559
        }
12560
#endif
12561
0
        Py_END_ALLOW_THREADS
12562
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12563
0
    if (ret < 0)
12564
0
        return (!async_err) ? posix_error() : NULL;
12565
0
    return PyLong_FromSsize_t(ret);
12566
0
#endif
12567
0
}
12568
#endif /* HAVE_SENDFILE */
12569
12570
12571
#if defined(__APPLE__)
12572
/*[clinic input]
12573
os._fcopyfile
12574
12575
    in_fd: int
12576
    out_fd: int
12577
    flags: int
12578
    /
12579
12580
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12581
[clinic start generated code]*/
12582
12583
static PyObject *
12584
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12585
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12586
{
12587
    int ret;
12588
12589
    Py_BEGIN_ALLOW_THREADS
12590
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12591
    Py_END_ALLOW_THREADS
12592
    if (ret < 0)
12593
        return posix_error();
12594
    Py_RETURN_NONE;
12595
}
12596
#endif
12597
12598
12599
/*[clinic input]
12600
os.fstat
12601
12602
    fd : int
12603
12604
Perform a stat system call on the given file descriptor.
12605
12606
Like stat(), but for an open file descriptor.
12607
Equivalent to os.stat(fd).
12608
[clinic start generated code]*/
12609
12610
static PyObject *
12611
os_fstat_impl(PyObject *module, int fd)
12612
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12613
124k
{
12614
124k
    STRUCT_STAT st;
12615
124k
    int res;
12616
124k
    int async_err = 0;
12617
12618
124k
    do {
12619
124k
        Py_BEGIN_ALLOW_THREADS
12620
124k
        res = FSTAT(fd, &st);
12621
124k
        Py_END_ALLOW_THREADS
12622
124k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12623
124k
    if (res != 0) {
12624
#ifdef MS_WINDOWS
12625
        return PyErr_SetFromWindowsErr(0);
12626
#else
12627
0
        return (!async_err) ? posix_error() : NULL;
12628
0
#endif
12629
0
    }
12630
12631
124k
    return _pystat_fromstructstat(module, &st);
12632
124k
}
12633
12634
12635
/*[clinic input]
12636
os.isatty -> bool
12637
    fd: int
12638
    /
12639
12640
Return True if the fd is connected to a terminal.
12641
12642
Return True if the file descriptor is an open file descriptor
12643
connected to the slave end of a terminal.
12644
[clinic start generated code]*/
12645
12646
static int
12647
os_isatty_impl(PyObject *module, int fd)
12648
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12649
0
{
12650
0
    int return_value;
12651
0
    Py_BEGIN_ALLOW_THREADS
12652
0
    _Py_BEGIN_SUPPRESS_IPH
12653
0
    return_value = isatty(fd);
12654
0
    _Py_END_SUPPRESS_IPH
12655
0
    Py_END_ALLOW_THREADS
12656
0
    return return_value;
12657
0
}
12658
12659
12660
#ifdef HAVE_PIPE
12661
/*[clinic input]
12662
os.pipe
12663
12664
Create a pipe.
12665
12666
Returns a tuple of two file descriptors:
12667
  (read_fd, write_fd)
12668
[clinic start generated code]*/
12669
12670
static PyObject *
12671
os_pipe_impl(PyObject *module)
12672
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12673
0
{
12674
0
    int fds[2];
12675
#ifdef MS_WINDOWS
12676
    HANDLE read, write;
12677
    SECURITY_ATTRIBUTES attr;
12678
    BOOL ok;
12679
#else
12680
0
    int res;
12681
0
#endif
12682
12683
#ifdef MS_WINDOWS
12684
    attr.nLength = sizeof(attr);
12685
    attr.lpSecurityDescriptor = NULL;
12686
    attr.bInheritHandle = FALSE;
12687
12688
    Py_BEGIN_ALLOW_THREADS
12689
    ok = CreatePipe(&read, &write, &attr, 0);
12690
    if (ok) {
12691
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12692
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12693
        if (fds[0] == -1 || fds[1] == -1) {
12694
            CloseHandle(read);
12695
            CloseHandle(write);
12696
            ok = 0;
12697
        }
12698
    }
12699
    Py_END_ALLOW_THREADS
12700
12701
    if (!ok)
12702
        return PyErr_SetFromWindowsErr(0);
12703
#else
12704
12705
0
#ifdef HAVE_PIPE2
12706
0
    Py_BEGIN_ALLOW_THREADS
12707
0
    res = pipe2(fds, O_CLOEXEC);
12708
0
    Py_END_ALLOW_THREADS
12709
12710
0
    if (res != 0 && errno == ENOSYS)
12711
0
    {
12712
0
#endif
12713
0
        Py_BEGIN_ALLOW_THREADS
12714
0
        res = pipe(fds);
12715
0
        Py_END_ALLOW_THREADS
12716
12717
0
        if (res == 0) {
12718
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12719
0
                close(fds[0]);
12720
0
                close(fds[1]);
12721
0
                return NULL;
12722
0
            }
12723
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12724
0
                close(fds[0]);
12725
0
                close(fds[1]);
12726
0
                return NULL;
12727
0
            }
12728
0
        }
12729
0
#ifdef HAVE_PIPE2
12730
0
    }
12731
0
#endif
12732
12733
0
    if (res != 0)
12734
0
        return PyErr_SetFromErrno(PyExc_OSError);
12735
0
#endif /* !MS_WINDOWS */
12736
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12737
0
}
12738
#endif  /* HAVE_PIPE */
12739
12740
12741
#ifdef HAVE_PIPE2
12742
/*[clinic input]
12743
os.pipe2
12744
12745
    flags: int
12746
    /
12747
12748
Create a pipe with flags set atomically.
12749
12750
Returns a tuple of two file descriptors:
12751
  (read_fd, write_fd)
12752
12753
flags can be constructed by ORing together one or more of these values:
12754
O_NONBLOCK, O_CLOEXEC.
12755
[clinic start generated code]*/
12756
12757
static PyObject *
12758
os_pipe2_impl(PyObject *module, int flags)
12759
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12760
0
{
12761
0
    int fds[2];
12762
0
    int res;
12763
12764
0
    res = pipe2(fds, flags);
12765
0
    if (res != 0)
12766
0
        return posix_error();
12767
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12768
0
}
12769
#endif /* HAVE_PIPE2 */
12770
12771
12772
#ifdef HAVE_WRITEV
12773
/*[clinic input]
12774
os.writev -> Py_ssize_t
12775
    fd: int
12776
    buffers: object
12777
    /
12778
12779
Iterate over buffers, and write the contents of each to a file descriptor.
12780
12781
Returns the total number of bytes written.
12782
buffers must be a sequence of bytes-like objects.
12783
[clinic start generated code]*/
12784
12785
static Py_ssize_t
12786
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12787
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12788
0
{
12789
0
    Py_ssize_t cnt;
12790
0
    Py_ssize_t result;
12791
0
    int async_err = 0;
12792
0
    struct iovec *iov;
12793
0
    Py_buffer *buf;
12794
12795
0
    if (!PySequence_Check(buffers)) {
12796
0
        PyErr_SetString(PyExc_TypeError,
12797
0
            "writev() arg 2 must be a sequence");
12798
0
        return -1;
12799
0
    }
12800
0
    cnt = PySequence_Size(buffers);
12801
0
    if (cnt < 0)
12802
0
        return -1;
12803
12804
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12805
0
        return -1;
12806
0
    }
12807
12808
0
    do {
12809
0
        Py_BEGIN_ALLOW_THREADS
12810
0
        result = writev(fd, iov, cnt);
12811
0
        Py_END_ALLOW_THREADS
12812
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12813
12814
0
    if (result < 0 && !async_err)
12815
0
        posix_error();
12816
12817
0
    iov_cleanup(iov, buf, cnt);
12818
0
    return result;
12819
0
}
12820
#endif /* HAVE_WRITEV */
12821
12822
12823
#ifdef HAVE_PWRITE
12824
/*[clinic input]
12825
os.pwrite -> Py_ssize_t
12826
12827
    fd: int
12828
    buffer: Py_buffer
12829
    offset: Py_off_t
12830
    /
12831
12832
Write bytes to a file descriptor starting at a particular offset.
12833
12834
Write buffer to fd, starting at offset bytes from the beginning of
12835
the file.  Returns the number of bytes written.  Does not change the
12836
current file offset.
12837
[clinic start generated code]*/
12838
12839
static Py_ssize_t
12840
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12841
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12842
0
{
12843
0
    Py_ssize_t size;
12844
0
    int async_err = 0;
12845
12846
0
    do {
12847
0
        Py_BEGIN_ALLOW_THREADS
12848
0
        _Py_BEGIN_SUPPRESS_IPH
12849
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12850
0
        _Py_END_SUPPRESS_IPH
12851
0
        Py_END_ALLOW_THREADS
12852
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12853
12854
0
    if (size < 0 && !async_err)
12855
0
        posix_error();
12856
0
    return size;
12857
0
}
12858
#endif /* HAVE_PWRITE */
12859
12860
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12861
/*[clinic input]
12862
@permit_long_summary
12863
@permit_long_docstring_body
12864
os.pwritev -> Py_ssize_t
12865
12866
    fd: int
12867
    buffers: object
12868
    offset: Py_off_t
12869
    flags: int = 0
12870
    /
12871
12872
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12873
12874
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12875
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12876
buffer is written before proceeding to second, and so on. The operating system may
12877
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12878
This function writes the contents of each object to the file descriptor and returns
12879
the total number of bytes written.
12880
12881
The flags argument contains a bitwise OR of zero or more of the following flags:
12882
12883
- RWF_DSYNC
12884
- RWF_SYNC
12885
- RWF_APPEND
12886
- RWF_DONTCACHE
12887
- RWF_ATOMIC
12888
12889
Using non-zero flags requires Linux 4.7 or newer.
12890
[clinic start generated code]*/
12891
12892
static Py_ssize_t
12893
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12894
                int flags)
12895
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=7de72245873f56bf]*/
12896
0
{
12897
0
    Py_ssize_t cnt;
12898
0
    Py_ssize_t result;
12899
0
    int async_err = 0;
12900
0
    struct iovec *iov;
12901
0
    Py_buffer *buf;
12902
12903
0
    if (!PySequence_Check(buffers)) {
12904
0
        PyErr_SetString(PyExc_TypeError,
12905
0
            "pwritev() arg 2 must be a sequence");
12906
0
        return -1;
12907
0
    }
12908
12909
0
    cnt = PySequence_Size(buffers);
12910
0
    if (cnt < 0) {
12911
0
        return -1;
12912
0
    }
12913
12914
#ifndef HAVE_PWRITEV2
12915
    if(flags != 0) {
12916
        argument_unavailable_error("pwritev2", "flags");
12917
        return -1;
12918
    }
12919
#endif
12920
12921
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12922
0
        return -1;
12923
0
    }
12924
0
#ifdef HAVE_PWRITEV2
12925
0
    do {
12926
0
        Py_BEGIN_ALLOW_THREADS
12927
0
        _Py_BEGIN_SUPPRESS_IPH
12928
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12929
0
        _Py_END_SUPPRESS_IPH
12930
0
        Py_END_ALLOW_THREADS
12931
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12932
#else
12933
12934
#if defined(__APPLE__) && defined(__clang__)
12935
/* This entire function will be removed from the module dict when the API
12936
 * is not available.
12937
 */
12938
#pragma clang diagnostic push
12939
#pragma clang diagnostic ignored "-Wunguarded-availability"
12940
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12941
#endif
12942
    do {
12943
        Py_BEGIN_ALLOW_THREADS
12944
        _Py_BEGIN_SUPPRESS_IPH
12945
        result = pwritev(fd, iov, cnt, offset);
12946
        _Py_END_SUPPRESS_IPH
12947
        Py_END_ALLOW_THREADS
12948
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12949
12950
#if defined(__APPLE__) && defined(__clang__)
12951
#pragma clang diagnostic pop
12952
#endif
12953
12954
#endif
12955
12956
0
    if (result < 0) {
12957
0
        if (!async_err) {
12958
0
            posix_error();
12959
0
        }
12960
0
        result = -1;
12961
0
    }
12962
0
    iov_cleanup(iov, buf, cnt);
12963
12964
0
    return result;
12965
0
}
12966
#endif /* HAVE_PWRITEV */
12967
12968
#ifdef HAVE_COPY_FILE_RANGE
12969
/*[clinic input]
12970
12971
os.copy_file_range
12972
    src: int
12973
        Source file descriptor.
12974
    dst: int
12975
        Destination file descriptor.
12976
    count: Py_ssize_t(allow_negative=False)
12977
        Number of bytes to copy.
12978
    offset_src: object = None
12979
        Starting offset in src.
12980
    offset_dst: object = None
12981
        Starting offset in dst.
12982
12983
Copy count bytes from one file descriptor to another.
12984
12985
If offset_src is None, then src is read from the current position;
12986
respectively for offset_dst.
12987
[clinic start generated code]*/
12988
12989
static PyObject *
12990
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12991
                        PyObject *offset_src, PyObject *offset_dst)
12992
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12993
0
{
12994
0
    off_t offset_src_val, offset_dst_val;
12995
0
    off_t *p_offset_src = NULL;
12996
0
    off_t *p_offset_dst = NULL;
12997
0
    Py_ssize_t ret;
12998
0
    int async_err = 0;
12999
    /* The flags argument is provided to allow
13000
     * for future extensions and currently must be to 0. */
13001
0
    int flags = 0;
13002
13003
13004
0
    if (offset_src != Py_None) {
13005
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13006
0
            return NULL;
13007
0
        }
13008
0
        p_offset_src = &offset_src_val;
13009
0
    }
13010
13011
0
    if (offset_dst != Py_None) {
13012
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13013
0
            return NULL;
13014
0
        }
13015
0
        p_offset_dst = &offset_dst_val;
13016
0
    }
13017
13018
0
    do {
13019
0
        Py_BEGIN_ALLOW_THREADS
13020
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13021
0
        Py_END_ALLOW_THREADS
13022
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13023
13024
0
    if (ret < 0) {
13025
0
        return (!async_err) ? posix_error() : NULL;
13026
0
    }
13027
13028
0
    return PyLong_FromSsize_t(ret);
13029
0
}
13030
#endif /* HAVE_COPY_FILE_RANGE*/
13031
13032
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13033
/*[clinic input]
13034
13035
os.splice
13036
    src: int
13037
        Source file descriptor.
13038
    dst: int
13039
        Destination file descriptor.
13040
    count: Py_ssize_t(allow_negative=False)
13041
        Number of bytes to copy.
13042
    offset_src: object = None
13043
        Starting offset in src.
13044
    offset_dst: object = None
13045
        Starting offset in dst.
13046
    flags: unsigned_int = 0
13047
        Flags to modify the semantics of the call.
13048
13049
Transfer count bytes from one pipe to a descriptor or vice versa.
13050
13051
If offset_src is None, then src is read from the current position;
13052
respectively for offset_dst. The offset associated to the file
13053
descriptor that refers to a pipe must be None.
13054
[clinic start generated code]*/
13055
13056
static PyObject *
13057
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13058
               PyObject *offset_src, PyObject *offset_dst,
13059
               unsigned int flags)
13060
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13061
0
{
13062
0
    off_t offset_src_val, offset_dst_val;
13063
0
    off_t *p_offset_src = NULL;
13064
0
    off_t *p_offset_dst = NULL;
13065
0
    Py_ssize_t ret;
13066
0
    int async_err = 0;
13067
13068
13069
0
    if (offset_src != Py_None) {
13070
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13071
0
            return NULL;
13072
0
        }
13073
0
        p_offset_src = &offset_src_val;
13074
0
    }
13075
13076
0
    if (offset_dst != Py_None) {
13077
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13078
0
            return NULL;
13079
0
        }
13080
0
        p_offset_dst = &offset_dst_val;
13081
0
    }
13082
13083
0
    do {
13084
0
        Py_BEGIN_ALLOW_THREADS
13085
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13086
0
        Py_END_ALLOW_THREADS
13087
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13088
13089
0
    if (ret < 0) {
13090
0
        return (!async_err) ? posix_error() : NULL;
13091
0
    }
13092
13093
0
    return PyLong_FromSsize_t(ret);
13094
0
}
13095
#endif /* HAVE_SPLICE*/
13096
13097
#ifdef HAVE_MKFIFO
13098
/*[clinic input]
13099
os.mkfifo
13100
13101
    path: path_t
13102
    mode: int=0o666
13103
    *
13104
    dir_fd: dir_fd(requires='mkfifoat')=None
13105
13106
Create a "fifo" (a POSIX named pipe).
13107
13108
If dir_fd is not None, it should be a file descriptor open to a directory,
13109
  and path should be relative; path will then be relative to that directory.
13110
dir_fd may not be implemented on your platform.
13111
  If it is unavailable, using it will raise a NotImplementedError.
13112
[clinic start generated code]*/
13113
13114
static PyObject *
13115
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13116
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
13117
0
{
13118
0
    int result;
13119
0
    int async_err = 0;
13120
0
#ifdef HAVE_MKFIFOAT
13121
0
    int mkfifoat_unavailable = 0;
13122
0
#endif
13123
13124
0
    do {
13125
0
        Py_BEGIN_ALLOW_THREADS
13126
0
#ifdef HAVE_MKFIFOAT
13127
0
        if (dir_fd != DEFAULT_DIR_FD) {
13128
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13129
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13130
13131
0
            } else {
13132
0
                mkfifoat_unavailable = 1;
13133
0
                result = 0;
13134
0
            }
13135
0
        } else
13136
0
#endif
13137
0
            result = mkfifo(path->narrow, mode);
13138
0
        Py_END_ALLOW_THREADS
13139
0
    } while (result != 0 && errno == EINTR &&
13140
0
             !(async_err = PyErr_CheckSignals()));
13141
13142
0
#ifdef HAVE_MKFIFOAT
13143
0
    if (mkfifoat_unavailable) {
13144
0
        argument_unavailable_error(NULL, "dir_fd");
13145
0
        return NULL;
13146
0
    }
13147
0
#endif
13148
13149
0
    if (result != 0)
13150
0
        return (!async_err) ? posix_error() : NULL;
13151
13152
0
    Py_RETURN_NONE;
13153
0
}
13154
#endif /* HAVE_MKFIFO */
13155
13156
13157
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13158
/*[clinic input]
13159
@permit_long_docstring_body
13160
os.mknod
13161
13162
    path: path_t
13163
    mode: int=0o600
13164
    device: dev_t=0
13165
    *
13166
    dir_fd: dir_fd(requires='mknodat')=None
13167
13168
Create a node in the file system.
13169
13170
Create a node in the file system (file, device special file or named pipe)
13171
at path.  mode specifies both the permissions to use and the
13172
type of node to be created, being combined (bitwise OR) with one of
13173
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
13174
device defines the newly created device special file (probably using
13175
os.makedev()).  Otherwise device is ignored.
13176
13177
If dir_fd is not None, it should be a file descriptor open to a directory,
13178
  and path should be relative; path will then be relative to that directory.
13179
dir_fd may not be implemented on your platform.
13180
  If it is unavailable, using it will raise a NotImplementedError.
13181
[clinic start generated code]*/
13182
13183
static PyObject *
13184
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13185
              int dir_fd)
13186
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
13187
0
{
13188
0
    int result;
13189
0
    int async_err = 0;
13190
0
#ifdef HAVE_MKNODAT
13191
0
    int mknodat_unavailable = 0;
13192
0
#endif
13193
13194
0
    do {
13195
0
        Py_BEGIN_ALLOW_THREADS
13196
0
#ifdef HAVE_MKNODAT
13197
0
        if (dir_fd != DEFAULT_DIR_FD) {
13198
0
            if (HAVE_MKNODAT_RUNTIME) {
13199
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13200
13201
0
            } else {
13202
0
                mknodat_unavailable = 1;
13203
0
                result = 0;
13204
0
            }
13205
0
        } else
13206
0
#endif
13207
0
            result = mknod(path->narrow, mode, device);
13208
0
        Py_END_ALLOW_THREADS
13209
0
    } while (result != 0 && errno == EINTR &&
13210
0
             !(async_err = PyErr_CheckSignals()));
13211
0
#ifdef HAVE_MKNODAT
13212
0
    if (mknodat_unavailable) {
13213
0
        argument_unavailable_error(NULL, "dir_fd");
13214
0
        return NULL;
13215
0
    }
13216
0
#endif
13217
0
    if (result != 0)
13218
0
        return (!async_err) ? posix_error() : NULL;
13219
13220
0
    Py_RETURN_NONE;
13221
0
}
13222
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13223
13224
13225
#ifdef HAVE_DEVICE_MACROS
13226
static PyObject *
13227
major_minor_conv(unsigned int value)
13228
0
{
13229
0
#ifdef NODEV
13230
0
    if (value == (unsigned int)NODEV) {
13231
0
        return PyLong_FromLong((int)NODEV);
13232
0
    }
13233
0
#endif
13234
0
    return PyLong_FromUnsignedLong(value);
13235
0
}
13236
13237
static int
13238
major_minor_check(dev_t value)
13239
0
{
13240
0
#ifdef NODEV
13241
0
    if (value == NODEV) {
13242
0
        return 1;
13243
0
    }
13244
0
#endif
13245
0
    return (dev_t)(unsigned int)value == value;
13246
0
}
13247
13248
/*[clinic input]
13249
os.major
13250
13251
    device: dev_t
13252
    /
13253
13254
Extracts a device major number from a raw device number.
13255
[clinic start generated code]*/
13256
13257
static PyObject *
13258
os_major_impl(PyObject *module, dev_t device)
13259
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13260
0
{
13261
0
    return major_minor_conv(major(device));
13262
0
}
13263
13264
13265
/*[clinic input]
13266
os.minor
13267
13268
    device: dev_t
13269
    /
13270
13271
Extracts a device minor number from a raw device number.
13272
[clinic start generated code]*/
13273
13274
static PyObject *
13275
os_minor_impl(PyObject *module, dev_t device)
13276
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13277
0
{
13278
0
    return major_minor_conv(minor(device));
13279
0
}
13280
13281
13282
/*[clinic input]
13283
os.makedev -> dev_t
13284
13285
    major: dev_t
13286
    minor: dev_t
13287
    /
13288
13289
Composes a raw device number from the major and minor device numbers.
13290
[clinic start generated code]*/
13291
13292
static dev_t
13293
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13294
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13295
0
{
13296
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13297
0
        PyErr_SetString(PyExc_OverflowError,
13298
0
                        "Python int too large to convert to C unsigned int");
13299
0
        return (dev_t)-1;
13300
0
    }
13301
0
    return makedev(major, minor);
13302
0
}
13303
#endif /* HAVE_DEVICE_MACROS */
13304
13305
13306
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13307
/*[clinic input]
13308
os.ftruncate
13309
13310
    fd: int
13311
    length: Py_off_t
13312
    /
13313
13314
Truncate a file, specified by file descriptor, to a specific length.
13315
[clinic start generated code]*/
13316
13317
static PyObject *
13318
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13319
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13320
0
{
13321
0
    int result;
13322
0
    int async_err = 0;
13323
13324
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13325
0
        return NULL;
13326
0
    }
13327
13328
0
    do {
13329
0
        Py_BEGIN_ALLOW_THREADS
13330
0
        _Py_BEGIN_SUPPRESS_IPH
13331
#ifdef MS_WINDOWS
13332
        result = _chsize_s(fd, length);
13333
#else
13334
0
        result = ftruncate(fd, length);
13335
0
#endif
13336
0
        _Py_END_SUPPRESS_IPH
13337
0
        Py_END_ALLOW_THREADS
13338
0
    } while (result != 0 && errno == EINTR &&
13339
0
             !(async_err = PyErr_CheckSignals()));
13340
0
    if (result != 0)
13341
0
        return (!async_err) ? posix_error() : NULL;
13342
0
    Py_RETURN_NONE;
13343
0
}
13344
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13345
13346
13347
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13348
/*[clinic input]
13349
os.truncate
13350
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13351
    length: Py_off_t
13352
13353
Truncate a file, specified by path, to a specific length.
13354
13355
On some platforms, path may also be specified as an open file descriptor.
13356
  If this functionality is unavailable, using it raises an exception.
13357
[clinic start generated code]*/
13358
13359
static PyObject *
13360
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13361
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
13362
0
{
13363
0
    int result;
13364
#ifdef MS_WINDOWS
13365
    int fd;
13366
#endif
13367
13368
0
    if (path->is_fd)
13369
0
        return os_ftruncate_impl(module, path->fd, length);
13370
13371
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13372
0
        return NULL;
13373
0
    }
13374
13375
0
    Py_BEGIN_ALLOW_THREADS
13376
0
    _Py_BEGIN_SUPPRESS_IPH
13377
#ifdef MS_WINDOWS
13378
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13379
    if (fd < 0)
13380
        result = -1;
13381
    else {
13382
        result = _chsize_s(fd, length);
13383
        close(fd);
13384
        if (result < 0)
13385
            errno = result;
13386
    }
13387
#else
13388
0
    result = truncate(path->narrow, length);
13389
0
#endif
13390
0
    _Py_END_SUPPRESS_IPH
13391
0
    Py_END_ALLOW_THREADS
13392
0
    if (result < 0)
13393
0
        return posix_path_error(path);
13394
13395
0
    Py_RETURN_NONE;
13396
0
}
13397
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13398
13399
13400
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13401
   OSs, support was dropped in WASI preview2. */
13402
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13403
/*[clinic input]
13404
os.posix_fallocate
13405
13406
    fd: int
13407
    offset: Py_off_t
13408
    length: Py_off_t
13409
    /
13410
13411
Ensure a file has allocated at least a particular number of bytes on disk.
13412
13413
Ensure that the file specified by fd encompasses a range of bytes
13414
starting at offset bytes from the beginning and continuing for length bytes.
13415
[clinic start generated code]*/
13416
13417
static PyObject *
13418
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13419
                        Py_off_t length)
13420
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
13421
0
{
13422
0
    int result;
13423
0
    int async_err = 0;
13424
13425
0
    do {
13426
0
        Py_BEGIN_ALLOW_THREADS
13427
0
        result = posix_fallocate(fd, offset, length);
13428
0
        Py_END_ALLOW_THREADS
13429
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13430
13431
0
    if (result == 0)
13432
0
        Py_RETURN_NONE;
13433
13434
0
    if (async_err)
13435
0
        return NULL;
13436
13437
0
    errno = result;
13438
0
    return posix_error();
13439
0
}
13440
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13441
13442
13443
#if defined(HAVE_POSIX_FADVISE)
13444
/*[clinic input]
13445
os.posix_fadvise
13446
13447
    fd: int
13448
    offset: Py_off_t
13449
    length: Py_off_t
13450
    advice: int
13451
    /
13452
13453
Announce an intention to access data in a specific pattern.
13454
13455
Announce an intention to access data in a specific pattern, thus allowing
13456
the kernel to make optimizations.
13457
The advice applies to the region of the file specified by fd starting at
13458
offset and continuing for length bytes.
13459
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13460
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13461
POSIX_FADV_DONTNEED.
13462
[clinic start generated code]*/
13463
13464
static PyObject *
13465
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13466
                      Py_off_t length, int advice)
13467
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13468
0
{
13469
0
    int result;
13470
0
    int async_err = 0;
13471
13472
0
    do {
13473
0
        Py_BEGIN_ALLOW_THREADS
13474
0
        result = posix_fadvise(fd, offset, length, advice);
13475
0
        Py_END_ALLOW_THREADS
13476
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13477
13478
0
    if (result == 0)
13479
0
        Py_RETURN_NONE;
13480
13481
0
    if (async_err)
13482
0
        return NULL;
13483
13484
0
    errno = result;
13485
0
    return posix_error();
13486
0
}
13487
#endif /* HAVE_POSIX_FADVISE */
13488
13489
13490
#ifdef MS_WINDOWS
13491
static PyObject*
13492
win32_putenv(PyObject *name, PyObject *value)
13493
{
13494
    /* Search from index 1 because on Windows starting '=' is allowed for
13495
       defining hidden environment variables. */
13496
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13497
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13498
    {
13499
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13500
        return NULL;
13501
    }
13502
    PyObject *unicode;
13503
    if (value != NULL) {
13504
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13505
    }
13506
    else {
13507
        unicode = PyUnicode_FromFormat("%U=", name);
13508
    }
13509
    if (unicode == NULL) {
13510
        return NULL;
13511
    }
13512
13513
    Py_ssize_t size;
13514
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13515
    Py_DECREF(unicode);
13516
13517
    if (env == NULL) {
13518
        return NULL;
13519
    }
13520
    if (size > _MAX_ENV) {
13521
        PyErr_Format(PyExc_ValueError,
13522
                     "the environment variable is longer than %u characters",
13523
                     _MAX_ENV);
13524
        PyMem_Free(env);
13525
        return NULL;
13526
    }
13527
    if (wcslen(env) != (size_t)size) {
13528
        PyErr_SetString(PyExc_ValueError,
13529
                        "embedded null character");
13530
        PyMem_Free(env);
13531
        return NULL;
13532
    }
13533
13534
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13535
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13536
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13537
13538
       Prefer _wputenv() to be compatible with C libraries using CRT
13539
       variables and CRT functions using these variables (ex: getenv()). */
13540
    int err = _wputenv(env);
13541
13542
    if (err) {
13543
        posix_error();
13544
        PyMem_Free(env);
13545
        return NULL;
13546
    }
13547
    PyMem_Free(env);
13548
13549
    Py_RETURN_NONE;
13550
}
13551
#endif
13552
13553
13554
#ifdef MS_WINDOWS
13555
/*[clinic input]
13556
os.putenv
13557
13558
    name: unicode
13559
    value: unicode
13560
    /
13561
13562
Change or add an environment variable.
13563
[clinic start generated code]*/
13564
13565
static PyObject *
13566
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13567
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13568
{
13569
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13570
        return NULL;
13571
    }
13572
    return win32_putenv(name, value);
13573
}
13574
#else
13575
/*[clinic input]
13576
os.putenv
13577
13578
    name: unicode_fs_encoded
13579
    value: unicode_fs_encoded
13580
    /
13581
13582
Change or add an environment variable.
13583
[clinic start generated code]*/
13584
13585
static PyObject *
13586
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13587
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13588
0
{
13589
0
    const char *name_string = PyBytes_AS_STRING(name);
13590
0
    const char *value_string = PyBytes_AS_STRING(value);
13591
13592
0
    if (strchr(name_string, '=') != NULL) {
13593
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13594
0
        return NULL;
13595
0
    }
13596
13597
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13598
0
        return NULL;
13599
0
    }
13600
13601
0
    if (setenv(name_string, value_string, 1)) {
13602
0
        return posix_error();
13603
0
    }
13604
0
    Py_RETURN_NONE;
13605
0
}
13606
#endif  /* !defined(MS_WINDOWS) */
13607
13608
13609
#ifdef MS_WINDOWS
13610
/*[clinic input]
13611
os.unsetenv
13612
    name: unicode
13613
    /
13614
13615
Delete an environment variable.
13616
[clinic start generated code]*/
13617
13618
static PyObject *
13619
os_unsetenv_impl(PyObject *module, PyObject *name)
13620
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13621
{
13622
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13623
        return NULL;
13624
    }
13625
    return win32_putenv(name, NULL);
13626
}
13627
#else
13628
/*[clinic input]
13629
os.unsetenv
13630
    name: unicode_fs_encoded
13631
    /
13632
13633
Delete an environment variable.
13634
[clinic start generated code]*/
13635
13636
static PyObject *
13637
os_unsetenv_impl(PyObject *module, PyObject *name)
13638
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13639
0
{
13640
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13641
0
        return NULL;
13642
0
    }
13643
#ifdef HAVE_BROKEN_UNSETENV
13644
    unsetenv(PyBytes_AS_STRING(name));
13645
#else
13646
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13647
0
    if (err) {
13648
0
        return posix_error();
13649
0
    }
13650
0
#endif
13651
13652
0
    Py_RETURN_NONE;
13653
0
}
13654
#endif /* !MS_WINDOWS */
13655
13656
13657
#ifdef HAVE_CLEARENV
13658
/*[clinic input]
13659
os._clearenv
13660
[clinic start generated code]*/
13661
13662
static PyObject *
13663
os__clearenv_impl(PyObject *module)
13664
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13665
0
{
13666
0
    errno = 0;
13667
0
    int err = clearenv();
13668
0
    if (err) {
13669
0
        return posix_error();
13670
0
    }
13671
0
    Py_RETURN_NONE;
13672
0
}
13673
#endif
13674
13675
13676
/*[clinic input]
13677
os.strerror
13678
13679
    code: int
13680
    /
13681
13682
Translate an error code to a message string.
13683
[clinic start generated code]*/
13684
13685
static PyObject *
13686
os_strerror_impl(PyObject *module, int code)
13687
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13688
0
{
13689
0
    char *message = strerror(code);
13690
0
    if (message == NULL) {
13691
0
        PyErr_SetString(PyExc_ValueError,
13692
0
                        "strerror() argument out of range");
13693
0
        return NULL;
13694
0
    }
13695
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13696
0
}
13697
13698
13699
#ifdef HAVE_SYS_WAIT_H
13700
#ifdef WCOREDUMP
13701
/*[clinic input]
13702
os.WCOREDUMP -> bool
13703
13704
    status: int
13705
    /
13706
13707
Return True if the process returning status was dumped to a core file.
13708
[clinic start generated code]*/
13709
13710
static int
13711
os_WCOREDUMP_impl(PyObject *module, int status)
13712
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13713
0
{
13714
0
    WAIT_TYPE wait_status;
13715
0
    WAIT_STATUS_INT(wait_status) = status;
13716
0
    return WCOREDUMP(wait_status);
13717
0
}
13718
#endif /* WCOREDUMP */
13719
13720
13721
#ifdef WIFCONTINUED
13722
/*[clinic input]
13723
os.WIFCONTINUED -> bool
13724
13725
    status: int
13726
13727
Return True if a particular process was continued from a job control stop.
13728
13729
Return True if the process returning status was continued from a
13730
job control stop.
13731
[clinic start generated code]*/
13732
13733
static int
13734
os_WIFCONTINUED_impl(PyObject *module, int status)
13735
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13736
0
{
13737
0
    WAIT_TYPE wait_status;
13738
0
    WAIT_STATUS_INT(wait_status) = status;
13739
0
    return WIFCONTINUED(wait_status);
13740
0
}
13741
#endif /* WIFCONTINUED */
13742
13743
13744
#ifdef WIFSTOPPED
13745
/*[clinic input]
13746
os.WIFSTOPPED -> bool
13747
13748
    status: int
13749
13750
Return True if the process returning status was stopped.
13751
[clinic start generated code]*/
13752
13753
static int
13754
os_WIFSTOPPED_impl(PyObject *module, int status)
13755
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13756
0
{
13757
0
    WAIT_TYPE wait_status;
13758
0
    WAIT_STATUS_INT(wait_status) = status;
13759
0
    return WIFSTOPPED(wait_status);
13760
0
}
13761
#endif /* WIFSTOPPED */
13762
13763
13764
#ifdef WIFSIGNALED
13765
/*[clinic input]
13766
os.WIFSIGNALED -> bool
13767
13768
    status: int
13769
13770
Return True if the process returning status was terminated by a signal.
13771
[clinic start generated code]*/
13772
13773
static int
13774
os_WIFSIGNALED_impl(PyObject *module, int status)
13775
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13776
0
{
13777
0
    WAIT_TYPE wait_status;
13778
0
    WAIT_STATUS_INT(wait_status) = status;
13779
0
    return WIFSIGNALED(wait_status);
13780
0
}
13781
#endif /* WIFSIGNALED */
13782
13783
13784
#ifdef WIFEXITED
13785
/*[clinic input]
13786
@permit_long_summary
13787
os.WIFEXITED -> bool
13788
13789
    status: int
13790
13791
Return True if the process returning status exited via the exit() system call.
13792
[clinic start generated code]*/
13793
13794
static int
13795
os_WIFEXITED_impl(PyObject *module, int status)
13796
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13797
0
{
13798
0
    WAIT_TYPE wait_status;
13799
0
    WAIT_STATUS_INT(wait_status) = status;
13800
0
    return WIFEXITED(wait_status);
13801
0
}
13802
#endif /* WIFEXITED */
13803
13804
13805
#ifdef WEXITSTATUS
13806
/*[clinic input]
13807
os.WEXITSTATUS -> int
13808
13809
    status: int
13810
13811
Return the process return code from status.
13812
[clinic start generated code]*/
13813
13814
static int
13815
os_WEXITSTATUS_impl(PyObject *module, int status)
13816
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13817
0
{
13818
0
    WAIT_TYPE wait_status;
13819
0
    WAIT_STATUS_INT(wait_status) = status;
13820
0
    return WEXITSTATUS(wait_status);
13821
0
}
13822
#endif /* WEXITSTATUS */
13823
13824
13825
#ifdef WTERMSIG
13826
/*[clinic input]
13827
@permit_long_summary
13828
os.WTERMSIG -> int
13829
13830
    status: int
13831
13832
Return the signal that terminated the process that provided the status value.
13833
[clinic start generated code]*/
13834
13835
static int
13836
os_WTERMSIG_impl(PyObject *module, int status)
13837
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13838
0
{
13839
0
    WAIT_TYPE wait_status;
13840
0
    WAIT_STATUS_INT(wait_status) = status;
13841
0
    return WTERMSIG(wait_status);
13842
0
}
13843
#endif /* WTERMSIG */
13844
13845
13846
#ifdef WSTOPSIG
13847
/*[clinic input]
13848
os.WSTOPSIG -> int
13849
13850
    status: int
13851
13852
Return the signal that stopped the process that provided the status value.
13853
[clinic start generated code]*/
13854
13855
static int
13856
os_WSTOPSIG_impl(PyObject *module, int status)
13857
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13858
0
{
13859
0
    WAIT_TYPE wait_status;
13860
0
    WAIT_STATUS_INT(wait_status) = status;
13861
0
    return WSTOPSIG(wait_status);
13862
0
}
13863
#endif /* WSTOPSIG */
13864
#endif /* HAVE_SYS_WAIT_H */
13865
13866
13867
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13868
#ifdef _SCO_DS
13869
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13870
   needed definitions in sys/statvfs.h */
13871
#define _SVID3
13872
#endif
13873
#include <sys/statvfs.h>
13874
13875
#ifdef __APPLE__
13876
/* On macOS struct statvfs uses 32-bit integers for block counts,
13877
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13878
 * os.statvfs is implemented in terms of statfs(2).
13879
 */
13880
13881
static PyObject*
13882
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13883
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13884
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13885
    if (v == NULL) {
13886
        return NULL;
13887
    }
13888
13889
    long flags = 0;
13890
    if (st.f_flags & MNT_RDONLY) {
13891
        flags |= ST_RDONLY;
13892
    }
13893
    if (st.f_flags & MNT_NOSUID) {
13894
        flags |= ST_NOSUID;
13895
    }
13896
13897
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13898
13899
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13900
    do {                                                 \
13901
        PyObject *obj = (EXPR);                          \
13902
        if (obj == NULL) {                               \
13903
            Py_DECREF((SEQ));                            \
13904
            return NULL;                                 \
13905
        }                                                \
13906
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13907
    } while (0)
13908
13909
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13910
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13911
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13912
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13913
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13914
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13915
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13916
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13917
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13918
13919
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13920
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13921
13922
#undef SET_ITEM
13923
13924
    return v;
13925
}
13926
13927
#else
13928
13929
13930
13931
static PyObject*
13932
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13933
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13934
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13935
0
    if (v == NULL)
13936
0
        return NULL;
13937
13938
0
    int pos = 0;
13939
13940
0
#define SET_RESULT(CALL)                                     \
13941
0
    do {                                                     \
13942
0
        PyObject *item = (CALL);                             \
13943
0
        if (item == NULL) {                                  \
13944
0
            Py_DECREF(v);                                    \
13945
0
            return NULL;                                     \
13946
0
        }                                                    \
13947
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13948
0
    } while(0)
13949
13950
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13951
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13952
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13953
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13954
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13955
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13956
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13957
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13958
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13959
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13960
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13961
#else
13962
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13963
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13964
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13965
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13966
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13967
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13968
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13969
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13970
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13971
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13972
#endif
13973
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13974
 * (issue #32390). */
13975
#if defined(_AIX) && defined(_ALL_SOURCE)
13976
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13977
#else
13978
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13979
0
#endif
13980
13981
0
#undef SET_RESULT
13982
13983
0
    return v;
13984
0
}
13985
13986
#endif
13987
13988
13989
/*[clinic input]
13990
os.fstatvfs
13991
    fd: int
13992
    /
13993
13994
Perform an fstatvfs system call on the given fd.
13995
13996
Equivalent to statvfs(fd).
13997
[clinic start generated code]*/
13998
13999
static PyObject *
14000
os_fstatvfs_impl(PyObject *module, int fd)
14001
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
14002
0
{
14003
0
    int result;
14004
0
    int async_err = 0;
14005
#ifdef __APPLE__
14006
    struct statfs st;
14007
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
14008
     * the former uses 32-bit values for block counts.
14009
     */
14010
    do {
14011
        Py_BEGIN_ALLOW_THREADS
14012
        result = fstatfs(fd, &st);
14013
        Py_END_ALLOW_THREADS
14014
    } while (result != 0 && errno == EINTR &&
14015
             !(async_err = PyErr_CheckSignals()));
14016
    if (result != 0)
14017
        return (!async_err) ? posix_error() : NULL;
14018
14019
    return _pystatvfs_fromstructstatfs(module, st);
14020
#else
14021
0
    struct statvfs st;
14022
14023
0
    do {
14024
0
        Py_BEGIN_ALLOW_THREADS
14025
0
        result = fstatvfs(fd, &st);
14026
0
        Py_END_ALLOW_THREADS
14027
0
    } while (result != 0 && errno == EINTR &&
14028
0
             !(async_err = PyErr_CheckSignals()));
14029
0
    if (result != 0)
14030
0
        return (!async_err) ? posix_error() : NULL;
14031
14032
0
    return _pystatvfs_fromstructstatvfs(module, st);
14033
0
#endif
14034
0
}
14035
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14036
14037
14038
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14039
#include <sys/statvfs.h>
14040
/*[clinic input]
14041
os.statvfs
14042
14043
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14044
14045
Perform a statvfs system call on the given path.
14046
14047
path may always be specified as a string.
14048
On some platforms, path may also be specified as an open file descriptor.
14049
  If this functionality is unavailable, using it raises an exception.
14050
[clinic start generated code]*/
14051
14052
static PyObject *
14053
os_statvfs_impl(PyObject *module, path_t *path)
14054
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
14055
0
{
14056
0
    int result;
14057
14058
#ifdef __APPLE__
14059
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14060
     * the former uses 32-bit values for block counts.
14061
     */
14062
    struct statfs st;
14063
14064
    Py_BEGIN_ALLOW_THREADS
14065
    if (path->is_fd) {
14066
        result = fstatfs(path->fd, &st);
14067
    }
14068
    else
14069
        result = statfs(path->narrow, &st);
14070
    Py_END_ALLOW_THREADS
14071
14072
    if (result) {
14073
        return path_error(path);
14074
    }
14075
14076
    return _pystatvfs_fromstructstatfs(module, st);
14077
14078
#else
14079
0
    struct statvfs st;
14080
14081
0
    Py_BEGIN_ALLOW_THREADS
14082
0
#ifdef HAVE_FSTATVFS
14083
0
    if (path->is_fd) {
14084
0
        result = fstatvfs(path->fd, &st);
14085
0
    }
14086
0
    else
14087
0
#endif
14088
0
        result = statvfs(path->narrow, &st);
14089
0
    Py_END_ALLOW_THREADS
14090
14091
0
    if (result) {
14092
0
        return path_error(path);
14093
0
    }
14094
14095
0
    return _pystatvfs_fromstructstatvfs(module, st);
14096
0
#endif
14097
0
}
14098
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14099
14100
14101
#ifdef MS_WINDOWS
14102
/*[clinic input]
14103
os._getdiskusage
14104
14105
    path: path_t
14106
14107
Return disk usage statistics about the given path as a (total, free) tuple.
14108
[clinic start generated code]*/
14109
14110
static PyObject *
14111
os__getdiskusage_impl(PyObject *module, path_t *path)
14112
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
14113
{
14114
    BOOL retval;
14115
    ULARGE_INTEGER _, total, free;
14116
    DWORD err = 0;
14117
14118
    Py_BEGIN_ALLOW_THREADS
14119
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14120
    Py_END_ALLOW_THREADS
14121
    if (retval == 0) {
14122
        if (GetLastError() == ERROR_DIRECTORY) {
14123
            wchar_t *dir_path = NULL;
14124
14125
            dir_path = PyMem_New(wchar_t, path->length + 1);
14126
            if (dir_path == NULL) {
14127
                return PyErr_NoMemory();
14128
            }
14129
14130
            wcscpy_s(dir_path, path->length + 1, path->wide);
14131
14132
            if (_dirnameW(dir_path) != -1) {
14133
                Py_BEGIN_ALLOW_THREADS
14134
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14135
                Py_END_ALLOW_THREADS
14136
            }
14137
            /* Record the last error in case it's modified by PyMem_Free. */
14138
            err = GetLastError();
14139
            PyMem_Free(dir_path);
14140
            if (retval) {
14141
                goto success;
14142
            }
14143
        }
14144
        return PyErr_SetFromWindowsErr(err);
14145
    }
14146
14147
success:
14148
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14149
}
14150
#endif /* MS_WINDOWS */
14151
14152
14153
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14154
 * It maps strings representing configuration variable names to
14155
 * integer values, allowing those functions to be called with the
14156
 * magic names instead of polluting the module's namespace with tons of
14157
 * rarely-used constants.  There are three separate tables that use
14158
 * these definitions.
14159
 *
14160
 * This code is always included, even if none of the interfaces that
14161
 * need it are included.  The #if hackery needed to avoid it would be
14162
 * sufficiently pervasive that it's not worth the loss of readability.
14163
 */
14164
struct constdef {
14165
    const char *name;
14166
    int value;
14167
};
14168
14169
static int
14170
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14171
8
{
14172
8
    if (PyUnicode_Check(arg)) {
14173
8
        PyObject *table = PyObject_GetAttrString(module, tablename);
14174
8
        if (table == NULL) {
14175
0
            return 0;
14176
0
        }
14177
14178
8
        arg = PyObject_GetItem(table, arg);
14179
8
        Py_DECREF(table);
14180
8
        if (arg == NULL) {
14181
0
            PyErr_SetString(
14182
0
                PyExc_ValueError, "unrecognized configuration name");
14183
0
            return 0;
14184
0
        }
14185
8
    } else {
14186
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14187
0
    }
14188
14189
8
    int success = 0;
14190
8
    if (!PyIndex_Check(arg)) {
14191
0
        PyErr_SetString(PyExc_TypeError,
14192
0
            "configuration names must be strings or integers");
14193
8
    } else {
14194
8
        int value = PyLong_AsInt(arg);
14195
8
        if (!(value == -1 && PyErr_Occurred())) {
14196
8
            *valuep = value;
14197
8
            success = 1;
14198
8
        }
14199
8
    }
14200
8
    Py_DECREF(arg);
14201
8
    return success;
14202
8
}
14203
14204
14205
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14206
static struct constdef  posix_constants_pathconf[] = {
14207
#ifdef _PC_ABI_AIO_XFER_MAX
14208
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14209
#endif
14210
#ifdef _PC_ABI_ASYNC_IO
14211
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14212
#endif
14213
#ifdef _PC_ASYNC_IO
14214
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14215
#endif
14216
#ifdef _PC_CHOWN_RESTRICTED
14217
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14218
#endif
14219
#ifdef _PC_FILESIZEBITS
14220
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14221
#endif
14222
#ifdef _PC_LAST
14223
    {"PC_LAST", _PC_LAST},
14224
#endif
14225
#ifdef _PC_LINK_MAX
14226
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14227
#endif
14228
#ifdef _PC_MAX_CANON
14229
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14230
#endif
14231
#ifdef _PC_MAX_INPUT
14232
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14233
#endif
14234
#ifdef _PC_NAME_MAX
14235
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14236
#endif
14237
#ifdef _PC_NO_TRUNC
14238
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14239
#endif
14240
#ifdef _PC_PATH_MAX
14241
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14242
#endif
14243
#ifdef _PC_PIPE_BUF
14244
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14245
#endif
14246
#ifdef _PC_PRIO_IO
14247
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14248
#endif
14249
#ifdef _PC_SOCK_MAXBUF
14250
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14251
#endif
14252
#ifdef _PC_SYNC_IO
14253
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14254
#endif
14255
#ifdef _PC_VDISABLE
14256
    {"PC_VDISABLE",     _PC_VDISABLE},
14257
#endif
14258
#ifdef _PC_ACL_ENABLED
14259
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14260
#endif
14261
#ifdef _PC_MIN_HOLE_SIZE
14262
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14263
#endif
14264
#ifdef _PC_ALLOC_SIZE_MIN
14265
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14266
#endif
14267
#ifdef _PC_REC_INCR_XFER_SIZE
14268
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14269
#endif
14270
#ifdef _PC_REC_MAX_XFER_SIZE
14271
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14272
#endif
14273
#ifdef _PC_REC_MIN_XFER_SIZE
14274
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14275
#endif
14276
#ifdef _PC_REC_XFER_ALIGN
14277
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14278
#endif
14279
#ifdef _PC_SYMLINK_MAX
14280
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14281
#endif
14282
#ifdef _PC_XATTR_ENABLED
14283
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14284
#endif
14285
#ifdef _PC_XATTR_EXISTS
14286
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14287
#endif
14288
#ifdef _PC_TIMESTAMP_RESOLUTION
14289
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14290
#endif
14291
};
14292
#endif
14293
14294
14295
#ifdef HAVE_FPATHCONF
14296
/*[clinic input]
14297
os.fpathconf -> long
14298
14299
    fd: fildes
14300
    name: confname(table="pathconf_names")
14301
    /
14302
14303
Return the configuration limit name for the file descriptor fd.
14304
14305
If there is no limit, return -1.
14306
[clinic start generated code]*/
14307
14308
static long
14309
os_fpathconf_impl(PyObject *module, int fd, int name)
14310
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14311
0
{
14312
0
    long limit;
14313
14314
0
    errno = 0;
14315
0
    limit = fpathconf(fd, name);
14316
0
    if (limit == -1 && errno != 0)
14317
0
        posix_error();
14318
14319
0
    return limit;
14320
0
}
14321
#endif /* HAVE_FPATHCONF */
14322
14323
14324
#ifdef HAVE_PATHCONF
14325
/*[clinic input]
14326
os.pathconf -> long
14327
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14328
    name: confname(table="pathconf_names")
14329
14330
Return the configuration limit name for the file or directory path.
14331
14332
If there is no limit, return -1.
14333
On some platforms, path may also be specified as an open file descriptor.
14334
  If this functionality is unavailable, using it raises an exception.
14335
[clinic start generated code]*/
14336
14337
static long
14338
os_pathconf_impl(PyObject *module, path_t *path, int name)
14339
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
14340
0
{
14341
0
    long limit;
14342
14343
0
    errno = 0;
14344
0
#ifdef HAVE_FPATHCONF
14345
0
    if (path->is_fd) {
14346
0
        limit = fpathconf(path->fd, name);
14347
0
    }
14348
0
    else
14349
0
#endif
14350
0
        limit = pathconf(path->narrow, name);
14351
0
    if (limit == -1 && errno != 0) {
14352
0
        if (errno == EINVAL)
14353
            /* could be a path or name problem */
14354
0
            posix_error();
14355
0
        else
14356
0
            path_error(path);
14357
0
    }
14358
14359
0
    return limit;
14360
0
}
14361
#endif /* HAVE_PATHCONF */
14362
14363
#ifdef HAVE_CONFSTR
14364
static struct constdef posix_constants_confstr[] = {
14365
#ifdef _CS_ARCHITECTURE
14366
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14367
#endif
14368
#ifdef _CS_GNU_LIBC_VERSION
14369
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14370
#endif
14371
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14372
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14373
#endif
14374
#ifdef _CS_HOSTNAME
14375
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14376
#endif
14377
#ifdef _CS_HW_PROVIDER
14378
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14379
#endif
14380
#ifdef _CS_HW_SERIAL
14381
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14382
#endif
14383
#ifdef _CS_INITTAB_NAME
14384
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14385
#endif
14386
#ifdef _CS_LFS64_CFLAGS
14387
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14388
#endif
14389
#ifdef _CS_LFS64_LDFLAGS
14390
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14391
#endif
14392
#ifdef _CS_LFS64_LIBS
14393
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14394
#endif
14395
#ifdef _CS_LFS64_LINTFLAGS
14396
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14397
#endif
14398
#ifdef _CS_LFS_CFLAGS
14399
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14400
#endif
14401
#ifdef _CS_LFS_LDFLAGS
14402
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14403
#endif
14404
#ifdef _CS_LFS_LIBS
14405
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14406
#endif
14407
#ifdef _CS_LFS_LINTFLAGS
14408
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14409
#endif
14410
#ifdef _CS_MACHINE
14411
    {"CS_MACHINE",      _CS_MACHINE},
14412
#endif
14413
#ifdef _CS_PATH
14414
    {"CS_PATH", _CS_PATH},
14415
#endif
14416
#ifdef _CS_RELEASE
14417
    {"CS_RELEASE",      _CS_RELEASE},
14418
#endif
14419
#ifdef _CS_SRPC_DOMAIN
14420
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14421
#endif
14422
#ifdef _CS_SYSNAME
14423
    {"CS_SYSNAME",      _CS_SYSNAME},
14424
#endif
14425
#ifdef _CS_VERSION
14426
    {"CS_VERSION",      _CS_VERSION},
14427
#endif
14428
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14429
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14430
#endif
14431
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14432
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14433
#endif
14434
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14435
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14436
#endif
14437
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14438
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14439
#endif
14440
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14441
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14442
#endif
14443
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14444
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14445
#endif
14446
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14447
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14448
#endif
14449
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14450
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14451
#endif
14452
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14453
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14454
#endif
14455
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14456
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14457
#endif
14458
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14459
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14460
#endif
14461
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14462
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14463
#endif
14464
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14465
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14466
#endif
14467
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14468
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14469
#endif
14470
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14471
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14472
#endif
14473
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14474
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14475
#endif
14476
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14477
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14478
#endif
14479
#ifdef _MIPS_CS_BASE
14480
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14481
#endif
14482
#ifdef _MIPS_CS_HOSTID
14483
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14484
#endif
14485
#ifdef _MIPS_CS_HW_NAME
14486
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14487
#endif
14488
#ifdef _MIPS_CS_NUM_PROCESSORS
14489
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14490
#endif
14491
#ifdef _MIPS_CS_OSREL_MAJ
14492
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14493
#endif
14494
#ifdef _MIPS_CS_OSREL_MIN
14495
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14496
#endif
14497
#ifdef _MIPS_CS_OSREL_PATCH
14498
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14499
#endif
14500
#ifdef _MIPS_CS_OS_NAME
14501
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14502
#endif
14503
#ifdef _MIPS_CS_OS_PROVIDER
14504
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14505
#endif
14506
#ifdef _MIPS_CS_PROCESSORS
14507
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14508
#endif
14509
#ifdef _MIPS_CS_SERIAL
14510
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14511
#endif
14512
#ifdef _MIPS_CS_VENDOR
14513
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14514
#endif
14515
};
14516
14517
14518
/*[clinic input]
14519
os.confstr
14520
14521
    name: confname(table="confstr_names")
14522
    /
14523
14524
Return a string-valued system configuration variable.
14525
[clinic start generated code]*/
14526
14527
static PyObject *
14528
os_confstr_impl(PyObject *module, int name)
14529
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14530
4
{
14531
4
    PyObject *result = NULL;
14532
4
    char buffer[255];
14533
4
    size_t len;
14534
14535
4
    errno = 0;
14536
4
    len = confstr(name, buffer, sizeof(buffer));
14537
4
    if (len == 0) {
14538
0
        if (errno) {
14539
0
            posix_error();
14540
0
            return NULL;
14541
0
        }
14542
0
        else {
14543
0
            Py_RETURN_NONE;
14544
0
        }
14545
0
    }
14546
14547
4
    if (len >= sizeof(buffer)) {
14548
0
        size_t len2;
14549
0
        char *buf = PyMem_Malloc(len);
14550
0
        if (buf == NULL)
14551
0
            return PyErr_NoMemory();
14552
0
        len2 = confstr(name, buf, len);
14553
0
        assert(len == len2);
14554
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14555
0
        PyMem_Free(buf);
14556
0
    }
14557
4
    else
14558
4
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14559
4
    return result;
14560
4
}
14561
#endif /* HAVE_CONFSTR */
14562
14563
14564
#ifdef HAVE_SYSCONF
14565
static struct constdef posix_constants_sysconf[] = {
14566
#ifdef _SC_2_CHAR_TERM
14567
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14568
#endif
14569
#ifdef _SC_2_C_BIND
14570
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14571
#endif
14572
#ifdef _SC_2_C_DEV
14573
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14574
#endif
14575
#ifdef _SC_2_C_VERSION
14576
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14577
#endif
14578
#ifdef _SC_2_FORT_DEV
14579
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14580
#endif
14581
#ifdef _SC_2_FORT_RUN
14582
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14583
#endif
14584
#ifdef _SC_2_LOCALEDEF
14585
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14586
#endif
14587
#ifdef _SC_2_SW_DEV
14588
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14589
#endif
14590
#ifdef _SC_2_UPE
14591
    {"SC_2_UPE",        _SC_2_UPE},
14592
#endif
14593
#ifdef _SC_2_VERSION
14594
    {"SC_2_VERSION",    _SC_2_VERSION},
14595
#endif
14596
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14597
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14598
#endif
14599
#ifdef _SC_ACL
14600
    {"SC_ACL",  _SC_ACL},
14601
#endif
14602
#ifdef _SC_AIO_LISTIO_MAX
14603
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14604
#endif
14605
#ifdef _SC_AIO_MAX
14606
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14607
#endif
14608
#ifdef _SC_AIO_PRIO_DELTA_MAX
14609
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14610
#endif
14611
#ifdef _SC_ARG_MAX
14612
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14613
#endif
14614
#ifdef _SC_ASYNCHRONOUS_IO
14615
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14616
#endif
14617
#ifdef _SC_ATEXIT_MAX
14618
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14619
#endif
14620
#ifdef _SC_AUDIT
14621
    {"SC_AUDIT",        _SC_AUDIT},
14622
#endif
14623
#ifdef _SC_AVPHYS_PAGES
14624
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14625
#endif
14626
#ifdef _SC_BC_BASE_MAX
14627
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14628
#endif
14629
#ifdef _SC_BC_DIM_MAX
14630
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14631
#endif
14632
#ifdef _SC_BC_SCALE_MAX
14633
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14634
#endif
14635
#ifdef _SC_BC_STRING_MAX
14636
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14637
#endif
14638
#ifdef _SC_CAP
14639
    {"SC_CAP",  _SC_CAP},
14640
#endif
14641
#ifdef _SC_CHARCLASS_NAME_MAX
14642
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14643
#endif
14644
#ifdef _SC_CHAR_BIT
14645
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14646
#endif
14647
#ifdef _SC_CHAR_MAX
14648
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14649
#endif
14650
#ifdef _SC_CHAR_MIN
14651
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14652
#endif
14653
#ifdef _SC_CHILD_MAX
14654
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14655
#endif
14656
#ifdef _SC_CLK_TCK
14657
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14658
#endif
14659
#ifdef _SC_COHER_BLKSZ
14660
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14661
#endif
14662
#ifdef _SC_COLL_WEIGHTS_MAX
14663
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14664
#endif
14665
#ifdef _SC_DCACHE_ASSOC
14666
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14667
#endif
14668
#ifdef _SC_DCACHE_BLKSZ
14669
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14670
#endif
14671
#ifdef _SC_DCACHE_LINESZ
14672
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14673
#endif
14674
#ifdef _SC_DCACHE_SZ
14675
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14676
#endif
14677
#ifdef _SC_DCACHE_TBLKSZ
14678
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14679
#endif
14680
#ifdef _SC_DELAYTIMER_MAX
14681
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14682
#endif
14683
#ifdef _SC_EQUIV_CLASS_MAX
14684
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14685
#endif
14686
#ifdef _SC_EXPR_NEST_MAX
14687
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14688
#endif
14689
#ifdef _SC_FSYNC
14690
    {"SC_FSYNC",        _SC_FSYNC},
14691
#endif
14692
#ifdef _SC_GETGR_R_SIZE_MAX
14693
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14694
#endif
14695
#ifdef _SC_GETPW_R_SIZE_MAX
14696
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14697
#endif
14698
#ifdef _SC_ICACHE_ASSOC
14699
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14700
#endif
14701
#ifdef _SC_ICACHE_BLKSZ
14702
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14703
#endif
14704
#ifdef _SC_ICACHE_LINESZ
14705
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14706
#endif
14707
#ifdef _SC_ICACHE_SZ
14708
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14709
#endif
14710
#ifdef _SC_INF
14711
    {"SC_INF",  _SC_INF},
14712
#endif
14713
#ifdef _SC_INT_MAX
14714
    {"SC_INT_MAX",      _SC_INT_MAX},
14715
#endif
14716
#ifdef _SC_INT_MIN
14717
    {"SC_INT_MIN",      _SC_INT_MIN},
14718
#endif
14719
#ifdef _SC_IOV_MAX
14720
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14721
#endif
14722
#ifdef _SC_IP_SECOPTS
14723
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14724
#endif
14725
#ifdef _SC_JOB_CONTROL
14726
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14727
#endif
14728
#ifdef _SC_KERN_POINTERS
14729
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14730
#endif
14731
#ifdef _SC_KERN_SIM
14732
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14733
#endif
14734
#ifdef _SC_LINE_MAX
14735
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14736
#endif
14737
#ifdef _SC_LOGIN_NAME_MAX
14738
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14739
#endif
14740
#ifdef _SC_LOGNAME_MAX
14741
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14742
#endif
14743
#ifdef _SC_LONG_BIT
14744
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14745
#endif
14746
#ifdef _SC_MAC
14747
    {"SC_MAC",  _SC_MAC},
14748
#endif
14749
#ifdef _SC_MAPPED_FILES
14750
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14751
#endif
14752
#ifdef _SC_MAXPID
14753
    {"SC_MAXPID",       _SC_MAXPID},
14754
#endif
14755
#ifdef _SC_MB_LEN_MAX
14756
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14757
#endif
14758
#ifdef _SC_MEMLOCK
14759
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14760
#endif
14761
#ifdef _SC_MEMLOCK_RANGE
14762
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14763
#endif
14764
#ifdef _SC_MEMORY_PROTECTION
14765
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14766
#endif
14767
#ifdef _SC_MESSAGE_PASSING
14768
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14769
#endif
14770
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14771
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14772
#endif
14773
#ifdef _SC_MQ_OPEN_MAX
14774
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14775
#endif
14776
#ifdef _SC_MQ_PRIO_MAX
14777
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14778
#endif
14779
#ifdef _SC_NACLS_MAX
14780
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14781
#endif
14782
#ifdef _SC_NGROUPS_MAX
14783
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14784
#endif
14785
#ifdef _SC_NL_ARGMAX
14786
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14787
#endif
14788
#ifdef _SC_NL_LANGMAX
14789
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14790
#endif
14791
#ifdef _SC_NL_MSGMAX
14792
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14793
#endif
14794
#ifdef _SC_NL_NMAX
14795
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14796
#endif
14797
#ifdef _SC_NL_SETMAX
14798
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14799
#endif
14800
#ifdef _SC_NL_TEXTMAX
14801
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14802
#endif
14803
#ifdef _SC_NPROCESSORS_CONF
14804
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14805
#endif
14806
#ifdef _SC_NPROCESSORS_ONLN
14807
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14808
#endif
14809
#ifdef _SC_NPROC_CONF
14810
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14811
#endif
14812
#ifdef _SC_NPROC_ONLN
14813
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14814
#endif
14815
#ifdef _SC_NZERO
14816
    {"SC_NZERO",        _SC_NZERO},
14817
#endif
14818
#ifdef _SC_OPEN_MAX
14819
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14820
#endif
14821
#ifdef _SC_PAGESIZE
14822
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14823
#endif
14824
#ifdef _SC_PAGE_SIZE
14825
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14826
#endif
14827
#ifdef _SC_AIX_REALMEM
14828
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14829
#endif
14830
#ifdef _SC_PASS_MAX
14831
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14832
#endif
14833
#ifdef _SC_PHYS_PAGES
14834
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14835
#endif
14836
#ifdef _SC_PII
14837
    {"SC_PII",  _SC_PII},
14838
#endif
14839
#ifdef _SC_PII_INTERNET
14840
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14841
#endif
14842
#ifdef _SC_PII_INTERNET_DGRAM
14843
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14844
#endif
14845
#ifdef _SC_PII_INTERNET_STREAM
14846
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14847
#endif
14848
#ifdef _SC_PII_OSI
14849
    {"SC_PII_OSI",      _SC_PII_OSI},
14850
#endif
14851
#ifdef _SC_PII_OSI_CLTS
14852
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14853
#endif
14854
#ifdef _SC_PII_OSI_COTS
14855
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14856
#endif
14857
#ifdef _SC_PII_OSI_M
14858
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14859
#endif
14860
#ifdef _SC_PII_SOCKET
14861
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14862
#endif
14863
#ifdef _SC_PII_XTI
14864
    {"SC_PII_XTI",      _SC_PII_XTI},
14865
#endif
14866
#ifdef _SC_POLL
14867
    {"SC_POLL", _SC_POLL},
14868
#endif
14869
#ifdef _SC_PRIORITIZED_IO
14870
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14871
#endif
14872
#ifdef _SC_PRIORITY_SCHEDULING
14873
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14874
#endif
14875
#ifdef _SC_REALTIME_SIGNALS
14876
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14877
#endif
14878
#ifdef _SC_RE_DUP_MAX
14879
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14880
#endif
14881
#ifdef _SC_RTSIG_MAX
14882
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14883
#endif
14884
#ifdef _SC_SAVED_IDS
14885
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14886
#endif
14887
#ifdef _SC_SCHAR_MAX
14888
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14889
#endif
14890
#ifdef _SC_SCHAR_MIN
14891
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14892
#endif
14893
#ifdef _SC_SELECT
14894
    {"SC_SELECT",       _SC_SELECT},
14895
#endif
14896
#ifdef _SC_SEMAPHORES
14897
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14898
#endif
14899
#ifdef _SC_SEM_NSEMS_MAX
14900
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14901
#endif
14902
#ifdef _SC_SEM_VALUE_MAX
14903
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14904
#endif
14905
#ifdef _SC_SHARED_MEMORY_OBJECTS
14906
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14907
#endif
14908
#ifdef _SC_SHRT_MAX
14909
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14910
#endif
14911
#ifdef _SC_SHRT_MIN
14912
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14913
#endif
14914
#ifdef _SC_SIGQUEUE_MAX
14915
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14916
#endif
14917
#ifdef _SC_SIGRT_MAX
14918
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14919
#endif
14920
#ifdef _SC_SIGRT_MIN
14921
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14922
#endif
14923
#ifdef _SC_SOFTPOWER
14924
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14925
#endif
14926
#ifdef _SC_SPLIT_CACHE
14927
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14928
#endif
14929
#ifdef _SC_SSIZE_MAX
14930
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14931
#endif
14932
#ifdef _SC_STACK_PROT
14933
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14934
#endif
14935
#ifdef _SC_STREAM_MAX
14936
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14937
#endif
14938
#ifdef _SC_SYNCHRONIZED_IO
14939
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14940
#endif
14941
#ifdef _SC_THREADS
14942
    {"SC_THREADS",      _SC_THREADS},
14943
#endif
14944
#ifdef _SC_THREAD_ATTR_STACKADDR
14945
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14946
#endif
14947
#ifdef _SC_THREAD_ATTR_STACKSIZE
14948
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14949
#endif
14950
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14951
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14952
#endif
14953
#ifdef _SC_THREAD_KEYS_MAX
14954
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14955
#endif
14956
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14957
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14958
#endif
14959
#ifdef _SC_THREAD_PRIO_INHERIT
14960
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14961
#endif
14962
#ifdef _SC_THREAD_PRIO_PROTECT
14963
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14964
#endif
14965
#ifdef _SC_THREAD_PROCESS_SHARED
14966
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14967
#endif
14968
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14969
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14970
#endif
14971
#ifdef _SC_THREAD_STACK_MIN
14972
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14973
#endif
14974
#ifdef _SC_THREAD_THREADS_MAX
14975
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14976
#endif
14977
#ifdef _SC_TIMERS
14978
    {"SC_TIMERS",       _SC_TIMERS},
14979
#endif
14980
#ifdef _SC_TIMER_MAX
14981
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14982
#endif
14983
#ifdef _SC_TTY_NAME_MAX
14984
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14985
#endif
14986
#ifdef _SC_TZNAME_MAX
14987
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14988
#endif
14989
#ifdef _SC_T_IOV_MAX
14990
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14991
#endif
14992
#ifdef _SC_UCHAR_MAX
14993
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14994
#endif
14995
#ifdef _SC_UINT_MAX
14996
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14997
#endif
14998
#ifdef _SC_UIO_MAXIOV
14999
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
15000
#endif
15001
#ifdef _SC_ULONG_MAX
15002
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
15003
#endif
15004
#ifdef _SC_USHRT_MAX
15005
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
15006
#endif
15007
#ifdef _SC_VERSION
15008
    {"SC_VERSION",      _SC_VERSION},
15009
#endif
15010
#ifdef _SC_WORD_BIT
15011
    {"SC_WORD_BIT",     _SC_WORD_BIT},
15012
#endif
15013
#ifdef _SC_XBS5_ILP32_OFF32
15014
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15015
#endif
15016
#ifdef _SC_XBS5_ILP32_OFFBIG
15017
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15018
#endif
15019
#ifdef _SC_XBS5_LP64_OFF64
15020
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15021
#endif
15022
#ifdef _SC_XBS5_LPBIG_OFFBIG
15023
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15024
#endif
15025
#ifdef _SC_XOPEN_CRYPT
15026
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15027
#endif
15028
#ifdef _SC_XOPEN_ENH_I18N
15029
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15030
#endif
15031
#ifdef _SC_XOPEN_LEGACY
15032
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15033
#endif
15034
#ifdef _SC_XOPEN_REALTIME
15035
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15036
#endif
15037
#ifdef _SC_XOPEN_REALTIME_THREADS
15038
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15039
#endif
15040
#ifdef _SC_XOPEN_SHM
15041
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15042
#endif
15043
#ifdef _SC_XOPEN_UNIX
15044
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15045
#endif
15046
#ifdef _SC_XOPEN_VERSION
15047
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15048
#endif
15049
#ifdef _SC_XOPEN_XCU_VERSION
15050
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15051
#endif
15052
#ifdef _SC_XOPEN_XPG2
15053
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15054
#endif
15055
#ifdef _SC_XOPEN_XPG3
15056
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15057
#endif
15058
#ifdef _SC_XOPEN_XPG4
15059
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15060
#endif
15061
#ifdef _SC_MINSIGSTKSZ
15062
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15063
#endif
15064
};
15065
15066
15067
/*[clinic input]
15068
os.sysconf -> long
15069
    name: confname(table="sysconf_names")
15070
    /
15071
15072
Return an integer-valued system configuration variable.
15073
[clinic start generated code]*/
15074
15075
static long
15076
os_sysconf_impl(PyObject *module, int name)
15077
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15078
4
{
15079
4
    long value;
15080
15081
4
    errno = 0;
15082
4
    value = sysconf(name);
15083
4
    if (value == -1 && errno != 0)
15084
0
        posix_error();
15085
4
    return value;
15086
4
}
15087
#endif /* HAVE_SYSCONF */
15088
15089
15090
static int
15091
setup_confname_table(struct constdef *table, size_t tablesize,
15092
                     const char *tablename, PyObject *module)
15093
111
{
15094
111
    PyObject *d = PyDict_New();
15095
111
    if (d == NULL)
15096
0
        return -1;
15097
15098
6.80k
    for (size_t i=0; i < tablesize; ++i) {
15099
6.69k
        PyObject *o = PyLong_FromLong(table[i].value);
15100
6.69k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15101
0
            Py_XDECREF(o);
15102
0
            Py_DECREF(d);
15103
0
            return -1;
15104
0
        }
15105
6.69k
        Py_DECREF(o);
15106
6.69k
    }
15107
111
    return PyModule_Add(module, tablename, d);
15108
111
}
15109
15110
/* Return -1 on failure, 0 on success. */
15111
static int
15112
setup_confname_tables(PyObject *module)
15113
37
{
15114
37
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15115
37
    if (setup_confname_table(posix_constants_pathconf,
15116
37
                             sizeof(posix_constants_pathconf)
15117
37
                               / sizeof(struct constdef),
15118
37
                             "pathconf_names", module))
15119
0
        return -1;
15120
37
#endif
15121
37
#ifdef HAVE_CONFSTR
15122
37
    if (setup_confname_table(posix_constants_confstr,
15123
37
                             sizeof(posix_constants_confstr)
15124
37
                               / sizeof(struct constdef),
15125
37
                             "confstr_names", module))
15126
0
        return -1;
15127
37
#endif
15128
37
#ifdef HAVE_SYSCONF
15129
37
    if (setup_confname_table(posix_constants_sysconf,
15130
37
                             sizeof(posix_constants_sysconf)
15131
37
                               / sizeof(struct constdef),
15132
37
                             "sysconf_names", module))
15133
0
        return -1;
15134
37
#endif
15135
37
    return 0;
15136
37
}
15137
15138
15139
/*[clinic input]
15140
os.abort
15141
15142
Abort the interpreter immediately.
15143
15144
This function 'dumps core' or otherwise fails in the hardest way possible
15145
on the hosting operating system.  This function never returns.
15146
[clinic start generated code]*/
15147
15148
static PyObject *
15149
os_abort_impl(PyObject *module)
15150
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
15151
0
{
15152
0
    abort();
15153
    /*NOTREACHED*/
15154
#ifndef __clang__
15155
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15156
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15157
       is smarter and emits a warning on the return. */
15158
    Py_FatalError("abort() called from Python code didn't abort!");
15159
    return NULL;
15160
#endif
15161
0
}
15162
15163
#ifdef MS_WINDOWS
15164
/* Grab ShellExecute dynamically from shell32 */
15165
static int has_ShellExecute = -1;
15166
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15167
                                              LPCWSTR, INT);
15168
static int
15169
check_ShellExecute(void)
15170
{
15171
    HINSTANCE hShell32;
15172
15173
    /* only recheck */
15174
    if (-1 == has_ShellExecute) {
15175
        Py_BEGIN_ALLOW_THREADS
15176
        /* Security note: this call is not vulnerable to "DLL hijacking".
15177
           SHELL32 is part of "KnownDLLs" and so Windows always load
15178
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15179
           in the DLL search path. */
15180
        hShell32 = LoadLibraryW(L"SHELL32");
15181
        if (hShell32) {
15182
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15183
                                            "ShellExecuteW");
15184
            has_ShellExecute = Py_ShellExecuteW != NULL;
15185
        } else {
15186
            has_ShellExecute = 0;
15187
        }
15188
        Py_END_ALLOW_THREADS
15189
    }
15190
    return has_ShellExecute;
15191
}
15192
15193
15194
/*[clinic input]
15195
os.startfile
15196
    filepath: path_t
15197
    operation: Py_UNICODE = NULL
15198
    arguments: Py_UNICODE = NULL
15199
    cwd: path_t(nullable=True) = None
15200
    show_cmd: int = 1
15201
15202
Start a file with its associated application.
15203
15204
When "operation" is not specified or "open", this acts like
15205
double-clicking the file in Explorer, or giving the file name as an
15206
argument to the DOS "start" command: the file is opened with whatever
15207
application (if any) its extension is associated.
15208
When another "operation" is given, it specifies what should be done with
15209
the file.  A typical operation is "print".
15210
15211
"arguments" is passed to the application, but should be omitted if the
15212
file is a document.
15213
15214
"cwd" is the working directory for the operation. If "filepath" is
15215
relative, it will be resolved against this directory. This argument
15216
should usually be an absolute path.
15217
15218
"show_cmd" can be used to override the recommended visibility option.
15219
See the Windows ShellExecute documentation for values.
15220
15221
startfile returns as soon as the associated application is launched.
15222
There is no option to wait for the application to close, and no way
15223
to retrieve the application's exit status.
15224
15225
The filepath is relative to the current directory.  If you want to use
15226
an absolute path, make sure the first character is not a slash ("/");
15227
the underlying Win32 ShellExecute function doesn't work if it is.
15228
[clinic start generated code]*/
15229
15230
static PyObject *
15231
os_startfile_impl(PyObject *module, path_t *filepath,
15232
                  const wchar_t *operation, const wchar_t *arguments,
15233
                  path_t *cwd, int show_cmd)
15234
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15235
{
15236
    HINSTANCE rc;
15237
15238
    if(!check_ShellExecute()) {
15239
        /* If the OS doesn't have ShellExecute, return a
15240
           NotImplementedError. */
15241
        return PyErr_Format(PyExc_NotImplementedError,
15242
            "startfile not available on this platform");
15243
    }
15244
15245
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15246
        return NULL;
15247
    }
15248
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15249
                    arguments, cwd->object ? cwd->object : Py_None,
15250
                    show_cmd) < 0) {
15251
        return NULL;
15252
    }
15253
15254
    Py_BEGIN_ALLOW_THREADS
15255
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15256
                          arguments, cwd->wide, show_cmd);
15257
    Py_END_ALLOW_THREADS
15258
15259
    if (rc <= (HINSTANCE)32) {
15260
        win32_error_object("startfile", filepath->object);
15261
        return NULL;
15262
    }
15263
    Py_RETURN_NONE;
15264
}
15265
#endif /* MS_WINDOWS */
15266
15267
15268
#ifdef HAVE_GETLOADAVG
15269
/*[clinic input]
15270
os.getloadavg
15271
15272
Return average recent system load information.
15273
15274
Return the number of processes in the system run queue averaged over
15275
the last 1, 5, and 15 minutes as a tuple of three floats.
15276
Raises OSError if the load average was unobtainable.
15277
[clinic start generated code]*/
15278
15279
static PyObject *
15280
os_getloadavg_impl(PyObject *module)
15281
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15282
0
{
15283
0
    double loadavg[3];
15284
0
    if (getloadavg(loadavg, 3)!=3) {
15285
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15286
0
        return NULL;
15287
0
    } else
15288
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15289
0
}
15290
#endif /* HAVE_GETLOADAVG */
15291
15292
15293
/*[clinic input]
15294
os.device_encoding
15295
    fd: int
15296
15297
Return a string describing the encoding of a terminal's file descriptor.
15298
15299
The file descriptor must be attached to a terminal.
15300
If the device is not a terminal, return None.
15301
[clinic start generated code]*/
15302
15303
static PyObject *
15304
os_device_encoding_impl(PyObject *module, int fd)
15305
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15306
0
{
15307
0
    return _Py_device_encoding(fd);
15308
0
}
15309
15310
15311
#ifdef HAVE_SETRESUID
15312
/*[clinic input]
15313
os.setresuid
15314
15315
    ruid: uid_t
15316
    euid: uid_t
15317
    suid: uid_t
15318
    /
15319
15320
Set the current process's real, effective, and saved user ids.
15321
[clinic start generated code]*/
15322
15323
static PyObject *
15324
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15325
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15326
0
{
15327
0
    if (setresuid(ruid, euid, suid) < 0)
15328
0
        return posix_error();
15329
0
    Py_RETURN_NONE;
15330
0
}
15331
#endif /* HAVE_SETRESUID */
15332
15333
15334
#ifdef HAVE_SETRESGID
15335
/*[clinic input]
15336
os.setresgid
15337
15338
    rgid: gid_t
15339
    egid: gid_t
15340
    sgid: gid_t
15341
    /
15342
15343
Set the current process's real, effective, and saved group ids.
15344
[clinic start generated code]*/
15345
15346
static PyObject *
15347
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15348
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15349
0
{
15350
0
    if (setresgid(rgid, egid, sgid) < 0)
15351
0
        return posix_error();
15352
0
    Py_RETURN_NONE;
15353
0
}
15354
#endif /* HAVE_SETRESGID */
15355
15356
15357
#ifdef HAVE_GETRESUID
15358
/*[clinic input]
15359
os.getresuid
15360
15361
Return a tuple of the current process's real, effective, and saved user ids.
15362
[clinic start generated code]*/
15363
15364
static PyObject *
15365
os_getresuid_impl(PyObject *module)
15366
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
15367
0
{
15368
0
    uid_t ruid, euid, suid;
15369
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15370
0
        return posix_error();
15371
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15372
0
                                  _PyLong_FromUid(euid),
15373
0
                                  _PyLong_FromUid(suid));
15374
0
}
15375
#endif /* HAVE_GETRESUID */
15376
15377
15378
#ifdef HAVE_GETRESGID
15379
/*[clinic input]
15380
@permit_long_summary
15381
os.getresgid
15382
15383
Return a tuple of the current process's real, effective, and saved group ids.
15384
[clinic start generated code]*/
15385
15386
static PyObject *
15387
os_getresgid_impl(PyObject *module)
15388
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15389
0
{
15390
0
    gid_t rgid, egid, sgid;
15391
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15392
0
        return posix_error();
15393
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15394
0
                                  _PyLong_FromGid(egid),
15395
0
                                  _PyLong_FromGid(sgid));
15396
0
}
15397
#endif /* HAVE_GETRESGID */
15398
15399
15400
#ifdef USE_XATTRS
15401
/*[clinic input]
15402
os.getxattr
15403
15404
    path: path_t(allow_fd=True)
15405
    attribute: path_t
15406
    *
15407
    follow_symlinks: bool = True
15408
15409
Return the value of extended attribute attribute on path.
15410
15411
path may be either a string, a path-like object, or an open file descriptor.
15412
If follow_symlinks is False, and the last element of the path is a symbolic
15413
  link, getxattr will examine the symbolic link itself instead of the file
15414
  the link points to.
15415
15416
[clinic start generated code]*/
15417
15418
static PyObject *
15419
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15420
                 int follow_symlinks)
15421
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
15422
0
{
15423
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
15424
0
        return NULL;
15425
15426
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15427
0
        return NULL;
15428
0
    }
15429
15430
0
    for (Py_ssize_t i = 0; ; i++) {
15431
0
        ssize_t result;
15432
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15433
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15434
0
        if (!buffer_size) {
15435
0
            path_error(path);
15436
0
            return NULL;
15437
0
        }
15438
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15439
0
        if (writer == NULL) {
15440
0
            return NULL;
15441
0
        }
15442
0
        void *ptr = PyBytesWriter_GetData(writer);
15443
15444
0
        Py_BEGIN_ALLOW_THREADS;
15445
0
        if (path->is_fd)
15446
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15447
0
        else if (follow_symlinks)
15448
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15449
0
        else
15450
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15451
0
        Py_END_ALLOW_THREADS;
15452
15453
0
        if (result < 0) {
15454
0
            PyBytesWriter_Discard(writer);
15455
0
            if (errno == ERANGE) {
15456
0
                continue;
15457
0
            }
15458
0
            path_error(path);
15459
0
            return NULL;
15460
0
        }
15461
15462
0
        return PyBytesWriter_FinishWithSize(writer, result);
15463
0
    }
15464
0
}
15465
15466
15467
/*[clinic input]
15468
@permit_long_docstring_body
15469
os.setxattr
15470
15471
    path: path_t(allow_fd=True)
15472
    attribute: path_t
15473
    value: Py_buffer
15474
    flags: int = 0
15475
    *
15476
    follow_symlinks: bool = True
15477
15478
Set extended attribute attribute on path to value.
15479
15480
path may be either a string, a path-like object,  or an open file descriptor.
15481
If follow_symlinks is False, and the last element of the path is a symbolic
15482
  link, setxattr will modify the symbolic link itself instead of the file
15483
  the link points to.
15484
15485
[clinic start generated code]*/
15486
15487
static PyObject *
15488
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15489
                 Py_buffer *value, int flags, int follow_symlinks)
15490
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15491
0
{
15492
0
    ssize_t result;
15493
15494
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
15495
0
        return NULL;
15496
15497
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15498
0
                    value->buf, value->len, flags) < 0) {
15499
0
        return NULL;
15500
0
    }
15501
15502
0
    Py_BEGIN_ALLOW_THREADS;
15503
0
    if (path->is_fd)
15504
0
        result = fsetxattr(path->fd, attribute->narrow,
15505
0
                           value->buf, value->len, flags);
15506
0
    else if (follow_symlinks)
15507
0
        result = setxattr(path->narrow, attribute->narrow,
15508
0
                           value->buf, value->len, flags);
15509
0
    else
15510
0
        result = lsetxattr(path->narrow, attribute->narrow,
15511
0
                           value->buf, value->len, flags);
15512
0
    Py_END_ALLOW_THREADS;
15513
15514
0
    if (result) {
15515
0
        path_error(path);
15516
0
        return NULL;
15517
0
    }
15518
15519
0
    Py_RETURN_NONE;
15520
0
}
15521
15522
15523
/*[clinic input]
15524
os.removexattr
15525
15526
    path: path_t(allow_fd=True)
15527
    attribute: path_t
15528
    *
15529
    follow_symlinks: bool = True
15530
15531
Remove extended attribute attribute on path.
15532
15533
path may be either a string, a path-like object, or an open file descriptor.
15534
If follow_symlinks is False, and the last element of the path is a symbolic
15535
  link, removexattr will modify the symbolic link itself instead of the file
15536
  the link points to.
15537
15538
[clinic start generated code]*/
15539
15540
static PyObject *
15541
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15542
                    int follow_symlinks)
15543
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15544
0
{
15545
0
    ssize_t result;
15546
15547
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
15548
0
        return NULL;
15549
15550
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15551
0
        return NULL;
15552
0
    }
15553
15554
0
    Py_BEGIN_ALLOW_THREADS;
15555
0
    if (path->is_fd)
15556
0
        result = fremovexattr(path->fd, attribute->narrow);
15557
0
    else if (follow_symlinks)
15558
0
        result = removexattr(path->narrow, attribute->narrow);
15559
0
    else
15560
0
        result = lremovexattr(path->narrow, attribute->narrow);
15561
0
    Py_END_ALLOW_THREADS;
15562
15563
0
    if (result) {
15564
0
        return path_error(path);
15565
0
    }
15566
15567
0
    Py_RETURN_NONE;
15568
0
}
15569
15570
15571
/*[clinic input]
15572
@permit_long_docstring_body
15573
os.listxattr
15574
15575
    path: path_t(allow_fd=True, nullable=True) = None
15576
    *
15577
    follow_symlinks: bool = True
15578
15579
Return a list of extended attributes on path.
15580
15581
path may be either None, a string, a path-like object, or an open file descriptor.
15582
if path is None, listxattr will examine the current directory.
15583
If follow_symlinks is False, and the last element of the path is a symbolic
15584
  link, listxattr will examine the symbolic link itself instead of the file
15585
  the link points to.
15586
[clinic start generated code]*/
15587
15588
static PyObject *
15589
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15590
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15591
0
{
15592
0
    Py_ssize_t i;
15593
0
    PyObject *result = NULL;
15594
0
    const char *name;
15595
0
    char *buffer = NULL;
15596
15597
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
15598
0
        goto exit;
15599
15600
0
    if (PySys_Audit("os.listxattr", "(O)",
15601
0
                    path->object ? path->object : Py_None) < 0) {
15602
0
        return NULL;
15603
0
    }
15604
15605
0
    name = path->narrow ? path->narrow : ".";
15606
15607
0
    for (i = 0; ; i++) {
15608
0
        const char *start, *trace, *end;
15609
0
        ssize_t length;
15610
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15611
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15612
0
        if (!buffer_size) {
15613
            /* ERANGE */
15614
0
            path_error(path);
15615
0
            break;
15616
0
        }
15617
0
        buffer = PyMem_Malloc(buffer_size);
15618
0
        if (!buffer) {
15619
0
            PyErr_NoMemory();
15620
0
            break;
15621
0
        }
15622
15623
0
        Py_BEGIN_ALLOW_THREADS;
15624
0
        if (path->is_fd)
15625
0
            length = flistxattr(path->fd, buffer, buffer_size);
15626
0
        else if (follow_symlinks)
15627
0
            length = listxattr(name, buffer, buffer_size);
15628
0
        else
15629
0
            length = llistxattr(name, buffer, buffer_size);
15630
0
        Py_END_ALLOW_THREADS;
15631
15632
0
        if (length < 0) {
15633
0
            if (errno == ERANGE) {
15634
0
                PyMem_Free(buffer);
15635
0
                buffer = NULL;
15636
0
                continue;
15637
0
            }
15638
0
            path_error(path);
15639
0
            break;
15640
0
        }
15641
15642
0
        result = PyList_New(0);
15643
0
        if (!result) {
15644
0
            goto exit;
15645
0
        }
15646
15647
0
        end = buffer + length;
15648
0
        for (trace = start = buffer; trace != end; trace++) {
15649
0
            if (!*trace) {
15650
0
                int error;
15651
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15652
0
                                                                 trace - start);
15653
0
                if (!attribute) {
15654
0
                    Py_SETREF(result, NULL);
15655
0
                    goto exit;
15656
0
                }
15657
0
                error = PyList_Append(result, attribute);
15658
0
                Py_DECREF(attribute);
15659
0
                if (error) {
15660
0
                    Py_SETREF(result, NULL);
15661
0
                    goto exit;
15662
0
                }
15663
0
                start = trace + 1;
15664
0
            }
15665
0
        }
15666
0
    break;
15667
0
    }
15668
0
exit:
15669
0
    if (buffer)
15670
0
        PyMem_Free(buffer);
15671
0
    return result;
15672
0
}
15673
#endif /* USE_XATTRS */
15674
15675
15676
/*[clinic input]
15677
@permit_long_summary
15678
os.urandom
15679
15680
    size: Py_ssize_t(allow_negative=False)
15681
    /
15682
15683
Return a bytes object containing random bytes suitable for cryptographic use.
15684
[clinic start generated code]*/
15685
15686
static PyObject *
15687
os_urandom_impl(PyObject *module, Py_ssize_t size)
15688
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15689
0
{
15690
0
    if (size < 0) {
15691
0
        return PyErr_Format(PyExc_ValueError,
15692
0
                            "negative argument not allowed");
15693
0
    }
15694
15695
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15696
0
    if (writer == NULL) {
15697
0
        return NULL;
15698
0
    }
15699
15700
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15701
0
    if (result == -1) {
15702
0
        PyBytesWriter_Discard(writer);
15703
0
        return NULL;
15704
0
    }
15705
0
    return PyBytesWriter_Finish(writer);
15706
0
}
15707
15708
#ifdef HAVE_MEMFD_CREATE
15709
/*[clinic input]
15710
os.memfd_create
15711
15712
    name: unicode_fs_encoded
15713
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15714
15715
[clinic start generated code]*/
15716
15717
static PyObject *
15718
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15719
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15720
0
{
15721
0
    int fd;
15722
0
    const char *bytes = PyBytes_AS_STRING(name);
15723
0
    Py_BEGIN_ALLOW_THREADS
15724
0
    fd = memfd_create(bytes, flags);
15725
0
    Py_END_ALLOW_THREADS
15726
0
    if (fd == -1) {
15727
0
        return PyErr_SetFromErrno(PyExc_OSError);
15728
0
    }
15729
0
    return PyLong_FromLong(fd);
15730
0
}
15731
#endif
15732
15733
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15734
/*[clinic input]
15735
os.eventfd
15736
15737
    initval: unsigned_int
15738
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15739
15740
Creates and returns an event notification file descriptor.
15741
[clinic start generated code]*/
15742
15743
static PyObject *
15744
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15745
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15746
15747
0
{
15748
    /* initval is limited to uint32_t, internal counter is uint64_t */
15749
0
    int fd;
15750
0
    Py_BEGIN_ALLOW_THREADS
15751
0
    fd = eventfd(initval, flags);
15752
0
    Py_END_ALLOW_THREADS
15753
0
    if (fd == -1) {
15754
0
        return PyErr_SetFromErrno(PyExc_OSError);
15755
0
    }
15756
0
    return PyLong_FromLong(fd);
15757
0
}
15758
15759
/*[clinic input]
15760
os.eventfd_read
15761
15762
    fd: fildes
15763
15764
Read eventfd value
15765
[clinic start generated code]*/
15766
15767
static PyObject *
15768
os_eventfd_read_impl(PyObject *module, int fd)
15769
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15770
0
{
15771
0
    eventfd_t value;
15772
0
    int result;
15773
0
    Py_BEGIN_ALLOW_THREADS
15774
0
    result = eventfd_read(fd, &value);
15775
0
    Py_END_ALLOW_THREADS
15776
0
    if (result == -1) {
15777
0
        return PyErr_SetFromErrno(PyExc_OSError);
15778
0
    }
15779
0
    return PyLong_FromUnsignedLongLong(value);
15780
0
}
15781
15782
/*[clinic input]
15783
os.eventfd_write
15784
15785
    fd: fildes
15786
    value: unsigned_long_long
15787
15788
Write eventfd value.
15789
[clinic start generated code]*/
15790
15791
static PyObject *
15792
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15793
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15794
0
{
15795
0
    int result;
15796
0
    Py_BEGIN_ALLOW_THREADS
15797
0
    result = eventfd_write(fd, value);
15798
0
    Py_END_ALLOW_THREADS
15799
0
    if (result == -1) {
15800
0
        return PyErr_SetFromErrno(PyExc_OSError);
15801
0
    }
15802
0
    Py_RETURN_NONE;
15803
0
}
15804
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15805
15806
/* Terminal size querying */
15807
15808
PyDoc_STRVAR(TerminalSize_docstring,
15809
    "A tuple of (columns, lines) for holding terminal window size");
15810
15811
static PyStructSequence_Field TerminalSize_fields[] = {
15812
    {"columns", "width of the terminal window in characters"},
15813
    {"lines", "height of the terminal window in characters"},
15814
    {NULL, NULL}
15815
};
15816
15817
static PyStructSequence_Desc TerminalSize_desc = {
15818
    "os.terminal_size",
15819
    TerminalSize_docstring,
15820
    TerminalSize_fields,
15821
    2,
15822
};
15823
15824
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15825
/*[clinic input]
15826
os.get_terminal_size
15827
15828
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15829
    /
15830
15831
Return the size of the terminal window as (columns, lines).
15832
15833
The optional argument fd (default standard output) specifies
15834
which file descriptor should be queried.
15835
15836
If the file descriptor is not connected to a terminal, an OSError
15837
is thrown.
15838
15839
This function will only be defined if an implementation is
15840
available for this system.
15841
15842
shutil.get_terminal_size is the high-level function which should
15843
normally be used, os.get_terminal_size is the low-level implementation.
15844
[clinic start generated code]*/
15845
15846
static PyObject *
15847
os_get_terminal_size_impl(PyObject *module, int fd)
15848
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15849
0
{
15850
0
    int columns, lines;
15851
0
    PyObject *termsize;
15852
15853
    /* Under some conditions stdout may not be connected and
15854
     * fileno(stdout) may point to an invalid file descriptor. For example
15855
     * GUI apps don't have valid standard streams by default.
15856
     *
15857
     * If this happens, and the optional fd argument is not present,
15858
     * the ioctl below will fail returning EBADF. This is what we want.
15859
     */
15860
15861
0
#ifdef TERMSIZE_USE_IOCTL
15862
0
    {
15863
0
        struct winsize w;
15864
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15865
0
            return PyErr_SetFromErrno(PyExc_OSError);
15866
0
        columns = w.ws_col;
15867
0
        lines = w.ws_row;
15868
0
    }
15869
0
#endif /* TERMSIZE_USE_IOCTL */
15870
15871
#ifdef TERMSIZE_USE_CONIO
15872
    {
15873
        HANDLE handle;
15874
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15875
        handle = _Py_get_osfhandle(fd);
15876
        if (handle == INVALID_HANDLE_VALUE)
15877
            return NULL;
15878
15879
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15880
            return PyErr_SetFromWindowsErr(0);
15881
15882
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15883
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15884
    }
15885
#endif /* TERMSIZE_USE_CONIO */
15886
15887
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15888
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15889
0
    if (termsize == NULL)
15890
0
        return NULL;
15891
15892
0
    int pos = 0;
15893
15894
0
#define SET_TERMSIZE(CALL)                                   \
15895
0
    do {                                                     \
15896
0
        PyObject *item = (CALL);                             \
15897
0
        if (item == NULL) {                                  \
15898
0
            Py_DECREF(termsize);                             \
15899
0
            return NULL;                                     \
15900
0
        }                                                    \
15901
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15902
0
    } while(0)
15903
15904
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15905
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15906
0
#undef SET_TERMSIZE
15907
15908
0
    return termsize;
15909
0
}
15910
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15911
15912
/*[clinic input]
15913
os.cpu_count
15914
15915
Return the number of logical CPUs in the system.
15916
15917
Return None if indeterminable.
15918
[clinic start generated code]*/
15919
15920
static PyObject *
15921
os_cpu_count_impl(PyObject *module)
15922
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15923
0
{
15924
0
    const PyConfig *config = _Py_GetConfig();
15925
0
    if (config->cpu_count > 0) {
15926
0
        return PyLong_FromLong(config->cpu_count);
15927
0
    }
15928
15929
0
    int ncpu = 0;
15930
#ifdef MS_WINDOWS
15931
# ifdef MS_WINDOWS_DESKTOP
15932
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15933
# else
15934
    ncpu = 0;
15935
# endif
15936
15937
#elif defined(__hpux)
15938
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15939
15940
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15941
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15942
15943
#elif defined(__VXWORKS__)
15944
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15945
15946
#elif defined(__DragonFly__) || \
15947
      defined(__OpenBSD__)   || \
15948
      defined(__FreeBSD__)   || \
15949
      defined(__NetBSD__)    || \
15950
      defined(__APPLE__)
15951
    ncpu = 0;
15952
    size_t len = sizeof(ncpu);
15953
    int mib[2] = {CTL_HW, HW_NCPU};
15954
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15955
        ncpu = 0;
15956
    }
15957
#endif
15958
15959
0
    if (ncpu < 1) {
15960
0
        Py_RETURN_NONE;
15961
0
    }
15962
0
    return PyLong_FromLong(ncpu);
15963
0
}
15964
15965
15966
/*[clinic input]
15967
os.get_inheritable -> bool
15968
15969
    fd: int
15970
    /
15971
15972
Get the close-on-exe flag of the specified file descriptor.
15973
[clinic start generated code]*/
15974
15975
static int
15976
os_get_inheritable_impl(PyObject *module, int fd)
15977
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15978
0
{
15979
0
    int return_value;
15980
0
    _Py_BEGIN_SUPPRESS_IPH
15981
0
    return_value = _Py_get_inheritable(fd);
15982
0
    _Py_END_SUPPRESS_IPH
15983
0
    return return_value;
15984
0
}
15985
15986
15987
/*[clinic input]
15988
os.set_inheritable
15989
    fd: int
15990
    inheritable: int
15991
    /
15992
15993
Set the inheritable flag of the specified file descriptor.
15994
[clinic start generated code]*/
15995
15996
static PyObject *
15997
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15998
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15999
0
{
16000
0
    int result;
16001
16002
0
    _Py_BEGIN_SUPPRESS_IPH
16003
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
16004
0
    _Py_END_SUPPRESS_IPH
16005
0
    if (result < 0)
16006
0
        return NULL;
16007
0
    Py_RETURN_NONE;
16008
0
}
16009
16010
16011
#ifdef MS_WINDOWS
16012
#ifndef HANDLE_FLAG_INHERIT
16013
#define HANDLE_FLAG_INHERIT 0x00000001
16014
#endif
16015
16016
/*[clinic input]
16017
os.get_handle_inheritable -> bool
16018
    handle: intptr_t
16019
    /
16020
16021
Get the close-on-exe flag of the specified file descriptor.
16022
[clinic start generated code]*/
16023
16024
static int
16025
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16026
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16027
{
16028
    DWORD flags;
16029
16030
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16031
        PyErr_SetFromWindowsErr(0);
16032
        return -1;
16033
    }
16034
16035
    return flags & HANDLE_FLAG_INHERIT;
16036
}
16037
16038
16039
/*[clinic input]
16040
os.set_handle_inheritable
16041
    handle: intptr_t
16042
    inheritable: bool
16043
    /
16044
16045
Set the inheritable flag of the specified handle.
16046
[clinic start generated code]*/
16047
16048
static PyObject *
16049
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16050
                               int inheritable)
16051
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16052
{
16053
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16054
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16055
        PyErr_SetFromWindowsErr(0);
16056
        return NULL;
16057
    }
16058
    Py_RETURN_NONE;
16059
}
16060
#endif /* MS_WINDOWS */
16061
16062
/*[clinic input]
16063
os.get_blocking -> bool
16064
    fd: int
16065
    /
16066
16067
Get the blocking mode of the file descriptor.
16068
16069
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16070
[clinic start generated code]*/
16071
16072
static int
16073
os_get_blocking_impl(PyObject *module, int fd)
16074
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16075
0
{
16076
0
    int blocking;
16077
16078
0
    _Py_BEGIN_SUPPRESS_IPH
16079
0
    blocking = _Py_get_blocking(fd);
16080
0
    _Py_END_SUPPRESS_IPH
16081
0
    return blocking;
16082
0
}
16083
16084
/*[clinic input]
16085
os.set_blocking
16086
    fd: int
16087
    blocking: bool
16088
    /
16089
16090
Set the blocking mode of the specified file descriptor.
16091
16092
Set the O_NONBLOCK flag if blocking is False,
16093
clear the O_NONBLOCK flag otherwise.
16094
[clinic start generated code]*/
16095
16096
static PyObject *
16097
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16098
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16099
0
{
16100
0
    int result;
16101
16102
0
    _Py_BEGIN_SUPPRESS_IPH
16103
0
    result = _Py_set_blocking(fd, blocking);
16104
0
    _Py_END_SUPPRESS_IPH
16105
0
    if (result < 0)
16106
0
        return NULL;
16107
0
    Py_RETURN_NONE;
16108
0
}
16109
16110
16111
/*[clinic input]
16112
class os.DirEntry "DirEntry *" "DirEntryType"
16113
[clinic start generated code]*/
16114
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16115
16116
typedef struct {
16117
    PyObject_HEAD
16118
    PyObject *name;
16119
    PyObject *path;
16120
    PyObject *stat;
16121
    PyObject *lstat;
16122
#ifdef MS_WINDOWS
16123
    struct _Py_stat_struct win32_lstat;
16124
    uint64_t win32_file_index;
16125
    uint64_t win32_file_index_high;
16126
    int got_file_index;
16127
#else /* POSIX */
16128
#ifdef HAVE_DIRENT_D_TYPE
16129
    unsigned char d_type;
16130
#endif
16131
    ino_t d_ino;
16132
    int dir_fd;
16133
#endif
16134
} DirEntry;
16135
16136
142k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16137
16138
static void
16139
DirEntry_dealloc(PyObject *op)
16140
142k
{
16141
142k
    DirEntry *entry = DirEntry_CAST(op);
16142
142k
    PyTypeObject *tp = Py_TYPE(entry);
16143
142k
    Py_XDECREF(entry->name);
16144
142k
    Py_XDECREF(entry->path);
16145
142k
    Py_XDECREF(entry->stat);
16146
142k
    Py_XDECREF(entry->lstat);
16147
142k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16148
142k
    free_func(entry);
16149
142k
    Py_DECREF(tp);
16150
142k
}
16151
16152
/* Forward reference */
16153
static int
16154
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16155
                   int follow_symlinks, unsigned short mode_bits);
16156
16157
/*[clinic input]
16158
os.DirEntry.is_symlink -> bool
16159
    defining_class: defining_class
16160
    /
16161
16162
Return True if the entry is a symbolic link; cached per entry.
16163
[clinic start generated code]*/
16164
16165
static int
16166
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16167
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16168
0
{
16169
#ifdef MS_WINDOWS
16170
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16171
#elif defined(HAVE_DIRENT_D_TYPE)
16172
    /* POSIX */
16173
0
    if (self->d_type != DT_UNKNOWN)
16174
0
        return self->d_type == DT_LNK;
16175
0
    else
16176
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16177
#else
16178
    /* POSIX without d_type */
16179
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16180
#endif
16181
0
}
16182
16183
/*[clinic input]
16184
os.DirEntry.is_junction -> bool
16185
16186
Return True if the entry is a junction; cached per entry.
16187
[clinic start generated code]*/
16188
16189
static int
16190
os_DirEntry_is_junction_impl(DirEntry *self)
16191
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16192
0
{
16193
#ifdef MS_WINDOWS
16194
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16195
#else
16196
0
    return 0;
16197
0
#endif
16198
0
}
16199
16200
static PyObject *
16201
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16202
119k
{
16203
119k
    int result;
16204
119k
    STRUCT_STAT st;
16205
119k
    PyObject *ub;
16206
16207
#ifdef MS_WINDOWS
16208
    if (!PyUnicode_FSDecoder(self->path, &ub))
16209
        return NULL;
16210
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16211
    Py_DECREF(ub);
16212
#else /* POSIX */
16213
119k
    if (!PyUnicode_FSConverter(self->path, &ub))
16214
0
        return NULL;
16215
119k
    const char *path = PyBytes_AS_STRING(ub);
16216
119k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16217
119k
#ifdef HAVE_FSTATAT
16218
119k
      if (HAVE_FSTATAT_RUNTIME) {
16219
119k
        Py_BEGIN_ALLOW_THREADS
16220
119k
        result = fstatat(self->dir_fd, path, &st,
16221
119k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16222
119k
        Py_END_ALLOW_THREADS
16223
119k
      } else
16224
16225
0
#endif /* HAVE_FSTATAT */
16226
0
      {
16227
0
        Py_DECREF(ub);
16228
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16229
0
        return NULL;
16230
0
      }
16231
119k
    }
16232
0
    else
16233
0
#endif
16234
0
    {
16235
0
        Py_BEGIN_ALLOW_THREADS
16236
0
        if (follow_symlinks) {
16237
0
            result = STAT(path, &st);
16238
0
        }
16239
0
        else {
16240
0
            result = LSTAT(path, &st);
16241
0
        }
16242
0
        Py_END_ALLOW_THREADS
16243
0
    }
16244
16245
119k
    int saved_errno = errno;
16246
#if defined(MS_WINDOWS)
16247
    PyMem_Free(path);
16248
#else
16249
119k
    Py_DECREF(ub);
16250
119k
#endif
16251
16252
119k
    if (result != 0) {
16253
0
        errno = saved_errno;
16254
0
        path_object_error(self->path);
16255
0
        return NULL;
16256
0
    }
16257
16258
119k
    return _pystat_fromstructstat(module, &st);
16259
119k
}
16260
16261
static PyObject *
16262
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16263
119k
{
16264
119k
    if (!self->lstat) {
16265
119k
        PyObject *module = PyType_GetModule(defining_class);
16266
#ifdef MS_WINDOWS
16267
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16268
#else /* POSIX */
16269
119k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16270
119k
#endif
16271
119k
    }
16272
119k
    return Py_XNewRef(self->lstat);
16273
119k
}
16274
16275
/*[clinic input]
16276
os.DirEntry.stat
16277
    defining_class: defining_class
16278
    /
16279
    *
16280
    follow_symlinks: bool = True
16281
16282
Return stat_result object for the entry; cached per entry.
16283
[clinic start generated code]*/
16284
16285
static PyObject *
16286
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16287
                      int follow_symlinks)
16288
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16289
119k
{
16290
119k
    if (!follow_symlinks) {
16291
119k
        return DirEntry_get_lstat(defining_class, self);
16292
119k
    }
16293
16294
0
    if (!self->stat) {
16295
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16296
0
        if (result == -1) {
16297
0
            return NULL;
16298
0
        }
16299
0
        if (result) {
16300
0
            PyObject *module = PyType_GetModule(defining_class);
16301
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16302
0
        }
16303
0
        else {
16304
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16305
0
        }
16306
0
    }
16307
16308
0
    return Py_XNewRef(self->stat);
16309
0
}
16310
16311
/* Set exception and return -1 on error, 0 for False, 1 for True */
16312
static int
16313
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16314
                   int follow_symlinks, unsigned short mode_bits)
16315
142k
{
16316
142k
    PyObject *stat = NULL;
16317
142k
    PyObject *st_mode = NULL;
16318
142k
    long mode;
16319
142k
    int result;
16320
142k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16321
142k
    int is_symlink;
16322
142k
    int need_stat;
16323
142k
#endif
16324
#ifdef MS_WINDOWS
16325
    unsigned long dir_bits;
16326
#endif
16327
16328
#ifdef MS_WINDOWS
16329
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16330
    need_stat = follow_symlinks && is_symlink;
16331
#elif defined(HAVE_DIRENT_D_TYPE)
16332
142k
    is_symlink = self->d_type == DT_LNK;
16333
142k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16334
142k
#endif
16335
16336
142k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16337
142k
    if (need_stat) {
16338
0
#endif
16339
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16340
0
        if (!stat) {
16341
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16342
                /* If file doesn't exist (anymore), then return False
16343
                   (i.e., say it's not a file/directory) */
16344
0
                PyErr_Clear();
16345
0
                return 0;
16346
0
            }
16347
0
            goto error;
16348
0
        }
16349
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16350
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16351
0
        if (!st_mode)
16352
0
            goto error;
16353
16354
0
        mode = PyLong_AsLong(st_mode);
16355
0
        if (mode == -1 && PyErr_Occurred())
16356
0
            goto error;
16357
0
        Py_CLEAR(st_mode);
16358
0
        Py_CLEAR(stat);
16359
0
        result = (mode & S_IFMT) == mode_bits;
16360
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16361
0
    }
16362
142k
    else if (is_symlink) {
16363
0
        assert(mode_bits != S_IFLNK);
16364
0
        result = 0;
16365
0
    }
16366
142k
    else {
16367
142k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16368
#ifdef MS_WINDOWS
16369
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16370
        if (mode_bits == S_IFDIR)
16371
            result = dir_bits != 0;
16372
        else
16373
            result = dir_bits == 0;
16374
#else /* POSIX */
16375
142k
        if (mode_bits == S_IFDIR)
16376
142k
            result = self->d_type == DT_DIR;
16377
0
        else
16378
0
            result = self->d_type == DT_REG;
16379
142k
#endif
16380
142k
    }
16381
142k
#endif
16382
16383
142k
    return result;
16384
16385
0
error:
16386
0
    Py_XDECREF(st_mode);
16387
0
    Py_XDECREF(stat);
16388
0
    return -1;
16389
142k
}
16390
16391
/*[clinic input]
16392
os.DirEntry.is_dir -> bool
16393
    defining_class: defining_class
16394
    /
16395
    *
16396
    follow_symlinks: bool = True
16397
16398
Return True if the entry is a directory; cached per entry.
16399
[clinic start generated code]*/
16400
16401
static int
16402
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16403
                        int follow_symlinks)
16404
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16405
142k
{
16406
142k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16407
142k
}
16408
16409
/*[clinic input]
16410
os.DirEntry.is_file -> bool
16411
    defining_class: defining_class
16412
    /
16413
    *
16414
    follow_symlinks: bool = True
16415
16416
Return True if the entry is a file; cached per entry.
16417
[clinic start generated code]*/
16418
16419
static int
16420
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16421
                         int follow_symlinks)
16422
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16423
0
{
16424
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16425
0
}
16426
16427
/*[clinic input]
16428
os.DirEntry.inode
16429
16430
Return inode of the entry; cached per entry.
16431
[clinic start generated code]*/
16432
16433
static PyObject *
16434
os_DirEntry_inode_impl(DirEntry *self)
16435
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16436
0
{
16437
#ifdef MS_WINDOWS
16438
    if (!self->got_file_index) {
16439
        PyObject *unicode;
16440
        STRUCT_STAT stat;
16441
        int result;
16442
16443
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16444
            return NULL;
16445
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16446
        Py_DECREF(unicode);
16447
        result = LSTAT(path, &stat);
16448
16449
        int saved_errno = errno;
16450
        PyMem_Free(path);
16451
16452
        if (result != 0) {
16453
            errno = saved_errno;
16454
            return path_object_error(self->path);
16455
        }
16456
16457
        self->win32_file_index = stat.st_ino;
16458
        self->win32_file_index_high = stat.st_ino_high;
16459
        self->got_file_index = 1;
16460
    }
16461
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16462
#else /* POSIX */
16463
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16464
0
                  "DirEntry.d_ino is larger than unsigned long long");
16465
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16466
0
#endif
16467
0
}
16468
16469
static PyObject *
16470
DirEntry_repr(PyObject *op)
16471
0
{
16472
0
    DirEntry *self = DirEntry_CAST(op);
16473
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16474
0
}
16475
16476
/*[clinic input]
16477
os.DirEntry.__fspath__
16478
16479
Returns the path for the entry.
16480
[clinic start generated code]*/
16481
16482
static PyObject *
16483
os_DirEntry___fspath___impl(DirEntry *self)
16484
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16485
0
{
16486
0
    return Py_NewRef(self->path);
16487
0
}
16488
16489
static PyMemberDef DirEntry_members[] = {
16490
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16491
     "the entry's base filename, relative to scandir() \"path\" argument"},
16492
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16493
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16494
    {NULL}
16495
};
16496
16497
#include "clinic/posixmodule.c.h"
16498
16499
static PyMethodDef DirEntry_methods[] = {
16500
    OS_DIRENTRY_IS_DIR_METHODDEF
16501
    OS_DIRENTRY_IS_FILE_METHODDEF
16502
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16503
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16504
    OS_DIRENTRY_STAT_METHODDEF
16505
    OS_DIRENTRY_INODE_METHODDEF
16506
    OS_DIRENTRY___FSPATH___METHODDEF
16507
    {"__class_getitem__",       Py_GenericAlias,
16508
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16509
    {NULL}
16510
};
16511
16512
static PyType_Slot DirEntryType_slots[] = {
16513
    {Py_tp_dealloc, DirEntry_dealloc},
16514
    {Py_tp_repr, DirEntry_repr},
16515
    {Py_tp_methods, DirEntry_methods},
16516
    {Py_tp_members, DirEntry_members},
16517
    {0, 0},
16518
};
16519
16520
static PyType_Spec DirEntryType_spec = {
16521
    .name = MODNAME ".DirEntry",
16522
    .basicsize = sizeof(DirEntry),
16523
    .flags = (
16524
        Py_TPFLAGS_DEFAULT
16525
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16526
        | Py_TPFLAGS_IMMUTABLETYPE
16527
    ),
16528
    .slots = DirEntryType_slots
16529
};
16530
16531
16532
#ifdef MS_WINDOWS
16533
16534
static wchar_t *
16535
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16536
{
16537
    Py_ssize_t path_len;
16538
    Py_ssize_t size;
16539
    wchar_t *result;
16540
    wchar_t ch;
16541
16542
    if (!path_wide) { /* Default arg: "." */
16543
        path_wide = L".";
16544
        path_len = 1;
16545
    }
16546
    else {
16547
        path_len = wcslen(path_wide);
16548
    }
16549
16550
    /* The +1's are for the path separator and the NUL */
16551
    size = path_len + 1 + wcslen(filename) + 1;
16552
    result = PyMem_New(wchar_t, size);
16553
    if (!result) {
16554
        PyErr_NoMemory();
16555
        return NULL;
16556
    }
16557
    wcscpy(result, path_wide);
16558
    if (path_len > 0) {
16559
        ch = result[path_len - 1];
16560
        if (ch != SEP && ch != ALTSEP && ch != L':')
16561
            result[path_len++] = SEP;
16562
        wcscpy(result + path_len, filename);
16563
    }
16564
    return result;
16565
}
16566
16567
static PyObject *
16568
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16569
{
16570
    DirEntry *entry;
16571
    BY_HANDLE_FILE_INFORMATION file_info;
16572
    ULONG reparse_tag;
16573
    wchar_t *joined_path;
16574
16575
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16576
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16577
    if (!entry)
16578
        return NULL;
16579
    entry->name = NULL;
16580
    entry->path = NULL;
16581
    entry->stat = NULL;
16582
    entry->lstat = NULL;
16583
    entry->got_file_index = 0;
16584
16585
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16586
    if (!entry->name)
16587
        goto error;
16588
    int return_bytes = path->wide && PyBytes_Check(path->object);
16589
    if (return_bytes) {
16590
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16591
        if (!entry->name)
16592
            goto error;
16593
    }
16594
16595
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16596
    if (!joined_path)
16597
        goto error;
16598
16599
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16600
    PyMem_Free(joined_path);
16601
    if (!entry->path)
16602
        goto error;
16603
    if (return_bytes) {
16604
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16605
        if (!entry->path)
16606
            goto error;
16607
    }
16608
16609
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16610
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16611
16612
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16613
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16614
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16615
16616
    return (PyObject *)entry;
16617
16618
error:
16619
    Py_DECREF(entry);
16620
    return NULL;
16621
}
16622
16623
#else /* POSIX */
16624
16625
static char *
16626
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16627
0
{
16628
0
    Py_ssize_t path_len;
16629
0
    Py_ssize_t size;
16630
0
    char *result;
16631
16632
0
    if (!path_narrow) { /* Default arg: "." */
16633
0
        path_narrow = ".";
16634
0
        path_len = 1;
16635
0
    }
16636
0
    else {
16637
0
        path_len = strlen(path_narrow);
16638
0
    }
16639
16640
0
    if (filename_len == -1)
16641
0
        filename_len = strlen(filename);
16642
16643
    /* The +1's are for the path separator and the NUL */
16644
0
    size = path_len + 1 + filename_len + 1;
16645
0
    result = PyMem_New(char, size);
16646
0
    if (!result) {
16647
0
        PyErr_NoMemory();
16648
0
        return NULL;
16649
0
    }
16650
0
    strcpy(result, path_narrow);
16651
0
    if (path_len > 0 && result[path_len - 1] != '/')
16652
0
        result[path_len++] = '/';
16653
0
    strcpy(result + path_len, filename);
16654
0
    return result;
16655
0
}
16656
16657
static PyObject *
16658
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16659
                         Py_ssize_t name_len, ino_t d_ino
16660
#ifdef HAVE_DIRENT_D_TYPE
16661
                         , unsigned char d_type
16662
#endif
16663
                         )
16664
142k
{
16665
142k
    DirEntry *entry;
16666
142k
    char *joined_path;
16667
16668
142k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16669
142k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16670
142k
    if (!entry)
16671
0
        return NULL;
16672
142k
    entry->name = NULL;
16673
142k
    entry->path = NULL;
16674
142k
    entry->stat = NULL;
16675
142k
    entry->lstat = NULL;
16676
16677
142k
    if (path->is_fd) {
16678
142k
        entry->dir_fd = path->fd;
16679
142k
        joined_path = NULL;
16680
142k
    }
16681
0
    else {
16682
0
        entry->dir_fd = DEFAULT_DIR_FD;
16683
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16684
0
        if (!joined_path)
16685
0
            goto error;
16686
0
    }
16687
16688
142k
    if (!path->narrow || !PyBytes_Check(path->object)) {
16689
142k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16690
142k
        if (joined_path)
16691
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16692
142k
    }
16693
0
    else {
16694
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16695
0
        if (joined_path)
16696
0
            entry->path = PyBytes_FromString(joined_path);
16697
0
    }
16698
142k
    PyMem_Free(joined_path);
16699
142k
    if (!entry->name)
16700
0
        goto error;
16701
16702
142k
    if (path->is_fd) {
16703
142k
        entry->path = Py_NewRef(entry->name);
16704
142k
    }
16705
0
    else if (!entry->path)
16706
0
        goto error;
16707
16708
142k
#ifdef HAVE_DIRENT_D_TYPE
16709
142k
    entry->d_type = d_type;
16710
142k
#endif
16711
142k
    entry->d_ino = d_ino;
16712
16713
142k
    return (PyObject *)entry;
16714
16715
0
error:
16716
0
    Py_XDECREF(entry);
16717
0
    return NULL;
16718
142k
}
16719
16720
#endif
16721
16722
16723
typedef struct {
16724
    PyObject_HEAD
16725
    path_t path;
16726
#ifdef MS_WINDOWS
16727
    HANDLE handle;
16728
    WIN32_FIND_DATAW file_data;
16729
    int first_time;
16730
#else /* POSIX */
16731
    DIR *dirp;
16732
#endif
16733
#ifdef HAVE_FDOPENDIR
16734
    int fd;
16735
#endif
16736
} ScandirIterator;
16737
16738
516k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16739
16740
#ifdef MS_WINDOWS
16741
16742
static int
16743
ScandirIterator_is_closed(ScandirIterator *iterator)
16744
{
16745
    return iterator->handle == INVALID_HANDLE_VALUE;
16746
}
16747
16748
static void
16749
ScandirIterator_closedir(ScandirIterator *iterator)
16750
{
16751
    HANDLE handle = iterator->handle;
16752
16753
    if (handle == INVALID_HANDLE_VALUE)
16754
        return;
16755
16756
    iterator->handle = INVALID_HANDLE_VALUE;
16757
    Py_BEGIN_ALLOW_THREADS
16758
    FindClose(handle);
16759
    Py_END_ALLOW_THREADS
16760
}
16761
16762
static PyObject *
16763
ScandirIterator_iternext(PyObject *op)
16764
{
16765
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16766
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16767
    BOOL success;
16768
    PyObject *entry;
16769
16770
    /* Happens if the iterator is iterated twice, or closed explicitly */
16771
    if (iterator->handle == INVALID_HANDLE_VALUE)
16772
        return NULL;
16773
16774
    while (1) {
16775
        if (!iterator->first_time) {
16776
            Py_BEGIN_ALLOW_THREADS
16777
            success = FindNextFileW(iterator->handle, file_data);
16778
            Py_END_ALLOW_THREADS
16779
            if (!success) {
16780
                /* Error or no more files */
16781
                if (GetLastError() != ERROR_NO_MORE_FILES)
16782
                    path_error(&iterator->path);
16783
                break;
16784
            }
16785
        }
16786
        iterator->first_time = 0;
16787
16788
        /* Skip over . and .. */
16789
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16790
            wcscmp(file_data->cFileName, L"..") != 0)
16791
        {
16792
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16793
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16794
            if (!entry)
16795
                break;
16796
            return entry;
16797
        }
16798
16799
        /* Loop till we get a non-dot directory or finish iterating */
16800
    }
16801
16802
    /* Error or no more files */
16803
    ScandirIterator_closedir(iterator);
16804
    return NULL;
16805
}
16806
16807
#else /* POSIX */
16808
16809
static int
16810
ScandirIterator_is_closed(ScandirIterator *iterator)
16811
124k
{
16812
124k
    return !iterator->dirp;
16813
124k
}
16814
16815
static void
16816
ScandirIterator_closedir(ScandirIterator *iterator)
16817
249k
{
16818
249k
    DIR *dirp = iterator->dirp;
16819
16820
249k
    if (!dirp)
16821
124k
        return;
16822
16823
124k
    iterator->dirp = NULL;
16824
124k
    Py_BEGIN_ALLOW_THREADS
16825
124k
#ifdef HAVE_FDOPENDIR
16826
124k
    if (iterator->path.is_fd) {
16827
124k
        rewinddir(dirp);
16828
124k
    }
16829
124k
#endif
16830
124k
    closedir(dirp);
16831
124k
    Py_END_ALLOW_THREADS
16832
124k
    return;
16833
249k
}
16834
16835
static PyObject *
16836
ScandirIterator_iternext(PyObject *op)
16837
267k
{
16838
267k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16839
267k
    struct dirent *direntp;
16840
267k
    Py_ssize_t name_len;
16841
267k
    int is_dot;
16842
267k
    PyObject *entry;
16843
16844
    /* Happens if the iterator is iterated twice, or closed explicitly */
16845
267k
    if (!iterator->dirp)
16846
0
        return NULL;
16847
16848
516k
    while (1) {
16849
516k
        errno = 0;
16850
516k
        Py_BEGIN_ALLOW_THREADS
16851
516k
        direntp = readdir(iterator->dirp);
16852
516k
        Py_END_ALLOW_THREADS
16853
16854
516k
        if (!direntp) {
16855
            /* Error or no more files */
16856
124k
            if (errno != 0)
16857
0
                path_error(&iterator->path);
16858
124k
            break;
16859
124k
        }
16860
16861
        /* Skip over . and .. */
16862
392k
        name_len = NAMLEN(direntp);
16863
392k
        is_dot = direntp->d_name[0] == '.' &&
16864
250k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16865
392k
        if (!is_dot) {
16866
142k
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16867
142k
            entry = DirEntry_from_posix_info(module,
16868
142k
                                             &iterator->path, direntp->d_name,
16869
142k
                                             name_len, direntp->d_ino
16870
142k
#ifdef HAVE_DIRENT_D_TYPE
16871
142k
                                             , direntp->d_type
16872
142k
#endif
16873
142k
                                            );
16874
142k
            if (!entry)
16875
0
                break;
16876
142k
            return entry;
16877
142k
        }
16878
16879
        /* Loop till we get a non-dot directory or finish iterating */
16880
392k
    }
16881
16882
    /* Error or no more files */
16883
124k
    ScandirIterator_closedir(iterator);
16884
124k
    return NULL;
16885
267k
}
16886
16887
#endif
16888
16889
static PyObject *
16890
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16891
0
{
16892
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16893
0
    ScandirIterator_closedir(self);
16894
0
    Py_RETURN_NONE;
16895
0
}
16896
16897
static PyObject *
16898
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16899
124k
{
16900
124k
    return Py_NewRef(self);
16901
124k
}
16902
16903
static PyObject *
16904
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16905
124k
{
16906
124k
    ScandirIterator *self = ScandirIterator_CAST(op);
16907
124k
    ScandirIterator_closedir(self);
16908
124k
    Py_RETURN_NONE;
16909
124k
}
16910
16911
static void
16912
ScandirIterator_finalize(PyObject *op)
16913
124k
{
16914
124k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16915
    /* Save the current exception, if any. */
16916
124k
    PyObject *exc = PyErr_GetRaisedException();
16917
16918
124k
    if (!ScandirIterator_is_closed(iterator)) {
16919
0
        ScandirIterator_closedir(iterator);
16920
16921
0
        if (PyErr_ResourceWarning(op, 1,
16922
0
                                  "unclosed scandir iterator %R", iterator))
16923
0
        {
16924
            /* Spurious errors can appear at shutdown */
16925
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16926
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16927
0
                                       "scandir iterator %R", iterator);
16928
0
            }
16929
0
        }
16930
0
    }
16931
16932
124k
    path_cleanup(&iterator->path);
16933
16934
    /* Restore the saved exception. */
16935
124k
    PyErr_SetRaisedException(exc);
16936
124k
}
16937
16938
static void
16939
ScandirIterator_dealloc(PyObject *op)
16940
124k
{
16941
124k
    PyTypeObject *tp = Py_TYPE(op);
16942
124k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16943
0
        return;
16944
16945
124k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16946
124k
    free_func(op);
16947
124k
    Py_DECREF(tp);
16948
124k
}
16949
16950
static PyMethodDef ScandirIterator_methods[] = {
16951
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16952
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16953
    {"close", ScandirIterator_close, METH_NOARGS},
16954
    {NULL}
16955
};
16956
16957
static PyType_Slot ScandirIteratorType_slots[] = {
16958
    {Py_tp_dealloc, ScandirIterator_dealloc},
16959
    {Py_tp_finalize, ScandirIterator_finalize},
16960
    {Py_tp_iter, PyObject_SelfIter},
16961
    {Py_tp_iternext, ScandirIterator_iternext},
16962
    {Py_tp_methods, ScandirIterator_methods},
16963
    {0, 0},
16964
};
16965
16966
static PyType_Spec ScandirIteratorType_spec = {
16967
    .name = MODNAME ".ScandirIterator",
16968
    .basicsize = sizeof(ScandirIterator),
16969
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16970
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16971
    .flags = (
16972
        Py_TPFLAGS_DEFAULT
16973
        | Py_TPFLAGS_HAVE_FINALIZE
16974
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16975
        | Py_TPFLAGS_IMMUTABLETYPE
16976
    ),
16977
    .slots = ScandirIteratorType_slots
16978
};
16979
16980
/*[clinic input]
16981
os.scandir
16982
16983
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16984
16985
Return an iterator of DirEntry objects for given path.
16986
16987
path can be specified as either str, bytes, or a path-like object.  If path
16988
is bytes, the names of yielded DirEntry objects will also be bytes; in
16989
all other circumstances they will be str.
16990
16991
If path is None, uses the path='.'.
16992
[clinic start generated code]*/
16993
16994
static PyObject *
16995
os_scandir_impl(PyObject *module, path_t *path)
16996
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16997
124k
{
16998
124k
    ScandirIterator *iterator;
16999
#ifdef MS_WINDOWS
17000
    wchar_t *path_strW;
17001
#else
17002
124k
    const char *path_str;
17003
124k
#ifdef HAVE_FDOPENDIR
17004
124k
    int fd = -1;
17005
124k
#endif
17006
124k
#endif
17007
17008
124k
    if (PySys_Audit("os.scandir", "O",
17009
124k
                    path->object ? path->object : Py_None) < 0) {
17010
0
        return NULL;
17011
0
    }
17012
17013
124k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
17014
124k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
17015
124k
    if (!iterator)
17016
0
        return NULL;
17017
17018
#ifdef MS_WINDOWS
17019
    iterator->handle = INVALID_HANDLE_VALUE;
17020
#else
17021
124k
    iterator->dirp = NULL;
17022
124k
#endif
17023
17024
    /* Move the ownership to iterator->path */
17025
124k
    memcpy(&iterator->path, path, sizeof(path_t));
17026
124k
    memset(path, 0, sizeof(path_t));
17027
17028
#ifdef MS_WINDOWS
17029
    iterator->first_time = 1;
17030
17031
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
17032
    if (!path_strW)
17033
        goto error;
17034
17035
    Py_BEGIN_ALLOW_THREADS
17036
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17037
    Py_END_ALLOW_THREADS
17038
17039
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17040
        path_error(&iterator->path);
17041
        PyMem_Free(path_strW);
17042
        goto error;
17043
    }
17044
    PyMem_Free(path_strW);
17045
#else /* POSIX */
17046
124k
    errno = 0;
17047
124k
#ifdef HAVE_FDOPENDIR
17048
124k
    if (iterator->path.is_fd) {
17049
124k
      if (HAVE_FDOPENDIR_RUNTIME) {
17050
        /* closedir() closes the FD, so we duplicate it */
17051
124k
        fd = _Py_dup(iterator->path.fd);
17052
124k
        if (fd == -1)
17053
0
            goto error;
17054
17055
124k
        Py_BEGIN_ALLOW_THREADS
17056
124k
        iterator->dirp = fdopendir(fd);
17057
124k
        Py_END_ALLOW_THREADS
17058
124k
      } else {
17059
0
        PyErr_SetString(PyExc_TypeError,
17060
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17061
0
        return NULL;
17062
0
      }
17063
124k
    }
17064
0
    else
17065
0
#endif
17066
0
    {
17067
0
        if (iterator->path.narrow)
17068
0
            path_str = iterator->path.narrow;
17069
0
        else
17070
0
            path_str = ".";
17071
17072
0
        Py_BEGIN_ALLOW_THREADS
17073
0
        iterator->dirp = opendir(path_str);
17074
0
        Py_END_ALLOW_THREADS
17075
0
    }
17076
17077
124k
    if (!iterator->dirp) {
17078
0
        path_error(&iterator->path);
17079
0
#ifdef HAVE_FDOPENDIR
17080
0
        if (fd != -1) {
17081
0
            Py_BEGIN_ALLOW_THREADS
17082
0
            close(fd);
17083
0
            Py_END_ALLOW_THREADS
17084
0
        }
17085
0
#endif
17086
0
        goto error;
17087
0
    }
17088
124k
#endif
17089
17090
124k
    return (PyObject *)iterator;
17091
17092
0
error:
17093
0
    Py_DECREF(iterator);
17094
0
    return NULL;
17095
124k
}
17096
17097
/*
17098
    Return the file system path representation of the object.
17099
17100
    If the object is str or bytes, then allow it to pass through with
17101
    an incremented refcount. If the object defines __fspath__(), then
17102
    return the result of that method. All other types raise a TypeError.
17103
*/
17104
PyObject *
17105
PyOS_FSPath(PyObject *path)
17106
1.26M
{
17107
    /* For error message reasons, this function is manually inlined in
17108
       path_converter(). */
17109
1.26M
    PyObject *func = NULL;
17110
1.26M
    PyObject *path_repr = NULL;
17111
17112
1.26M
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17113
1.26M
        return Py_NewRef(path);
17114
1.26M
    }
17115
17116
275
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17117
275
    if ((NULL == func) || (func == Py_None)) {
17118
0
        return PyErr_Format(PyExc_TypeError,
17119
0
                            "expected str, bytes or os.PathLike object, "
17120
0
                            "not %.200s",
17121
0
                            _PyType_Name(Py_TYPE(path)));
17122
0
    }
17123
17124
275
    path_repr = _PyObject_CallNoArgs(func);
17125
275
    Py_DECREF(func);
17126
275
    if (NULL == path_repr) {
17127
0
        return NULL;
17128
0
    }
17129
17130
275
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17131
0
        PyErr_Format(PyExc_TypeError,
17132
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17133
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17134
0
                     _PyType_Name(Py_TYPE(path_repr)));
17135
0
        Py_DECREF(path_repr);
17136
0
        return NULL;
17137
0
    }
17138
17139
275
    return path_repr;
17140
275
}
17141
17142
/*[clinic input]
17143
@permit_long_docstring_body
17144
os.fspath
17145
17146
    path: object
17147
17148
Return the file system path representation of the object.
17149
17150
If the object is str or bytes, then allow it to pass through as-is. If the
17151
object defines __fspath__(), then return the result of that method. All other
17152
types raise a TypeError.
17153
[clinic start generated code]*/
17154
17155
static PyObject *
17156
os_fspath_impl(PyObject *module, PyObject *path)
17157
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
17158
898k
{
17159
898k
    return PyOS_FSPath(path);
17160
898k
}
17161
17162
#ifdef HAVE_GETRANDOM_SYSCALL
17163
/*[clinic input]
17164
os.getrandom
17165
17166
    size: Py_ssize_t
17167
    flags: int=0
17168
17169
Obtain a series of random bytes.
17170
[clinic start generated code]*/
17171
17172
static PyObject *
17173
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17174
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17175
0
{
17176
0
    if (size < 0) {
17177
0
        errno = EINVAL;
17178
0
        return posix_error();
17179
0
    }
17180
17181
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17182
0
    if (writer == NULL) {
17183
0
        return NULL;
17184
0
    }
17185
0
    void *data = PyBytesWriter_GetData(writer);
17186
17187
0
    Py_ssize_t n;
17188
0
    while (1) {
17189
0
        n = syscall(SYS_getrandom, data, size, flags);
17190
0
        if (n < 0 && errno == EINTR) {
17191
0
            if (PyErr_CheckSignals() < 0) {
17192
0
                goto error;
17193
0
            }
17194
17195
            /* getrandom() was interrupted by a signal: retry */
17196
0
            continue;
17197
0
        }
17198
0
        break;
17199
0
    }
17200
17201
0
    if (n < 0) {
17202
0
        PyErr_SetFromErrno(PyExc_OSError);
17203
0
        goto error;
17204
0
    }
17205
17206
0
    _Py_MSAN_UNPOISON(data, size);
17207
17208
0
    return PyBytesWriter_FinishWithSize(writer, n);
17209
17210
0
error:
17211
0
    PyBytesWriter_Discard(writer);
17212
0
    return NULL;
17213
0
}
17214
#endif   /* HAVE_GETRANDOM_SYSCALL */
17215
17216
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17217
17218
/* bpo-36085: Helper functions for managing DLL search directories
17219
 * on win32
17220
 */
17221
17222
/*[clinic input]
17223
os._add_dll_directory
17224
17225
    path: path_t
17226
17227
Add a path to the DLL search path.
17228
17229
This search path is used when resolving dependencies for imported
17230
extension modules (the module itself is resolved through sys.path),
17231
and also by ctypes.
17232
17233
Returns an opaque value that may be passed to os.remove_dll_directory
17234
to remove this directory from the search path.
17235
[clinic start generated code]*/
17236
17237
static PyObject *
17238
os__add_dll_directory_impl(PyObject *module, path_t *path)
17239
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17240
{
17241
    DLL_DIRECTORY_COOKIE cookie = 0;
17242
    DWORD err = 0;
17243
17244
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17245
        return NULL;
17246
    }
17247
17248
    Py_BEGIN_ALLOW_THREADS
17249
    if (!(cookie = AddDllDirectory(path->wide))) {
17250
        err = GetLastError();
17251
    }
17252
    Py_END_ALLOW_THREADS
17253
17254
    if (err) {
17255
        return win32_error_object_err("add_dll_directory",
17256
                                      path->object, err);
17257
    }
17258
17259
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17260
}
17261
17262
/*[clinic input]
17263
os._remove_dll_directory
17264
17265
    cookie: object
17266
17267
Removes a path from the DLL search path.
17268
17269
The parameter is an opaque value that was returned from
17270
os.add_dll_directory. You can only remove directories that you added
17271
yourself.
17272
[clinic start generated code]*/
17273
17274
static PyObject *
17275
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17276
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17277
{
17278
    DLL_DIRECTORY_COOKIE cookieValue;
17279
    DWORD err = 0;
17280
17281
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17282
        PyErr_SetString(PyExc_TypeError,
17283
            "Provided cookie was not returned from os.add_dll_directory");
17284
        return NULL;
17285
    }
17286
17287
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17288
        cookie, "DLL directory cookie");
17289
17290
    Py_BEGIN_ALLOW_THREADS
17291
    if (!RemoveDllDirectory(cookieValue)) {
17292
        err = GetLastError();
17293
    }
17294
    Py_END_ALLOW_THREADS
17295
17296
    if (err) {
17297
        return win32_error_object_err("remove_dll_directory",
17298
                                      NULL, err);
17299
    }
17300
17301
    if (PyCapsule_SetName(cookie, NULL)) {
17302
        return NULL;
17303
    }
17304
17305
    Py_RETURN_NONE;
17306
}
17307
17308
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17309
17310
17311
/* Only check if WIFEXITED is available: expect that it comes
17312
   with WEXITSTATUS, WIFSIGNALED, etc.
17313
17314
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17315
   subprocess can safely call it during late Python finalization without
17316
   risking that used os attributes were set to None by finalize_modules(). */
17317
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17318
/*[clinic input]
17319
os.waitstatus_to_exitcode
17320
17321
    status as status_obj: object
17322
17323
Convert a wait status to an exit code.
17324
17325
On Unix:
17326
17327
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17328
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17329
* Otherwise, raise a ValueError.
17330
17331
On Windows, return status shifted right by 8 bits.
17332
17333
On Unix, if the process is being traced or if waitpid() was called with
17334
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
17335
This function must not be called if WIFSTOPPED(status) is true.
17336
[clinic start generated code]*/
17337
17338
static PyObject *
17339
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17340
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
17341
0
{
17342
0
#ifndef MS_WINDOWS
17343
0
    int status = PyLong_AsInt(status_obj);
17344
0
    if (status == -1 && PyErr_Occurred()) {
17345
0
        return NULL;
17346
0
    }
17347
17348
0
    WAIT_TYPE wait_status;
17349
0
    WAIT_STATUS_INT(wait_status) = status;
17350
0
    int exitcode;
17351
0
    if (WIFEXITED(wait_status)) {
17352
0
        exitcode = WEXITSTATUS(wait_status);
17353
        /* Sanity check to provide warranty on the function behavior.
17354
           It should not occur in practice */
17355
0
        if (exitcode < 0) {
17356
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17357
0
            return NULL;
17358
0
        }
17359
0
    }
17360
0
    else if (WIFSIGNALED(wait_status)) {
17361
0
        int signum = WTERMSIG(wait_status);
17362
        /* Sanity check to provide warranty on the function behavior.
17363
           It should not occurs in practice */
17364
0
        if (signum <= 0) {
17365
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17366
0
            return NULL;
17367
0
        }
17368
0
        exitcode = -signum;
17369
0
    } else if (WIFSTOPPED(wait_status)) {
17370
        /* Status only received if the process is being traced
17371
           or if waitpid() was called with WUNTRACED option. */
17372
0
        int signum = WSTOPSIG(wait_status);
17373
0
        PyErr_Format(PyExc_ValueError,
17374
0
                     "process stopped by delivery of signal %i",
17375
0
                     signum);
17376
0
        return NULL;
17377
0
    }
17378
0
    else {
17379
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17380
0
        return NULL;
17381
0
    }
17382
0
    return PyLong_FromLong(exitcode);
17383
#else
17384
    /* Windows implementation: see os.waitpid() implementation
17385
       which uses _cwait(). */
17386
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17387
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17388
        return NULL;
17389
    }
17390
17391
    unsigned long long exitcode = (status >> 8);
17392
    /* ExitProcess() accepts an UINT type:
17393
       reject exit code which doesn't fit in an UINT */
17394
    if (exitcode > UINT_MAX) {
17395
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17396
        return NULL;
17397
    }
17398
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17399
#endif
17400
0
}
17401
#endif
17402
17403
#if defined(MS_WINDOWS)
17404
/*[clinic input]
17405
os._supports_virtual_terminal
17406
17407
Checks if virtual terminal is supported in windows
17408
[clinic start generated code]*/
17409
17410
static PyObject *
17411
os__supports_virtual_terminal_impl(PyObject *module)
17412
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17413
{
17414
#ifdef HAVE_WINDOWS_CONSOLE_IO
17415
    DWORD mode = 0;
17416
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17417
    if (!GetConsoleMode(handle, &mode)) {
17418
        Py_RETURN_FALSE;
17419
    }
17420
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17421
#else
17422
    Py_RETURN_FALSE;
17423
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17424
}
17425
#endif
17426
17427
/*[clinic input]
17428
os._inputhook
17429
17430
Calls PyOS_InputHook dropping the GIL first
17431
[clinic start generated code]*/
17432
17433
static PyObject *
17434
os__inputhook_impl(PyObject *module)
17435
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17436
0
{
17437
0
     int result = 0;
17438
0
     if (PyOS_InputHook) {
17439
0
         Py_BEGIN_ALLOW_THREADS;
17440
0
         result = PyOS_InputHook();
17441
0
         Py_END_ALLOW_THREADS;
17442
0
     }
17443
0
     return PyLong_FromLong(result);
17444
0
}
17445
17446
/*[clinic input]
17447
os._is_inputhook_installed
17448
17449
Checks if PyOS_InputHook is set
17450
[clinic start generated code]*/
17451
17452
static PyObject *
17453
os__is_inputhook_installed_impl(PyObject *module)
17454
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17455
0
{
17456
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17457
0
}
17458
17459
/*[clinic input]
17460
os._create_environ
17461
17462
Create the environment dictionary.
17463
[clinic start generated code]*/
17464
17465
static PyObject *
17466
os__create_environ_impl(PyObject *module)
17467
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17468
0
{
17469
0
    return convertenviron();
17470
0
}
17471
17472
17473
#ifdef __EMSCRIPTEN__
17474
/*[clinic input]
17475
os._emscripten_debugger
17476
17477
Create a breakpoint for the JavaScript debugger. Emscripten only.
17478
[clinic start generated code]*/
17479
17480
static PyObject *
17481
os__emscripten_debugger_impl(PyObject *module)
17482
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17483
{
17484
    emscripten_debugger();
17485
    Py_RETURN_NONE;
17486
}
17487
17488
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17489
    console.warn(UTF8ToString(arg));
17490
});
17491
17492
/*[clinic input]
17493
os._emscripten_log
17494
   arg: str
17495
17496
Log something to the JS console. Emscripten only.
17497
[clinic start generated code]*/
17498
17499
static PyObject *
17500
os__emscripten_log_impl(PyObject *module, const char *arg)
17501
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17502
{
17503
    emscripten_log_impl_js(arg);
17504
    Py_RETURN_NONE;
17505
}
17506
#endif /* __EMSCRIPTEN__ */
17507
17508
17509
static PyMethodDef posix_methods[] = {
17510
    OS_STAT_METHODDEF
17511
    OS_STATX_METHODDEF
17512
    OS_ACCESS_METHODDEF
17513
    OS_TTYNAME_METHODDEF
17514
    OS_CHDIR_METHODDEF
17515
    OS_CHFLAGS_METHODDEF
17516
    OS_CHMOD_METHODDEF
17517
    OS_FCHMOD_METHODDEF
17518
    OS_LCHMOD_METHODDEF
17519
    OS_CHOWN_METHODDEF
17520
    OS_FCHOWN_METHODDEF
17521
    OS_LCHOWN_METHODDEF
17522
    OS_LCHFLAGS_METHODDEF
17523
    OS_CHROOT_METHODDEF
17524
    OS_CTERMID_METHODDEF
17525
    OS_GETCWD_METHODDEF
17526
    OS_GETCWDB_METHODDEF
17527
    OS_LINK_METHODDEF
17528
    OS_LISTDIR_METHODDEF
17529
    OS_LISTDRIVES_METHODDEF
17530
    OS_LISTMOUNTS_METHODDEF
17531
    OS_LISTVOLUMES_METHODDEF
17532
    OS_LSTAT_METHODDEF
17533
    OS_MKDIR_METHODDEF
17534
    OS_NICE_METHODDEF
17535
    OS_GETPRIORITY_METHODDEF
17536
    OS_SETPRIORITY_METHODDEF
17537
    OS_POSIX_SPAWN_METHODDEF
17538
    OS_POSIX_SPAWNP_METHODDEF
17539
    OS_READLINK_METHODDEF
17540
    OS_COPY_FILE_RANGE_METHODDEF
17541
    OS_SPLICE_METHODDEF
17542
    OS_RENAME_METHODDEF
17543
    OS_REPLACE_METHODDEF
17544
    OS_RMDIR_METHODDEF
17545
    OS_SYMLINK_METHODDEF
17546
    OS_SYSTEM_METHODDEF
17547
    OS_UMASK_METHODDEF
17548
    OS_UNAME_METHODDEF
17549
    OS_UNLINK_METHODDEF
17550
    OS_REMOVE_METHODDEF
17551
    OS_UTIME_METHODDEF
17552
    OS_TIMES_METHODDEF
17553
    OS__EXIT_METHODDEF
17554
    OS__FCOPYFILE_METHODDEF
17555
    OS_EXECV_METHODDEF
17556
    OS_EXECVE_METHODDEF
17557
    OS_SPAWNV_METHODDEF
17558
    OS_SPAWNVE_METHODDEF
17559
    OS_FORK1_METHODDEF
17560
    OS_FORK_METHODDEF
17561
    OS_REGISTER_AT_FORK_METHODDEF
17562
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17563
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17564
    OS_SCHED_GETPARAM_METHODDEF
17565
    OS_SCHED_GETSCHEDULER_METHODDEF
17566
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17567
    OS_SCHED_SETPARAM_METHODDEF
17568
    OS_SCHED_SETSCHEDULER_METHODDEF
17569
    OS_SCHED_YIELD_METHODDEF
17570
    OS_SCHED_SETAFFINITY_METHODDEF
17571
    OS_SCHED_GETAFFINITY_METHODDEF
17572
    OS_POSIX_OPENPT_METHODDEF
17573
    OS_GRANTPT_METHODDEF
17574
    OS_UNLOCKPT_METHODDEF
17575
    OS_PTSNAME_METHODDEF
17576
    OS_OPENPTY_METHODDEF
17577
    OS_LOGIN_TTY_METHODDEF
17578
    OS_FORKPTY_METHODDEF
17579
    OS_GETEGID_METHODDEF
17580
    OS_GETEUID_METHODDEF
17581
    OS_GETGID_METHODDEF
17582
    OS_GETGROUPLIST_METHODDEF
17583
    OS_GETGROUPS_METHODDEF
17584
    OS_GETPID_METHODDEF
17585
    OS_GETPGRP_METHODDEF
17586
    OS_GETPPID_METHODDEF
17587
    OS_GETUID_METHODDEF
17588
    OS_GETLOGIN_METHODDEF
17589
    OS_KILL_METHODDEF
17590
    OS_KILLPG_METHODDEF
17591
    OS_PLOCK_METHODDEF
17592
    OS_STARTFILE_METHODDEF
17593
    OS_SETUID_METHODDEF
17594
    OS_SETEUID_METHODDEF
17595
    OS_SETREUID_METHODDEF
17596
    OS_SETGID_METHODDEF
17597
    OS_SETEGID_METHODDEF
17598
    OS_SETREGID_METHODDEF
17599
    OS_SETGROUPS_METHODDEF
17600
    OS_INITGROUPS_METHODDEF
17601
    OS_GETPGID_METHODDEF
17602
    OS_SETPGRP_METHODDEF
17603
    OS_WAIT_METHODDEF
17604
    OS_WAIT3_METHODDEF
17605
    OS_WAIT4_METHODDEF
17606
    OS_WAITID_METHODDEF
17607
    OS_WAITPID_METHODDEF
17608
    OS_PIDFD_OPEN_METHODDEF
17609
    OS_GETSID_METHODDEF
17610
    OS_SETSID_METHODDEF
17611
    OS_SETPGID_METHODDEF
17612
    OS_TCGETPGRP_METHODDEF
17613
    OS_TCSETPGRP_METHODDEF
17614
    OS_OPEN_METHODDEF
17615
    OS_CLOSE_METHODDEF
17616
    OS_CLOSERANGE_METHODDEF
17617
    OS_DEVICE_ENCODING_METHODDEF
17618
    OS_DUP_METHODDEF
17619
    OS_DUP2_METHODDEF
17620
    OS_LOCKF_METHODDEF
17621
    OS_LSEEK_METHODDEF
17622
    OS_READ_METHODDEF
17623
    OS_READINTO_METHODDEF
17624
    OS_READV_METHODDEF
17625
    OS_PREAD_METHODDEF
17626
    OS_PREADV_METHODDEF
17627
    OS_WRITE_METHODDEF
17628
    OS_WRITEV_METHODDEF
17629
    OS_PWRITE_METHODDEF
17630
    OS_PWRITEV_METHODDEF
17631
    OS_SENDFILE_METHODDEF
17632
    OS_FSTAT_METHODDEF
17633
    OS_ISATTY_METHODDEF
17634
    OS_PIPE_METHODDEF
17635
    OS_PIPE2_METHODDEF
17636
    OS_MKFIFO_METHODDEF
17637
    OS_MKNOD_METHODDEF
17638
    OS_MAJOR_METHODDEF
17639
    OS_MINOR_METHODDEF
17640
    OS_MAKEDEV_METHODDEF
17641
    OS_FTRUNCATE_METHODDEF
17642
    OS_TRUNCATE_METHODDEF
17643
    OS_POSIX_FALLOCATE_METHODDEF
17644
    OS_POSIX_FADVISE_METHODDEF
17645
    OS_PUTENV_METHODDEF
17646
    OS_UNSETENV_METHODDEF
17647
    OS__CLEARENV_METHODDEF
17648
    OS_STRERROR_METHODDEF
17649
    OS_FCHDIR_METHODDEF
17650
    OS_FSYNC_METHODDEF
17651
    OS_SYNC_METHODDEF
17652
    OS_FDATASYNC_METHODDEF
17653
    OS_WCOREDUMP_METHODDEF
17654
    OS_WIFCONTINUED_METHODDEF
17655
    OS_WIFSTOPPED_METHODDEF
17656
    OS_WIFSIGNALED_METHODDEF
17657
    OS_WIFEXITED_METHODDEF
17658
    OS_WEXITSTATUS_METHODDEF
17659
    OS_WTERMSIG_METHODDEF
17660
    OS_WSTOPSIG_METHODDEF
17661
    OS_FSTATVFS_METHODDEF
17662
    OS_STATVFS_METHODDEF
17663
    OS_CONFSTR_METHODDEF
17664
    OS_SYSCONF_METHODDEF
17665
    OS_FPATHCONF_METHODDEF
17666
    OS_PATHCONF_METHODDEF
17667
    OS_ABORT_METHODDEF
17668
    OS__GETFULLPATHNAME_METHODDEF
17669
    OS__GETDISKUSAGE_METHODDEF
17670
    OS__GETFINALPATHNAME_METHODDEF
17671
    OS__FINDFIRSTFILE_METHODDEF
17672
    OS__GETVOLUMEPATHNAME_METHODDEF
17673
    OS__PATH_SPLITROOT_METHODDEF
17674
    OS__PATH_SPLITROOT_EX_METHODDEF
17675
    OS__PATH_NORMPATH_METHODDEF
17676
    OS_GETLOADAVG_METHODDEF
17677
    OS_URANDOM_METHODDEF
17678
    OS_SETRESUID_METHODDEF
17679
    OS_SETRESGID_METHODDEF
17680
    OS_GETRESUID_METHODDEF
17681
    OS_GETRESGID_METHODDEF
17682
17683
    OS_GETXATTR_METHODDEF
17684
    OS_SETXATTR_METHODDEF
17685
    OS_REMOVEXATTR_METHODDEF
17686
    OS_LISTXATTR_METHODDEF
17687
17688
    OS_GET_TERMINAL_SIZE_METHODDEF
17689
    OS_CPU_COUNT_METHODDEF
17690
    OS_GET_INHERITABLE_METHODDEF
17691
    OS_SET_INHERITABLE_METHODDEF
17692
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17693
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17694
    OS_GET_BLOCKING_METHODDEF
17695
    OS_SET_BLOCKING_METHODDEF
17696
    OS_SCANDIR_METHODDEF
17697
    OS_FSPATH_METHODDEF
17698
    OS_GETRANDOM_METHODDEF
17699
    OS_MEMFD_CREATE_METHODDEF
17700
    OS_EVENTFD_METHODDEF
17701
    OS_EVENTFD_READ_METHODDEF
17702
    OS_EVENTFD_WRITE_METHODDEF
17703
    OS__ADD_DLL_DIRECTORY_METHODDEF
17704
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17705
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17706
    OS_SETNS_METHODDEF
17707
    OS_UNSHARE_METHODDEF
17708
    OS_TIMERFD_CREATE_METHODDEF
17709
    OS_TIMERFD_SETTIME_METHODDEF
17710
    OS_TIMERFD_SETTIME_NS_METHODDEF
17711
    OS_TIMERFD_GETTIME_METHODDEF
17712
    OS_TIMERFD_GETTIME_NS_METHODDEF
17713
17714
    OS__PATH_ISDEVDRIVE_METHODDEF
17715
    OS__PATH_ISDIR_METHODDEF
17716
    OS__PATH_ISFILE_METHODDEF
17717
    OS__PATH_ISLINK_METHODDEF
17718
    OS__PATH_ISJUNCTION_METHODDEF
17719
    OS__PATH_EXISTS_METHODDEF
17720
    OS__PATH_LEXISTS_METHODDEF
17721
17722
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17723
    OS__INPUTHOOK_METHODDEF
17724
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17725
    OS__CREATE_ENVIRON_METHODDEF
17726
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17727
    OS__EMSCRIPTEN_LOG_METHODDEF
17728
    {NULL,              NULL}            /* Sentinel */
17729
};
17730
17731
static int
17732
all_ins(PyObject *m)
17733
37
{
17734
37
#ifdef F_OK
17735
37
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17736
37
#endif
17737
37
#ifdef R_OK
17738
37
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17739
37
#endif
17740
37
#ifdef W_OK
17741
37
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17742
37
#endif
17743
37
#ifdef X_OK
17744
37
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17745
37
#endif
17746
37
#ifdef NGROUPS_MAX
17747
37
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17748
37
#endif
17749
37
#ifdef TMP_MAX
17750
37
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17751
37
#endif
17752
37
#ifdef WCONTINUED
17753
37
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17754
37
#endif
17755
37
#ifdef WNOHANG
17756
37
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17757
37
#endif
17758
37
#ifdef WUNTRACED
17759
37
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17760
37
#endif
17761
37
#ifdef O_RDONLY
17762
37
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17763
37
#endif
17764
37
#ifdef O_WRONLY
17765
37
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17766
37
#endif
17767
37
#ifdef O_RDWR
17768
37
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17769
37
#endif
17770
37
#ifdef O_NDELAY
17771
37
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17772
37
#endif
17773
37
#ifdef O_NONBLOCK
17774
37
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17775
37
#endif
17776
37
#ifdef O_APPEND
17777
37
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17778
37
#endif
17779
37
#ifdef O_DSYNC
17780
37
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17781
37
#endif
17782
37
#ifdef O_RSYNC
17783
37
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17784
37
#endif
17785
37
#ifdef O_SYNC
17786
37
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17787
37
#endif
17788
37
#ifdef O_NOCTTY
17789
37
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17790
37
#endif
17791
37
#ifdef O_CREAT
17792
37
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17793
37
#endif
17794
37
#ifdef O_EXCL
17795
37
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17796
37
#endif
17797
37
#ifdef O_TRUNC
17798
37
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17799
37
#endif
17800
#ifdef O_BINARY
17801
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17802
#endif
17803
#ifdef O_TEXT
17804
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17805
#endif
17806
#ifdef O_XATTR
17807
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17808
#endif
17809
37
#ifdef O_LARGEFILE
17810
37
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17811
37
#endif
17812
37
#ifndef __GNU__
17813
#ifdef O_SHLOCK
17814
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17815
#endif
17816
#ifdef O_EXLOCK
17817
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17818
#endif
17819
37
#endif
17820
#ifdef O_EXEC
17821
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17822
#endif
17823
#ifdef O_SEARCH
17824
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17825
#endif
17826
37
#ifdef O_PATH
17827
37
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17828
37
#endif
17829
#ifdef O_TTY_INIT
17830
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17831
#endif
17832
37
#ifdef O_TMPFILE
17833
37
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17834
37
#endif
17835
37
#ifdef PRIO_PROCESS
17836
37
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17837
37
#endif
17838
37
#ifdef PRIO_PGRP
17839
37
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17840
37
#endif
17841
37
#ifdef PRIO_USER
17842
37
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17843
37
#endif
17844
#ifdef PRIO_DARWIN_THREAD
17845
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17846
#endif
17847
#ifdef PRIO_DARWIN_PROCESS
17848
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17849
#endif
17850
#ifdef PRIO_DARWIN_BG
17851
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17852
#endif
17853
#ifdef PRIO_DARWIN_NONUI
17854
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17855
#endif
17856
37
#ifdef O_CLOEXEC
17857
37
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17858
37
#endif
17859
37
#ifdef O_ACCMODE
17860
37
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17861
37
#endif
17862
#ifdef O_EVTONLY
17863
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17864
#endif
17865
37
#ifdef O_FSYNC
17866
37
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17867
37
#endif
17868
#ifdef O_SYMLINK
17869
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17870
#endif
17871
17872
37
#ifdef SEEK_HOLE
17873
37
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17874
37
#endif
17875
37
#ifdef SEEK_DATA
17876
37
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17877
37
#endif
17878
17879
/* MS Windows */
17880
#ifdef O_NOINHERIT
17881
    /* Don't inherit in child processes. */
17882
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17883
#endif
17884
#ifdef _O_SHORT_LIVED
17885
    /* Optimize for short life (keep in memory). */
17886
    /* MS forgot to define this one with a non-underscore form too. */
17887
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17888
#endif
17889
#ifdef O_TEMPORARY
17890
    /* Automatically delete when last handle is closed. */
17891
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17892
#endif
17893
#ifdef O_RANDOM
17894
    /* Optimize for random access. */
17895
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17896
#endif
17897
#ifdef O_SEQUENTIAL
17898
    /* Optimize for sequential access. */
17899
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17900
#endif
17901
17902
/* GNU extensions. */
17903
37
#ifdef O_ASYNC
17904
    /* Send a SIGIO signal whenever input or output
17905
       becomes available on file descriptor */
17906
37
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17907
37
#endif
17908
37
#ifdef O_DIRECT
17909
    /* Direct disk access. */
17910
37
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17911
37
#endif
17912
37
#ifdef O_DIRECTORY
17913
    /* Must be a directory.      */
17914
37
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17915
37
#endif
17916
37
#ifdef O_NOFOLLOW
17917
    /* Do not follow links.      */
17918
37
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17919
37
#endif
17920
#ifdef O_NOFOLLOW_ANY
17921
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17922
#endif
17923
#ifdef O_NOLINKS
17924
    /* Fails if link count of the named file is greater than 1 */
17925
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17926
#endif
17927
37
#ifdef O_NOATIME
17928
    /* Do not update the access time. */
17929
37
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17930
37
#endif
17931
17932
    /* These come from sysexits.h */
17933
37
#ifdef EX_OK
17934
37
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17935
37
#endif /* EX_OK */
17936
37
#ifdef EX_USAGE
17937
37
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17938
37
#endif /* EX_USAGE */
17939
37
#ifdef EX_DATAERR
17940
37
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17941
37
#endif /* EX_DATAERR */
17942
37
#ifdef EX_NOINPUT
17943
37
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17944
37
#endif /* EX_NOINPUT */
17945
37
#ifdef EX_NOUSER
17946
37
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17947
37
#endif /* EX_NOUSER */
17948
37
#ifdef EX_NOHOST
17949
37
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17950
37
#endif /* EX_NOHOST */
17951
37
#ifdef EX_UNAVAILABLE
17952
37
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17953
37
#endif /* EX_UNAVAILABLE */
17954
37
#ifdef EX_SOFTWARE
17955
37
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17956
37
#endif /* EX_SOFTWARE */
17957
37
#ifdef EX_OSERR
17958
37
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17959
37
#endif /* EX_OSERR */
17960
37
#ifdef EX_OSFILE
17961
37
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17962
37
#endif /* EX_OSFILE */
17963
37
#ifdef EX_CANTCREAT
17964
37
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17965
37
#endif /* EX_CANTCREAT */
17966
37
#ifdef EX_IOERR
17967
37
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17968
37
#endif /* EX_IOERR */
17969
37
#ifdef EX_TEMPFAIL
17970
37
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17971
37
#endif /* EX_TEMPFAIL */
17972
37
#ifdef EX_PROTOCOL
17973
37
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17974
37
#endif /* EX_PROTOCOL */
17975
37
#ifdef EX_NOPERM
17976
37
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17977
37
#endif /* EX_NOPERM */
17978
37
#ifdef EX_CONFIG
17979
37
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17980
37
#endif /* EX_CONFIG */
17981
#ifdef EX_NOTFOUND
17982
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17983
#endif /* EX_NOTFOUND */
17984
17985
    /* statvfs */
17986
37
#ifdef ST_RDONLY
17987
37
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17988
37
#endif /* ST_RDONLY */
17989
37
#ifdef ST_NOSUID
17990
37
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17991
37
#endif /* ST_NOSUID */
17992
17993
       /* GNU extensions */
17994
37
#ifdef ST_NODEV
17995
37
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17996
37
#endif /* ST_NODEV */
17997
37
#ifdef ST_NOEXEC
17998
37
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17999
37
#endif /* ST_NOEXEC */
18000
37
#ifdef ST_SYNCHRONOUS
18001
37
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
18002
37
#endif /* ST_SYNCHRONOUS */
18003
37
#ifdef ST_MANDLOCK
18004
37
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
18005
37
#endif /* ST_MANDLOCK */
18006
37
#ifdef ST_WRITE
18007
37
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
18008
37
#endif /* ST_WRITE */
18009
37
#ifdef ST_APPEND
18010
37
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
18011
37
#endif /* ST_APPEND */
18012
37
#ifdef ST_NOATIME
18013
37
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
18014
37
#endif /* ST_NOATIME */
18015
37
#ifdef ST_NODIRATIME
18016
37
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
18017
37
#endif /* ST_NODIRATIME */
18018
37
#ifdef ST_RELATIME
18019
37
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18020
37
#endif /* ST_RELATIME */
18021
18022
    /* FreeBSD sendfile() constants */
18023
#ifdef SF_NODISKIO
18024
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18025
#endif
18026
    /* is obsolete since the 11.x release */
18027
#ifdef SF_MNOWAIT
18028
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18029
#endif
18030
#ifdef SF_SYNC
18031
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18032
#endif
18033
#ifdef SF_NOCACHE
18034
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18035
#endif
18036
18037
37
#ifdef TFD_NONBLOCK
18038
37
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18039
37
#endif
18040
37
#ifdef TFD_CLOEXEC
18041
37
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18042
37
#endif
18043
37
#ifdef TFD_TIMER_ABSTIME
18044
37
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18045
37
#endif
18046
37
#ifdef TFD_TIMER_CANCEL_ON_SET
18047
37
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18048
37
#endif
18049
18050
    /* constants for posix_fadvise */
18051
37
#ifdef POSIX_FADV_NORMAL
18052
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18053
37
#endif
18054
37
#ifdef POSIX_FADV_SEQUENTIAL
18055
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18056
37
#endif
18057
37
#ifdef POSIX_FADV_RANDOM
18058
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18059
37
#endif
18060
37
#ifdef POSIX_FADV_NOREUSE
18061
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18062
37
#endif
18063
37
#ifdef POSIX_FADV_WILLNEED
18064
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18065
37
#endif
18066
37
#ifdef POSIX_FADV_DONTNEED
18067
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18068
37
#endif
18069
18070
    /* constants for waitid */
18071
37
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18072
37
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18073
37
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18074
37
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18075
37
#ifdef P_PIDFD
18076
37
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18077
37
#endif
18078
#ifdef PIDFD_NONBLOCK
18079
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18080
#endif
18081
37
#endif
18082
37
#ifdef WEXITED
18083
37
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18084
37
#endif
18085
37
#ifdef WNOWAIT
18086
37
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18087
37
#endif
18088
37
#ifdef WSTOPPED
18089
37
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18090
37
#endif
18091
37
#ifdef CLD_EXITED
18092
37
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18093
37
#endif
18094
37
#ifdef CLD_KILLED
18095
37
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18096
37
#endif
18097
37
#ifdef CLD_DUMPED
18098
37
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18099
37
#endif
18100
37
#ifdef CLD_TRAPPED
18101
37
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18102
37
#endif
18103
37
#ifdef CLD_STOPPED
18104
37
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18105
37
#endif
18106
37
#ifdef CLD_CONTINUED
18107
37
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18108
37
#endif
18109
18110
    /* constants for lockf */
18111
37
#ifdef F_LOCK
18112
37
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18113
37
#endif
18114
37
#ifdef F_TLOCK
18115
37
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18116
37
#endif
18117
37
#ifdef F_ULOCK
18118
37
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18119
37
#endif
18120
37
#ifdef F_TEST
18121
37
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18122
37
#endif
18123
18124
37
#ifdef RWF_DSYNC
18125
37
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18126
37
#endif
18127
37
#ifdef RWF_HIPRI
18128
37
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18129
37
#endif
18130
37
#ifdef RWF_SYNC
18131
37
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18132
37
#endif
18133
37
#ifdef RWF_NOWAIT
18134
37
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18135
37
#endif
18136
#ifdef RWF_DONTCACHE
18137
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18138
#endif
18139
#ifdef RWF_ATOMIC
18140
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18141
#endif
18142
37
#ifdef RWF_APPEND
18143
37
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18144
37
#endif
18145
18146
/* constants for splice */
18147
37
#if defined(HAVE_SPLICE) && defined(__linux__)
18148
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18149
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18150
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18151
37
#endif
18152
18153
/* constants for posix_spawn */
18154
37
#ifdef HAVE_POSIX_SPAWN
18155
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18156
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18157
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18158
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18159
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18160
#endif
18161
37
#endif
18162
18163
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18164
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18165
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18166
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18167
#endif
18168
#ifdef HAVE_SPAWNV
18169
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18170
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18171
#endif
18172
18173
37
#ifdef HAVE_SCHED_H
18174
37
#ifdef SCHED_OTHER
18175
37
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18176
37
#endif
18177
37
#ifdef SCHED_DEADLINE
18178
37
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18179
37
#endif
18180
37
#ifdef SCHED_FIFO
18181
37
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18182
37
#endif
18183
37
#ifdef SCHED_NORMAL
18184
37
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18185
37
#endif
18186
37
#ifdef SCHED_RR
18187
37
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18188
37
#endif
18189
#ifdef SCHED_SPORADIC
18190
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18191
#endif
18192
37
#ifdef SCHED_BATCH
18193
37
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18194
37
#endif
18195
37
#ifdef SCHED_IDLE
18196
37
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18197
37
#endif
18198
37
#ifdef SCHED_RESET_ON_FORK
18199
37
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18200
37
#endif
18201
#ifdef SCHED_SYS
18202
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18203
#endif
18204
#ifdef SCHED_IA
18205
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18206
#endif
18207
#ifdef SCHED_FSS
18208
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18209
#endif
18210
#ifdef SCHED_FX
18211
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18212
#endif
18213
18214
/* constants for namespaces */
18215
37
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18216
37
#ifdef CLONE_FS
18217
37
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18218
37
#endif
18219
37
#ifdef CLONE_FILES
18220
37
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18221
37
#endif
18222
37
#ifdef CLONE_NEWNS
18223
37
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18224
37
#endif
18225
37
#ifdef CLONE_NEWCGROUP
18226
37
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18227
37
#endif
18228
37
#ifdef CLONE_NEWUTS
18229
37
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18230
37
#endif
18231
37
#ifdef CLONE_NEWIPC
18232
37
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18233
37
#endif
18234
37
#ifdef CLONE_NEWUSER
18235
37
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18236
37
#endif
18237
37
#ifdef CLONE_NEWPID
18238
37
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18239
37
#endif
18240
37
#ifdef CLONE_NEWNET
18241
37
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18242
37
#endif
18243
#ifdef CLONE_NEWTIME
18244
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18245
#endif
18246
37
#ifdef CLONE_SYSVSEM
18247
37
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18248
37
#endif
18249
37
#ifdef CLONE_THREAD
18250
37
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18251
37
#endif
18252
37
#ifdef CLONE_SIGHAND
18253
37
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18254
37
#endif
18255
37
#ifdef CLONE_VM
18256
37
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18257
37
#endif
18258
37
#endif
18259
18260
37
#endif
18261
18262
37
#ifdef USE_XATTRS
18263
37
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18264
37
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18265
37
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18266
37
#endif
18267
18268
37
#if HAVE_DECL_RTLD_LAZY
18269
37
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18270
37
#endif
18271
37
#if HAVE_DECL_RTLD_NOW
18272
37
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18273
37
#endif
18274
37
#if HAVE_DECL_RTLD_GLOBAL
18275
37
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18276
37
#endif
18277
37
#if HAVE_DECL_RTLD_LOCAL
18278
37
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18279
37
#endif
18280
37
#if HAVE_DECL_RTLD_NODELETE
18281
37
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18282
37
#endif
18283
37
#if HAVE_DECL_RTLD_NOLOAD
18284
37
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18285
37
#endif
18286
37
#if HAVE_DECL_RTLD_DEEPBIND
18287
37
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18288
37
#endif
18289
#if HAVE_DECL_RTLD_MEMBER
18290
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18291
#endif
18292
18293
37
#ifdef HAVE_GETRANDOM_SYSCALL
18294
37
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18295
37
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18296
37
#endif
18297
37
#ifdef HAVE_MEMFD_CREATE
18298
37
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18299
37
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18300
37
#ifdef MFD_HUGETLB
18301
37
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18302
37
#endif
18303
37
#ifdef MFD_HUGE_SHIFT
18304
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18305
37
#endif
18306
37
#ifdef MFD_HUGE_MASK
18307
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18308
37
#endif
18309
37
#ifdef MFD_HUGE_64KB
18310
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18311
37
#endif
18312
37
#ifdef MFD_HUGE_512KB
18313
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18314
37
#endif
18315
37
#ifdef MFD_HUGE_1MB
18316
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18317
37
#endif
18318
37
#ifdef MFD_HUGE_2MB
18319
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18320
37
#endif
18321
37
#ifdef MFD_HUGE_8MB
18322
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18323
37
#endif
18324
37
#ifdef MFD_HUGE_16MB
18325
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18326
37
#endif
18327
37
#ifdef MFD_HUGE_32MB
18328
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18329
37
#endif
18330
37
#ifdef MFD_HUGE_256MB
18331
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18332
37
#endif
18333
37
#ifdef MFD_HUGE_512MB
18334
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18335
37
#endif
18336
37
#ifdef MFD_HUGE_1GB
18337
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18338
37
#endif
18339
37
#ifdef MFD_HUGE_2GB
18340
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18341
37
#endif
18342
37
#ifdef MFD_HUGE_16GB
18343
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18344
37
#endif
18345
37
#endif /* HAVE_MEMFD_CREATE */
18346
18347
37
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18348
37
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18349
37
#ifdef EFD_NONBLOCK
18350
37
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18351
37
#endif
18352
37
#ifdef EFD_SEMAPHORE
18353
37
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18354
37
#endif
18355
37
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18356
18357
37
#ifdef NODEV
18358
37
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18359
37
#endif
18360
18361
37
#ifdef AT_NO_AUTOMOUNT
18362
37
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18363
37
#endif
18364
18365
37
#ifdef HAVE_STATX
18366
37
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18367
37
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18368
37
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18369
37
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18370
37
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18371
37
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18372
37
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18373
37
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18374
37
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18375
37
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18376
37
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18377
37
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18378
37
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18379
#ifdef STATX_MNT_ID
18380
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18381
#endif
18382
#ifdef STATX_DIOALIGN
18383
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18384
#endif
18385
#ifdef STATX_MNT_ID_UNIQUE
18386
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18387
#endif
18388
#ifdef STATX_SUBVOL
18389
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18390
#endif
18391
#ifdef STATX_WRITE_ATOMIC
18392
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18393
#endif
18394
#ifdef STATX_DIO_READ_ALIGN
18395
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18396
#endif
18397
    /* STATX_ALL intentionally omitted because it is deprecated */
18398
37
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18399
37
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18400
37
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18401
    /* STATX_ATTR_* constants are in the stat module */
18402
37
#endif /* HAVE_STATX */
18403
18404
#if defined(__APPLE__)
18405
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18406
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18407
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18408
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18409
#endif
18410
18411
#ifdef MS_WINDOWS
18412
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18413
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18414
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18415
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18416
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18417
#endif
18418
18419
37
    return 0;
18420
37
}
18421
18422
18423
18424
#define PROBE(name, test) \
18425
   static int name(void)  \
18426
629
   {                      \
18427
629
      if (test) {        \
18428
629
          return 1;       \
18429
629
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
629
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_futimens
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_linkat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_openat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_renameat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18426
37
   {                      \
18427
37
      if (test) {        \
18428
37
          return 1;       \
18429
37
      } else {            \
18430
0
          return 0;       \
18431
0
      }                   \
18432
37
   }
18433
18434
#ifdef HAVE_FSTATAT
18435
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18436
#endif
18437
18438
#ifdef HAVE_FACCESSAT
18439
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18440
#endif
18441
18442
#ifdef HAVE_FCHMODAT
18443
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18444
#endif
18445
18446
#ifdef HAVE_FCHOWNAT
18447
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18448
#endif
18449
18450
#ifdef HAVE_LINKAT
18451
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18452
#endif
18453
18454
#ifdef HAVE_FDOPENDIR
18455
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18456
#endif
18457
18458
#ifdef HAVE_MKDIRAT
18459
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18460
#endif
18461
18462
#ifdef HAVE_MKFIFOAT
18463
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18464
#endif
18465
18466
#ifdef HAVE_MKNODAT
18467
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18468
#endif
18469
18470
#ifdef HAVE_RENAMEAT
18471
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18472
#endif
18473
18474
#ifdef HAVE_UNLINKAT
18475
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18476
#endif
18477
18478
#ifdef HAVE_OPENAT
18479
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18480
#endif
18481
18482
#ifdef HAVE_READLINKAT
18483
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18484
#endif
18485
18486
#ifdef HAVE_SYMLINKAT
18487
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18488
#endif
18489
18490
#ifdef HAVE_FUTIMENS
18491
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18492
#endif
18493
18494
#ifdef HAVE_UTIMENSAT
18495
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18496
#endif
18497
18498
#ifdef HAVE_PTSNAME_R
18499
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18500
#endif
18501
18502
18503
18504
static const struct have_function {
18505
    const char * const label;
18506
    int (*probe)(void);
18507
} have_functions[] = {
18508
18509
#ifdef HAVE_EVENTFD
18510
    {"HAVE_EVENTFD", NULL},
18511
#endif
18512
18513
#ifdef HAVE_TIMERFD_CREATE
18514
    {"HAVE_TIMERFD_CREATE", NULL},
18515
#endif
18516
18517
#ifdef HAVE_FACCESSAT
18518
    { "HAVE_FACCESSAT", probe_faccessat },
18519
#endif
18520
18521
#ifdef HAVE_FCHDIR
18522
    { "HAVE_FCHDIR", NULL },
18523
#endif
18524
18525
#ifdef HAVE_FCHMOD
18526
    { "HAVE_FCHMOD", NULL },
18527
#endif
18528
18529
#ifdef HAVE_FCHMODAT
18530
    { "HAVE_FCHMODAT", probe_fchmodat },
18531
#endif
18532
18533
#ifdef HAVE_FCHOWN
18534
    { "HAVE_FCHOWN", NULL },
18535
#endif
18536
18537
#ifdef HAVE_FCHOWNAT
18538
    { "HAVE_FCHOWNAT", probe_fchownat },
18539
#endif
18540
18541
#ifdef HAVE_FEXECVE
18542
    { "HAVE_FEXECVE", NULL },
18543
#endif
18544
18545
#ifdef HAVE_FDOPENDIR
18546
    { "HAVE_FDOPENDIR", probe_fdopendir },
18547
#endif
18548
18549
#ifdef HAVE_FPATHCONF
18550
    { "HAVE_FPATHCONF", NULL },
18551
#endif
18552
18553
#ifdef HAVE_FSTATAT
18554
    { "HAVE_FSTATAT", probe_fstatat },
18555
#endif
18556
18557
#ifdef HAVE_FSTATVFS
18558
    { "HAVE_FSTATVFS", NULL },
18559
#endif
18560
18561
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18562
    { "HAVE_FTRUNCATE", NULL },
18563
#endif
18564
18565
#ifdef HAVE_FUTIMENS
18566
    { "HAVE_FUTIMENS", probe_futimens },
18567
#endif
18568
18569
#ifdef HAVE_FUTIMES
18570
    { "HAVE_FUTIMES", NULL },
18571
#endif
18572
18573
#ifdef HAVE_FUTIMESAT
18574
    { "HAVE_FUTIMESAT", NULL },
18575
#endif
18576
18577
#ifdef HAVE_LINKAT
18578
    { "HAVE_LINKAT", probe_linkat },
18579
#endif
18580
18581
#ifdef HAVE_LCHFLAGS
18582
    { "HAVE_LCHFLAGS", NULL },
18583
#endif
18584
18585
#ifdef HAVE_LCHMOD
18586
    { "HAVE_LCHMOD", NULL },
18587
#endif
18588
18589
#ifdef HAVE_LCHOWN
18590
    { "HAVE_LCHOWN", NULL },
18591
#endif
18592
18593
#ifdef HAVE_LSTAT
18594
    { "HAVE_LSTAT", NULL },
18595
#endif
18596
18597
#ifdef HAVE_LUTIMES
18598
    { "HAVE_LUTIMES", NULL },
18599
#endif
18600
18601
#ifdef HAVE_MEMFD_CREATE
18602
    { "HAVE_MEMFD_CREATE", NULL },
18603
#endif
18604
18605
#ifdef HAVE_MKDIRAT
18606
    { "HAVE_MKDIRAT", probe_mkdirat },
18607
#endif
18608
18609
#ifdef HAVE_MKFIFOAT
18610
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18611
#endif
18612
18613
#ifdef HAVE_MKNODAT
18614
    { "HAVE_MKNODAT", probe_mknodat },
18615
#endif
18616
18617
#ifdef HAVE_OPENAT
18618
    { "HAVE_OPENAT", probe_openat },
18619
#endif
18620
18621
#ifdef HAVE_READLINKAT
18622
    { "HAVE_READLINKAT", probe_readlinkat },
18623
#endif
18624
18625
#ifdef HAVE_RENAMEAT
18626
    { "HAVE_RENAMEAT", probe_renameat },
18627
#endif
18628
18629
#ifdef HAVE_SYMLINKAT
18630
    { "HAVE_SYMLINKAT", probe_symlinkat },
18631
#endif
18632
18633
#ifdef HAVE_UNLINKAT
18634
    { "HAVE_UNLINKAT", probe_unlinkat },
18635
#endif
18636
18637
#ifdef HAVE_UTIMENSAT
18638
    { "HAVE_UTIMENSAT", probe_utimensat },
18639
#endif
18640
18641
#ifdef HAVE_PTSNAME_R
18642
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18643
#endif
18644
18645
#ifdef MS_WINDOWS
18646
    { "MS_WINDOWS", NULL },
18647
#endif
18648
18649
    { NULL, NULL }
18650
};
18651
18652
18653
static int
18654
posixmodule_exec(PyObject *m)
18655
37
{
18656
37
    _posixstate *state = get_posix_state(m);
18657
18658
37
#if defined(HAVE_PWRITEV)
18659
37
    if (HAVE_PWRITEV_RUNTIME) {} else {
18660
0
        PyObject* dct = PyModule_GetDict(m);
18661
18662
0
        if (dct == NULL) {
18663
0
            return -1;
18664
0
        }
18665
18666
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18667
0
            return -1;
18668
0
        }
18669
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18670
0
            return -1;
18671
0
        }
18672
0
    }
18673
37
#endif
18674
18675
37
#ifdef HAVE_STATX
18676
37
    if (statx == NULL) {
18677
0
        PyObject* dct = PyModule_GetDict(m);
18678
0
        if (dct == NULL) {
18679
0
            return -1;
18680
0
        }
18681
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18682
0
            return -1;
18683
0
        }
18684
0
    }
18685
37
    else {
18686
37
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18687
37
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18688
0
            return -1;
18689
0
        }
18690
37
    }
18691
37
#endif
18692
18693
    /* Initialize environ dictionary */
18694
37
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18695
0
        return -1;
18696
0
    }
18697
18698
37
    if (all_ins(m))
18699
0
        return -1;
18700
18701
37
    if (setup_confname_tables(m))
18702
0
        return -1;
18703
18704
37
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18705
0
        return -1;
18706
0
    }
18707
18708
37
#if defined(HAVE_WAITID)
18709
37
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18710
37
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18711
0
        return -1;
18712
0
    }
18713
37
#endif
18714
18715
37
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18716
37
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18717
37
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18718
37
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18719
37
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18720
0
        return -1;
18721
0
    }
18722
37
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18723
37
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18724
18725
37
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18726
37
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18727
0
        return -1;
18728
0
    }
18729
18730
37
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18731
37
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18732
37
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18733
0
        return -1;
18734
0
    }
18735
37
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18736
37
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18737
37
                          &os_sched_param_reduce_method) < 0)
18738
0
    {
18739
0
        return -1;
18740
0
    }
18741
37
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18742
37
#endif
18743
18744
    /* initialize TerminalSize_info */
18745
37
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18746
37
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18747
0
        return -1;
18748
0
    }
18749
18750
    /* initialize scandir types */
18751
37
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18752
37
    if (ScandirIteratorType == NULL) {
18753
0
        return -1;
18754
0
    }
18755
37
    state->ScandirIteratorType = ScandirIteratorType;
18756
18757
37
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18758
37
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18759
0
        return -1;
18760
0
    }
18761
18762
37
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18763
37
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18764
0
        return -1;
18765
0
    }
18766
18767
37
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18768
37
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18769
0
        return -1;
18770
0
    }
18771
18772
37
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18773
0
        return -1;
18774
37
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18775
37
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18776
37
    if (state->struct_rusage == NULL)
18777
0
        return -1;
18778
37
#endif
18779
37
    state->st_mode = PyUnicode_InternFromString("st_mode");
18780
37
    if (state->st_mode == NULL)
18781
0
        return -1;
18782
18783
    /* suppress "function not used" warnings */
18784
37
    {
18785
37
    int ignored;
18786
37
    fd_specified("", -1);
18787
37
    follow_symlinks_specified("", 1);
18788
37
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18789
37
    dir_fd_converter(Py_None, &ignored);
18790
37
    dir_fd_unavailable(Py_None, &ignored);
18791
37
    }
18792
18793
    /*
18794
     * provide list of locally available functions
18795
     * so os.py can populate support_* lists
18796
     */
18797
37
    PyObject *list = PyList_New(0);
18798
37
    if (!list) {
18799
0
        return -1;
18800
0
    }
18801
1.22k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18802
1.18k
        PyObject *unicode;
18803
1.18k
        if (trace->probe && !trace->probe()) continue;
18804
1.18k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18805
1.18k
        if (!unicode)
18806
0
            return -1;
18807
1.18k
        if (PyList_Append(list, unicode))
18808
0
            return -1;
18809
1.18k
        Py_DECREF(unicode);
18810
1.18k
    }
18811
18812
37
#ifndef MS_WINDOWS
18813
37
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18814
0
        PyErr_SetString(PyExc_RuntimeError,
18815
0
                        "cannot read ticks_per_second");
18816
0
        return -1;
18817
0
    }
18818
37
    assert(state->ticks_per_second >= 1);
18819
37
#endif
18820
18821
37
    return PyModule_Add(m, "_have_functions", list);
18822
37
}
18823
18824
18825
static PyModuleDef_Slot posixmodile_slots[] = {
18826
    _Py_ABI_SLOT,
18827
    {Py_mod_exec, posixmodule_exec},
18828
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18829
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18830
    {0, NULL}
18831
};
18832
18833
static struct PyModuleDef posixmodule = {
18834
    PyModuleDef_HEAD_INIT,
18835
    .m_name = MODNAME,
18836
    .m_doc = posix__doc__,
18837
    .m_size = sizeof(_posixstate),
18838
    .m_methods = posix_methods,
18839
    .m_slots = posixmodile_slots,
18840
    .m_traverse = _posix_traverse,
18841
    .m_clear = _posix_clear,
18842
    .m_free = _posix_free,
18843
};
18844
18845
PyMODINIT_FUNC
18846
INITFUNC(void)
18847
37
{
18848
37
    return PyModuleDef_Init(&posixmodule);
18849
37
}