Coverage Report

Created: 2026-05-30 06:18

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
326k
#  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
256k
#  define STAT stat
409
10.8k
#  define LSTAT lstat
410
96.6k
#  define FSTAT fstat
411
456k
#  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
92.1k
#  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
96.6k
#  define HAVE_FDOPENDIR_RUNTIME 1
610
0
#  define HAVE_MKDIRAT_RUNTIME 1
611
0
#  define HAVE_RENAMEAT_RUNTIME 1
612
113k
#  define HAVE_UNLINKAT_RUNTIME 1
613
92.1k
#  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
260k
{
844
260k
    if (uid == (uid_t)-1)
845
0
        return PyLong_FromLong(-1);
846
260k
    return PyLong_FromUnsignedLong(uid);
847
260k
}
848
849
PyObject *
850
_PyLong_FromGid(gid_t gid)
851
260k
{
852
260k
    if (gid == (gid_t)-1)
853
0
        return PyLong_FromLong(-1);
854
260k
    return PyLong_FromUnsignedLong(gid);
855
260k
}
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
520k
{
1075
520k
#ifdef NODEV
1076
520k
    if (dev == NODEV) {
1077
37
        return PyLong_FromLongLong((long long)dev);
1078
37
    }
1079
520k
#endif
1080
520k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1081
520k
}
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.01M
#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
301k
{
1146
301k
    int overflow;
1147
301k
    long long_value;
1148
1149
301k
    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
301k
    PyObject *index = _PyNumber_Index(o);
1157
301k
    if (index == NULL) {
1158
0
        return 0;
1159
0
    }
1160
1161
301k
    assert(PyLong_Check(index));
1162
301k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1163
301k
    Py_DECREF(index);
1164
301k
    assert(!PyErr_Occurred());
1165
301k
    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
301k
    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
301k
    *p = (int)long_value;
1177
301k
    return 1;
1178
301k
}
1179
1180
static int
1181
dir_fd_converter(PyObject *o, void *p)
1182
223k
{
1183
223k
    if (o == Py_None) {
1184
17.9k
        *(int *)p = DEFAULT_DIR_FD;
1185
17.9k
        return 1;
1186
17.9k
    }
1187
205k
    else if (PyIndex_Check(o)) {
1188
205k
        return _fd_converter(o, (int *)p);
1189
205k
    }
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
223k
}
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
471k
{
1231
471k
    void *state = _PyModule_GetState(module);
1232
471k
    assert(state != NULL);
1233
471k
    return (_posixstate *)state;
1234
471k
}
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
849k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1356
849k
     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
676k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1366
676k
                      suppress_value_error, allow_fd)
1367
#endif
1368
1369
static void
1370
path_cleanup(path_t *path)
1371
945k
{
1372
945k
    wchar_t *wide = (wchar_t *)path->wide;
1373
945k
    path->wide = NULL;
1374
945k
    PyMem_Free(wide);
1375
945k
    Py_CLEAR(path->object);
1376
945k
    Py_CLEAR(path->cleanup);
1377
945k
}
1378
1379
static int
1380
path_converter(PyObject *o, void *p)
1381
849k
{
1382
849k
    path_t *path = (path_t *)p;
1383
849k
    PyObject *bytes = NULL;
1384
849k
    Py_ssize_t length = 0;
1385
849k
    int is_index, is_bytes, is_unicode;
1386
849k
    const char *narrow;
1387
849k
    PyObject *wo = NULL;
1388
849k
    wchar_t *wide = NULL;
1389
1390
849k
#define FORMAT_EXCEPTION(exc, fmt) \
1391
849k
    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
849k
    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
849k
    path->object = path->cleanup = NULL;
1404
    /* path->object owns a reference to the original object */
1405
849k
    Py_INCREF(o);
1406
1407
849k
    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
849k
    is_index = path->allow_fd && PyIndex_Check(o);
1417
849k
    is_bytes = PyBytes_Check(o);
1418
849k
    is_unicode = PyUnicode_Check(o);
1419
1420
849k
    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
849k
    if (is_unicode) {
1453
752k
        if (path->make_wide) {
1454
173k
            wide = PyUnicode_AsWideCharString(o, &length);
1455
173k
            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
173k
            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
173k
            path->wide = wide;
1471
173k
            path->narrow = NULL;
1472
173k
            path->fd = -1;
1473
173k
            wide = NULL;
1474
173k
            goto success_exit;
1475
173k
        }
1476
579k
        bytes = PyUnicode_EncodeFSDefault(o);
1477
579k
        if (!bytes) {
1478
0
            goto error_exit;
1479
0
        }
1480
579k
    }
1481
96.6k
    else if (is_bytes) {
1482
0
        bytes = Py_NewRef(o);
1483
0
    }
1484
96.6k
    else if (is_index) {
1485
96.6k
        if (!_fd_converter(o, &path->fd)) {
1486
0
            goto error_exit;
1487
0
        }
1488
96.6k
        path->wide = NULL;
1489
96.6k
        path->narrow = NULL;
1490
96.6k
        path->is_fd = true;
1491
96.6k
        goto success_exit;
1492
96.6k
    }
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
579k
    length = PyBytes_GET_SIZE(bytes);
1509
579k
    narrow = PyBytes_AS_STRING(bytes);
1510
579k
    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
579k
    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
579k
    else {
1543
579k
        path->wide = NULL;
1544
579k
        path->narrow = narrow;
1545
579k
        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
579k
        else {
1551
579k
            path->cleanup = bytes;
1552
579k
        }
1553
579k
    }
1554
579k
    path->fd = -1;
1555
1556
849k
 success_exit:
1557
849k
    path->value_error = 0;
1558
849k
    path->length = length;
1559
849k
    path->object = o;
1560
849k
    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
267k
{
1628
267k
    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
267k
    return 0;
1635
267k
}
1636
1637
static int
1638
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1639
267k
{
1640
267k
    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
267k
    return 0;
1647
267k
}
1648
1649
static int
1650
fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
1651
                               int follow_symlinks)
1652
267k
{
1653
267k
    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
267k
    return 0;
1660
267k
}
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
196k
{
1908
196k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1909
196k
}
1910
1911
static PyObject *
1912
path_object_error(PyObject *path)
1913
196k
{
1914
#ifdef MS_WINDOWS
1915
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1916
                PyExc_OSError, 0, path);
1917
#else
1918
196k
    return posix_path_object_error(path);
1919
196k
#endif
1920
196k
}
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
196k
{
1936
196k
    return path_object_error(path->object);
1937
196k
}
1938
1939
static PyObject *
1940
posix_path_error(path_t *path)
1941
0
{
1942
0
    return posix_path_object_error(path->object);
1943
0
}
1944
1945
static PyObject *
1946
path_error2(path_t *path, path_t *path2)
1947
0
{
1948
0
    return path_object_error2(path->object, path2->object);
1949
0
}
1950
1951
1952
/* POSIX generic methods */
1953
1954
static PyObject *
1955
posix_fildes_fd(int fd, int (*func)(int))
1956
0
{
1957
0
    int res;
1958
0
    int async_err = 0;
1959
1960
0
    do {
1961
0
        Py_BEGIN_ALLOW_THREADS
1962
0
        _Py_BEGIN_SUPPRESS_IPH
1963
0
        res = (*func)(fd);
1964
0
        _Py_END_SUPPRESS_IPH
1965
0
        Py_END_ALLOW_THREADS
1966
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1967
0
    if (res != 0)
1968
0
        return (!async_err) ? posix_error() : NULL;
1969
0
    Py_RETURN_NONE;
1970
0
}
1971
1972
1973
#ifdef MS_WINDOWS
1974
/* This is a reimplementation of the C library's chdir function,
1975
   but one that produces Win32 errors instead of DOS error codes.
1976
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1977
   it also needs to set "magic" environment variables indicating
1978
   the per-drive current directory, which are of the form =<drive>: */
1979
static BOOL __stdcall
1980
win32_wchdir(LPCWSTR path)
1981
{
1982
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1983
    int result;
1984
    wchar_t env[4] = L"=x:";
1985
1986
    if(!SetCurrentDirectoryW(path))
1987
        return FALSE;
1988
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1989
    if (!result)
1990
        return FALSE;
1991
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1992
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1993
        if (!new_path) {
1994
            SetLastError(ERROR_OUTOFMEMORY);
1995
            return FALSE;
1996
        }
1997
        result = GetCurrentDirectoryW(result, new_path);
1998
        if (!result) {
1999
            PyMem_RawFree(new_path);
2000
            return FALSE;
2001
        }
2002
    }
2003
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
2004
                            wcsncmp(new_path, L"//", 2) == 0);
2005
    if (!is_unc_like_path) {
2006
        env[1] = new_path[0];
2007
        result = SetEnvironmentVariableW(env, new_path);
2008
    }
2009
    if (new_path != path_buf)
2010
        PyMem_RawFree(new_path);
2011
    return result ? TRUE : FALSE;
2012
}
2013
#endif
2014
2015
#ifdef MS_WINDOWS
2016
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2017
   - time stamps are restricted to second resolution
2018
   - file modification times suffer from forth-and-back conversions between
2019
     UTC and local time
2020
   Therefore, we implement our own stat, based on the Win32 API directly.
2021
*/
2022
#define HAVE_STAT_NSEC 1
2023
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2024
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2025
2026
static void
2027
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2028
                       BY_HANDLE_FILE_INFORMATION *info,
2029
                       ULONG *reparse_tag)
2030
{
2031
    memset(info, 0, sizeof(*info));
2032
    info->dwFileAttributes = pFileData->dwFileAttributes;
2033
    info->ftCreationTime   = pFileData->ftCreationTime;
2034
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
2035
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
2036
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
2037
    info->nFileSizeLow     = pFileData->nFileSizeLow;
2038
/*  info->nNumberOfLinks   = 1; */
2039
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2040
        *reparse_tag = pFileData->dwReserved0;
2041
    else
2042
        *reparse_tag = 0;
2043
}
2044
2045
static BOOL
2046
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
2047
{
2048
    HANDLE hFindFile;
2049
    WIN32_FIND_DATAW FileData;
2050
    LPCWSTR filename = pszFile;
2051
    size_t n = wcslen(pszFile);
2052
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2053
        // cannot use PyMem_Malloc here because we do not hold the GIL
2054
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2055
        if(!filename) {
2056
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2057
            return FALSE;
2058
        }
2059
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2060
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2061
            ((LPWSTR)filename)[n] = L'\0';
2062
        }
2063
        if (!n || (n == 1 && filename[1] == L':')) {
2064
            // Nothing left to query
2065
            free((void *)filename);
2066
            return FALSE;
2067
        }
2068
    }
2069
    hFindFile = FindFirstFileW(filename, &FileData);
2070
    if (pszFile != filename) {
2071
        free((void *)filename);
2072
    }
2073
    if (hFindFile == INVALID_HANDLE_VALUE) {
2074
        return FALSE;
2075
    }
2076
    FindClose(hFindFile);
2077
    find_data_to_file_info(&FileData, info, reparse_tag);
2078
    return TRUE;
2079
}
2080
2081
2082
static void
2083
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2084
                         struct _Py_stat_struct *result)
2085
{
2086
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2087
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2088
           the filename has an extension that is commonly used by files
2089
           that CreateProcessW can execute. A real implementation calls
2090
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2091
           AccessCheck to check for generic read, write, and execute
2092
           access. */
2093
        const wchar_t *fileExtension = wcsrchr(path, '.');
2094
        if (fileExtension) {
2095
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2096
                _wcsicmp(fileExtension, L".bat") == 0 ||
2097
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2098
                _wcsicmp(fileExtension, L".com") == 0) {
2099
                result->st_mode |= 0111;
2100
            }
2101
        }
2102
    }
2103
}
2104
2105
2106
static int
2107
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2108
                      BOOL traverse)
2109
{
2110
    HANDLE hFile;
2111
    BY_HANDLE_FILE_INFORMATION fileInfo;
2112
    FILE_BASIC_INFO basicInfo;
2113
    FILE_BASIC_INFO *pBasicInfo = NULL;
2114
    FILE_ID_INFO idInfo;
2115
    FILE_ID_INFO *pIdInfo = NULL;
2116
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2117
    DWORD fileType, error;
2118
    BOOL isUnhandledTag = FALSE;
2119
    int retval = 0;
2120
2121
    DWORD access = FILE_READ_ATTRIBUTES;
2122
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2123
    if (!traverse) {
2124
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2125
    }
2126
2127
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2128
    if (hFile == INVALID_HANDLE_VALUE) {
2129
        /* Either the path doesn't exist, or the caller lacks access. */
2130
        error = GetLastError();
2131
        switch (error) {
2132
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2133
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2134
            /* Try reading the parent directory. */
2135
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2136
                /* Cannot read the parent directory. */
2137
                switch (GetLastError()) {
2138
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2139
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2140
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2141
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2142
                    break;
2143
                /* Restore the error from CreateFileW(). */
2144
                default:
2145
                    SetLastError(error);
2146
                }
2147
2148
                return -1;
2149
            }
2150
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2151
                if (traverse ||
2152
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2153
                    /* The stat call has to traverse but cannot, so fail. */
2154
                    SetLastError(error);
2155
                    return -1;
2156
                }
2157
            }
2158
            break;
2159
2160
        case ERROR_INVALID_PARAMETER:
2161
            /* \\.\con requires read or write access. */
2162
            hFile = CreateFileW(path, access | GENERIC_READ,
2163
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2164
                        OPEN_EXISTING, flags, NULL);
2165
            if (hFile == INVALID_HANDLE_VALUE) {
2166
                SetLastError(error);
2167
                return -1;
2168
            }
2169
            break;
2170
2171
        case ERROR_CANT_ACCESS_FILE:
2172
            /* bpo37834: open unhandled reparse points if traverse fails. */
2173
            if (traverse) {
2174
                traverse = FALSE;
2175
                isUnhandledTag = TRUE;
2176
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2177
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2178
            }
2179
            if (hFile == INVALID_HANDLE_VALUE) {
2180
                SetLastError(error);
2181
                return -1;
2182
            }
2183
            break;
2184
2185
        default:
2186
            return -1;
2187
        }
2188
    }
2189
2190
    if (hFile != INVALID_HANDLE_VALUE) {
2191
        /* Handle types other than files on disk. */
2192
        fileType = GetFileType(hFile);
2193
        if (fileType != FILE_TYPE_DISK) {
2194
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2195
                retval = -1;
2196
                goto cleanup;
2197
            }
2198
            DWORD fileAttributes = GetFileAttributesW(path);
2199
            memset(result, 0, sizeof(*result));
2200
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2201
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2202
                /* \\.\pipe\ or \\.\mailslot\ */
2203
                result->st_mode = _S_IFDIR;
2204
            } else if (fileType == FILE_TYPE_CHAR) {
2205
                /* \\.\nul */
2206
                result->st_mode = _S_IFCHR;
2207
            } else if (fileType == FILE_TYPE_PIPE) {
2208
                /* \\.\pipe\spam */
2209
                result->st_mode = _S_IFIFO;
2210
            }
2211
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2212
            goto cleanup;
2213
        }
2214
2215
        /* Query the reparse tag, and traverse a non-link. */
2216
        if (!traverse) {
2217
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2218
                    &tagInfo, sizeof(tagInfo))) {
2219
                /* Allow devices that do not support FileAttributeTagInfo. */
2220
                switch (GetLastError()) {
2221
                case ERROR_INVALID_PARAMETER:
2222
                case ERROR_INVALID_FUNCTION:
2223
                case ERROR_NOT_SUPPORTED:
2224
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2225
                    tagInfo.ReparseTag = 0;
2226
                    break;
2227
                default:
2228
                    retval = -1;
2229
                    goto cleanup;
2230
                }
2231
            } else if (tagInfo.FileAttributes &
2232
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2233
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2234
                    if (isUnhandledTag) {
2235
                        /* Traversing previously failed for either this link
2236
                           or its target. */
2237
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2238
                        retval = -1;
2239
                        goto cleanup;
2240
                    }
2241
                /* Traverse a non-link, but not if traversing already failed
2242
                   for an unhandled tag. */
2243
                } else if (!isUnhandledTag) {
2244
                    CloseHandle(hFile);
2245
                    return win32_xstat_slow_impl(path, result, TRUE);
2246
                }
2247
            }
2248
        }
2249
2250
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2251
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2252
                                          &basicInfo, sizeof(basicInfo))) {
2253
            switch (GetLastError()) {
2254
            case ERROR_INVALID_PARAMETER:
2255
            case ERROR_INVALID_FUNCTION:
2256
            case ERROR_NOT_SUPPORTED:
2257
                /* Volumes and physical disks are block devices, e.g.
2258
                   \\.\C: and \\.\PhysicalDrive0. */
2259
                memset(result, 0, sizeof(*result));
2260
                result->st_mode = 0x6000; /* S_IFBLK */
2261
                goto cleanup;
2262
            }
2263
            retval = -1;
2264
            goto cleanup;
2265
        }
2266
2267
        /* Successfully got FileBasicInfo, so we'll pass it along */
2268
        pBasicInfo = &basicInfo;
2269
2270
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2271
            /* Successfully got FileIdInfo, so pass it along */
2272
            pIdInfo = &idInfo;
2273
        }
2274
    }
2275
2276
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2277
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2278
2279
cleanup:
2280
    if (hFile != INVALID_HANDLE_VALUE) {
2281
        /* Preserve last error if we are failing */
2282
        error = retval ? GetLastError() : 0;
2283
        if (!CloseHandle(hFile)) {
2284
            retval = -1;
2285
        } else if (retval) {
2286
            /* Restore last error */
2287
            SetLastError(error);
2288
        }
2289
    }
2290
2291
    return retval;
2292
}
2293
2294
static int
2295
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2296
                 BOOL traverse)
2297
{
2298
    FILE_STAT_BASIC_INFORMATION statInfo;
2299
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2300
                                     &statInfo, sizeof(statInfo))) {
2301
        if (// Cannot use fast path for reparse points ...
2302
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2303
            // ... unless it's a name surrogate (symlink) and we're not following
2304
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2305
        ) {
2306
            _Py_stat_basic_info_to_stat(&statInfo, result);
2307
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2308
            return 0;
2309
        }
2310
    } else {
2311
        switch(GetLastError()) {
2312
        case ERROR_FILE_NOT_FOUND:
2313
        case ERROR_PATH_NOT_FOUND:
2314
        case ERROR_NOT_READY:
2315
        case ERROR_BAD_NET_NAME:
2316
            /* These errors aren't worth retrying with the slow path */
2317
            return -1;
2318
        case ERROR_NOT_SUPPORTED:
2319
            /* indicates the API couldn't be loaded */
2320
            break;
2321
        }
2322
    }
2323
2324
    return win32_xstat_slow_impl(path, result, traverse);
2325
}
2326
2327
static int
2328
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2329
{
2330
    /* Protocol violation: we explicitly clear errno, instead of
2331
       setting it to a POSIX error. Callers should use GetLastError. */
2332
    int code = win32_xstat_impl(path, result, traverse);
2333
    errno = 0;
2334
2335
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2336
    result->st_ctime = result->st_birthtime;
2337
    result->st_ctime_nsec = result->st_birthtime_nsec;
2338
    return code;
2339
}
2340
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2341
2342
   In Posix, stat automatically traverses symlinks and returns the stat
2343
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2344
   default does not traverse symlinks and instead returns attributes for
2345
   the symlink.
2346
2347
   Instead, we will open the file (which *does* traverse symlinks by default)
2348
   and GetFileInformationByHandle(). */
2349
2350
static int
2351
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2352
{
2353
    return win32_xstat(path, result, FALSE);
2354
}
2355
2356
static int
2357
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2358
{
2359
    return win32_xstat(path, result, TRUE);
2360
}
2361
2362
#endif /* MS_WINDOWS */
2363
2364
PyDoc_STRVAR(stat_result__doc__,
2365
"stat_result: Result from stat, fstat, or lstat.\n\n\
2366
This object may be accessed either as a tuple of\n\
2367
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2368
or via the attributes st_mode, st_ino, st_dev, st_nlink, and so on.\n\
2369
\n\
2370
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2371
or st_flags, they are available as attributes only.\n\
2372
\n\
2373
See os.stat for more information.");
2374
2375
static PyStructSequence_Field stat_result_fields[] = {
2376
    {"st_mode",    "protection bits"},
2377
    {"st_ino",     "inode"},
2378
    {"st_dev",     "device"},
2379
    {"st_nlink",   "number of hard links"},
2380
    {"st_uid",     "user ID of owner"},
2381
    {"st_gid",     "group ID of owner"},
2382
    {"st_size",    "total size, in bytes"},
2383
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2384
    {NULL,   "integer time of last access"},
2385
    {NULL,   "integer time of last modification"},
2386
    {NULL,   "integer time of last change"},
2387
    {"st_atime",   "time of last access"},
2388
    {"st_mtime",   "time of last modification"},
2389
    {"st_ctime",   "time of last change"},
2390
    {"st_atime_ns",   "time of last access in nanoseconds"},
2391
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2392
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2393
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2394
    {"st_blksize", "blocksize for filesystem I/O"},
2395
#endif
2396
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2397
    {"st_blocks",  "number of blocks allocated"},
2398
#endif
2399
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2400
    {"st_rdev",    "device type (if inode device)"},
2401
#endif
2402
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2403
    {"st_flags",   "user defined flags for file"},
2404
#endif
2405
#ifdef HAVE_STRUCT_STAT_ST_GEN
2406
    {"st_gen",    "generation number"},
2407
#endif
2408
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2409
    {"st_birthtime",   "time of creation"},
2410
#endif
2411
#ifdef MS_WINDOWS
2412
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2413
#endif
2414
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2415
    {"st_file_attributes", "Windows file attribute bits"},
2416
#endif
2417
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2418
    {"st_fstype",  "Type of filesystem"},
2419
#endif
2420
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2421
    {"st_reparse_tag", "Windows reparse tag"},
2422
#endif
2423
    {0}
2424
};
2425
2426
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2427
#define ST_BLKSIZE_IDX 16
2428
#else
2429
#define ST_BLKSIZE_IDX 15
2430
#endif
2431
2432
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2433
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2434
#else
2435
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2436
#endif
2437
2438
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2439
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2440
#else
2441
#define ST_RDEV_IDX ST_BLOCKS_IDX
2442
#endif
2443
2444
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2445
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2446
#else
2447
#define ST_FLAGS_IDX ST_RDEV_IDX
2448
#endif
2449
2450
#ifdef HAVE_STRUCT_STAT_ST_GEN
2451
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2452
#else
2453
#define ST_GEN_IDX ST_FLAGS_IDX
2454
#endif
2455
2456
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2457
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2458
#else
2459
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2460
#endif
2461
2462
#ifdef MS_WINDOWS
2463
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2464
#else
2465
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2466
#endif
2467
2468
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2469
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2470
#else
2471
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2472
#endif
2473
2474
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2475
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2476
#else
2477
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2478
#endif
2479
2480
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2481
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2482
#else
2483
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2484
#endif
2485
2486
static PyStructSequence_Desc stat_result_desc = {
2487
    "os.stat_result", /* name; see issue gh-63408 */
2488
    stat_result__doc__, /* doc */
2489
    stat_result_fields,
2490
    10
2491
};
2492
2493
PyDoc_STRVAR(statvfs_result__doc__,
2494
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2495
This object may be accessed either as a tuple of\n\
2496
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2497
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2498
\n\
2499
See os.statvfs for more information.");
2500
2501
static PyStructSequence_Field statvfs_result_fields[] = {
2502
    {"f_bsize",  },
2503
    {"f_frsize", },
2504
    {"f_blocks", },
2505
    {"f_bfree",  },
2506
    {"f_bavail", },
2507
    {"f_files",  },
2508
    {"f_ffree",  },
2509
    {"f_favail", },
2510
    {"f_flag",   },
2511
    {"f_namemax",},
2512
    {"f_fsid",   },
2513
    {0}
2514
};
2515
2516
static PyStructSequence_Desc statvfs_result_desc = {
2517
    "os.statvfs_result", /* name; see issue gh-63408 */
2518
    statvfs_result__doc__, /* doc */
2519
    statvfs_result_fields,
2520
    10
2521
};
2522
2523
#if defined(HAVE_WAITID)
2524
PyDoc_STRVAR(waitid_result__doc__,
2525
"waitid_result: Result from waitid.\n\n\
2526
This object may be accessed either as a tuple of\n\
2527
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2528
or via the attributes si_pid, si_uid, and so on.\n\
2529
\n\
2530
See os.waitid for more information.");
2531
2532
static PyStructSequence_Field waitid_result_fields[] = {
2533
    {"si_pid",  },
2534
    {"si_uid", },
2535
    {"si_signo", },
2536
    {"si_status",  },
2537
    {"si_code", },
2538
    {0}
2539
};
2540
2541
static PyStructSequence_Desc waitid_result_desc = {
2542
    MODNAME ".waitid_result", /* name */
2543
    waitid_result__doc__, /* doc */
2544
    waitid_result_fields,
2545
    5
2546
};
2547
#endif
2548
2549
static PyObject *
2550
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2551
0
{
2552
0
    PyStructSequence *result;
2553
0
    int i;
2554
2555
    // ht_module doesn't get set in PyStructSequence_NewType(),
2556
    // so we can't use PyType_GetModule().
2557
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2558
0
    if (mod == NULL) {
2559
0
        return NULL;
2560
0
    }
2561
0
    _posixstate *state = get_posix_state(mod);
2562
0
    Py_DECREF(mod);
2563
0
    if (state == NULL) {
2564
0
        return NULL;
2565
0
    }
2566
0
#define structseq_new state->statresult_new_orig
2567
2568
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2569
0
    if (!result)
2570
0
        return NULL;
2571
    /* If we have been initialized from a tuple,
2572
       st_?time might be set to None. Initialize it
2573
       from the int slots.  */
2574
0
    for (i = 7; i <= 9; i++) {
2575
0
        if (result->ob_item[i+3] == Py_None) {
2576
0
            Py_DECREF(Py_None);
2577
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2578
0
        }
2579
0
    }
2580
0
    return (PyObject*)result;
2581
0
}
2582
2583
static int
2584
_posix_clear(PyObject *module)
2585
0
{
2586
0
    _posixstate *state = get_posix_state(module);
2587
0
    Py_CLEAR(state->billion);
2588
0
    Py_CLEAR(state->DirEntryType);
2589
0
    Py_CLEAR(state->ScandirIteratorType);
2590
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2591
0
    Py_CLEAR(state->SchedParamType);
2592
0
#endif
2593
0
    Py_CLEAR(state->StatResultType);
2594
0
#ifdef HAVE_STATX
2595
0
    Py_CLEAR(state->StatxResultType);
2596
0
#endif
2597
0
    Py_CLEAR(state->StatVFSResultType);
2598
0
    Py_CLEAR(state->TerminalSizeType);
2599
0
    Py_CLEAR(state->TimesResultType);
2600
0
    Py_CLEAR(state->UnameResultType);
2601
0
#if defined(HAVE_WAITID)
2602
0
    Py_CLEAR(state->WaitidResultType);
2603
0
#endif
2604
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2605
0
    Py_CLEAR(state->struct_rusage);
2606
0
#endif
2607
0
    Py_CLEAR(state->st_mode);
2608
0
    return 0;
2609
0
}
2610
2611
static int
2612
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2613
1.37k
{
2614
1.37k
    _posixstate *state = get_posix_state(module);
2615
1.37k
    Py_VISIT(state->billion);
2616
1.37k
    Py_VISIT(state->DirEntryType);
2617
1.37k
    Py_VISIT(state->ScandirIteratorType);
2618
1.37k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2619
1.37k
    Py_VISIT(state->SchedParamType);
2620
1.37k
#endif
2621
1.37k
    Py_VISIT(state->StatResultType);
2622
1.37k
#ifdef HAVE_STATX
2623
1.37k
    Py_VISIT(state->StatxResultType);
2624
1.37k
#endif
2625
1.37k
    Py_VISIT(state->StatVFSResultType);
2626
1.37k
    Py_VISIT(state->TerminalSizeType);
2627
1.37k
    Py_VISIT(state->TimesResultType);
2628
1.37k
    Py_VISIT(state->UnameResultType);
2629
1.37k
#if defined(HAVE_WAITID)
2630
1.37k
    Py_VISIT(state->WaitidResultType);
2631
1.37k
#endif
2632
1.37k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2633
1.37k
    Py_VISIT(state->struct_rusage);
2634
1.37k
#endif
2635
1.37k
    Py_VISIT(state->st_mode);
2636
1.37k
    return 0;
2637
1.37k
}
2638
2639
static void
2640
_posix_free(void *module)
2641
0
{
2642
0
   _posix_clear((PyObject *)module);
2643
0
}
2644
2645
2646
2.34M
#define SEC_TO_NS (1000000000LL)
2647
static PyObject *
2648
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2649
780k
{
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
780k
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2655
780k
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2656
780k
    }
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
780k
#endif
2681
780k
}
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
780k
{
2687
780k
    assert(!PyErr_Occurred());
2688
780k
    assert(nsec < SEC_TO_NS);
2689
2690
780k
    if (s_index >= 0) {
2691
780k
        PyObject *s = _PyLong_FromTime_t(sec);
2692
780k
        if (s == NULL) {
2693
0
            return -1;
2694
0
        }
2695
780k
        PyStructSequence_SET_ITEM(v, s_index, s);
2696
780k
    }
2697
2698
780k
    if (f_index >= 0) {
2699
780k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2700
780k
        if (float_s == NULL) {
2701
0
            return -1;
2702
0
        }
2703
780k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2704
780k
    }
2705
2706
780k
    if (ns_index >= 0) {
2707
780k
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2708
780k
        if (ns_total == NULL) {
2709
0
            return -1;
2710
0
        }
2711
780k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2712
780k
    }
2713
2714
780k
    assert(!PyErr_Occurred());
2715
780k
    return 0;
2716
780k
}
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
260k
{
2751
260k
    assert(!PyErr_Occurred());
2752
2753
260k
    _posixstate *state = get_posix_state(module);
2754
260k
    PyObject *StatResultType = state->StatResultType;
2755
260k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2756
260k
    if (v == NULL) {
2757
0
        return NULL;
2758
0
    }
2759
2760
260k
#define SET_ITEM(pos, expr) \
2761
2.60M
    do { \
2762
2.60M
        PyObject *obj = (expr); \
2763
2.60M
        if (obj == NULL) { \
2764
0
            goto error; \
2765
0
        } \
2766
2.60M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2767
2.60M
    } while (0)
2768
2769
260k
    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
260k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2775
260k
                  "stat.st_ino is larger than unsigned long long");
2776
260k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2777
260k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2778
260k
#endif
2779
260k
    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
260k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2785
260k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2786
260k
#endif
2787
260k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2788
260k
                  "stat.st_size is larger than long long");
2789
260k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2790
2791
    // Set st_atime, st_mtime and st_ctime
2792
260k
    unsigned long ansec, mnsec, cnsec;
2793
260k
#if defined(HAVE_STAT_TV_NSEC)
2794
260k
    ansec = st->st_atim.tv_nsec;
2795
260k
    mnsec = st->st_mtim.tv_nsec;
2796
260k
    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
260k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2809
0
        goto error;
2810
0
    }
2811
260k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2812
0
        goto error;
2813
0
    }
2814
260k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2815
0
        goto error;
2816
0
    }
2817
2818
260k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2819
260k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2820
260k
#endif
2821
260k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2822
260k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2823
260k
#endif
2824
260k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2825
260k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2826
260k
#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
260k
    assert(!PyErr_Occurred());
2862
260k
    return v;
2863
2864
0
error:
2865
0
    Py_DECREF(v);
2866
0
    return NULL;
2867
2868
260k
#undef SET_ITEM
2869
260k
}
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
267k
{
2878
267k
    STRUCT_STAT st;
2879
267k
    int result;
2880
2881
267k
#ifdef HAVE_FSTATAT
2882
267k
    int fstatat_unavailable = 0;
2883
267k
#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
267k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2891
267k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2892
267k
        fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
2893
0
        return NULL;
2894
2895
267k
    Py_BEGIN_ALLOW_THREADS
2896
267k
    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
267k
    else
2906
267k
#if defined(HAVE_LSTAT)
2907
267k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2908
10.8k
        result = LSTAT(path->narrow, &st);
2909
256k
    else
2910
256k
#endif /* HAVE_LSTAT */
2911
256k
#ifdef HAVE_FSTATAT
2912
256k
    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
256k
#endif /* HAVE_FSTATAT */
2922
256k
        result = STAT(path->narrow, &st);
2923
267k
#endif /* MS_WINDOWS */
2924
267k
    Py_END_ALLOW_THREADS
2925
2926
267k
#ifdef HAVE_FSTATAT
2927
267k
    if (fstatat_unavailable) {
2928
0
        argument_unavailable_error("stat", "dir_fd");
2929
0
        return NULL;
2930
0
    }
2931
267k
#endif
2932
2933
267k
    if (result != 0) {
2934
195k
        return path_error(path);
2935
195k
    }
2936
2937
71.5k
    return _pystat_fromstructstat(module, &st);
2938
267k
}
2939
2940
/*[python input]
2941
2942
for s in """
2943
2944
FACCESSAT
2945
FCHMODAT
2946
FCHOWNAT
2947
FSTATAT
2948
LINKAT
2949
MKDIRAT
2950
MKFIFOAT
2951
MKNODAT
2952
OPENAT
2953
READLINKAT
2954
SYMLINKAT
2955
UNLINKAT
2956
2957
""".strip().split():
2958
    s = s.strip()
2959
    print("""
2960
#ifdef HAVE_{s}
2961
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2962
#else
2963
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2964
#endif
2965
""".rstrip().format(s=s))
2966
2967
for s in """
2968
2969
FCHDIR
2970
FCHMOD
2971
FCHOWN
2972
FDOPENDIR
2973
FEXECVE
2974
FPATHCONF
2975
FSTATVFS
2976
FTRUNCATE
2977
2978
""".strip().split():
2979
    s = s.strip()
2980
    print("""
2981
#ifdef HAVE_{s}
2982
    #define PATH_HAVE_{s} 1
2983
#else
2984
    #define PATH_HAVE_{s} 0
2985
#endif
2986
2987
""".rstrip().format(s=s))
2988
[python start generated code]*/
2989
2990
#ifdef HAVE_FACCESSAT
2991
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2992
#else
2993
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2994
#endif
2995
2996
#ifdef HAVE_FCHMODAT
2997
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2998
#else
2999
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
3000
#endif
3001
3002
#ifdef HAVE_FCHOWNAT
3003
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
3004
#else
3005
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
3006
#endif
3007
3008
#ifdef HAVE_FSTATAT
3009
8.93k
    #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
96.6k
    #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
117k
    #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
256k
{
3306
256k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3307
256k
}
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
10.8k
{
3330
10.8k
    int follow_symlinks = 0;
3331
10.8k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3332
10.8k
}
3333
3334
3335
#ifdef HAVE_STATX
3336
typedef struct {
3337
    PyObject_HEAD
3338
    dev_t rdev, dev;
3339
    struct statx stx;
3340
} Py_statx_result;
3341
3342
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3343
3344
#define M(attr, type, offset, doc) \
3345
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3346
#define MM(attr, type, member, doc) \
3347
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3348
#define MX(attr, type, member, doc) \
3349
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3350
3351
static PyMemberDef pystatx_result_members[] = {
3352
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3353
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3354
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3355
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3356
        "Mask of supported bits in stx_attributes"),
3357
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3358
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3359
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3360
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3361
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3362
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3363
    {NULL},
3364
};
3365
3366
#undef MX
3367
#undef MM
3368
#undef M
3369
3370
3371
#define STATX_GET_UINT(ATTR, MASK) \
3372
    static PyObject* \
3373
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3374
0
    { \
3375
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3376
0
        if (!(self->stx.stx_mask & MASK)) { \
3377
0
            Py_RETURN_NONE; \
3378
0
        } \
3379
0
        unsigned long value = self->stx.ATTR; \
3380
0
        return PyLong_FromUnsignedLong(value); \
3381
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_nlink
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_uid
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_gid
3382
3383
STATX_GET_UINT(stx_uid, STATX_UID)
3384
STATX_GET_UINT(stx_gid, STATX_GID)
3385
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3386
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3387
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3388
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3389
#endif
3390
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3391
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3392
#endif
3393
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3394
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3395
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3396
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3397
#endif
3398
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3399
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3400
#endif
3401
3402
3403
static PyObject*
3404
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3405
0
{
3406
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3407
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3408
0
        Py_RETURN_NONE;
3409
0
    }
3410
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3411
0
}
3412
3413
3414
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3415
    static PyObject* \
3416
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3417
0
    { \
3418
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3419
0
        if (!(self->stx.stx_mask & MASK)) { \
3420
0
            Py_RETURN_NONE; \
3421
0
        } \
3422
0
        unsigned long long value = self->stx.ATTR; \
3423
0
        return PyLong_FromUnsignedLongLong(value); \
3424
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_ino
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_size
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_blocks
3425
3426
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3427
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3428
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3429
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3430
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3431
#endif
3432
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3433
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3434
#endif
3435
3436
3437
#define STATX_GET_DOUBLE(ATTR, MASK) \
3438
    static PyObject* \
3439
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3440
0
    { \
3441
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3442
0
        if (!(self->stx.stx_mask & MASK)) { \
3443
0
            Py_RETURN_NONE; \
3444
0
        } \
3445
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3446
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3447
0
        return PyFloat_FromDouble(sec); \
3448
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_atime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_btime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_ctime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_mtime
3449
3450
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3451
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3452
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3453
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3454
3455
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3456
    static PyObject* \
3457
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3458
0
    { \
3459
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3460
0
        if (!(self->stx.stx_mask & MASK)) { \
3461
0
            Py_RETURN_NONE; \
3462
0
        } \
3463
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3464
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3465
0
        assert(state != NULL); \
3466
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3467
0
    }
3468
3469
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3470
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3471
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3472
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3473
3474
#define G(attr, doc) \
3475
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3476
3477
static PyGetSetDef pystatx_result_getset[] = {
3478
    G(stx_mode, "protection bits"),
3479
    G(stx_nlink, "number of hard links"),
3480
    G(stx_uid, "user ID of owner"),
3481
    G(stx_gid, "group ID of owner"),
3482
    G(stx_ino, "inode"),
3483
    G(stx_size, "total size, in bytes"),
3484
    G(stx_blocks, "number of blocks allocated"),
3485
    G(stx_atime, "time of last access"),
3486
    G(stx_atime_ns, "time of last access in nanoseconds"),
3487
    G(stx_btime, "time of creation"),
3488
    G(stx_btime_ns, "time of creation in nanoseconds"),
3489
    G(stx_ctime, "time of last change"),
3490
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3491
    G(stx_mtime, "time of last modification"),
3492
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3493
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3494
    G(stx_mnt_id, "mount ID"),
3495
#endif
3496
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3497
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3498
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3499
#endif
3500
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3501
    G(stx_subvol, "subvolume ID"),
3502
#endif
3503
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3504
    G(stx_atomic_write_unit_min,
3505
      "minimum size for direct I/O with torn-write protection"),
3506
    G(stx_atomic_write_unit_max,
3507
        "maximum size for direct I/O with torn-write protection"),
3508
    G(stx_atomic_write_segments_max,
3509
        "maximum iovecs for direct I/O with torn-write protection"),
3510
#endif
3511
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3512
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3513
#endif
3514
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3515
    G(stx_atomic_write_unit_max_opt,
3516
        "maximum optimized size for direct I/O with torn-write protection"),
3517
#endif
3518
    {NULL},
3519
};
3520
3521
#undef G
3522
3523
static PyObject *
3524
pystatx_result_repr(PyObject *op)
3525
0
{
3526
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3527
0
    if (writer == NULL) {
3528
0
        return NULL;
3529
0
    }
3530
0
#define WRITE_ASCII(s) \
3531
0
    do { \
3532
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3533
0
            goto error; \
3534
0
        } \
3535
0
    } while (0)
3536
3537
0
    WRITE_ASCII("os.statx_result(");
3538
3539
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3540
0
        if (i > 0) {
3541
0
            WRITE_ASCII(", ");
3542
0
        }
3543
3544
0
        PyMemberDef *d = &pystatx_result_members[i];
3545
0
        WRITE_ASCII(d->name);
3546
0
        WRITE_ASCII("=");
3547
3548
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3549
0
        if (o == NULL) {
3550
0
            goto error;
3551
0
        }
3552
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3553
0
            Py_DECREF(o);
3554
0
            goto error;
3555
0
        }
3556
0
        Py_DECREF(o);
3557
0
    }
3558
3559
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3560
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3561
0
        PyObject *o = d->get(op, d->closure);
3562
0
        if (o == NULL) {
3563
0
            goto error;
3564
0
        }
3565
0
        if (o == Py_None) {
3566
0
            continue;
3567
0
        }
3568
3569
0
        WRITE_ASCII(", ");
3570
0
        WRITE_ASCII(d->name);
3571
0
        WRITE_ASCII("=");
3572
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3573
0
            Py_DECREF(o);
3574
0
            goto error;
3575
0
        }
3576
0
        Py_DECREF(o);
3577
0
    }
3578
3579
0
    WRITE_ASCII(")");
3580
0
    return PyUnicodeWriter_Finish(writer);
3581
0
#undef WRITE_ASCII
3582
3583
0
error:
3584
0
    PyUnicodeWriter_Discard(writer);
3585
0
    return NULL;
3586
0
}
3587
3588
static int
3589
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3590
0
{
3591
0
    Py_VISIT(Py_TYPE(self));
3592
0
    return 0;
3593
0
}
3594
3595
static void
3596
pystatx_result_dealloc(PyObject *op)
3597
0
{
3598
0
    Py_statx_result *self = (Py_statx_result *) op;
3599
0
    PyTypeObject *tp = Py_TYPE(self);
3600
0
    PyObject_GC_UnTrack(self);
3601
0
    tp->tp_free(self);
3602
0
    Py_DECREF(tp);
3603
0
}
3604
3605
static PyType_Slot pystatx_result_slots[] = {
3606
    {Py_tp_repr, pystatx_result_repr},
3607
    {Py_tp_traverse, pystatx_result_traverse},
3608
    {Py_tp_dealloc, pystatx_result_dealloc},
3609
    {Py_tp_members, pystatx_result_members},
3610
    {Py_tp_getset, pystatx_result_getset},
3611
    {0, NULL},
3612
};
3613
3614
static PyType_Spec pystatx_result_spec = {
3615
    .name = "os.statx_result",
3616
    .basicsize = sizeof(Py_statx_result),
3617
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3618
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3619
    .slots = pystatx_result_slots,
3620
};
3621
3622
/*[clinic input]
3623
3624
os.statx
3625
3626
    path : path_t(allow_fd=True)
3627
        Path to be examined; can be string, bytes, a path-like object or
3628
        open-file-descriptor int.
3629
3630
    mask: unsigned_int(bitwise=True)
3631
        A bitmask of STATX_* constants defining the requested information.
3632
3633
    *
3634
3635
    flags: int = 0
3636
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3637
3638
    dir_fd : dir_fd = None
3639
        If not None, it should be a file descriptor open to a directory,
3640
        and path should be a relative string; path will then be relative to
3641
        that directory.
3642
3643
    follow_symlinks: bool = True
3644
        If False, and the last element of the path is a symbolic link,
3645
        statx will examine the symbolic link itself instead of the file
3646
        the link points to.
3647
3648
Perform a statx system call on the given path.
3649
3650
It's an error to use dir_fd or follow_symlinks when specifying path as
3651
  an open file descriptor.
3652
3653
[clinic start generated code]*/
3654
3655
static PyObject *
3656
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3657
              int dir_fd, int follow_symlinks)
3658
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3659
0
{
3660
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3661
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3662
0
        fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) {
3663
0
        return NULL;
3664
0
    }
3665
3666
    /* reject flags covered by kwargs, but allow unknown flags that may be
3667
       future AT_STATX_* extensions */
3668
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3669
0
        PyErr_Format(PyExc_ValueError,
3670
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3671
0
        return NULL;
3672
0
    }
3673
0
    if (flags & AT_EMPTY_PATH) {
3674
0
        PyErr_Format(PyExc_ValueError,
3675
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3676
0
        return NULL;
3677
0
    }
3678
3679
    /* Future bits may refer to members beyond the current size of struct
3680
       statx, so we need to mask them off to prevent memory corruption. */
3681
0
    mask &= _Py_STATX_KNOWN;
3682
3683
0
    _posixstate *state = get_posix_state(module);
3684
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3685
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3686
0
    if (v == NULL) {
3687
0
        return NULL;
3688
0
    }
3689
3690
0
    int result;
3691
0
    Py_BEGIN_ALLOW_THREADS
3692
0
    if (path->is_fd) {
3693
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3694
0
    }
3695
0
    else {
3696
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3697
0
    }
3698
0
    Py_END_ALLOW_THREADS
3699
3700
0
    if (result != 0) {
3701
0
        Py_DECREF(v);
3702
0
        return path_error(path);
3703
0
    }
3704
3705
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3706
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3707
3708
0
    assert(!PyErr_Occurred());
3709
0
    return (PyObject *)v;
3710
0
}
3711
#endif /* HAVE_STATX */
3712
3713
3714
/*[clinic input]
3715
os.access -> bool
3716
3717
    path: path_t
3718
        Path to be tested; can be string, bytes, or a path-like object.
3719
3720
    mode: int
3721
        Operating-system mode bitfield.  Can be F_OK to test existence,
3722
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3723
3724
    *
3725
3726
    dir_fd : dir_fd(requires='faccessat') = None
3727
        If not None, it should be a file descriptor open to a directory,
3728
        and path should be relative; path will then be relative to that
3729
        directory.
3730
3731
    effective_ids: bool = False
3732
        If True, access will use the effective uid/gid instead of
3733
        the real uid/gid.
3734
3735
    follow_symlinks: bool = True
3736
        If False, and the last element of the path is a symbolic link,
3737
        access will examine the symbolic link itself instead of the file
3738
        the link points to.
3739
3740
Use the real uid/gid to test for access to a path.
3741
3742
{parameters}
3743
dir_fd, effective_ids, and follow_symlinks may not be implemented
3744
  on your platform.  If they are unavailable, using them will raise a
3745
  NotImplementedError.
3746
3747
Note that most operations will use the effective uid/gid, therefore this
3748
  routine can be used in a suid/sgid environment to test if the invoking
3749
  user has the specified access to the path.
3750
3751
[clinic start generated code]*/
3752
3753
static int
3754
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3755
               int effective_ids, int follow_symlinks)
3756
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3757
0
{
3758
0
    int return_value;
3759
3760
#ifdef MS_WINDOWS
3761
    DWORD attr;
3762
#else
3763
0
    int result;
3764
0
#endif
3765
3766
0
#ifdef HAVE_FACCESSAT
3767
0
    int faccessat_unavailable = 0;
3768
0
#endif
3769
3770
#ifndef HAVE_FACCESSAT
3771
    if (follow_symlinks_specified("access", follow_symlinks))
3772
        return -1;
3773
3774
    if (effective_ids) {
3775
        argument_unavailable_error("access", "effective_ids");
3776
        return -1;
3777
    }
3778
#endif
3779
3780
#ifdef MS_WINDOWS
3781
    Py_BEGIN_ALLOW_THREADS
3782
    attr = GetFileAttributesW(path->wide);
3783
    Py_END_ALLOW_THREADS
3784
3785
    /*
3786
     * Access is possible if
3787
     *   * we didn't get a -1, and
3788
     *     * write access wasn't requested,
3789
     *     * or the file isn't read-only,
3790
     *     * or it's a directory.
3791
     * (Directories cannot be read-only on Windows.)
3792
    */
3793
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3794
            (!(mode & 2) ||
3795
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3796
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3797
#else
3798
3799
0
    Py_BEGIN_ALLOW_THREADS
3800
0
#ifdef HAVE_FACCESSAT
3801
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3802
0
        effective_ids ||
3803
0
        !follow_symlinks) {
3804
3805
0
        if (HAVE_FACCESSAT_RUNTIME) {
3806
0
            int flags = 0;
3807
0
            if (!follow_symlinks)
3808
0
                flags |= AT_SYMLINK_NOFOLLOW;
3809
0
            if (effective_ids)
3810
0
                flags |= AT_EACCESS;
3811
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3812
0
        } else {
3813
0
            faccessat_unavailable = 1;
3814
0
        }
3815
0
    }
3816
0
    else
3817
0
#endif
3818
0
        result = access(path->narrow, mode);
3819
0
    Py_END_ALLOW_THREADS
3820
3821
0
#ifdef HAVE_FACCESSAT
3822
0
    if (faccessat_unavailable) {
3823
0
        if (dir_fd != DEFAULT_DIR_FD) {
3824
0
            argument_unavailable_error("access", "dir_fd");
3825
0
            return -1;
3826
0
        }
3827
0
        if (follow_symlinks_specified("access", follow_symlinks))
3828
0
            return -1;
3829
3830
0
        if (effective_ids) {
3831
0
            argument_unavailable_error("access", "effective_ids");
3832
0
            return -1;
3833
0
        }
3834
        /* should be unreachable */
3835
0
        return -1;
3836
0
    }
3837
0
#endif
3838
0
    return_value = !result;
3839
0
#endif
3840
3841
0
    return return_value;
3842
0
}
3843
3844
#ifndef F_OK
3845
#define F_OK 0
3846
#endif
3847
#ifndef R_OK
3848
#define R_OK 4
3849
#endif
3850
#ifndef W_OK
3851
#define W_OK 2
3852
#endif
3853
#ifndef X_OK
3854
#define X_OK 1
3855
#endif
3856
3857
3858
#ifdef HAVE_TTYNAME_R
3859
/*[clinic input]
3860
os.ttyname
3861
3862
    fd: int
3863
        Integer file descriptor handle.
3864
3865
    /
3866
3867
Return the name of the terminal device connected to 'fd'.
3868
[clinic start generated code]*/
3869
3870
static PyObject *
3871
os_ttyname_impl(PyObject *module, int fd)
3872
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3873
0
{
3874
3875
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3876
0
    if (size == -1) {
3877
0
        return posix_error();
3878
0
    }
3879
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3880
0
    if (buffer == NULL) {
3881
0
        return PyErr_NoMemory();
3882
0
    }
3883
0
    int ret = ttyname_r(fd, buffer, size);
3884
0
    if (ret != 0) {
3885
0
        PyMem_RawFree(buffer);
3886
0
        errno = ret;
3887
0
        return posix_error();
3888
0
    }
3889
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3890
0
    PyMem_RawFree(buffer);
3891
0
    return res;
3892
0
}
3893
#endif
3894
3895
#ifdef HAVE_CTERMID
3896
/*[clinic input]
3897
os.ctermid
3898
3899
Return the name of the controlling terminal for this process.
3900
[clinic start generated code]*/
3901
3902
static PyObject *
3903
os_ctermid_impl(PyObject *module)
3904
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3905
0
{
3906
0
    char *ret;
3907
0
    char buffer[L_ctermid];
3908
3909
#ifdef USE_CTERMID_R
3910
    ret = ctermid_r(buffer);
3911
#else
3912
0
    ret = ctermid(buffer);
3913
0
#endif
3914
0
    if (ret == NULL)
3915
0
        return posix_error();
3916
0
    return PyUnicode_DecodeFSDefault(buffer);
3917
0
}
3918
#endif /* HAVE_CTERMID */
3919
3920
3921
/*[clinic input]
3922
os.chdir
3923
3924
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3925
3926
Change the current working directory to the specified path.
3927
3928
path may always be specified as a string.  On some platforms, path may
3929
also be specified as an open file descriptor.  If this functionality is
3930
unavailable, using it raises an exception.
3931
[clinic start generated code]*/
3932
3933
static PyObject *
3934
os_chdir_impl(PyObject *module, path_t *path)
3935
/*[clinic end generated code: output=3be6400eee26eaae input=64673c342e4369f1]*/
3936
0
{
3937
0
    int result;
3938
3939
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3940
0
        return NULL;
3941
0
    }
3942
3943
0
    Py_BEGIN_ALLOW_THREADS
3944
#ifdef MS_WINDOWS
3945
    /* on unix, success = 0, on windows, success = !0 */
3946
    result = !win32_wchdir(path->wide);
3947
#else
3948
0
#ifdef HAVE_FCHDIR
3949
0
    if (path->is_fd)
3950
0
        result = fchdir(path->fd);
3951
0
    else
3952
0
#endif
3953
0
        result = chdir(path->narrow);
3954
0
#endif
3955
0
    Py_END_ALLOW_THREADS
3956
3957
0
    if (result) {
3958
0
        return path_error(path);
3959
0
    }
3960
3961
0
    Py_RETURN_NONE;
3962
0
}
3963
3964
3965
#ifdef HAVE_FCHDIR
3966
/*[clinic input]
3967
os.fchdir
3968
3969
    fd: fildes
3970
3971
Change to the directory of the given file descriptor.
3972
3973
fd must be opened on a directory, not a file.
3974
Equivalent to os.chdir(fd).
3975
3976
[clinic start generated code]*/
3977
3978
static PyObject *
3979
os_fchdir_impl(PyObject *module, int fd)
3980
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3981
0
{
3982
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3983
0
        return NULL;
3984
0
    }
3985
0
    return posix_fildes_fd(fd, fchdir);
3986
0
}
3987
#endif /* HAVE_FCHDIR */
3988
3989
#ifdef MS_WINDOWS
3990
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3991
#else
3992
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3993
#endif
3994
3995
#ifdef MS_WINDOWS
3996
static int
3997
win32_lchmod(LPCWSTR path, int mode)
3998
{
3999
    DWORD attr = GetFileAttributesW(path);
4000
    if (attr == INVALID_FILE_ATTRIBUTES) {
4001
        return 0;
4002
    }
4003
    if (mode & _S_IWRITE) {
4004
        attr &= ~FILE_ATTRIBUTE_READONLY;
4005
    }
4006
    else {
4007
        attr |= FILE_ATTRIBUTE_READONLY;
4008
    }
4009
    return SetFileAttributesW(path, attr);
4010
}
4011
4012
static int
4013
win32_hchmod(HANDLE hfile, int mode)
4014
{
4015
    FILE_BASIC_INFO info;
4016
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4017
                                      &info, sizeof(info)))
4018
    {
4019
        return 0;
4020
    }
4021
    if (mode & _S_IWRITE) {
4022
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4023
    }
4024
    else {
4025
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4026
    }
4027
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4028
                                      &info, sizeof(info));
4029
}
4030
4031
static int
4032
win32_fchmod(int fd, int mode)
4033
{
4034
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4035
    if (hfile == INVALID_HANDLE_VALUE) {
4036
        SetLastError(ERROR_INVALID_HANDLE);
4037
        return 0;
4038
    }
4039
    return win32_hchmod(hfile, mode);
4040
}
4041
4042
#endif /* MS_WINDOWS */
4043
4044
/*[clinic input]
4045
os.chmod
4046
4047
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4048
        Path to be modified.  May always be specified as a str, bytes, or
4049
        a path-like object.  On some platforms, path may also be specified
4050
        as an open file descriptor.  If this functionality is unavailable,
4051
        using it raises an exception.
4052
4053
    mode: int
4054
        Operating-system mode bitfield.
4055
        Be careful when using number literals for *mode*. The conventional
4056
        UNIX notation for numeric modes uses an octal base, which needs to
4057
        be indicated with a ``0o`` prefix in Python.
4058
4059
    *
4060
4061
    dir_fd : dir_fd(requires='fchmodat') = None
4062
        If not None, it should be a file descriptor open to a directory,
4063
        and path should be relative; path will then be relative to that
4064
        directory.
4065
4066
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4067
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4068
        If False, and the last element of the path is a symbolic link,
4069
        chmod will modify the symbolic link itself instead of the file
4070
        the link points to.
4071
4072
Change the access permissions of a file.
4073
4074
It is an error to use dir_fd or follow_symlinks when specifying path as
4075
  an open file descriptor.
4076
dir_fd and follow_symlinks may not be implemented on your platform.
4077
  If they are unavailable, using them will raise a NotImplementedError.
4078
4079
[clinic start generated code]*/
4080
4081
static PyObject *
4082
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4083
              int follow_symlinks)
4084
/*[clinic end generated code: output=5cf6a94915cc7bff input=7b6e2eeadd8bf199]*/
4085
0
{
4086
0
    int result;
4087
4088
0
#ifdef HAVE_FCHMODAT
4089
0
    int fchmodat_nofollow_unsupported = 0;
4090
0
    int fchmodat_unsupported = 0;
4091
0
#endif
4092
4093
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4094
    if (follow_symlinks_specified("chmod", follow_symlinks))
4095
        return NULL;
4096
#endif
4097
4098
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4099
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4100
0
        return NULL;
4101
0
    }
4102
4103
#ifdef MS_WINDOWS
4104
    result = 0;
4105
    Py_BEGIN_ALLOW_THREADS
4106
    if (path->is_fd) {
4107
        result = win32_fchmod(path->fd, mode);
4108
    }
4109
    else if (follow_symlinks) {
4110
        HANDLE hfile = CreateFileW(path->wide,
4111
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4112
                                   0, NULL,
4113
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4114
        if (hfile != INVALID_HANDLE_VALUE) {
4115
            result = win32_hchmod(hfile, mode);
4116
            (void)CloseHandle(hfile);
4117
        }
4118
    }
4119
    else {
4120
        result = win32_lchmod(path->wide, mode);
4121
    }
4122
    Py_END_ALLOW_THREADS
4123
    if (!result) {
4124
        return path_error(path);
4125
    }
4126
#else /* MS_WINDOWS */
4127
0
    Py_BEGIN_ALLOW_THREADS
4128
0
#ifdef HAVE_FCHMOD
4129
0
    if (path->is_fd) {
4130
0
        result = fchmod(path->fd, mode);
4131
0
    }
4132
0
    else
4133
0
#endif /* HAVE_CHMOD */
4134
#ifdef HAVE_LCHMOD
4135
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4136
        result = lchmod(path->narrow, mode);
4137
    else
4138
#endif /* HAVE_LCHMOD */
4139
0
#ifdef HAVE_FCHMODAT
4140
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4141
0
        if (HAVE_FCHMODAT_RUNTIME) {
4142
            /*
4143
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4144
             * The documentation specifically shows how to use it,
4145
             * and then says it isn't implemented yet.
4146
             * (true on linux with glibc 2.15, and openindiana 3.x)
4147
             *
4148
             * Once it is supported, os.chmod will automatically
4149
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4150
             * Until then, we need to be careful what exception we raise.
4151
             */
4152
0
            result = fchmodat(dir_fd, path->narrow, mode,
4153
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4154
            /*
4155
             * But wait!  We can't throw the exception without allowing threads,
4156
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4157
             */
4158
0
            fchmodat_nofollow_unsupported =
4159
0
                             result &&
4160
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4161
0
                             !follow_symlinks;
4162
0
        } else {
4163
0
            fchmodat_unsupported = 1;
4164
0
            fchmodat_nofollow_unsupported = 1;
4165
4166
0
            result = -1;
4167
0
        }
4168
0
    }
4169
0
    else
4170
0
#endif /* HAVE_FHCMODAT */
4171
0
    {
4172
0
#ifdef HAVE_CHMOD
4173
0
        result = chmod(path->narrow, mode);
4174
#elif defined(__wasi__)
4175
        // WASI SDK 15.0 does not support chmod.
4176
        // Ignore missing syscall for now.
4177
        result = 0;
4178
#else
4179
        result = -1;
4180
        errno = ENOSYS;
4181
#endif
4182
0
    }
4183
0
    Py_END_ALLOW_THREADS
4184
4185
0
    if (result) {
4186
0
#ifdef HAVE_FCHMODAT
4187
0
        if (fchmodat_unsupported) {
4188
0
            if (dir_fd != DEFAULT_DIR_FD) {
4189
0
                argument_unavailable_error("chmod", "dir_fd");
4190
0
                return NULL;
4191
0
            }
4192
0
        }
4193
4194
0
        if (fchmodat_nofollow_unsupported) {
4195
0
            if (dir_fd != DEFAULT_DIR_FD)
4196
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4197
0
                                                   dir_fd, follow_symlinks);
4198
0
            else
4199
0
                follow_symlinks_specified("chmod", follow_symlinks);
4200
0
            return NULL;
4201
0
        }
4202
0
        else
4203
0
#endif /* HAVE_FCHMODAT */
4204
0
        return path_error(path);
4205
0
    }
4206
0
#endif /* MS_WINDOWS */
4207
4208
0
    Py_RETURN_NONE;
4209
0
}
4210
4211
4212
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4213
/*[clinic input]
4214
os.fchmod
4215
4216
    fd: int
4217
        The file descriptor of the file to be modified.
4218
    mode: int
4219
        Operating-system mode bitfield.
4220
        Be careful when using number literals for *mode*.  The conventional
4221
        UNIX notation for numeric modes uses an octal base, which needs to
4222
        be indicated with a ``0o`` prefix in Python.
4223
4224
Change the access permissions of the file given by file descriptor fd.
4225
4226
Equivalent to os.chmod(fd, mode).
4227
[clinic start generated code]*/
4228
4229
static PyObject *
4230
os_fchmod_impl(PyObject *module, int fd, int mode)
4231
/*[clinic end generated code: output=afd9bc05b4e426b3 input=d24331f9fdc17f49]*/
4232
0
{
4233
0
    int res;
4234
4235
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4236
0
        return NULL;
4237
0
    }
4238
4239
#ifdef MS_WINDOWS
4240
    res = 0;
4241
    Py_BEGIN_ALLOW_THREADS
4242
    res = win32_fchmod(fd, mode);
4243
    Py_END_ALLOW_THREADS
4244
    if (!res) {
4245
        return PyErr_SetFromWindowsErr(0);
4246
    }
4247
#else /* MS_WINDOWS */
4248
0
    int async_err = 0;
4249
0
    do {
4250
0
        Py_BEGIN_ALLOW_THREADS
4251
0
        res = fchmod(fd, mode);
4252
0
        Py_END_ALLOW_THREADS
4253
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4254
0
    if (res != 0)
4255
0
        return (!async_err) ? posix_error() : NULL;
4256
0
#endif /* MS_WINDOWS */
4257
4258
0
    Py_RETURN_NONE;
4259
0
}
4260
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4261
4262
4263
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4264
/*[clinic input]
4265
@permit_long_summary
4266
os.lchmod
4267
4268
    path: path_t
4269
    mode: int
4270
4271
Change the access permissions of a file, without following symbolic links.
4272
4273
If path is a symlink, this affects the link itself rather than the
4274
target.  Equivalent to chmod(path, mode, follow_symlinks=False).
4275
[clinic start generated code]*/
4276
4277
static PyObject *
4278
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4279
/*[clinic end generated code: output=082344022b51a1d5 input=13110fb62911b015]*/
4280
{
4281
    int res;
4282
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4283
        return NULL;
4284
    }
4285
#ifdef MS_WINDOWS
4286
    Py_BEGIN_ALLOW_THREADS
4287
    res = win32_lchmod(path->wide, mode);
4288
    Py_END_ALLOW_THREADS
4289
    if (!res) {
4290
        path_error(path);
4291
        return NULL;
4292
    }
4293
#else /* MS_WINDOWS */
4294
    Py_BEGIN_ALLOW_THREADS
4295
    res = lchmod(path->narrow, mode);
4296
    Py_END_ALLOW_THREADS
4297
    if (res < 0) {
4298
        path_error(path);
4299
        return NULL;
4300
    }
4301
#endif /* MS_WINDOWS */
4302
    Py_RETURN_NONE;
4303
}
4304
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4305
4306
4307
#ifdef HAVE_CHFLAGS
4308
/*[clinic input]
4309
os.chflags
4310
4311
    path: path_t
4312
    flags: unsigned_long(bitwise=True)
4313
    follow_symlinks: bool=True
4314
4315
Set file flags.
4316
4317
If follow_symlinks is False, and the last element of the path is
4318
a symbolic link, chflags() will change flags on the symbolic link itself
4319
instead of the file the link points to.
4320
follow_symlinks may not be implemented on your platform.  If it is
4321
unavailable, using it will raise a NotImplementedError.
4322
4323
[clinic start generated code]*/
4324
4325
static PyObject *
4326
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4327
                int follow_symlinks)
4328
/*[clinic end generated code: output=85571c6737661ce9 input=31391927707be1de]*/
4329
{
4330
    int result;
4331
4332
#ifndef HAVE_LCHFLAGS
4333
    if (follow_symlinks_specified("chflags", follow_symlinks))
4334
        return NULL;
4335
#endif
4336
4337
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4338
        return NULL;
4339
    }
4340
4341
    Py_BEGIN_ALLOW_THREADS
4342
#ifdef HAVE_LCHFLAGS
4343
    if (!follow_symlinks)
4344
        result = lchflags(path->narrow, flags);
4345
    else
4346
#endif
4347
        result = chflags(path->narrow, flags);
4348
    Py_END_ALLOW_THREADS
4349
4350
    if (result)
4351
        return path_error(path);
4352
4353
    Py_RETURN_NONE;
4354
}
4355
#endif /* HAVE_CHFLAGS */
4356
4357
4358
#ifdef HAVE_LCHFLAGS
4359
/*[clinic input]
4360
os.lchflags
4361
4362
    path: path_t
4363
    flags: unsigned_long(bitwise=True)
4364
4365
Set file flags.
4366
4367
This function will not follow symbolic links.
4368
Equivalent to chflags(path, flags, follow_symlinks=False).
4369
[clinic start generated code]*/
4370
4371
static PyObject *
4372
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4373
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4374
{
4375
    int res;
4376
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4377
        return NULL;
4378
    }
4379
    Py_BEGIN_ALLOW_THREADS
4380
    res = lchflags(path->narrow, flags);
4381
    Py_END_ALLOW_THREADS
4382
    if (res < 0) {
4383
        return path_error(path);
4384
    }
4385
    Py_RETURN_NONE;
4386
}
4387
#endif /* HAVE_LCHFLAGS */
4388
4389
4390
#ifdef HAVE_CHROOT
4391
/*[clinic input]
4392
os.chroot
4393
    path: path_t
4394
4395
Change root directory to path.
4396
4397
[clinic start generated code]*/
4398
4399
static PyObject *
4400
os_chroot_impl(PyObject *module, path_t *path)
4401
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4402
0
{
4403
0
    int res;
4404
0
    Py_BEGIN_ALLOW_THREADS
4405
0
    res = chroot(path->narrow);
4406
0
    Py_END_ALLOW_THREADS
4407
0
    if (res < 0)
4408
0
        return path_error(path);
4409
0
    Py_RETURN_NONE;
4410
0
}
4411
#endif /* HAVE_CHROOT */
4412
4413
4414
#ifdef HAVE_FSYNC
4415
/*[clinic input]
4416
os.fsync
4417
4418
    fd: fildes
4419
4420
Force write of fd to disk.
4421
[clinic start generated code]*/
4422
4423
static PyObject *
4424
os_fsync_impl(PyObject *module, int fd)
4425
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4426
0
{
4427
0
    return posix_fildes_fd(fd, fsync);
4428
0
}
4429
#endif /* HAVE_FSYNC */
4430
4431
4432
#ifdef HAVE_SYNC
4433
/*[clinic input]
4434
os.sync
4435
4436
Force write of everything to disk.
4437
[clinic start generated code]*/
4438
4439
static PyObject *
4440
os_sync_impl(PyObject *module)
4441
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4442
0
{
4443
0
    Py_BEGIN_ALLOW_THREADS
4444
0
    sync();
4445
0
    Py_END_ALLOW_THREADS
4446
0
    Py_RETURN_NONE;
4447
0
}
4448
#endif /* HAVE_SYNC */
4449
4450
4451
#ifdef HAVE_FDATASYNC
4452
#ifdef __hpux
4453
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4454
#endif
4455
4456
/*[clinic input]
4457
os.fdatasync
4458
4459
    fd: fildes
4460
4461
Force write of fd to disk without forcing update of metadata.
4462
[clinic start generated code]*/
4463
4464
static PyObject *
4465
os_fdatasync_impl(PyObject *module, int fd)
4466
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4467
0
{
4468
0
    return posix_fildes_fd(fd, fdatasync);
4469
0
}
4470
#endif /* HAVE_FDATASYNC */
4471
4472
4473
#ifdef HAVE_CHOWN
4474
/*[clinic input]
4475
os.chown
4476
4477
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4478
        Path to be examined; can be string, bytes, a path-like object, or
4479
        open-file-descriptor int.
4480
4481
    uid: uid_t
4482
4483
    gid: gid_t
4484
4485
    *
4486
4487
    dir_fd: dir_fd(requires='fchownat') = None
4488
        If not None, it should be a file descriptor open to a directory,
4489
        and path should be relative; path will then be relative to that
4490
        directory.
4491
4492
    follow_symlinks: bool = True
4493
        If False, and the last element of the path is a symbolic link,
4494
        stat will examine the symbolic link itself instead of the file
4495
        the link points to.
4496
4497
Change the owner and group id of path to the numeric uid and gid.
4498
4499
path may always be specified as a string.  On some platforms, path may
4500
also be specified as an open file descriptor.  If this functionality is
4501
unavailable, using it raises an exception.
4502
If dir_fd is not None, it should be a file descriptor open to
4503
a directory, and path should be relative; path will then be relative to
4504
that directory.
4505
If follow_symlinks is False, and the last element of the path is
4506
a symbolic link, chown will modify the symbolic link itself instead of
4507
the file the link points to.
4508
It is an error to use dir_fd or follow_symlinks when specifying path as
4509
an open file descriptor.
4510
dir_fd and follow_symlinks may not be implemented on your platform.  If
4511
they are unavailable, using them will raise a NotImplementedError.
4512
4513
[clinic start generated code]*/
4514
4515
static PyObject *
4516
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4517
              int dir_fd, int follow_symlinks)
4518
/*[clinic end generated code: output=4beadab0db5f70cd input=509c91b7a0e72f52]*/
4519
0
{
4520
0
    int result;
4521
4522
0
#if defined(HAVE_FCHOWNAT)
4523
0
    int fchownat_unsupported = 0;
4524
0
#endif
4525
4526
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4527
    if (follow_symlinks_specified("chown", follow_symlinks))
4528
        return NULL;
4529
#endif
4530
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4531
0
        fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
4532
0
        return NULL;
4533
4534
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4535
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4536
0
        return NULL;
4537
0
    }
4538
4539
0
    Py_BEGIN_ALLOW_THREADS
4540
0
#ifdef HAVE_FCHOWN
4541
0
    if (path->is_fd)
4542
0
        result = fchown(path->fd, uid, gid);
4543
0
    else
4544
0
#endif
4545
0
#ifdef HAVE_LCHOWN
4546
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4547
0
        result = lchown(path->narrow, uid, gid);
4548
0
    else
4549
0
#endif
4550
0
#ifdef HAVE_FCHOWNAT
4551
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4552
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4553
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4554
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4555
0
      } else {
4556
0
         fchownat_unsupported = 1;
4557
0
      }
4558
0
    } else
4559
0
#endif
4560
0
        result = chown(path->narrow, uid, gid);
4561
0
    Py_END_ALLOW_THREADS
4562
4563
0
#ifdef HAVE_FCHOWNAT
4564
0
    if (fchownat_unsupported) {
4565
        /* This would be incorrect if the current platform
4566
         * doesn't support lchown.
4567
         */
4568
0
        argument_unavailable_error(NULL, "dir_fd");
4569
0
        return NULL;
4570
0
    }
4571
0
#endif
4572
4573
0
    if (result)
4574
0
        return path_error(path);
4575
4576
0
    Py_RETURN_NONE;
4577
0
}
4578
#endif /* HAVE_CHOWN */
4579
4580
4581
#ifdef HAVE_FCHOWN
4582
/*[clinic input]
4583
os.fchown
4584
4585
    fd: int
4586
    uid: uid_t
4587
    gid: gid_t
4588
4589
Change the owner and group id of the file specified by file descriptor.
4590
4591
Equivalent to os.chown(fd, uid, gid).
4592
4593
[clinic start generated code]*/
4594
4595
static PyObject *
4596
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4597
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4598
0
{
4599
0
    int res;
4600
0
    int async_err = 0;
4601
4602
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4603
0
        return NULL;
4604
0
    }
4605
4606
0
    do {
4607
0
        Py_BEGIN_ALLOW_THREADS
4608
0
        res = fchown(fd, uid, gid);
4609
0
        Py_END_ALLOW_THREADS
4610
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4611
0
    if (res != 0)
4612
0
        return (!async_err) ? posix_error() : NULL;
4613
4614
0
    Py_RETURN_NONE;
4615
0
}
4616
#endif /* HAVE_FCHOWN */
4617
4618
4619
#ifdef HAVE_LCHOWN
4620
/*[clinic input]
4621
os.lchown
4622
4623
    path : path_t
4624
    uid: uid_t
4625
    gid: gid_t
4626
4627
Change the owner and group id of path to the numeric uid and gid.
4628
4629
This function will not follow symbolic links.
4630
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4631
[clinic start generated code]*/
4632
4633
static PyObject *
4634
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4635
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4636
0
{
4637
0
    int res;
4638
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4639
0
        return NULL;
4640
0
    }
4641
0
    Py_BEGIN_ALLOW_THREADS
4642
0
    res = lchown(path->narrow, uid, gid);
4643
0
    Py_END_ALLOW_THREADS
4644
0
    if (res < 0) {
4645
0
        return path_error(path);
4646
0
    }
4647
0
    Py_RETURN_NONE;
4648
0
}
4649
#endif /* HAVE_LCHOWN */
4650
4651
4652
static PyObject *
4653
posix_getcwd(int use_bytes)
4654
6
{
4655
#ifdef MS_WINDOWS
4656
    wchar_t wbuf[MAXPATHLEN];
4657
    wchar_t *wbuf2 = wbuf;
4658
    DWORD len;
4659
4660
    Py_BEGIN_ALLOW_THREADS
4661
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4662
    /* If the buffer is large enough, len does not include the
4663
       terminating \0. If the buffer is too small, len includes
4664
       the space needed for the terminator. */
4665
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4666
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4667
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4668
        }
4669
        else {
4670
            wbuf2 = NULL;
4671
        }
4672
        if (wbuf2) {
4673
            len = GetCurrentDirectoryW(len, wbuf2);
4674
        }
4675
    }
4676
    Py_END_ALLOW_THREADS
4677
4678
    if (!wbuf2) {
4679
        PyErr_NoMemory();
4680
        return NULL;
4681
    }
4682
    if (!len) {
4683
        PyErr_SetFromWindowsErr(0);
4684
        if (wbuf2 != wbuf)
4685
            PyMem_RawFree(wbuf2);
4686
        return NULL;
4687
    }
4688
4689
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4690
    if (wbuf2 != wbuf) {
4691
        PyMem_RawFree(wbuf2);
4692
    }
4693
4694
    if (use_bytes) {
4695
        if (resobj == NULL) {
4696
            return NULL;
4697
        }
4698
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4699
    }
4700
4701
    return resobj;
4702
#else
4703
6
    const size_t chunk = 1024;
4704
4705
6
    char *buf = NULL;
4706
6
    char *cwd = NULL;
4707
6
    size_t buflen = 0;
4708
4709
6
    Py_BEGIN_ALLOW_THREADS
4710
6
    do {
4711
6
        char *newbuf;
4712
6
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4713
6
            buflen += chunk;
4714
6
            newbuf = PyMem_RawRealloc(buf, buflen);
4715
6
        }
4716
0
        else {
4717
0
            newbuf = NULL;
4718
0
        }
4719
6
        if (newbuf == NULL) {
4720
0
            PyMem_RawFree(buf);
4721
0
            buf = NULL;
4722
0
            break;
4723
0
        }
4724
6
        buf = newbuf;
4725
4726
6
        cwd = getcwd(buf, buflen);
4727
6
    } while (cwd == NULL && errno == ERANGE);
4728
6
    Py_END_ALLOW_THREADS
4729
4730
6
    if (buf == NULL) {
4731
0
        return PyErr_NoMemory();
4732
0
    }
4733
6
    if (cwd == NULL) {
4734
0
        posix_error();
4735
0
        PyMem_RawFree(buf);
4736
0
        return NULL;
4737
0
    }
4738
4739
6
    PyObject *obj;
4740
6
    if (use_bytes) {
4741
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4742
0
    }
4743
6
    else {
4744
6
        obj = PyUnicode_DecodeFSDefault(buf);
4745
6
    }
4746
6
#ifdef __linux__
4747
6
    if (buf[0] != '/') {
4748
        /*
4749
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4750
         * relative pathname starting with '(unreachable)'. We detect this
4751
         * and fail with ENOENT, matching newer glibc behaviour.
4752
         */
4753
0
        errno = ENOENT;
4754
0
        path_object_error(obj);
4755
0
        PyMem_RawFree(buf);
4756
0
        return NULL;
4757
0
    }
4758
6
#endif
4759
6
    assert(buf[0] == '/');
4760
6
    PyMem_RawFree(buf);
4761
4762
6
    return obj;
4763
6
#endif   /* !MS_WINDOWS */
4764
6
}
4765
4766
4767
/*[clinic input]
4768
os.getcwd
4769
4770
Return a unicode string representing the current working directory.
4771
[clinic start generated code]*/
4772
4773
static PyObject *
4774
os_getcwd_impl(PyObject *module)
4775
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4776
6
{
4777
6
    return posix_getcwd(0);
4778
6
}
4779
4780
4781
/*[clinic input]
4782
os.getcwdb
4783
4784
Return a bytes string representing the current working directory.
4785
[clinic start generated code]*/
4786
4787
static PyObject *
4788
os_getcwdb_impl(PyObject *module)
4789
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4790
0
{
4791
0
    return posix_getcwd(1);
4792
0
}
4793
4794
4795
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4796
#define HAVE_LINK 1
4797
#endif
4798
4799
#ifdef HAVE_LINK
4800
/*[clinic input]
4801
4802
os.link
4803
4804
    src : path_t
4805
    dst : path_t
4806
    *
4807
    src_dir_fd : dir_fd = None
4808
    dst_dir_fd : dir_fd = None
4809
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4810
4811
Create a hard link to a file.
4812
4813
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4814
descriptor open to a directory, and the respective path string (src or
4815
dst) should be relative; the path will then be relative to that
4816
directory.
4817
If follow_symlinks is False, and the last element of src is a symbolic
4818
link, link will create a link to the symbolic link itself instead of the
4819
file the link points to.
4820
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on
4821
your platform.  If they are unavailable, using them will raise
4822
a NotImplementedError.
4823
[clinic start generated code]*/
4824
4825
static PyObject *
4826
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4827
             int dst_dir_fd, int follow_symlinks)
4828
/*[clinic end generated code: output=7f00f6007fd5269a input=a28e6866fbd20a01]*/
4829
0
{
4830
#ifdef MS_WINDOWS
4831
    BOOL result = FALSE;
4832
#else
4833
0
    int result;
4834
0
#endif
4835
4836
0
#ifdef HAVE_LINKAT
4837
0
    if (HAVE_LINKAT_RUNTIME) {
4838
0
        if (follow_symlinks < 0) {
4839
0
            follow_symlinks = 1;
4840
0
        }
4841
0
    }
4842
0
    else
4843
0
#endif
4844
0
    {
4845
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4846
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4847
0
            return NULL;
4848
0
        }
4849
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4850
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4851
0
#if defined(MS_WINDOWS) || defined(__linux__)
4852
0
        if (follow_symlinks == 1) {
4853
0
            argument_unavailable_error("link", "follow_symlinks=True");
4854
0
            return NULL;
4855
0
        }
4856
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4857
        if (follow_symlinks == 0) {
4858
            argument_unavailable_error("link", "follow_symlinks=False");
4859
            return NULL;
4860
        }
4861
#else
4862
        if (follow_symlinks >= 0) {
4863
            argument_unavailable_error("link", "follow_symlinks");
4864
            return NULL;
4865
        }
4866
#endif
4867
0
    }
4868
4869
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4870
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4871
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4872
0
        return NULL;
4873
0
    }
4874
4875
#ifdef MS_WINDOWS
4876
    Py_BEGIN_ALLOW_THREADS
4877
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4878
    Py_END_ALLOW_THREADS
4879
4880
    if (!result)
4881
        return path_error2(src, dst);
4882
#else
4883
0
    Py_BEGIN_ALLOW_THREADS
4884
0
#ifdef HAVE_LINKAT
4885
0
    if (HAVE_LINKAT_RUNTIME) {
4886
0
        result = linkat(src_dir_fd, src->narrow,
4887
0
            dst_dir_fd, dst->narrow,
4888
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4889
0
    }
4890
0
    else
4891
0
#endif
4892
0
    {
4893
        /* linkat not available */
4894
0
        result = link(src->narrow, dst->narrow);
4895
0
    }
4896
0
    Py_END_ALLOW_THREADS
4897
4898
0
    if (result)
4899
0
        return path_error2(src, dst);
4900
0
#endif /* MS_WINDOWS */
4901
4902
0
    Py_RETURN_NONE;
4903
0
}
4904
#endif
4905
4906
4907
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4908
static PyObject *
4909
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4910
{
4911
    PyObject *v;
4912
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4913
    BOOL result, return_bytes;
4914
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4915
    /* only claim to have space for MAX_PATH */
4916
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4917
    wchar_t *wnamebuf = NULL;
4918
4919
    WIN32_FIND_DATAW wFileData;
4920
    const wchar_t *po_wchars;
4921
4922
    if (!path->wide) { /* Default arg: "." */
4923
        po_wchars = L".";
4924
        len = 1;
4925
        return_bytes = 0;
4926
    } else {
4927
        po_wchars = path->wide;
4928
        len = wcslen(path->wide);
4929
        return_bytes = PyBytes_Check(path->object);
4930
    }
4931
    /* The +5 is so we can append "\\*.*\0" */
4932
    wnamebuf = PyMem_New(wchar_t, len + 5);
4933
    if (!wnamebuf) {
4934
        PyErr_NoMemory();
4935
        goto exit;
4936
    }
4937
    wcscpy(wnamebuf, po_wchars);
4938
    if (len > 0) {
4939
        wchar_t wch = wnamebuf[len-1];
4940
        if (wch != SEP && wch != ALTSEP && wch != L':')
4941
            wnamebuf[len++] = SEP;
4942
        wcscpy(wnamebuf + len, L"*.*");
4943
    }
4944
    if ((list = PyList_New(0)) == NULL) {
4945
        goto exit;
4946
    }
4947
    Py_BEGIN_ALLOW_THREADS
4948
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4949
    Py_END_ALLOW_THREADS
4950
    if (hFindFile == INVALID_HANDLE_VALUE) {
4951
        int error = GetLastError();
4952
        if (error == ERROR_FILE_NOT_FOUND)
4953
            goto exit;
4954
        path_error(path);
4955
        Py_CLEAR(list);
4956
        goto exit;
4957
    }
4958
    do {
4959
        /* Skip over . and .. */
4960
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4961
            wcscmp(wFileData.cFileName, L"..") != 0) {
4962
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4963
                                       wcslen(wFileData.cFileName));
4964
            if (return_bytes && v) {
4965
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4966
            }
4967
            if (v == NULL) {
4968
                Py_CLEAR(list);
4969
                break;
4970
            }
4971
            if (PyList_Append(list, v) != 0) {
4972
                Py_DECREF(v);
4973
                Py_CLEAR(list);
4974
                break;
4975
            }
4976
            Py_DECREF(v);
4977
        }
4978
        Py_BEGIN_ALLOW_THREADS
4979
        result = FindNextFileW(hFindFile, &wFileData);
4980
        Py_END_ALLOW_THREADS
4981
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4982
           it got to the end of the directory. */
4983
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4984
            path_error(path);
4985
            Py_CLEAR(list);
4986
            goto exit;
4987
        }
4988
    } while (result == TRUE);
4989
4990
exit:
4991
    if (hFindFile != INVALID_HANDLE_VALUE) {
4992
        if (FindClose(hFindFile) == FALSE) {
4993
            if (list != NULL) {
4994
                path_error(path);
4995
                Py_CLEAR(list);
4996
            }
4997
        }
4998
    }
4999
    PyMem_Free(wnamebuf);
5000
5001
    return list;
5002
}  /* end of _listdir_windows_no_opendir */
5003
5004
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
5005
5006
static PyObject *
5007
_posix_listdir(path_t *path, PyObject *list)
5008
397
{
5009
397
    PyObject *v;
5010
397
    DIR *dirp = NULL;
5011
397
    struct dirent *ep;
5012
397
    int return_str; /* if false, return bytes */
5013
397
#ifdef HAVE_FDOPENDIR
5014
397
    int fd = -1;
5015
397
#endif
5016
5017
397
    errno = 0;
5018
397
#ifdef HAVE_FDOPENDIR
5019
397
    if (path->is_fd) {
5020
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5021
        /* closedir() closes the FD, so we duplicate it */
5022
0
        fd = _Py_dup(path->fd);
5023
0
        if (fd == -1)
5024
0
            return NULL;
5025
5026
0
        return_str = 1;
5027
5028
0
        Py_BEGIN_ALLOW_THREADS
5029
0
        dirp = fdopendir(fd);
5030
0
        Py_END_ALLOW_THREADS
5031
0
      } else {
5032
0
        PyErr_SetString(PyExc_TypeError,
5033
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5034
0
        return NULL;
5035
0
      }
5036
0
    }
5037
397
    else
5038
397
#endif
5039
397
    {
5040
397
        const char *name;
5041
397
        if (path->narrow) {
5042
397
            name = path->narrow;
5043
            /* only return bytes if they specified a bytes object */
5044
397
            return_str = !PyBytes_Check(path->object);
5045
397
        }
5046
0
        else {
5047
0
            name = ".";
5048
0
            return_str = 1;
5049
0
        }
5050
5051
397
        Py_BEGIN_ALLOW_THREADS
5052
397
        dirp = opendir(name);
5053
397
        Py_END_ALLOW_THREADS
5054
397
    }
5055
5056
397
    if (dirp == NULL) {
5057
4
        path_error(path);
5058
4
        list = NULL;
5059
4
#ifdef HAVE_FDOPENDIR
5060
4
        if (fd != -1) {
5061
0
            Py_BEGIN_ALLOW_THREADS
5062
0
            close(fd);
5063
0
            Py_END_ALLOW_THREADS
5064
0
        }
5065
4
#endif
5066
4
        goto exit;
5067
4
    }
5068
393
    if ((list = PyList_New(0)) == NULL) {
5069
0
        goto exit;
5070
0
    }
5071
19.7k
    for (;;) {
5072
19.7k
        errno = 0;
5073
19.7k
        Py_BEGIN_ALLOW_THREADS
5074
19.7k
        ep = readdir(dirp);
5075
19.7k
        Py_END_ALLOW_THREADS
5076
19.7k
        if (ep == NULL) {
5077
393
            if (errno == 0) {
5078
393
                break;
5079
393
            } else {
5080
0
                path_error(path);
5081
0
                Py_CLEAR(list);
5082
0
                goto exit;
5083
0
            }
5084
393
        }
5085
19.3k
        if (ep->d_name[0] == '.' &&
5086
825
            (NAMLEN(ep) == 1 ||
5087
432
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5088
786
            continue;
5089
18.5k
        if (return_str)
5090
18.5k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5091
0
        else
5092
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5093
18.5k
        if (v == NULL) {
5094
0
            Py_CLEAR(list);
5095
0
            break;
5096
0
        }
5097
18.5k
        if (PyList_Append(list, v) != 0) {
5098
0
            Py_DECREF(v);
5099
0
            Py_CLEAR(list);
5100
0
            break;
5101
0
        }
5102
18.5k
        Py_DECREF(v);
5103
18.5k
    }
5104
5105
397
exit:
5106
397
    if (dirp != NULL) {
5107
393
        Py_BEGIN_ALLOW_THREADS
5108
393
#ifdef HAVE_FDOPENDIR
5109
393
        if (fd > -1)
5110
0
            rewinddir(dirp);
5111
393
#endif
5112
393
        closedir(dirp);
5113
393
        Py_END_ALLOW_THREADS
5114
393
    }
5115
5116
397
    return list;
5117
393
}  /* end of _posix_listdir */
5118
#endif  /* which OS */
5119
5120
5121
/*[clinic input]
5122
os.listdir
5123
5124
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5125
5126
Return a list containing the names of the files in the directory.
5127
5128
path can be specified as either str, bytes, or a path-like object.  If
5129
path is bytes, the filenames returned will also be bytes; in all other
5130
circumstances the filenames returned will be str.
5131
If path is None, uses the path='.'.
5132
On some platforms, path may also be specified as an open file
5133
descriptor; the file descriptor must refer to a directory.  If this
5134
functionality is unavailable, using it raises NotImplementedError.
5135
5136
The list is in arbitrary order.  It does not include the special
5137
entries '.' and '..' even if they are present in the directory.
5138
5139
[clinic start generated code]*/
5140
5141
static PyObject *
5142
os_listdir_impl(PyObject *module, path_t *path)
5143
/*[clinic end generated code: output=293045673fcd1a75 input=4eefe7c6a42ec9b2]*/
5144
397
{
5145
397
    if (PySys_Audit("os.listdir", "O",
5146
397
                    path->object ? path->object : Py_None) < 0) {
5147
0
        return NULL;
5148
0
    }
5149
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5150
    return _listdir_windows_no_opendir(path, NULL);
5151
#else
5152
397
    return _posix_listdir(path, NULL);
5153
397
#endif
5154
397
}
5155
5156
5157
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5158
5159
/*[clinic input]
5160
os.listdrives
5161
5162
Return a list containing the names of drives in the system.
5163
5164
A drive name typically looks like 'C:\\'.
5165
5166
[clinic start generated code]*/
5167
5168
static PyObject *
5169
os_listdrives_impl(PyObject *module)
5170
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5171
{
5172
    /* Number of possible drives is limited, so 256 should always be enough.
5173
       On the day when it is not, listmounts() will have to be used. */
5174
    wchar_t buffer[256];
5175
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5176
    PyObject *result = NULL;
5177
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5178
        return NULL;
5179
    }
5180
5181
    Py_BEGIN_ALLOW_THREADS;
5182
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5183
    Py_END_ALLOW_THREADS;
5184
5185
    if (!buflen) {
5186
        PyErr_SetFromWindowsErr(0);
5187
        return NULL;
5188
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5189
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5190
        return NULL;
5191
    }
5192
5193
    /* buflen includes a null terminator, so remove it */
5194
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5195
    if (str) {
5196
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5197
        if (nullchar) {
5198
            result = PyUnicode_Split(str, nullchar, -1);
5199
            Py_DECREF(nullchar);
5200
        }
5201
        Py_DECREF(str);
5202
    }
5203
    return result;
5204
}
5205
5206
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5207
5208
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5209
5210
/*[clinic input]
5211
os.listvolumes
5212
5213
Return a list containing the volumes in the system.
5214
5215
Volumes are typically represented as a GUID path.
5216
5217
[clinic start generated code]*/
5218
5219
static PyObject *
5220
os_listvolumes_impl(PyObject *module)
5221
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5222
{
5223
    PyObject *result = PyList_New(0);
5224
    HANDLE find = INVALID_HANDLE_VALUE;
5225
    wchar_t buffer[MAX_PATH + 1];
5226
    if (!result) {
5227
        return NULL;
5228
    }
5229
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5230
        Py_DECREF(result);
5231
        return NULL;
5232
    }
5233
5234
    int err = 0;
5235
    Py_BEGIN_ALLOW_THREADS;
5236
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5237
    if (find == INVALID_HANDLE_VALUE) {
5238
        err = GetLastError();
5239
    }
5240
    Py_END_ALLOW_THREADS;
5241
5242
    while (!err) {
5243
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5244
        if (!s || PyList_Append(result, s) < 0) {
5245
            Py_XDECREF(s);
5246
            Py_CLEAR(result);
5247
            break;
5248
        }
5249
        Py_DECREF(s);
5250
5251
        Py_BEGIN_ALLOW_THREADS;
5252
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5253
            err = GetLastError();
5254
        }
5255
        Py_END_ALLOW_THREADS;
5256
    }
5257
5258
    if (find != INVALID_HANDLE_VALUE) {
5259
        Py_BEGIN_ALLOW_THREADS;
5260
        FindVolumeClose(find);
5261
        Py_END_ALLOW_THREADS;
5262
    }
5263
    if (err && err != ERROR_NO_MORE_FILES) {
5264
        PyErr_SetFromWindowsErr(err);
5265
        Py_XDECREF(result);
5266
        result = NULL;
5267
    }
5268
    return result;
5269
}
5270
5271
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5272
5273
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5274
5275
/*[clinic input]
5276
os.listmounts
5277
5278
    volume: path_t
5279
5280
Return a list containing mount points for a particular volume.
5281
5282
'volume' should be a GUID path as returned from os.listvolumes.
5283
5284
[clinic start generated code]*/
5285
5286
static PyObject *
5287
os_listmounts_impl(PyObject *module, path_t *volume)
5288
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5289
{
5290
    wchar_t default_buffer[MAX_PATH + 1];
5291
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5292
    LPWSTR buffer = default_buffer;
5293
    DWORD attributes;
5294
    PyObject *str = NULL;
5295
    PyObject *nullchar = NULL;
5296
    PyObject *result = NULL;
5297
5298
    /* Ensure we have a valid volume path before continuing */
5299
    Py_BEGIN_ALLOW_THREADS
5300
    attributes = GetFileAttributesW(volume->wide);
5301
    Py_END_ALLOW_THREADS
5302
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5303
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5304
    {
5305
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5306
    }
5307
5308
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5309
        return NULL;
5310
    }
5311
5312
    while (1) {
5313
        BOOL success;
5314
        Py_BEGIN_ALLOW_THREADS
5315
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5316
                                                   buflen, &buflen);
5317
        Py_END_ALLOW_THREADS
5318
        if (success) {
5319
            break;
5320
        }
5321
        if (GetLastError() != ERROR_MORE_DATA) {
5322
            PyErr_SetFromWindowsErr(0);
5323
            goto exit;
5324
        }
5325
        if (buffer != default_buffer) {
5326
            PyMem_Free((void *)buffer);
5327
        }
5328
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5329
        if (!buffer) {
5330
            PyErr_NoMemory();
5331
            goto exit;
5332
        }
5333
    }
5334
    if (buflen < 2) {
5335
        result = PyList_New(0);
5336
        goto exit;
5337
    }
5338
    // buflen includes two null terminators, one for the last string
5339
    // and one for the array of strings.
5340
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5341
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5342
    if (str && nullchar) {
5343
        result = PyUnicode_Split(str, nullchar, -1);
5344
    }
5345
exit:
5346
    if (buffer != default_buffer) {
5347
        PyMem_Free(buffer);
5348
    }
5349
    Py_XDECREF(nullchar);
5350
    Py_XDECREF(str);
5351
    return result;
5352
}
5353
5354
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5355
5356
#ifdef MS_WINDOWS
5357
5358
/*[clinic input]
5359
os._path_isdevdrive
5360
5361
    path: path_t
5362
5363
Determines whether the specified path is on a Windows Dev Drive.
5364
5365
[clinic start generated code]*/
5366
5367
static PyObject *
5368
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5369
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5370
{
5371
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5372
    /* This flag will be documented at
5373
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5374
       after release, and will be available in the latest WinSDK.
5375
       We include the flag to avoid a specific version dependency
5376
       on the latest WinSDK. */
5377
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5378
#endif
5379
    int err = 0;
5380
    PyObject *r = NULL;
5381
    wchar_t volume[MAX_PATH];
5382
5383
    Py_BEGIN_ALLOW_THREADS
5384
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5385
        /* invalid path of some kind */
5386
        /* Note that this also includes the case where a volume is mounted
5387
           in a path longer than 260 characters. This is likely to be rare
5388
           and problematic for other reasons, so a (soft) failure in this
5389
           check seems okay. */
5390
        err = GetLastError();
5391
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5392
        /* only care about local dev drives */
5393
        r = Py_False;
5394
    } else {
5395
        HANDLE hVolume = CreateFileW(
5396
            volume,
5397
            FILE_READ_ATTRIBUTES,
5398
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5399
            NULL,
5400
            OPEN_EXISTING,
5401
            FILE_FLAG_BACKUP_SEMANTICS,
5402
            NULL
5403
        );
5404
        if (hVolume == INVALID_HANDLE_VALUE) {
5405
            err = GetLastError();
5406
        } else {
5407
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5408
            volumeState.Version = 1;
5409
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5410
            if (!DeviceIoControl(
5411
                hVolume,
5412
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5413
                &volumeState,
5414
                sizeof(volumeState),
5415
                &volumeState,
5416
                sizeof(volumeState),
5417
                NULL,
5418
                NULL
5419
            )) {
5420
                err = GetLastError();
5421
            }
5422
            CloseHandle(hVolume);
5423
            if (err == ERROR_INVALID_PARAMETER) {
5424
                /* not supported on this platform */
5425
                r = Py_False;
5426
            } else if (!err) {
5427
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5428
                    ? Py_True : Py_False;
5429
            }
5430
        }
5431
    }
5432
    Py_END_ALLOW_THREADS
5433
5434
    if (err) {
5435
        PyErr_SetFromWindowsErr(err);
5436
        return NULL;
5437
    }
5438
5439
    if (r) {
5440
        return Py_NewRef(r);
5441
    }
5442
5443
    return NULL;
5444
}
5445
5446
5447
int
5448
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5449
{
5450
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5451
    DWORD result;
5452
5453
    result = GetFullPathNameW(path,
5454
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5455
                              NULL);
5456
    if (!result) {
5457
        return -1;
5458
    }
5459
5460
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5461
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5462
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5463
        }
5464
        else {
5465
            woutbufp = NULL;
5466
        }
5467
        if (!woutbufp) {
5468
            *abspath_p = NULL;
5469
            return 0;
5470
        }
5471
5472
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5473
        if (!result) {
5474
            PyMem_RawFree(woutbufp);
5475
            return -1;
5476
        }
5477
    }
5478
5479
    if (woutbufp != woutbuf) {
5480
        *abspath_p = woutbufp;
5481
        return 0;
5482
    }
5483
5484
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5485
    return 0;
5486
}
5487
5488
5489
/* A helper function for abspath on win32 */
5490
/*[clinic input]
5491
os._getfullpathname
5492
5493
    path: path_t
5494
    /
5495
5496
[clinic start generated code]*/
5497
5498
static PyObject *
5499
os__getfullpathname_impl(PyObject *module, path_t *path)
5500
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5501
{
5502
    wchar_t *abspath;
5503
5504
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5505
        return win32_error_object("GetFullPathNameW", path->object);
5506
    }
5507
    if (abspath == NULL) {
5508
        return PyErr_NoMemory();
5509
    }
5510
5511
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5512
    PyMem_RawFree(abspath);
5513
    if (str == NULL) {
5514
        return NULL;
5515
    }
5516
    if (PyBytes_Check(path->object)) {
5517
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5518
    }
5519
    return str;
5520
}
5521
5522
5523
/*[clinic input]
5524
os._getfinalpathname
5525
5526
    path: path_t
5527
    /
5528
5529
A helper function for samepath on windows.
5530
[clinic start generated code]*/
5531
5532
static PyObject *
5533
os__getfinalpathname_impl(PyObject *module, path_t *path)
5534
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5535
{
5536
    HANDLE hFile;
5537
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5538
    int buf_size = Py_ARRAY_LENGTH(buf);
5539
    int result_length;
5540
    PyObject *result;
5541
5542
    Py_BEGIN_ALLOW_THREADS
5543
    hFile = CreateFileW(
5544
        path->wide,
5545
        0, /* desired access */
5546
        0, /* share mode */
5547
        NULL, /* security attributes */
5548
        OPEN_EXISTING,
5549
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5550
        FILE_FLAG_BACKUP_SEMANTICS,
5551
        NULL);
5552
    Py_END_ALLOW_THREADS
5553
5554
    if (hFile == INVALID_HANDLE_VALUE) {
5555
        return win32_error_object("CreateFileW", path->object);
5556
    }
5557
5558
    /* We have a good handle to the target, use it to determine the
5559
       target path name. */
5560
    while (1) {
5561
        Py_BEGIN_ALLOW_THREADS
5562
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5563
                                                  buf_size, VOLUME_NAME_DOS);
5564
        Py_END_ALLOW_THREADS
5565
5566
        if (!result_length) {
5567
            result = win32_error_object("GetFinalPathNameByHandleW",
5568
                                         path->object);
5569
            goto cleanup;
5570
        }
5571
5572
        if (result_length < buf_size) {
5573
            break;
5574
        }
5575
5576
        wchar_t *tmp;
5577
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5578
                            result_length * sizeof(*tmp));
5579
        if (!tmp) {
5580
            result = PyErr_NoMemory();
5581
            goto cleanup;
5582
        }
5583
5584
        buf_size = result_length;
5585
        target_path = tmp;
5586
    }
5587
5588
    result = PyUnicode_FromWideChar(target_path, result_length);
5589
    if (result && PyBytes_Check(path->object)) {
5590
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5591
    }
5592
5593
cleanup:
5594
    if (target_path != buf) {
5595
        PyMem_Free(target_path);
5596
    }
5597
    CloseHandle(hFile);
5598
    return result;
5599
}
5600
5601
/*[clinic input]
5602
@permit_long_summary
5603
os._findfirstfile
5604
    path: path_t
5605
    /
5606
A function to get the real file name without accessing the file in Windows.
5607
[clinic start generated code]*/
5608
5609
static PyObject *
5610
os__findfirstfile_impl(PyObject *module, path_t *path)
5611
/*[clinic end generated code: output=106dd3f0779c83dd input=48c319aaa48d05d4]*/
5612
{
5613
    PyObject *result;
5614
    HANDLE hFindFile;
5615
    WIN32_FIND_DATAW wFileData;
5616
    WCHAR *wRealFileName;
5617
5618
    Py_BEGIN_ALLOW_THREADS
5619
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5620
    Py_END_ALLOW_THREADS
5621
5622
    if (hFindFile == INVALID_HANDLE_VALUE) {
5623
        path_error(path);
5624
        return NULL;
5625
    }
5626
5627
    wRealFileName = wFileData.cFileName;
5628
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5629
    FindClose(hFindFile);
5630
    return result;
5631
}
5632
5633
5634
/*[clinic input]
5635
os._getvolumepathname
5636
5637
    path: path_t
5638
5639
A helper function for ismount on Win32.
5640
[clinic start generated code]*/
5641
5642
static PyObject *
5643
os__getvolumepathname_impl(PyObject *module, path_t *path)
5644
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5645
{
5646
    PyObject *result;
5647
    wchar_t *mountpath=NULL;
5648
    size_t buflen;
5649
    BOOL ret;
5650
5651
    /* Volume path should be shorter than entire path */
5652
    buflen = Py_MAX(path->length, MAX_PATH);
5653
5654
    if (buflen > PY_DWORD_MAX) {
5655
        PyErr_SetString(PyExc_OverflowError, "path too long");
5656
        return NULL;
5657
    }
5658
5659
    mountpath = PyMem_New(wchar_t, buflen);
5660
    if (mountpath == NULL)
5661
        return PyErr_NoMemory();
5662
5663
    Py_BEGIN_ALLOW_THREADS
5664
    ret = GetVolumePathNameW(path->wide, mountpath,
5665
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5666
    Py_END_ALLOW_THREADS
5667
5668
    if (!ret) {
5669
        result = win32_error_object("_getvolumepathname", path->object);
5670
        goto exit;
5671
    }
5672
    result = PyUnicode_FromWideChar(mountpath, -1);
5673
    if (PyBytes_Check(path->object))
5674
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5675
5676
exit:
5677
    PyMem_Free(mountpath);
5678
    return result;
5679
}
5680
5681
5682
/*[clinic input]
5683
os._path_splitroot
5684
5685
    path: path_t
5686
    /
5687
5688
Removes everything after the root on Win32.
5689
[clinic start generated code]*/
5690
5691
static PyObject *
5692
os__path_splitroot_impl(PyObject *module, path_t *path)
5693
/*[clinic end generated code: output=ab7f1a88b654581c input=d356de1edb6050a2]*/
5694
{
5695
    wchar_t *buffer;
5696
    wchar_t *end;
5697
    PyObject *result = NULL;
5698
    HRESULT ret;
5699
5700
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5701
    if (!buffer) {
5702
        return NULL;
5703
    }
5704
    wcscpy(buffer, path->wide);
5705
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5706
        *p = L'\\';
5707
    }
5708
5709
    Py_BEGIN_ALLOW_THREADS
5710
    ret = PathCchSkipRoot(buffer, &end);
5711
    Py_END_ALLOW_THREADS
5712
    if (FAILED(ret)) {
5713
        result = Py_BuildValue("sO", "", path->object);
5714
    } else if (end != buffer) {
5715
        size_t rootLen = (size_t)(end - buffer);
5716
        result = Py_BuildValue("NN",
5717
            PyUnicode_FromWideChar(path->wide, rootLen),
5718
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5719
        );
5720
    } else {
5721
        result = Py_BuildValue("Os", path->object, "");
5722
    }
5723
    PyMem_Free(buffer);
5724
5725
    return result;
5726
}
5727
5728
5729
#define PY_IFREG  1 // Regular file
5730
#define PY_IFDIR  2 // Directory
5731
#define PY_IFLNK  4 // Symlink
5732
#define PY_IFMNT  8 // Mount Point (junction)
5733
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5734
#define PY_IFRRP 32 // Regular Reparse Point
5735
5736
static inline BOOL
5737
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5738
{
5739
    switch (testedType) {
5740
    case PY_IFREG:
5741
        return diskDevice && attributes &&
5742
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5743
    case PY_IFDIR:
5744
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5745
    case PY_IFLNK:
5746
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5747
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5748
    case PY_IFMNT:
5749
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5750
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5751
    case PY_IFLRP:
5752
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5753
               IsReparseTagNameSurrogate(reparseTag);
5754
    case PY_IFRRP:
5755
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5756
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5757
    }
5758
5759
    return FALSE;
5760
}
5761
5762
static BOOL
5763
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5764
{
5765
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5766
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5767
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5768
5769
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5770
    if (diskOnly && !diskDevice) {
5771
        return FALSE;
5772
    }
5773
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5774
        FILE_ATTRIBUTE_TAG_INFO info;
5775
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5776
                                            sizeof(info)) &&
5777
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5778
                         testedType);
5779
    }
5780
    FILE_BASIC_INFO info;
5781
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5782
                                        sizeof(info)) &&
5783
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5784
}
5785
5786
static BOOL
5787
_testFileTypeByName(LPCWSTR path, int testedType)
5788
{
5789
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5790
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5791
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5792
5793
    FILE_STAT_BASIC_INFORMATION info;
5794
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5795
                                     sizeof(info)))
5796
    {
5797
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5798
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5799
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5800
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5801
                                diskDevice, testedType);
5802
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5803
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5804
        {
5805
            return result;
5806
        }
5807
    }
5808
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5809
                GetLastError()))
5810
    {
5811
        return FALSE;
5812
    }
5813
5814
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5815
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5816
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5817
    }
5818
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5819
                               OPEN_EXISTING, flags, NULL);
5820
    if (hfile != INVALID_HANDLE_VALUE) {
5821
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5822
        CloseHandle(hfile);
5823
        return result;
5824
    }
5825
5826
    switch (GetLastError()) {
5827
    case ERROR_ACCESS_DENIED:
5828
    case ERROR_SHARING_VIOLATION:
5829
    case ERROR_CANT_ACCESS_FILE:
5830
    case ERROR_INVALID_PARAMETER:
5831
        int rc;
5832
        STRUCT_STAT st;
5833
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5834
            rc = STAT(path, &st);
5835
        }
5836
        else {
5837
            // PY_IFRRP is not generally supported in this case, except for
5838
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5839
            rc = LSTAT(path, &st);
5840
        }
5841
        if (!rc) {
5842
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5843
                             st.st_mode & S_IFREG, testedType);
5844
        }
5845
    }
5846
5847
    return FALSE;
5848
}
5849
5850
5851
static BOOL
5852
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5853
{
5854
    FILE_STAT_BASIC_INFORMATION info;
5855
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5856
                                     sizeof(info)))
5857
    {
5858
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5859
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5860
        {
5861
            return TRUE;
5862
        }
5863
    }
5864
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5865
                    GetLastError()))
5866
    {
5867
        return FALSE;
5868
    }
5869
5870
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5871
    if (!followLinks) {
5872
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5873
    }
5874
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5875
                               OPEN_EXISTING, flags, NULL);
5876
    if (hfile != INVALID_HANDLE_VALUE) {
5877
        if (followLinks) {
5878
            CloseHandle(hfile);
5879
            return TRUE;
5880
        }
5881
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5882
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5883
        CloseHandle(hfile);
5884
        if (!result) {
5885
            return TRUE;
5886
        }
5887
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5888
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5889
        if (hfile != INVALID_HANDLE_VALUE) {
5890
            CloseHandle(hfile);
5891
            return TRUE;
5892
        }
5893
    }
5894
5895
    switch (GetLastError()) {
5896
    case ERROR_ACCESS_DENIED:
5897
    case ERROR_SHARING_VIOLATION:
5898
    case ERROR_CANT_ACCESS_FILE:
5899
    case ERROR_INVALID_PARAMETER:
5900
        STRUCT_STAT _st;
5901
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5902
    }
5903
5904
    return FALSE;
5905
}
5906
5907
5908
static BOOL
5909
_testFileExists(path_t *path, BOOL followLinks)
5910
{
5911
    BOOL result = FALSE;
5912
    if (path->value_error) {
5913
        return FALSE;
5914
    }
5915
5916
    Py_BEGIN_ALLOW_THREADS
5917
    if (path->is_fd) {
5918
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5919
        if (hfile != INVALID_HANDLE_VALUE) {
5920
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5921
                result = TRUE;
5922
            }
5923
        }
5924
    }
5925
    else if (path->wide) {
5926
        result = _testFileExistsByName(path->wide, followLinks);
5927
    }
5928
    Py_END_ALLOW_THREADS
5929
5930
    return result;
5931
}
5932
5933
5934
static BOOL
5935
_testFileType(path_t *path, int testedType)
5936
{
5937
    BOOL result = FALSE;
5938
    if (path->value_error) {
5939
        return FALSE;
5940
    }
5941
5942
    Py_BEGIN_ALLOW_THREADS
5943
    if (path->is_fd) {
5944
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5945
        if (hfile != INVALID_HANDLE_VALUE) {
5946
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5947
        }
5948
    }
5949
    else if (path->wide) {
5950
        result = _testFileTypeByName(path->wide, testedType);
5951
    }
5952
    Py_END_ALLOW_THREADS
5953
5954
    return result;
5955
}
5956
5957
5958
/*[clinic input]
5959
os._path_exists -> bool
5960
5961
    path: path_t(allow_fd=True, suppress_value_error=True)
5962
5963
Test whether a path exists.  Returns False for broken symbolic links.
5964
5965
[clinic start generated code]*/
5966
5967
static int
5968
os__path_exists_impl(PyObject *module, path_t *path)
5969
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5970
{
5971
    return _testFileExists(path, TRUE);
5972
}
5973
5974
5975
/*[clinic input]
5976
os._path_lexists -> bool
5977
5978
    path: path_t(allow_fd=True, suppress_value_error=True)
5979
5980
Test whether a path exists.  Returns True for broken symbolic links.
5981
5982
[clinic start generated code]*/
5983
5984
static int
5985
os__path_lexists_impl(PyObject *module, path_t *path)
5986
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5987
{
5988
    return _testFileExists(path, FALSE);
5989
}
5990
5991
5992
/*[clinic input]
5993
os._path_isdir -> bool
5994
5995
    path: path_t(allow_fd=True, suppress_value_error=True)
5996
    /
5997
5998
Return true if the pathname refers to an existing directory.
5999
6000
[clinic start generated code]*/
6001
6002
static int
6003
os__path_isdir_impl(PyObject *module, path_t *path)
6004
/*[clinic end generated code: output=d5786196f9e2fa7a input=b15f9b697a7a759f]*/
6005
{
6006
    return _testFileType(path, PY_IFDIR);
6007
}
6008
6009
6010
/*[clinic input]
6011
os._path_isfile -> bool
6012
6013
    path: path_t(allow_fd=True, suppress_value_error=True)
6014
6015
Test whether a path is a regular file
6016
6017
[clinic start generated code]*/
6018
6019
static int
6020
os__path_isfile_impl(PyObject *module, path_t *path)
6021
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6022
{
6023
    return _testFileType(path, PY_IFREG);
6024
}
6025
6026
6027
/*[clinic input]
6028
os._path_islink -> bool
6029
6030
    path: path_t(allow_fd=True, suppress_value_error=True)
6031
6032
Test whether a path is a symbolic link
6033
6034
[clinic start generated code]*/
6035
6036
static int
6037
os__path_islink_impl(PyObject *module, path_t *path)
6038
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6039
{
6040
    return _testFileType(path, PY_IFLNK);
6041
}
6042
6043
6044
/*[clinic input]
6045
os._path_isjunction -> bool
6046
6047
    path: path_t(allow_fd=True, suppress_value_error=True)
6048
6049
Test whether a path is a junction
6050
6051
[clinic start generated code]*/
6052
6053
static int
6054
os__path_isjunction_impl(PyObject *module, path_t *path)
6055
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6056
{
6057
    return _testFileType(path, PY_IFMNT);
6058
}
6059
6060
#undef PY_IFREG
6061
#undef PY_IFDIR
6062
#undef PY_IFLNK
6063
#undef PY_IFMNT
6064
#undef PY_IFLRP
6065
#undef PY_IFRRP
6066
6067
#endif /* MS_WINDOWS */
6068
6069
6070
/*[clinic input]
6071
os._path_splitroot_ex
6072
6073
    path: path_t(make_wide=True, nonstrict=True)
6074
    /
6075
6076
Split a pathname into drive, root and tail.
6077
6078
The tail contains anything after the root.
6079
[clinic start generated code]*/
6080
6081
static PyObject *
6082
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6083
/*[clinic end generated code: output=4b0072b6cdf4b611 input=012fbfad14888b2b]*/
6084
143k
{
6085
143k
    Py_ssize_t drvsize, rootsize;
6086
143k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6087
6088
143k
    const wchar_t *buffer = path->wide;
6089
143k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6090
143k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6091
143k
    if (drv == NULL) {
6092
0
        goto exit;
6093
0
    }
6094
143k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6095
143k
    if (root == NULL) {
6096
0
        goto exit;
6097
0
    }
6098
143k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6099
143k
                                  path->length - drvsize - rootsize);
6100
143k
    if (tail == NULL) {
6101
0
        goto exit;
6102
0
    }
6103
143k
    if (PyBytes_Check(path->object)) {
6104
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6105
0
        if (drv == NULL) {
6106
0
            goto exit;
6107
0
        }
6108
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6109
0
        if (root == NULL) {
6110
0
            goto exit;
6111
0
        }
6112
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6113
0
        if (tail == NULL) {
6114
0
            goto exit;
6115
0
        }
6116
0
    }
6117
143k
    result = PyTuple_Pack(3, drv, root, tail);
6118
143k
exit:
6119
143k
    Py_XDECREF(drv);
6120
143k
    Py_XDECREF(root);
6121
143k
    Py_XDECREF(tail);
6122
143k
    return result;
6123
143k
}
6124
6125
6126
/*[clinic input]
6127
os._path_normpath
6128
6129
    path: path_t(make_wide=True, nonstrict=True)
6130
6131
Normalize path, eliminating double slashes, etc.
6132
[clinic start generated code]*/
6133
6134
static PyObject *
6135
os__path_normpath_impl(PyObject *module, path_t *path)
6136
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6137
29.8k
{
6138
29.8k
    PyObject *result;
6139
29.8k
    Py_ssize_t norm_len;
6140
29.8k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6141
29.8k
                                               path->length, &norm_len);
6142
29.8k
    if (!norm_len) {
6143
0
        result = PyUnicode_FromOrdinal('.');
6144
0
    }
6145
29.8k
    else {
6146
29.8k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6147
29.8k
    }
6148
29.8k
    if (PyBytes_Check(path->object)) {
6149
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6150
0
    }
6151
29.8k
    return result;
6152
29.8k
}
6153
6154
/*[clinic input]
6155
os.mkdir
6156
6157
    path : path_t
6158
6159
    mode: int = 0o777
6160
6161
    *
6162
6163
    dir_fd : dir_fd(requires='mkdirat') = None
6164
6165
Create a directory.
6166
6167
If dir_fd is not None, it should be a file descriptor open to
6168
a directory, and path should be relative; path will then be relative to
6169
that directory.
6170
dir_fd may not be implemented on your platform.  If it is unavailable,
6171
using it will raise a NotImplementedError.
6172
6173
The mode argument is ignored on Windows.  Where it is used, the current
6174
umask value is first masked out.
6175
[clinic start generated code]*/
6176
6177
static PyObject *
6178
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6179
/*[clinic end generated code: output=a70446903abe821f input=30270d369599634b]*/
6180
97.0k
{
6181
97.0k
    int result;
6182
#ifdef MS_WINDOWS
6183
    int error = 0;
6184
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6185
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6186
#endif
6187
97.0k
#ifdef HAVE_MKDIRAT
6188
97.0k
    int mkdirat_unavailable = 0;
6189
97.0k
#endif
6190
6191
97.0k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6192
97.0k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6193
0
        return NULL;
6194
0
    }
6195
6196
#ifdef MS_WINDOWS
6197
    Py_BEGIN_ALLOW_THREADS
6198
    // For API sets that don't support these APIs, we have no choice
6199
    // but to silently create a directory with default ACL.
6200
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6201
    if (mode == 0700 /* 0o700 */) {
6202
        ULONG sdSize;
6203
        pSecAttr = &secAttr;
6204
        // Set a discretionary ACL (D) that is protected (P) and includes
6205
        // inheritable (OICI) entries that allow (A) full control (FA) to
6206
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6207
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6208
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6209
            SDDL_REVISION_1,
6210
            &secAttr.lpSecurityDescriptor,
6211
            &sdSize
6212
        )) {
6213
            error = GetLastError();
6214
        }
6215
    }
6216
#endif
6217
    if (!error) {
6218
        result = CreateDirectoryW(path->wide, pSecAttr);
6219
        if (secAttr.lpSecurityDescriptor &&
6220
            // uncommonly, LocalFree returns non-zero on error, but still uses
6221
            // GetLastError() to see what the error code is
6222
            LocalFree(secAttr.lpSecurityDescriptor)) {
6223
            error = GetLastError();
6224
        }
6225
    }
6226
    Py_END_ALLOW_THREADS
6227
6228
    if (error) {
6229
        return PyErr_SetFromWindowsErr(error);
6230
    }
6231
    if (!result) {
6232
        return path_error(path);
6233
    }
6234
#else
6235
97.0k
    Py_BEGIN_ALLOW_THREADS
6236
97.0k
#if HAVE_MKDIRAT
6237
97.0k
    if (dir_fd != DEFAULT_DIR_FD) {
6238
0
      if (HAVE_MKDIRAT_RUNTIME) {
6239
0
        result = mkdirat(dir_fd, path->narrow, mode);
6240
6241
0
      } else {
6242
0
        mkdirat_unavailable = 1;
6243
0
      }
6244
0
    } else
6245
97.0k
#endif
6246
#if defined(__WATCOMC__) && !defined(__QNX__)
6247
        result = mkdir(path->narrow);
6248
#else
6249
97.0k
        result = mkdir(path->narrow, mode);
6250
97.0k
#endif
6251
97.0k
    Py_END_ALLOW_THREADS
6252
6253
97.0k
#if HAVE_MKDIRAT
6254
97.0k
    if (mkdirat_unavailable) {
6255
0
        argument_unavailable_error(NULL, "dir_fd");
6256
0
        return NULL;
6257
0
    }
6258
97.0k
#endif
6259
6260
97.0k
    if (result < 0)
6261
353
        return path_error(path);
6262
96.6k
#endif /* MS_WINDOWS */
6263
97.0k
    Py_RETURN_NONE;
6264
97.0k
}
6265
6266
6267
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6268
#if defined(HAVE_SYS_RESOURCE_H)
6269
#include <sys/resource.h>
6270
#endif
6271
6272
6273
#ifdef HAVE_NICE
6274
/*[clinic input]
6275
os.nice
6276
6277
    increment: int
6278
    /
6279
6280
Add increment to the priority of process and return the new priority.
6281
[clinic start generated code]*/
6282
6283
static PyObject *
6284
os_nice_impl(PyObject *module, int increment)
6285
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6286
0
{
6287
0
    int value;
6288
6289
    /* There are two flavours of 'nice': one that returns the new
6290
       priority (as required by almost all standards out there) and the
6291
       Linux/FreeBSD one, which returns '0' on success and advices
6292
       the use of getpriority() to get the new priority.
6293
6294
       If we are of the nice family that returns the new priority, we
6295
       need to clear errno before the call, and check if errno is filled
6296
       before calling posix_error() on a returnvalue of -1, because the
6297
       -1 may be the actual new priority! */
6298
6299
0
    errno = 0;
6300
0
    value = nice(increment);
6301
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6302
    if (value == 0)
6303
        value = getpriority(PRIO_PROCESS, 0);
6304
#endif
6305
0
    if (value == -1 && errno != 0)
6306
        /* either nice() or getpriority() returned an error */
6307
0
        return posix_error();
6308
0
    return PyLong_FromLong((long) value);
6309
0
}
6310
#endif /* HAVE_NICE */
6311
6312
6313
#ifdef HAVE_GETPRIORITY
6314
/*[clinic input]
6315
os.getpriority
6316
6317
    which: int
6318
    who: int
6319
6320
Return program scheduling priority.
6321
[clinic start generated code]*/
6322
6323
static PyObject *
6324
os_getpriority_impl(PyObject *module, int which, int who)
6325
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6326
0
{
6327
0
    int retval;
6328
6329
0
    errno = 0;
6330
0
    retval = getpriority(which, who);
6331
0
    if (errno != 0)
6332
0
        return posix_error();
6333
0
    return PyLong_FromLong((long)retval);
6334
0
}
6335
#endif /* HAVE_GETPRIORITY */
6336
6337
6338
#ifdef HAVE_SETPRIORITY
6339
/*[clinic input]
6340
os.setpriority
6341
6342
    which: int
6343
    who: int
6344
    priority: int
6345
6346
Set program scheduling priority.
6347
[clinic start generated code]*/
6348
6349
static PyObject *
6350
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6351
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6352
0
{
6353
0
    int retval;
6354
6355
0
    retval = setpriority(which, who, priority);
6356
0
    if (retval == -1)
6357
0
        return posix_error();
6358
0
    Py_RETURN_NONE;
6359
0
}
6360
#endif /* HAVE_SETPRIORITY */
6361
6362
6363
static PyObject *
6364
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6365
178
{
6366
178
    const char *function_name = is_replace ? "replace" : "rename";
6367
178
    int dir_fd_specified;
6368
6369
178
#ifdef HAVE_RENAMEAT
6370
178
    int renameat_unavailable = 0;
6371
178
#endif
6372
6373
#ifdef MS_WINDOWS
6374
    BOOL result;
6375
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6376
#else
6377
178
    int result;
6378
178
#endif
6379
6380
178
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6381
178
                       (dst_dir_fd != DEFAULT_DIR_FD);
6382
#ifndef HAVE_RENAMEAT
6383
    if (dir_fd_specified) {
6384
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6385
        return NULL;
6386
    }
6387
#endif
6388
6389
178
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6390
178
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6391
178
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6392
0
        return NULL;
6393
0
    }
6394
6395
#ifdef MS_WINDOWS
6396
    Py_BEGIN_ALLOW_THREADS
6397
    result = MoveFileExW(src->wide, dst->wide, flags);
6398
    Py_END_ALLOW_THREADS
6399
6400
    if (!result)
6401
        return path_error2(src, dst);
6402
6403
#else
6404
178
    Py_BEGIN_ALLOW_THREADS
6405
178
#ifdef HAVE_RENAMEAT
6406
178
    if (dir_fd_specified) {
6407
0
        if (HAVE_RENAMEAT_RUNTIME) {
6408
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6409
0
        } else {
6410
0
            renameat_unavailable = 1;
6411
0
        }
6412
0
    } else
6413
178
#endif
6414
178
    result = rename(src->narrow, dst->narrow);
6415
178
    Py_END_ALLOW_THREADS
6416
6417
6418
178
#ifdef HAVE_RENAMEAT
6419
178
    if (renameat_unavailable) {
6420
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6421
0
        return NULL;
6422
0
    }
6423
178
#endif
6424
6425
178
    if (result)
6426
0
        return path_error2(src, dst);
6427
178
#endif
6428
178
    Py_RETURN_NONE;
6429
178
}
6430
6431
6432
/*[clinic input]
6433
os.rename
6434
6435
    src : path_t
6436
    dst : path_t
6437
    *
6438
    src_dir_fd : dir_fd = None
6439
    dst_dir_fd : dir_fd = None
6440
6441
Rename a file or directory.
6442
6443
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6444
descriptor open to a directory, and the respective path string (src or
6445
dst) should be relative; the path will then be relative to that
6446
directory.
6447
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6448
If they are unavailable, using them will raise a NotImplementedError.
6449
[clinic start generated code]*/
6450
6451
static PyObject *
6452
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6453
               int dst_dir_fd)
6454
/*[clinic end generated code: output=59e803072cf41230 input=7d320d687c715fd6]*/
6455
5
{
6456
5
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6457
5
}
6458
6459
6460
/*[clinic input]
6461
os.replace = os.rename
6462
6463
Rename a file or directory, overwriting the destination.
6464
6465
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6466
descriptor open to a directory, and the respective path string (src or
6467
dst) should be relative; the path will then be relative to that
6468
directory.
6469
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6470
If they are unavailable, using them will raise a NotImplementedError.
6471
[clinic start generated code]*/
6472
6473
static PyObject *
6474
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6475
                int dst_dir_fd)
6476
/*[clinic end generated code: output=1968c02e7857422b input=44ed6b762d5953fc]*/
6477
173
{
6478
173
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6479
173
}
6480
6481
6482
/*[clinic input]
6483
os.rmdir
6484
6485
    path: path_t
6486
    *
6487
    dir_fd: dir_fd(requires='unlinkat') = None
6488
6489
Remove a directory.
6490
6491
If dir_fd is not None, it should be a file descriptor open to
6492
a directory, and path should be relative; path will then be relative
6493
to that directory.
6494
dir_fd may not be implemented on your platform.
6495
If it is unavailable, using it will raise a NotImplementedError.
6496
[clinic start generated code]*/
6497
6498
static PyObject *
6499
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6500
/*[clinic end generated code: output=080eb54f506e8301 input=84325211e33a98e0]*/
6501
96.6k
{
6502
96.6k
    int result;
6503
96.6k
#ifdef HAVE_UNLINKAT
6504
96.6k
    int unlinkat_unavailable = 0;
6505
96.6k
#endif
6506
6507
96.6k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6508
96.6k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6509
0
        return NULL;
6510
0
    }
6511
6512
96.6k
    Py_BEGIN_ALLOW_THREADS
6513
#ifdef MS_WINDOWS
6514
    /* Windows, success=1, UNIX, success=0 */
6515
    result = !RemoveDirectoryW(path->wide);
6516
#else
6517
96.6k
#ifdef HAVE_UNLINKAT
6518
96.6k
    if (dir_fd != DEFAULT_DIR_FD) {
6519
92.1k
      if (HAVE_UNLINKAT_RUNTIME) {
6520
92.1k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6521
92.1k
      } else {
6522
0
        unlinkat_unavailable = 1;
6523
0
        result = -1;
6524
0
      }
6525
92.1k
    } else
6526
4.47k
#endif
6527
4.47k
        result = rmdir(path->narrow);
6528
96.6k
#endif
6529
96.6k
    Py_END_ALLOW_THREADS
6530
6531
96.6k
#ifdef HAVE_UNLINKAT
6532
96.6k
    if (unlinkat_unavailable) {
6533
0
        argument_unavailable_error("rmdir", "dir_fd");
6534
0
        return NULL;
6535
0
    }
6536
96.6k
#endif
6537
6538
96.6k
    if (result)
6539
5
        return path_error(path);
6540
6541
96.6k
    Py_RETURN_NONE;
6542
96.6k
}
6543
6544
6545
#ifdef HAVE_SYSTEM
6546
#ifdef MS_WINDOWS
6547
/*[clinic input]
6548
os.system -> long
6549
6550
    command: Py_UNICODE
6551
6552
Execute the command in a subshell.
6553
[clinic start generated code]*/
6554
6555
static long
6556
os_system_impl(PyObject *module, const wchar_t *command)
6557
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6558
{
6559
    long result;
6560
6561
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6562
        return -1;
6563
    }
6564
6565
    Py_BEGIN_ALLOW_THREADS
6566
    _Py_BEGIN_SUPPRESS_IPH
6567
    result = _wsystem(command);
6568
    _Py_END_SUPPRESS_IPH
6569
    Py_END_ALLOW_THREADS
6570
    return result;
6571
}
6572
#else /* MS_WINDOWS */
6573
/*[clinic input]
6574
os.system -> long
6575
6576
    command: unicode_fs_encoded
6577
6578
Execute the command in a subshell.
6579
[clinic start generated code]*/
6580
6581
static long
6582
os_system_impl(PyObject *module, PyObject *command)
6583
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6584
0
{
6585
0
    long result;
6586
0
    const char *bytes = PyBytes_AsString(command);
6587
6588
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6589
0
        return -1;
6590
0
    }
6591
6592
0
    Py_BEGIN_ALLOW_THREADS
6593
0
    result = system(bytes);
6594
0
    Py_END_ALLOW_THREADS
6595
0
    return result;
6596
0
}
6597
#endif
6598
#endif /* HAVE_SYSTEM */
6599
6600
6601
#ifdef HAVE_UMASK
6602
/*[clinic input]
6603
os.umask
6604
6605
    mask: int
6606
    /
6607
6608
Set the current numeric umask and return the previous umask.
6609
[clinic start generated code]*/
6610
6611
static PyObject *
6612
os_umask_impl(PyObject *module, int mask)
6613
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6614
0
{
6615
0
    int i = (int)umask(mask);
6616
0
    if (i < 0)
6617
0
        return posix_error();
6618
0
    return PyLong_FromLong((long)i);
6619
0
}
6620
#endif
6621
6622
#ifdef MS_WINDOWS
6623
6624
/* override the default DeleteFileW behavior so that directory
6625
symlinks can be removed with this function, the same as with
6626
Unix symlinks */
6627
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6628
{
6629
    WIN32_FILE_ATTRIBUTE_DATA info;
6630
    WIN32_FIND_DATAW find_data;
6631
    HANDLE find_data_handle;
6632
    int is_directory = 0;
6633
    int is_link = 0;
6634
6635
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6636
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6637
6638
        /* Get WIN32_FIND_DATA structure for the path to determine if
6639
           it is a symlink */
6640
        if(is_directory &&
6641
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6642
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6643
6644
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6645
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6646
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6647
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6648
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6649
                FindClose(find_data_handle);
6650
            }
6651
        }
6652
    }
6653
6654
    if (is_directory && is_link)
6655
        return RemoveDirectoryW(lpFileName);
6656
6657
    return DeleteFileW(lpFileName);
6658
}
6659
#endif /* MS_WINDOWS */
6660
6661
6662
/*[clinic input]
6663
os.unlink
6664
6665
    path: path_t
6666
    *
6667
    dir_fd: dir_fd(requires='unlinkat')=None
6668
6669
Remove a file (same as remove()).
6670
6671
If dir_fd is not None, it should be a file descriptor open to
6672
a directory, and path should be relative; path will then be relative to
6673
that directory.
6674
dir_fd may not be implemented on your platform.
6675
If it is unavailable, using it will raise a NotImplementedError.
6676
6677
[clinic start generated code]*/
6678
6679
static PyObject *
6680
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6681
/*[clinic end generated code: output=621797807b9963b1 input=1a2ef2579207eab1]*/
6682
20.9k
{
6683
20.9k
    int result;
6684
20.9k
#ifdef HAVE_UNLINKAT
6685
20.9k
    int unlinkat_unavailable = 0;
6686
20.9k
#endif
6687
6688
20.9k
    if (PySys_Audit("os.remove", "Oi", path->object,
6689
20.9k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6690
0
        return NULL;
6691
0
    }
6692
6693
20.9k
    Py_BEGIN_ALLOW_THREADS
6694
20.9k
    _Py_BEGIN_SUPPRESS_IPH
6695
#ifdef MS_WINDOWS
6696
    /* Windows, success=1, UNIX, success=0 */
6697
    result = !Py_DeleteFileW(path->wide);
6698
#else
6699
20.9k
#ifdef HAVE_UNLINKAT
6700
20.9k
    if (dir_fd != DEFAULT_DIR_FD) {
6701
20.9k
      if (HAVE_UNLINKAT_RUNTIME) {
6702
6703
20.9k
        result = unlinkat(dir_fd, path->narrow, 0);
6704
20.9k
      } else {
6705
0
        unlinkat_unavailable = 1;
6706
0
      }
6707
20.9k
    } else
6708
2
#endif /* HAVE_UNLINKAT */
6709
2
        result = unlink(path->narrow);
6710
20.9k
#endif
6711
20.9k
    _Py_END_SUPPRESS_IPH
6712
20.9k
    Py_END_ALLOW_THREADS
6713
6714
20.9k
#ifdef HAVE_UNLINKAT
6715
20.9k
    if (unlinkat_unavailable) {
6716
0
        argument_unavailable_error(NULL, "dir_fd");
6717
0
        return NULL;
6718
0
    }
6719
20.9k
#endif
6720
6721
20.9k
    if (result)
6722
0
        return path_error(path);
6723
6724
20.9k
    Py_RETURN_NONE;
6725
20.9k
}
6726
6727
6728
/*[clinic input]
6729
os.remove = os.unlink
6730
6731
Remove a file (same as unlink()).
6732
6733
If dir_fd is not None, it should be a file descriptor open to
6734
a directory, and path should be relative; path will then be relative
6735
to that directory.
6736
dir_fd may not be implemented on your platform.
6737
If it is unavailable, using it will raise a NotImplementedError.
6738
[clinic start generated code]*/
6739
6740
static PyObject *
6741
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6742
/*[clinic end generated code: output=a8535b28f0068883 input=9f6e66912126bd56]*/
6743
0
{
6744
0
    return os_unlink_impl(module, path, dir_fd);
6745
0
}
6746
6747
6748
static PyStructSequence_Field uname_result_fields[] = {
6749
    {"sysname",    "operating system name"},
6750
    {"nodename",   "name of machine on network (implementation-defined)"},
6751
    {"release",    "operating system release"},
6752
    {"version",    "operating system version"},
6753
    {"machine",    "hardware identifier"},
6754
    {NULL}
6755
};
6756
6757
PyDoc_STRVAR(uname_result__doc__,
6758
"uname_result: Result from os.uname().\n\n\
6759
This object may be accessed either as a tuple of\n\
6760
  (sysname, nodename, release, version, machine),\n\
6761
or via the attributes sysname, nodename, release, version, and machine.\n\
6762
\n\
6763
See os.uname for more information.");
6764
6765
static PyStructSequence_Desc uname_result_desc = {
6766
    MODNAME ".uname_result", /* name */
6767
    uname_result__doc__, /* doc */
6768
    uname_result_fields,
6769
    5
6770
};
6771
6772
#ifdef HAVE_UNAME
6773
/*[clinic input]
6774
os.uname
6775
6776
Return an object identifying the current operating system.
6777
6778
The object behaves like a named tuple with the following fields:
6779
  (sysname, nodename, release, version, machine)
6780
6781
[clinic start generated code]*/
6782
6783
static PyObject *
6784
os_uname_impl(PyObject *module)
6785
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6786
4
{
6787
4
    struct utsname u;
6788
4
    int res;
6789
4
    PyObject *value;
6790
6791
4
    Py_BEGIN_ALLOW_THREADS
6792
4
    res = uname(&u);
6793
4
    Py_END_ALLOW_THREADS
6794
4
    if (res < 0)
6795
0
        return posix_error();
6796
6797
4
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6798
4
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6799
4
    if (value == NULL)
6800
0
        return NULL;
6801
6802
4
#define SET(i, field) \
6803
20
    { \
6804
20
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6805
20
    if (!o) { \
6806
0
        Py_DECREF(value); \
6807
0
        return NULL; \
6808
0
    } \
6809
20
    PyStructSequence_SET_ITEM(value, i, o); \
6810
20
    } \
6811
4
6812
8
    SET(0, u.sysname);
6813
8
    SET(1, u.nodename);
6814
4
    SET(2, u.release);
6815
4
    SET(3, u.version);
6816
4
    SET(4, u.machine);
6817
6818
4
#undef SET
6819
6820
4
    return value;
6821
4
}
6822
#endif /* HAVE_UNAME */
6823
6824
6825
6826
typedef struct {
6827
    int    now;
6828
    time_t atime_s;
6829
    long   atime_ns;
6830
    time_t mtime_s;
6831
    long   mtime_ns;
6832
} utime_t;
6833
6834
/*
6835
 * these macros assume that "ut" is a pointer to a utime_t
6836
 * they also intentionally leak the declaration of a pointer named "time"
6837
 */
6838
#define UTIME_TO_TIMESPEC \
6839
0
    struct timespec ts[2]; \
6840
0
    struct timespec *time; \
6841
0
    if (ut->now) \
6842
0
        time = NULL; \
6843
0
    else { \
6844
0
        ts[0].tv_sec = ut->atime_s; \
6845
0
        ts[0].tv_nsec = ut->atime_ns; \
6846
0
        ts[1].tv_sec = ut->mtime_s; \
6847
0
        ts[1].tv_nsec = ut->mtime_ns; \
6848
0
        time = ts; \
6849
0
    } \
6850
6851
#define UTIME_TO_TIMEVAL \
6852
0
    struct timeval tv[2]; \
6853
0
    struct timeval *time; \
6854
0
    if (ut->now) \
6855
0
        time = NULL; \
6856
0
    else { \
6857
0
        tv[0].tv_sec = ut->atime_s; \
6858
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6859
0
        tv[1].tv_sec = ut->mtime_s; \
6860
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6861
0
        time = tv; \
6862
0
    } \
6863
6864
#define UTIME_TO_UTIMBUF \
6865
    struct utimbuf u; \
6866
    struct utimbuf *time; \
6867
    if (ut->now) \
6868
        time = NULL; \
6869
    else { \
6870
        u.actime = ut->atime_s; \
6871
        u.modtime = ut->mtime_s; \
6872
        time = &u; \
6873
    }
6874
6875
#define UTIME_TO_TIME_T \
6876
    time_t timet[2]; \
6877
    time_t *time; \
6878
    if (ut->now) \
6879
        time = NULL; \
6880
    else { \
6881
        timet[0] = ut->atime_s; \
6882
        timet[1] = ut->mtime_s; \
6883
        time = timet; \
6884
    } \
6885
6886
6887
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6888
6889
static int
6890
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6891
0
{
6892
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6893
    if (HAVE_UTIMENSAT_RUNTIME) {
6894
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6895
        UTIME_TO_TIMESPEC;
6896
        return utimensat(dir_fd, path, time, flags);
6897
    }  else {
6898
        errno = ENOSYS;
6899
        return -1;
6900
    }
6901
#elif defined(HAVE_UTIMENSAT)
6902
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6903
0
    UTIME_TO_TIMESPEC;
6904
0
    return utimensat(dir_fd, path, time, flags);
6905
#elif defined(HAVE_FUTIMESAT)
6906
    UTIME_TO_TIMEVAL;
6907
    /*
6908
     * follow_symlinks will never be false here;
6909
     * we only allow !follow_symlinks and dir_fd together
6910
     * if we have utimensat()
6911
     */
6912
    assert(follow_symlinks);
6913
    return futimesat(dir_fd, path, time);
6914
#endif
6915
0
}
6916
6917
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6918
#else
6919
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6920
#endif
6921
6922
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6923
6924
static int
6925
utime_fd(utime_t *ut, int fd)
6926
0
{
6927
0
#ifdef HAVE_FUTIMENS
6928
6929
0
    if (HAVE_FUTIMENS_RUNTIME) {
6930
6931
0
    UTIME_TO_TIMESPEC;
6932
0
    return futimens(fd, time);
6933
6934
0
    } else
6935
#ifndef HAVE_FUTIMES
6936
    {
6937
        /* Not sure if this can happen */
6938
        PyErr_SetString(
6939
            PyExc_RuntimeError,
6940
            "neither futimens nor futimes are supported"
6941
            " on this system");
6942
        return -1;
6943
    }
6944
#endif
6945
6946
0
#endif
6947
0
#ifdef HAVE_FUTIMES
6948
0
    {
6949
0
    UTIME_TO_TIMEVAL;
6950
0
    return futimes(fd, time);
6951
0
    }
6952
0
#endif
6953
0
}
6954
6955
    #define PATH_UTIME_HAVE_FD 1
6956
#else
6957
    #define PATH_UTIME_HAVE_FD 0
6958
#endif
6959
6960
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6961
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6962
#endif
6963
6964
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6965
6966
static int
6967
utime_nofollow_symlinks(utime_t *ut, const char *path)
6968
0
{
6969
0
#ifdef HAVE_UTIMENSAT
6970
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6971
0
        UTIME_TO_TIMESPEC;
6972
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6973
0
    } else
6974
#ifndef HAVE_LUTIMES
6975
    {
6976
        /* Not sure if this can happen */
6977
        PyErr_SetString(
6978
            PyExc_RuntimeError,
6979
            "neither utimensat nor lutimes are supported"
6980
            " on this system");
6981
        return -1;
6982
    }
6983
#endif
6984
0
#endif
6985
6986
0
#ifdef HAVE_LUTIMES
6987
0
    {
6988
0
    UTIME_TO_TIMEVAL;
6989
0
    return lutimes(path, time);
6990
0
    }
6991
0
#endif
6992
0
}
6993
6994
#endif
6995
6996
#ifndef MS_WINDOWS
6997
6998
static int
6999
utime_default(utime_t *ut, const char *path)
7000
0
{
7001
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7002
    if (HAVE_UTIMENSAT_RUNTIME) {
7003
        UTIME_TO_TIMESPEC;
7004
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
7005
    } else {
7006
        UTIME_TO_TIMEVAL;
7007
        return utimes(path, time);
7008
    }
7009
#elif defined(HAVE_UTIMENSAT)
7010
0
    UTIME_TO_TIMESPEC;
7011
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
7012
#elif defined(HAVE_UTIMES)
7013
    UTIME_TO_TIMEVAL;
7014
    return utimes(path, time);
7015
#elif defined(HAVE_UTIME_H)
7016
    UTIME_TO_UTIMBUF;
7017
    return utime(path, time);
7018
#else
7019
    UTIME_TO_TIME_T;
7020
    return utime(path, time);
7021
#endif
7022
0
}
7023
7024
#endif
7025
7026
static int
7027
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7028
0
{
7029
0
    int result = 0;
7030
0
    PyObject *divmod;
7031
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7032
0
    if (!divmod)
7033
0
        goto exit;
7034
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7035
0
        PyErr_Format(PyExc_TypeError,
7036
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7037
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7038
0
        goto exit;
7039
0
    }
7040
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7041
0
    if ((*s == -1) && PyErr_Occurred())
7042
0
        goto exit;
7043
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7044
0
    if ((*ns == -1) && PyErr_Occurred())
7045
0
        goto exit;
7046
7047
0
    result = 1;
7048
0
exit:
7049
0
    Py_XDECREF(divmod);
7050
0
    return result;
7051
0
}
7052
7053
7054
/*[clinic input]
7055
os.utime
7056
7057
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7058
    times: object = None
7059
    *
7060
    ns: object = NULL
7061
    dir_fd: dir_fd(requires='futimensat') = None
7062
    follow_symlinks: bool=True
7063
7064
Set the access and modified time of path.
7065
7066
path may always be specified as a string.  On some platforms, path may
7067
also be specified as an open file descriptor.  If this functionality is
7068
unavailable, using it raises an exception.
7069
7070
If times is not None, it must be a tuple (atime, mtime);
7071
atime and mtime should be expressed as float seconds since the epoch.
7072
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7073
atime_ns and mtime_ns should be expressed as integer nanoseconds
7074
since the epoch.
7075
If times is None and ns is unspecified, utime uses the current time.
7076
Specifying tuples for both times and ns is an error.
7077
7078
If dir_fd is not None, it should be a file descriptor open to
7079
a directory, and path should be relative; path will then be relative to
7080
that directory.
7081
If follow_symlinks is False, and the last element of the path is
7082
a symbolic link, utime will modify the symbolic link itself instead of
7083
the file the link points to.
7084
It is an error to use dir_fd or follow_symlinks when specifying path as
7085
an open file descriptor.
7086
dir_fd and follow_symlinks may not be available on your platform.
7087
If they are unavailable, using them will raise a NotImplementedError.
7088
7089
[clinic start generated code]*/
7090
7091
static PyObject *
7092
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7093
              int dir_fd, int follow_symlinks)
7094
/*[clinic end generated code: output=cfcac69d027b82cf input=5ab470b2bc250788]*/
7095
0
{
7096
#ifdef MS_WINDOWS
7097
    HANDLE hFile;
7098
    FILETIME atime, mtime;
7099
#else
7100
0
    int result;
7101
0
#endif
7102
7103
0
    utime_t utime;
7104
7105
0
    memset(&utime, 0, sizeof(utime_t));
7106
7107
0
    if (times != Py_None && ns) {
7108
0
        PyErr_SetString(PyExc_ValueError,
7109
0
                     "utime: you may specify either 'times'"
7110
0
                     " or 'ns' but not both");
7111
0
        return NULL;
7112
0
    }
7113
7114
0
    if (times != Py_None) {
7115
0
        time_t a_sec, m_sec;
7116
0
        long a_nsec, m_nsec;
7117
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7118
0
            PyErr_SetString(PyExc_TypeError,
7119
0
                         "utime: 'times' must be either"
7120
0
                         " a tuple of two numbers or None");
7121
0
            return NULL;
7122
0
        }
7123
0
        utime.now = 0;
7124
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7125
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7126
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7127
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7128
0
            return NULL;
7129
0
        }
7130
0
        utime.atime_s = a_sec;
7131
0
        utime.atime_ns = a_nsec;
7132
0
        utime.mtime_s = m_sec;
7133
0
        utime.mtime_ns = m_nsec;
7134
0
    }
7135
0
    else if (ns) {
7136
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7137
0
            PyErr_SetString(PyExc_TypeError,
7138
0
                         "utime: 'ns' must be a tuple of two ints");
7139
0
            return NULL;
7140
0
        }
7141
0
        utime.now = 0;
7142
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7143
0
                                      &utime.atime_s, &utime.atime_ns) ||
7144
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7145
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7146
0
            return NULL;
7147
0
        }
7148
0
    }
7149
0
    else {
7150
        /* times and ns are both None/unspecified. use "now". */
7151
0
        utime.now = 1;
7152
0
    }
7153
7154
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7155
    if (follow_symlinks_specified("utime", follow_symlinks))
7156
        return NULL;
7157
#endif
7158
7159
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7160
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7161
0
        fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
7162
0
        return NULL;
7163
7164
#if !defined(HAVE_UTIMENSAT)
7165
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7166
        PyErr_SetString(PyExc_ValueError,
7167
                     "utime: cannot use dir_fd and follow_symlinks "
7168
                     "together on this platform");
7169
        return NULL;
7170
    }
7171
#endif
7172
7173
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7174
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7175
0
        return NULL;
7176
0
    }
7177
7178
#ifdef MS_WINDOWS
7179
    Py_BEGIN_ALLOW_THREADS
7180
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7181
                        NULL, OPEN_EXISTING,
7182
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7183
    Py_END_ALLOW_THREADS
7184
    if (hFile == INVALID_HANDLE_VALUE) {
7185
        path_error(path);
7186
        return NULL;
7187
    }
7188
7189
    if (utime.now) {
7190
        GetSystemTimeAsFileTime(&mtime);
7191
        atime = mtime;
7192
    }
7193
    else {
7194
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7195
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7196
    }
7197
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7198
        path_error(path);
7199
        CloseHandle(hFile);
7200
        return NULL;
7201
    }
7202
    CloseHandle(hFile);
7203
#else /* MS_WINDOWS */
7204
0
    Py_BEGIN_ALLOW_THREADS
7205
7206
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7207
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7208
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7209
0
    else
7210
0
#endif
7211
7212
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7213
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7214
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7215
7216
0
    } else
7217
0
#endif
7218
7219
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7220
0
    if (path->is_fd)
7221
0
        result = utime_fd(&utime, path->fd);
7222
0
    else
7223
0
#endif
7224
7225
0
    result = utime_default(&utime, path->narrow);
7226
7227
0
    Py_END_ALLOW_THREADS
7228
7229
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7230
    /* See utime_dir_fd implementation */
7231
    if (result == -1 && errno == ENOSYS) {
7232
        argument_unavailable_error(NULL, "dir_fd");
7233
        return NULL;
7234
    }
7235
#endif
7236
7237
0
    if (result < 0) {
7238
0
        path_error(path);
7239
0
        return NULL;
7240
0
    }
7241
7242
0
#endif /* MS_WINDOWS */
7243
7244
0
    Py_RETURN_NONE;
7245
0
}
7246
7247
/* Process operations */
7248
7249
7250
/*[clinic input]
7251
@permit_long_summary
7252
os._exit
7253
7254
    status: int
7255
7256
Exit to the system with specified status, without normal exit processing.
7257
[clinic start generated code]*/
7258
7259
static PyObject *
7260
os__exit_impl(PyObject *module, int status)
7261
/*[clinic end generated code: output=116e52d9c2260d54 input=c35d282acfebe8fd]*/
7262
0
{
7263
0
    _exit(status);
7264
0
    return NULL; /* Make gcc -Wall happy */
7265
0
}
7266
7267
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7268
#define EXECV_CHAR wchar_t
7269
#else
7270
0
#define EXECV_CHAR char
7271
#endif
7272
7273
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7274
static void
7275
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7276
0
{
7277
0
    Py_ssize_t i;
7278
0
    for (i = 0; i < count; i++)
7279
0
        PyMem_Free(array[i]);
7280
0
    PyMem_Free(array);
7281
0
}
7282
7283
static int
7284
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7285
0
{
7286
0
    Py_ssize_t size;
7287
0
    PyObject *ub;
7288
0
    int result = 0;
7289
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7290
    if (!PyUnicode_FSDecoder(o, &ub))
7291
        return 0;
7292
    *out = PyUnicode_AsWideCharString(ub, &size);
7293
    if (*out)
7294
        result = 1;
7295
#else
7296
0
    if (!PyUnicode_FSConverter(o, &ub))
7297
0
        return 0;
7298
0
    size = PyBytes_GET_SIZE(ub);
7299
0
    *out = PyMem_Malloc(size + 1);
7300
0
    if (*out) {
7301
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7302
0
        result = 1;
7303
0
    } else
7304
0
        PyErr_NoMemory();
7305
0
#endif
7306
0
    Py_DECREF(ub);
7307
0
    return result;
7308
0
}
7309
#endif
7310
7311
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7312
static EXECV_CHAR**
7313
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7314
0
{
7315
0
    Py_ssize_t i, pos, envc;
7316
0
    PyObject *keys = NULL, *vals = NULL;
7317
0
    PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
7318
0
    EXECV_CHAR **envlist;
7319
7320
0
    i = PyMapping_Size(env);
7321
0
    if (i < 0)
7322
0
        return NULL;
7323
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7324
0
    if (envlist == NULL) {
7325
0
        PyErr_NoMemory();
7326
0
        return NULL;
7327
0
    }
7328
0
    envc = 0;
7329
0
    keys = PyMapping_Keys(env);
7330
0
    if (!keys)
7331
0
        goto error;
7332
0
    vals = PyMapping_Values(env);
7333
0
    if (!vals)
7334
0
        goto error;
7335
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7336
0
        PyErr_Format(PyExc_TypeError,
7337
0
                     "env.keys() or env.values() is not a list");
7338
0
        goto error;
7339
0
    }
7340
7341
0
    for (pos = 0; pos < i; pos++) {
7342
        // The 'key' and 'val' must be strong references because of
7343
        // possible side-effects by PyUnicode_FS{Converter,Decoder}().
7344
0
        key = PyList_GetItemRef(keys, pos);
7345
0
        if (key == NULL) {
7346
0
            goto error;
7347
0
        }
7348
0
        val = PyList_GetItemRef(vals, pos);
7349
0
        if (val == NULL) {
7350
0
            goto error;
7351
0
        }
7352
7353
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7354
        if (!PyUnicode_FSDecoder(key, &key2)) {
7355
            goto error;
7356
        }
7357
        if (!PyUnicode_FSDecoder(val, &val2)) {
7358
            goto error;
7359
        }
7360
        /* Search from index 1 because on Windows starting '=' is allowed for
7361
           defining hidden environment variables. */
7362
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7363
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7364
        {
7365
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7366
            goto error;
7367
        }
7368
        PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7369
#else
7370
0
        if (!PyUnicode_FSConverter(key, &key2)) {
7371
0
            goto error;
7372
0
        }
7373
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7374
0
            goto error;
7375
0
        }
7376
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7377
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7378
0
        {
7379
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7380
0
            goto error;
7381
0
        }
7382
0
        PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7383
0
                                              PyBytes_AS_STRING(val2));
7384
0
#endif
7385
0
        if (!keyval) {
7386
0
            goto error;
7387
0
        }
7388
7389
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7390
0
            Py_DECREF(keyval);
7391
0
            goto error;
7392
0
        }
7393
7394
0
        Py_CLEAR(key);
7395
0
        Py_CLEAR(val);
7396
0
        Py_CLEAR(key2);
7397
0
        Py_CLEAR(val2);
7398
0
        Py_DECREF(keyval);
7399
0
    }
7400
0
    Py_DECREF(vals);
7401
0
    Py_DECREF(keys);
7402
7403
0
    envlist[envc] = 0;
7404
0
    *envc_ptr = envc;
7405
0
    return envlist;
7406
7407
0
error:
7408
0
    Py_XDECREF(key);
7409
0
    Py_XDECREF(val);
7410
0
    Py_XDECREF(key2);
7411
0
    Py_XDECREF(val2);
7412
0
    Py_XDECREF(keys);
7413
0
    Py_XDECREF(vals);
7414
0
    free_string_array(envlist, envc);
7415
0
    return NULL;
7416
0
}
7417
7418
static EXECV_CHAR**
7419
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7420
0
{
7421
0
    int i;
7422
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7423
0
    if (argvlist == NULL) {
7424
0
        PyErr_NoMemory();
7425
0
        return NULL;
7426
0
    }
7427
0
    for (i = 0; i < *argc; i++) {
7428
0
        PyObject* item = PySequence_ITEM(argv, i);
7429
0
        if (item == NULL)
7430
0
            goto fail;
7431
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7432
0
            Py_DECREF(item);
7433
0
            goto fail;
7434
0
        }
7435
0
        Py_DECREF(item);
7436
0
    }
7437
0
    argvlist[*argc] = NULL;
7438
0
    return argvlist;
7439
0
fail:
7440
0
    *argc = i;
7441
0
    free_string_array(argvlist, *argc);
7442
0
    return NULL;
7443
0
}
7444
7445
#endif
7446
7447
7448
#ifdef HAVE_EXECV
7449
/*[clinic input]
7450
os.execv
7451
7452
    path: path_t
7453
        Path of executable file.
7454
    argv: object
7455
        Tuple or list of strings.
7456
    /
7457
7458
Execute an executable path with arguments, replacing current process.
7459
[clinic start generated code]*/
7460
7461
static PyObject *
7462
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7463
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7464
0
{
7465
0
    EXECV_CHAR **argvlist;
7466
0
    Py_ssize_t argc;
7467
7468
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7469
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7470
0
        PyErr_SetString(PyExc_RuntimeError,
7471
0
                        "exec not supported for isolated subinterpreters");
7472
0
        return NULL;
7473
0
    }
7474
7475
    /* execv has two arguments: (path, argv), where
7476
       argv is a list or tuple of strings. */
7477
7478
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7479
0
        PyErr_SetString(PyExc_TypeError,
7480
0
                        "execv() arg 2 must be a tuple or list");
7481
0
        return NULL;
7482
0
    }
7483
0
    argc = PySequence_Size(argv);
7484
0
    if (argc < 1) {
7485
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7486
0
        return NULL;
7487
0
    }
7488
7489
0
    argvlist = parse_arglist(argv, &argc);
7490
0
    if (argvlist == NULL) {
7491
0
        return NULL;
7492
0
    }
7493
0
    if (!argvlist[0][0]) {
7494
0
        PyErr_SetString(PyExc_ValueError,
7495
0
            "execv() arg 2 first element cannot be empty");
7496
0
        free_string_array(argvlist, argc);
7497
0
        return NULL;
7498
0
    }
7499
7500
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7501
0
        free_string_array(argvlist, argc);
7502
0
        return NULL;
7503
0
    }
7504
7505
0
    _Py_BEGIN_SUPPRESS_IPH
7506
#ifdef HAVE_WEXECV
7507
    _wexecv(path->wide, argvlist);
7508
#else
7509
0
    execv(path->narrow, argvlist);
7510
0
#endif
7511
0
    _Py_END_SUPPRESS_IPH
7512
7513
    /* If we get here it's definitely an error */
7514
7515
0
    posix_error();
7516
0
    free_string_array(argvlist, argc);
7517
0
    return NULL;
7518
0
}
7519
7520
7521
/*[clinic input]
7522
os.execve
7523
7524
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7525
        Path of executable file.
7526
    argv: object
7527
        Tuple or list of strings.
7528
    env: object
7529
        Dictionary of strings mapping to strings.
7530
7531
Execute an executable path with arguments, replacing current process.
7532
[clinic start generated code]*/
7533
7534
static PyObject *
7535
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7536
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7537
0
{
7538
0
    EXECV_CHAR **argvlist = NULL;
7539
0
    EXECV_CHAR **envlist;
7540
0
    Py_ssize_t argc, envc;
7541
7542
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7543
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7544
0
        PyErr_SetString(PyExc_RuntimeError,
7545
0
                        "exec not supported for isolated subinterpreters");
7546
0
        return NULL;
7547
0
    }
7548
7549
    /* execve has three arguments: (path, argv, env), where
7550
       argv is a list or tuple of strings and env is a dictionary
7551
       like posix.environ. */
7552
7553
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7554
0
        PyErr_SetString(PyExc_TypeError,
7555
0
                        "execve: argv must be a tuple or list");
7556
0
        goto fail_0;
7557
0
    }
7558
0
    argc = PySequence_Size(argv);
7559
0
    if (argc < 1) {
7560
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7561
0
        return NULL;
7562
0
    }
7563
7564
0
    if (!PyMapping_Check(env)) {
7565
0
        PyErr_SetString(PyExc_TypeError,
7566
0
                        "execve: environment must be a mapping object");
7567
0
        goto fail_0;
7568
0
    }
7569
7570
0
    argvlist = parse_arglist(argv, &argc);
7571
0
    if (argvlist == NULL) {
7572
0
        goto fail_0;
7573
0
    }
7574
0
    if (!argvlist[0][0]) {
7575
0
        PyErr_SetString(PyExc_ValueError,
7576
0
            "execve: argv first element cannot be empty");
7577
0
        goto fail_0;
7578
0
    }
7579
7580
0
    envlist = parse_envlist(env, &envc);
7581
0
    if (envlist == NULL)
7582
0
        goto fail_0;
7583
7584
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7585
0
        goto fail_1;
7586
0
    }
7587
7588
0
    _Py_BEGIN_SUPPRESS_IPH
7589
0
#ifdef HAVE_FEXECVE
7590
0
    if (path->is_fd)
7591
0
        fexecve(path->fd, argvlist, envlist);
7592
0
    else
7593
0
#endif
7594
#ifdef HAVE_WEXECV
7595
        _wexecve(path->wide, argvlist, envlist);
7596
#else
7597
0
        execve(path->narrow, argvlist, envlist);
7598
0
#endif
7599
0
    _Py_END_SUPPRESS_IPH
7600
7601
    /* If we get here it's definitely an error */
7602
7603
0
    posix_path_error(path);
7604
0
  fail_1:
7605
0
    free_string_array(envlist, envc);
7606
0
  fail_0:
7607
0
    if (argvlist)
7608
0
        free_string_array(argvlist, argc);
7609
0
    return NULL;
7610
0
}
7611
7612
#endif /* HAVE_EXECV */
7613
7614
#ifdef HAVE_POSIX_SPAWN
7615
7616
enum posix_spawn_file_actions_identifier {
7617
    POSIX_SPAWN_OPEN,
7618
    POSIX_SPAWN_CLOSE,
7619
    POSIX_SPAWN_DUP2
7620
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7621
    ,POSIX_SPAWN_CLOSEFROM
7622
#endif
7623
};
7624
7625
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7626
static int
7627
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7628
#endif
7629
7630
static int
7631
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7632
                        int resetids, int setsid, PyObject *setsigmask,
7633
                        PyObject *setsigdef, PyObject *scheduler,
7634
                        posix_spawnattr_t *attrp)
7635
0
{
7636
0
    assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
7637
0
    long all_flags = 0;
7638
7639
0
    errno = posix_spawnattr_init(attrp);
7640
0
    if (errno) {
7641
0
        posix_error();
7642
0
        return -1;
7643
0
    }
7644
7645
0
    if (setpgroup && setpgroup != Py_None) {
7646
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7647
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7648
0
            goto fail;
7649
0
        }
7650
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7651
0
        if (errno) {
7652
0
            posix_error();
7653
0
            goto fail;
7654
0
        }
7655
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7656
0
    }
7657
7658
0
    if (resetids) {
7659
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7660
0
    }
7661
7662
0
    if (setsid) {
7663
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7664
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7665
#endif
7666
0
#ifdef POSIX_SPAWN_SETSID
7667
0
        all_flags |= POSIX_SPAWN_SETSID;
7668
#elif defined(POSIX_SPAWN_SETSID_NP)
7669
        all_flags |= POSIX_SPAWN_SETSID_NP;
7670
#else
7671
        argument_unavailable_error(func_name, "setsid");
7672
        return -1;
7673
#endif
7674
7675
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7676
        } else {
7677
            argument_unavailable_error(func_name, "setsid");
7678
            return -1;
7679
        }
7680
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7681
7682
0
    }
7683
7684
0
#ifdef HAVE_SIGSET_T
7685
0
   if (setsigmask) {
7686
0
        sigset_t set;
7687
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7688
0
            goto fail;
7689
0
        }
7690
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7691
0
        if (errno) {
7692
0
            posix_error();
7693
0
            goto fail;
7694
0
        }
7695
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7696
0
    }
7697
7698
0
    if (setsigdef) {
7699
0
        sigset_t set;
7700
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7701
0
            goto fail;
7702
0
        }
7703
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7704
0
        if (errno) {
7705
0
            posix_error();
7706
0
            goto fail;
7707
0
        }
7708
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7709
0
    }
7710
#else
7711
    if (setsigmask || setsigdef) {
7712
        PyErr_SetString(PyExc_NotImplementedError,
7713
                        "sigset is not supported on this platform");
7714
        goto fail;
7715
    }
7716
#endif
7717
7718
0
    if (scheduler && scheduler != Py_None) {
7719
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7720
0
        PyObject *py_schedpolicy;
7721
0
        PyObject *schedparam_obj;
7722
0
        struct sched_param schedparam;
7723
7724
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7725
0
                        ";A scheduler tuple must have two elements",
7726
0
                        &py_schedpolicy, &schedparam_obj)) {
7727
0
            goto fail;
7728
0
        }
7729
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7730
0
            goto fail;
7731
0
        }
7732
0
        if (py_schedpolicy != Py_None) {
7733
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7734
7735
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7736
0
                goto fail;
7737
0
            }
7738
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7739
0
            if (errno) {
7740
0
                posix_error();
7741
0
                goto fail;
7742
0
            }
7743
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7744
0
        }
7745
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7746
0
        if (errno) {
7747
0
            posix_error();
7748
0
            goto fail;
7749
0
        }
7750
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7751
#else
7752
        PyErr_SetString(PyExc_NotImplementedError,
7753
                "The scheduler option is not supported in this system.");
7754
        goto fail;
7755
#endif
7756
0
    }
7757
7758
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7759
0
    if (errno) {
7760
0
        posix_error();
7761
0
        goto fail;
7762
0
    }
7763
7764
0
    return 0;
7765
7766
0
fail:
7767
0
    (void)posix_spawnattr_destroy(attrp);
7768
0
    return -1;
7769
0
}
7770
7771
static int
7772
parse_file_actions(PyObject *file_actions,
7773
                   posix_spawn_file_actions_t *file_actionsp,
7774
                   PyObject *temp_buffer)
7775
0
{
7776
0
    PyObject *seq;
7777
0
    PyObject *file_action = NULL;
7778
0
    PyObject *tag_obj;
7779
7780
0
    seq = PySequence_Fast(file_actions,
7781
0
                          "file_actions must be a sequence or None");
7782
0
    if (seq == NULL) {
7783
0
        return -1;
7784
0
    }
7785
7786
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7787
0
    if (errno) {
7788
0
        posix_error();
7789
0
        Py_DECREF(seq);
7790
0
        return -1;
7791
0
    }
7792
7793
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7794
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7795
0
        Py_INCREF(file_action);
7796
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7797
0
            PyErr_SetString(PyExc_TypeError,
7798
0
                "Each file_actions element must be a non-empty tuple");
7799
0
            goto fail;
7800
0
        }
7801
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7802
0
        if (tag == -1 && PyErr_Occurred()) {
7803
0
            goto fail;
7804
0
        }
7805
7806
        /* Populate the file_actions object */
7807
0
        switch (tag) {
7808
0
            case POSIX_SPAWN_OPEN: {
7809
0
                int fd, oflag;
7810
0
                PyObject *path;
7811
0
                unsigned long mode;
7812
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7813
0
                        ";A open file_action tuple must have 5 elements",
7814
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7815
0
                        &oflag, &mode))
7816
0
                {
7817
0
                    goto fail;
7818
0
                }
7819
0
                if (PyList_Append(temp_buffer, path)) {
7820
0
                    Py_DECREF(path);
7821
0
                    goto fail;
7822
0
                }
7823
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7824
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7825
0
                if (errno) {
7826
0
                    posix_error();
7827
0
                    Py_DECREF(path);
7828
0
                    goto fail;
7829
0
                }
7830
0
                Py_DECREF(path);
7831
0
                break;
7832
0
            }
7833
0
            case POSIX_SPAWN_CLOSE: {
7834
0
                int fd;
7835
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7836
0
                        ";A close file_action tuple must have 2 elements",
7837
0
                        &tag_obj, &fd))
7838
0
                {
7839
0
                    goto fail;
7840
0
                }
7841
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7842
0
                if (errno) {
7843
0
                    posix_error();
7844
0
                    goto fail;
7845
0
                }
7846
0
                break;
7847
0
            }
7848
0
            case POSIX_SPAWN_DUP2: {
7849
0
                int fd1, fd2;
7850
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7851
0
                        ";A dup2 file_action tuple must have 3 elements",
7852
0
                        &tag_obj, &fd1, &fd2))
7853
0
                {
7854
0
                    goto fail;
7855
0
                }
7856
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7857
0
                                                         fd1, fd2);
7858
0
                if (errno) {
7859
0
                    posix_error();
7860
0
                    goto fail;
7861
0
                }
7862
0
                break;
7863
0
            }
7864
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7865
            case POSIX_SPAWN_CLOSEFROM: {
7866
                int fd;
7867
                if (!PyArg_ParseTuple(file_action, "Oi"
7868
                        ";A closefrom file_action tuple must have 2 elements",
7869
                        &tag_obj, &fd))
7870
                {
7871
                    goto fail;
7872
                }
7873
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7874
                                                                 fd);
7875
                if (errno) {
7876
                    posix_error();
7877
                    goto fail;
7878
                }
7879
                break;
7880
            }
7881
#endif
7882
0
            default: {
7883
0
                PyErr_SetString(PyExc_TypeError,
7884
0
                                "Unknown file_actions identifier");
7885
0
                goto fail;
7886
0
            }
7887
0
        }
7888
0
        Py_DECREF(file_action);
7889
0
    }
7890
7891
0
    Py_DECREF(seq);
7892
0
    return 0;
7893
7894
0
fail:
7895
0
    Py_DECREF(seq);
7896
0
    Py_DECREF(file_action);
7897
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7898
0
    return -1;
7899
0
}
7900
7901
7902
static PyObject *
7903
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7904
               PyObject *env, PyObject *file_actions,
7905
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7906
               PyObject *setsigdef, PyObject *scheduler)
7907
0
{
7908
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7909
0
    EXECV_CHAR **argvlist = NULL;
7910
0
    EXECV_CHAR **envlist = NULL;
7911
0
    posix_spawn_file_actions_t file_actions_buf;
7912
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7913
0
    posix_spawnattr_t attr;
7914
0
    posix_spawnattr_t *attrp = NULL;
7915
0
    Py_ssize_t argc, envc;
7916
0
    PyObject *result = NULL;
7917
0
    PyObject *temp_buffer = NULL;
7918
0
    pid_t pid;
7919
0
    int err_code;
7920
7921
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7922
       argv is a list or tuple of strings and env is a dictionary
7923
       like posix.environ. */
7924
7925
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7926
0
        PyErr_Format(PyExc_TypeError,
7927
0
                     "%s: argv must be a tuple or list", func_name);
7928
0
        goto exit;
7929
0
    }
7930
0
    argc = PySequence_Size(argv);
7931
0
    if (argc < 1) {
7932
0
        PyErr_Format(PyExc_ValueError,
7933
0
                     "%s: argv must not be empty", func_name);
7934
0
        goto exit;
7935
0
    }
7936
7937
0
    if (!PyMapping_Check(env) && env != Py_None) {
7938
0
        PyErr_Format(PyExc_TypeError,
7939
0
                     "%s: environment must be a mapping object or None", func_name);
7940
0
        goto exit;
7941
0
    }
7942
7943
0
    if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7944
0
        PyErr_Format(PyExc_TypeError,
7945
0
                     "%s: scheduler must be a tuple or None", func_name);
7946
0
        goto exit;
7947
0
    }
7948
7949
0
    argvlist = parse_arglist(argv, &argc);
7950
0
    if (argvlist == NULL) {
7951
0
        goto exit;
7952
0
    }
7953
0
    if (!argvlist[0][0]) {
7954
0
        PyErr_Format(PyExc_ValueError,
7955
0
                     "%s: argv first element cannot be empty", func_name);
7956
0
        goto exit;
7957
0
    }
7958
7959
#ifdef USE_DARWIN_NS_GET_ENVIRON
7960
    // There is no environ global in this situation.
7961
    char **environ = NULL;
7962
#endif
7963
7964
0
    if (env == Py_None) {
7965
#ifdef USE_DARWIN_NS_GET_ENVIRON
7966
        environ = *_NSGetEnviron();
7967
#endif
7968
0
        envlist = environ;
7969
0
    } else {
7970
0
        envlist = parse_envlist(env, &envc);
7971
0
        if (envlist == NULL) {
7972
0
            goto exit;
7973
0
        }
7974
0
    }
7975
7976
0
    if (file_actions != NULL && file_actions != Py_None) {
7977
        /* There is a bug in old versions of glibc that makes some of the
7978
         * helper functions for manipulating file actions not copy the provided
7979
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7980
         * copy the value of path for some old versions of glibc (<2.20).
7981
         * The use of temp_buffer here is a workaround that keeps the
7982
         * python objects that own the buffers alive until posix_spawn gets called.
7983
         * Check https://bugs.python.org/issue33630 and
7984
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7985
0
        temp_buffer = PyList_New(0);
7986
0
        if (!temp_buffer) {
7987
0
            goto exit;
7988
0
        }
7989
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7990
0
            goto exit;
7991
0
        }
7992
0
        file_actionsp = &file_actions_buf;
7993
0
    }
7994
7995
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7996
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7997
0
        goto exit;
7998
0
    }
7999
0
    attrp = &attr;
8000
8001
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
8002
0
        goto exit;
8003
0
    }
8004
8005
0
    _Py_BEGIN_SUPPRESS_IPH
8006
0
#ifdef HAVE_POSIX_SPAWNP
8007
0
    if (use_posix_spawnp) {
8008
0
        err_code = posix_spawnp(&pid, path->narrow,
8009
0
                                file_actionsp, attrp, argvlist, envlist);
8010
0
    }
8011
0
    else
8012
0
#endif /* HAVE_POSIX_SPAWNP */
8013
0
    {
8014
0
        err_code = posix_spawn(&pid, path->narrow,
8015
0
                               file_actionsp, attrp, argvlist, envlist);
8016
0
    }
8017
0
    _Py_END_SUPPRESS_IPH
8018
8019
0
    if (err_code) {
8020
0
        errno = err_code;
8021
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8022
0
        goto exit;
8023
0
    }
8024
#ifdef _Py_MEMORY_SANITIZER
8025
    __msan_unpoison(&pid, sizeof(pid));
8026
#endif
8027
0
    result = PyLong_FromPid(pid);
8028
8029
0
exit:
8030
0
    if (file_actionsp) {
8031
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
8032
0
    }
8033
0
    if (attrp) {
8034
0
        (void)posix_spawnattr_destroy(attrp);
8035
0
    }
8036
0
    if (envlist && envlist != environ) {
8037
0
        free_string_array(envlist, envc);
8038
0
    }
8039
0
    if (argvlist) {
8040
0
        free_string_array(argvlist, argc);
8041
0
    }
8042
0
    Py_XDECREF(temp_buffer);
8043
0
    return result;
8044
0
}
8045
8046
8047
/*[clinic input]
8048
8049
os.posix_spawn
8050
    path: path_t
8051
        Path of executable file.
8052
    argv: object
8053
        Tuple or list of strings.
8054
    env: object
8055
        Dictionary of strings mapping to strings.
8056
    /
8057
    *
8058
    file_actions: object(c_default='NULL') = ()
8059
        A sequence of file action tuples.
8060
    setpgroup: object(c_default='NULL') = None
8061
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8062
    resetids: bool = False
8063
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8064
    setsid: bool = False
8065
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP
8066
        will be activated.
8067
    setsigmask: object(c_default='NULL') = ()
8068
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8069
    setsigdef: object(c_default='NULL') = ()
8070
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8071
    scheduler: object(c_default='NULL') = None
8072
        A tuple with the scheduler policy (optional) and parameters.
8073
8074
Execute the program specified by path in a new process.
8075
[clinic start generated code]*/
8076
8077
static PyObject *
8078
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8079
                    PyObject *env, PyObject *file_actions,
8080
                    PyObject *setpgroup, int resetids, int setsid,
8081
                    PyObject *setsigmask, PyObject *setsigdef,
8082
                    PyObject *scheduler)
8083
/*[clinic end generated code: output=14a1098c566bc675 input=c7592dcbc96e8114]*/
8084
0
{
8085
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8086
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8087
0
                          scheduler);
8088
0
}
8089
 #endif /* HAVE_POSIX_SPAWN */
8090
8091
8092
8093
#ifdef HAVE_POSIX_SPAWNP
8094
/*[clinic input]
8095
8096
os.posix_spawnp
8097
    path: path_t
8098
        Path of executable file.
8099
    argv: object
8100
        Tuple or list of strings.
8101
    env: object
8102
        Dictionary of strings mapping to strings.
8103
    /
8104
    *
8105
    file_actions: object(c_default='NULL') = ()
8106
        A sequence of file action tuples.
8107
    setpgroup: object(c_default='NULL') = None
8108
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8109
    resetids: bool = False
8110
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8111
    setsid: bool = False
8112
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP
8113
        will be activated.
8114
    setsigmask: object(c_default='NULL') = ()
8115
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8116
    setsigdef: object(c_default='NULL') = ()
8117
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8118
    scheduler: object(c_default='NULL') = None
8119
        A tuple with the scheduler policy (optional) and parameters.
8120
8121
Execute the program specified by path in a new process.
8122
[clinic start generated code]*/
8123
8124
static PyObject *
8125
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8126
                     PyObject *env, PyObject *file_actions,
8127
                     PyObject *setpgroup, int resetids, int setsid,
8128
                     PyObject *setsigmask, PyObject *setsigdef,
8129
                     PyObject *scheduler)
8130
/*[clinic end generated code: output=7b9aaefe3031238d input=43ccc1452cae2be3]*/
8131
0
{
8132
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8133
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8134
0
                          scheduler);
8135
0
}
8136
#endif /* HAVE_POSIX_SPAWNP */
8137
8138
#ifdef HAVE_RTPSPAWN
8139
static intptr_t
8140
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8141
               const char  *envp[])
8142
{
8143
     RTP_ID rtpid;
8144
     int status;
8145
     pid_t res;
8146
     int async_err = 0;
8147
8148
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8149
        uStackSize=0 cannot be used, the default stack size is too small for
8150
        Python. */
8151
     if (envp) {
8152
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8153
                          100, 0x1000000, 0, VX_FP_TASK);
8154
     }
8155
     else {
8156
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8157
                          100, 0x1000000, 0, VX_FP_TASK);
8158
     }
8159
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8160
         do {
8161
             res = waitpid((pid_t)rtpid, &status, 0);
8162
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8163
8164
         if (res < 0)
8165
             return RTP_ID_ERROR;
8166
         return ((intptr_t)status);
8167
     }
8168
     return ((intptr_t)rtpid);
8169
}
8170
#endif
8171
8172
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8173
/*[clinic input]
8174
os.spawnv
8175
8176
    mode: int
8177
        Mode of process creation.
8178
    path: path_t
8179
        Path of executable file.
8180
    argv: object
8181
        Tuple or list of strings.
8182
    /
8183
8184
Execute the program specified by path in a new process.
8185
[clinic start generated code]*/
8186
8187
static PyObject *
8188
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8189
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8190
{
8191
    EXECV_CHAR **argvlist;
8192
    int i;
8193
    Py_ssize_t argc;
8194
    intptr_t spawnval;
8195
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8196
8197
    /* spawnv has three arguments: (mode, path, argv), where
8198
       argv is a list or tuple of strings. */
8199
8200
    if (PyList_Check(argv)) {
8201
        argc = PyList_Size(argv);
8202
        getitem = PyList_GetItem;
8203
    }
8204
    else if (PyTuple_Check(argv)) {
8205
        argc = PyTuple_Size(argv);
8206
        getitem = PyTuple_GetItem;
8207
    }
8208
    else {
8209
        PyErr_SetString(PyExc_TypeError,
8210
                        "spawnv() arg 2 must be a tuple or list");
8211
        return NULL;
8212
    }
8213
    if (argc == 0) {
8214
        PyErr_SetString(PyExc_ValueError,
8215
            "spawnv() arg 2 cannot be empty");
8216
        return NULL;
8217
    }
8218
8219
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8220
    if (argvlist == NULL) {
8221
        return PyErr_NoMemory();
8222
    }
8223
    for (i = 0; i < argc; i++) {
8224
        if (!fsconvert_strdup((*getitem)(argv, i),
8225
                              &argvlist[i])) {
8226
            free_string_array(argvlist, i);
8227
            PyErr_SetString(
8228
                PyExc_TypeError,
8229
                "spawnv() arg 2 must contain only strings");
8230
            return NULL;
8231
        }
8232
        if (i == 0 && !argvlist[0][0]) {
8233
            free_string_array(argvlist, i + 1);
8234
            PyErr_SetString(
8235
                PyExc_ValueError,
8236
                "spawnv() arg 2 first element cannot be empty");
8237
            return NULL;
8238
        }
8239
    }
8240
    argvlist[argc] = NULL;
8241
8242
#if !defined(HAVE_RTPSPAWN)
8243
    if (mode == _OLD_P_OVERLAY)
8244
        mode = _P_OVERLAY;
8245
#endif
8246
8247
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8248
                    Py_None) < 0) {
8249
        free_string_array(argvlist, argc);
8250
        return NULL;
8251
    }
8252
8253
    Py_BEGIN_ALLOW_THREADS
8254
    _Py_BEGIN_SUPPRESS_IPH
8255
#ifdef HAVE_WSPAWNV
8256
    spawnval = _wspawnv(mode, path->wide, argvlist);
8257
#elif defined(HAVE_RTPSPAWN)
8258
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8259
#else
8260
    spawnval = _spawnv(mode, path->narrow, argvlist);
8261
#endif
8262
    _Py_END_SUPPRESS_IPH
8263
    Py_END_ALLOW_THREADS
8264
8265
    int saved_errno = errno;
8266
    free_string_array(argvlist, argc);
8267
8268
    if (spawnval == -1) {
8269
        errno = saved_errno;
8270
        posix_error();
8271
        return NULL;
8272
    }
8273
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8274
}
8275
8276
/*[clinic input]
8277
os.spawnve
8278
8279
    mode: int
8280
        Mode of process creation.
8281
    path: path_t
8282
        Path of executable file.
8283
    argv: object
8284
        Tuple or list of strings.
8285
    env: object
8286
        Dictionary of strings mapping to strings.
8287
    /
8288
8289
Execute the program specified by path in a new process.
8290
[clinic start generated code]*/
8291
8292
static PyObject *
8293
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8294
                PyObject *env)
8295
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8296
{
8297
    EXECV_CHAR **argvlist;
8298
    EXECV_CHAR **envlist;
8299
    PyObject *res = NULL;
8300
    Py_ssize_t argc, i, envc;
8301
    intptr_t spawnval;
8302
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8303
    Py_ssize_t lastarg = 0;
8304
8305
    /* spawnve has four arguments: (mode, path, argv, env), where
8306
       argv is a list or tuple of strings and env is a dictionary
8307
       like posix.environ. */
8308
8309
    if (PyList_Check(argv)) {
8310
        argc = PyList_Size(argv);
8311
        getitem = PyList_GetItem;
8312
    }
8313
    else if (PyTuple_Check(argv)) {
8314
        argc = PyTuple_Size(argv);
8315
        getitem = PyTuple_GetItem;
8316
    }
8317
    else {
8318
        PyErr_SetString(PyExc_TypeError,
8319
                        "spawnve() arg 2 must be a tuple or list");
8320
        goto fail_0;
8321
    }
8322
    if (argc == 0) {
8323
        PyErr_SetString(PyExc_ValueError,
8324
            "spawnve() arg 2 cannot be empty");
8325
        goto fail_0;
8326
    }
8327
    if (!PyMapping_Check(env)) {
8328
        PyErr_SetString(PyExc_TypeError,
8329
                        "spawnve() arg 3 must be a mapping object");
8330
        goto fail_0;
8331
    }
8332
8333
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8334
    if (argvlist == NULL) {
8335
        PyErr_NoMemory();
8336
        goto fail_0;
8337
    }
8338
    for (i = 0; i < argc; i++) {
8339
        if (!fsconvert_strdup((*getitem)(argv, i),
8340
                              &argvlist[i]))
8341
        {
8342
            lastarg = i;
8343
            goto fail_1;
8344
        }
8345
        if (i == 0 && !argvlist[0][0]) {
8346
            lastarg = i + 1;
8347
            PyErr_SetString(
8348
                PyExc_ValueError,
8349
                "spawnv() arg 2 first element cannot be empty");
8350
            goto fail_1;
8351
        }
8352
    }
8353
    lastarg = argc;
8354
    argvlist[argc] = NULL;
8355
8356
    envlist = parse_envlist(env, &envc);
8357
    if (envlist == NULL)
8358
        goto fail_1;
8359
8360
#if !defined(HAVE_RTPSPAWN)
8361
    if (mode == _OLD_P_OVERLAY)
8362
        mode = _P_OVERLAY;
8363
#endif
8364
8365
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8366
        goto fail_2;
8367
    }
8368
8369
    Py_BEGIN_ALLOW_THREADS
8370
    _Py_BEGIN_SUPPRESS_IPH
8371
#ifdef HAVE_WSPAWNV
8372
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8373
#elif defined(HAVE_RTPSPAWN)
8374
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8375
                           (const char **)envlist);
8376
#else
8377
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8378
#endif
8379
    _Py_END_SUPPRESS_IPH
8380
    Py_END_ALLOW_THREADS
8381
8382
    if (spawnval == -1)
8383
        (void) posix_error();
8384
    else
8385
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8386
8387
  fail_2:
8388
    while (--envc >= 0) {
8389
        PyMem_Free(envlist[envc]);
8390
    }
8391
    PyMem_Free(envlist);
8392
  fail_1:
8393
    free_string_array(argvlist, lastarg);
8394
  fail_0:
8395
    return res;
8396
}
8397
8398
#endif /* HAVE_SPAWNV */
8399
8400
#ifdef HAVE_FORK
8401
8402
/* Helper function to validate arguments.
8403
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8404
   If obj is non-NULL it must be callable.  */
8405
static int
8406
check_null_or_callable(PyObject *obj, const char* obj_name)
8407
84
{
8408
84
    if (obj && !PyCallable_Check(obj)) {
8409
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8410
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8411
0
        return -1;
8412
0
    }
8413
84
    return 0;
8414
84
}
8415
8416
/*[clinic input]
8417
os.register_at_fork
8418
8419
    *
8420
    before: object=NULL
8421
        A callable to be called in the parent before the fork() syscall.
8422
    after_in_child: object=NULL
8423
        A callable to be called in the child after fork().
8424
    after_in_parent: object=NULL
8425
        A callable to be called in the parent after fork().
8426
8427
Register callables to be called when forking a new process.
8428
8429
'before' callbacks are called in reverse order.
8430
'after_in_child' and 'after_in_parent' callbacks are called in order.
8431
8432
[clinic start generated code]*/
8433
8434
static PyObject *
8435
os_register_at_fork_impl(PyObject *module, PyObject *before,
8436
                         PyObject *after_in_child, PyObject *after_in_parent)
8437
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8438
28
{
8439
28
    PyInterpreterState *interp;
8440
8441
28
    if (!before && !after_in_child && !after_in_parent) {
8442
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8443
0
        return NULL;
8444
0
    }
8445
28
    if (check_null_or_callable(before, "before") ||
8446
28
        check_null_or_callable(after_in_child, "after_in_child") ||
8447
28
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8448
0
        return NULL;
8449
0
    }
8450
28
    interp = _PyInterpreterState_GET();
8451
8452
28
    if (register_at_forker(&interp->before_forkers, before)) {
8453
0
        return NULL;
8454
0
    }
8455
28
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8456
0
        return NULL;
8457
0
    }
8458
28
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8459
0
        return NULL;
8460
0
    }
8461
28
    Py_RETURN_NONE;
8462
28
}
8463
#endif /* HAVE_FORK */
8464
8465
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8466
// Common code to raise a warning if we detect there is more than one thread
8467
// running in the process. Best effort, silent if unable to count threads.
8468
// Constraint: Quick. Never overcounts. Never leaves an error set.
8469
//
8470
// This MUST only be called from the parent process after
8471
// PyOS_AfterFork_Parent().
8472
static int
8473
warn_about_fork_with_threads(
8474
    const char* name,  // Name of the API to use in the warning message.
8475
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8476
)
8477
0
{
8478
    // It's not safe to issue the warning while the world is stopped, because
8479
    // other threads might be holding locks that we need, which would deadlock.
8480
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8481
8482
0
    Py_ssize_t num_python_threads = num_os_threads;
8483
0
    if (num_python_threads <= 0) {
8484
        // Fall back to just the number our threading module knows about.
8485
        // An incomplete view of the world, but better than nothing.
8486
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8487
0
        if (!threading) {
8488
0
            PyErr_Clear();
8489
0
            return 0;
8490
0
        }
8491
0
        PyObject *threading_active =
8492
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8493
0
        if (!threading_active) {
8494
0
            PyErr_Clear();
8495
0
            Py_DECREF(threading);
8496
0
            return 0;
8497
0
        }
8498
0
        PyObject *threading_limbo =
8499
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8500
0
        if (!threading_limbo) {
8501
0
            PyErr_Clear();
8502
0
            Py_DECREF(threading);
8503
0
            Py_DECREF(threading_active);
8504
0
            return 0;
8505
0
        }
8506
0
        Py_DECREF(threading);
8507
        // Duplicating what threading.active_count() does but without holding
8508
        // threading._active_limbo_lock so our count could be inaccurate if
8509
        // these dicts are mid-update from another thread.  Not a big deal.
8510
        // Worst case if someone replaced threading._active or threading._limbo
8511
        // with non-dicts, we get -1 from *Length() below and undercount.
8512
        // Nobody should, but we're best effort so we clear errors and move on.
8513
0
        num_python_threads = (PyMapping_Length(threading_active)
8514
0
                              + PyMapping_Length(threading_limbo));
8515
0
        PyErr_Clear();
8516
0
        Py_DECREF(threading_active);
8517
0
        Py_DECREF(threading_limbo);
8518
0
    }
8519
0
    if (num_python_threads > 1) {
8520
0
        return PyErr_WarnFormat(
8521
0
                PyExc_DeprecationWarning, 1,
8522
0
#ifdef HAVE_GETPID
8523
0
                "This process (pid=%d) is multi-threaded, "
8524
#else
8525
                "This process is multi-threaded, "
8526
#endif
8527
0
                "use of %s() may lead to deadlocks in the child.",
8528
0
#ifdef HAVE_GETPID
8529
0
                getpid(),
8530
0
#endif
8531
0
                name);
8532
0
    }
8533
0
    return 0;
8534
0
}
8535
8536
// If this returns <= 0, we were unable to successfully use any OS APIs.
8537
// Returns a positive number of threads otherwise.
8538
static Py_ssize_t get_number_of_os_threads(void)
8539
0
{
8540
    // TODO: Consider making an `os` module API to return the current number
8541
    // of threads in the process. That'd presumably use this platform code but
8542
    // raise an error rather than using the inaccurate fallback.
8543
0
    Py_ssize_t num_python_threads = 0;
8544
#if defined(__APPLE__) && defined(HAVE_GETPID)
8545
    mach_port_t macos_self = mach_task_self();
8546
    mach_port_t macos_task;
8547
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8548
        thread_array_t macos_threads;
8549
        mach_msg_type_number_t macos_n_threads;
8550
        if (task_threads(macos_task, &macos_threads,
8551
                         &macos_n_threads) == KERN_SUCCESS) {
8552
            num_python_threads = macos_n_threads;
8553
        }
8554
    }
8555
#elif defined(__linux__)
8556
    // Linux /proc/self/stat 20th field is the number of threads.
8557
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8558
0
    if (proc_stat) {
8559
0
        size_t n;
8560
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8561
        // observed on the author's workstation.
8562
0
        char stat_line[160];
8563
0
        n = fread(&stat_line, 1, 159, proc_stat);
8564
0
        stat_line[n] = '\0';
8565
0
        fclose(proc_stat);
8566
8567
0
        char *saveptr = NULL;
8568
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8569
0
        unsigned int idx;
8570
0
        for (idx = 19; idx && field; --idx) {
8571
0
            field = strtok_r(NULL, " ", &saveptr);
8572
0
        }
8573
0
        if (idx == 0 && field) {  // found the 20th field
8574
0
            num_python_threads = atoi(field);  // 0 on error
8575
0
        }
8576
0
    }
8577
0
#endif
8578
0
    return num_python_threads;
8579
0
}
8580
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8581
8582
#ifdef HAVE_FORK1
8583
/*[clinic input]
8584
os.fork1
8585
8586
Fork a child process with a single multiplexed (i.e., not bound) thread.
8587
8588
Return 0 to child process and PID of child to parent process.
8589
[clinic start generated code]*/
8590
8591
static PyObject *
8592
os_fork1_impl(PyObject *module)
8593
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8594
{
8595
    pid_t pid;
8596
8597
    PyInterpreterState *interp = _PyInterpreterState_GET();
8598
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8599
        PyErr_SetString(PyExc_PythonFinalizationError,
8600
                        "can't fork at interpreter shutdown");
8601
        return NULL;
8602
    }
8603
    if (!_Py_IsMainInterpreter(interp)) {
8604
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8605
        return NULL;
8606
    }
8607
    PyOS_BeforeFork();
8608
    pid = fork1();
8609
    int saved_errno = errno;
8610
    if (pid == 0) {
8611
        /* child: this clobbers and resets the import lock. */
8612
        PyOS_AfterFork_Child();
8613
    } else {
8614
        // Called before AfterFork_Parent in case those hooks start threads.
8615
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8616
        /* parent: release the import lock. */
8617
        PyOS_AfterFork_Parent();
8618
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8619
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8620
            return NULL;
8621
        }
8622
    }
8623
    if (pid == -1) {
8624
        errno = saved_errno;
8625
        return posix_error();
8626
    }
8627
    return PyLong_FromPid(pid);
8628
}
8629
#endif /* HAVE_FORK1 */
8630
8631
8632
#ifdef HAVE_FORK
8633
/*[clinic input]
8634
os.fork
8635
8636
Fork a child process.
8637
8638
Return 0 to child process and PID of child to parent process.
8639
[clinic start generated code]*/
8640
8641
static PyObject *
8642
os_fork_impl(PyObject *module)
8643
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8644
0
{
8645
0
    pid_t pid;
8646
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8647
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8648
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8649
0
                        "can't fork at interpreter shutdown");
8650
0
        return NULL;
8651
0
    }
8652
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8653
0
        PyErr_SetString(PyExc_RuntimeError,
8654
0
                        "fork not supported for isolated subinterpreters");
8655
0
        return NULL;
8656
0
    }
8657
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8658
0
        return NULL;
8659
0
    }
8660
0
    PyOS_BeforeFork();
8661
0
    pid = fork();
8662
0
    int saved_errno = errno;
8663
0
    if (pid == 0) {
8664
        /* child: this clobbers and resets the import lock. */
8665
0
        PyOS_AfterFork_Child();
8666
0
    } else {
8667
        // Called before AfterFork_Parent in case those hooks start threads.
8668
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8669
        /* parent: release the import lock. */
8670
0
        PyOS_AfterFork_Parent();
8671
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8672
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8673
0
            return NULL;
8674
0
    }
8675
0
    if (pid == -1) {
8676
0
        errno = saved_errno;
8677
0
        return posix_error();
8678
0
    }
8679
0
    return PyLong_FromPid(pid);
8680
0
}
8681
#endif /* HAVE_FORK */
8682
8683
8684
#ifdef HAVE_SCHED_H
8685
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8686
/*[clinic input]
8687
os.sched_get_priority_max
8688
8689
    policy: int
8690
8691
Get the maximum scheduling priority for policy.
8692
[clinic start generated code]*/
8693
8694
static PyObject *
8695
os_sched_get_priority_max_impl(PyObject *module, int policy)
8696
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8697
0
{
8698
    /* make sure that errno is cleared before the call */
8699
0
    errno = 0;
8700
0
    int max = sched_get_priority_max(policy);
8701
0
    if (max == -1 && errno)
8702
0
        return posix_error();
8703
0
    return PyLong_FromLong(max);
8704
0
}
8705
8706
8707
/*[clinic input]
8708
os.sched_get_priority_min
8709
8710
    policy: int
8711
8712
Get the minimum scheduling priority for policy.
8713
[clinic start generated code]*/
8714
8715
static PyObject *
8716
os_sched_get_priority_min_impl(PyObject *module, int policy)
8717
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8718
0
{
8719
    /* make sure that errno is cleared before the call */
8720
0
    errno = 0;
8721
0
    int min = sched_get_priority_min(policy);
8722
0
    if (min == -1 && errno)
8723
0
        return posix_error();
8724
0
    return PyLong_FromLong(min);
8725
0
}
8726
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8727
8728
8729
#ifdef HAVE_SCHED_SETSCHEDULER
8730
/*[clinic input]
8731
os.sched_getscheduler
8732
    pid: pid_t
8733
    /
8734
8735
Get the scheduling policy for the process identified by pid.
8736
8737
Passing 0 for pid returns the scheduling policy for the calling process.
8738
[clinic start generated code]*/
8739
8740
static PyObject *
8741
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8742
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8743
0
{
8744
0
    int policy;
8745
8746
0
    policy = sched_getscheduler(pid);
8747
0
    if (policy < 0)
8748
0
        return posix_error();
8749
0
    return PyLong_FromLong(policy);
8750
0
}
8751
#endif /* HAVE_SCHED_SETSCHEDULER */
8752
8753
8754
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8755
/*[clinic input]
8756
class os.sched_param "PyObject *" "SchedParamType"
8757
8758
@classmethod
8759
os.sched_param.__new__
8760
8761
    sched_priority: object
8762
        A scheduling parameter.
8763
8764
Currently has only one field: sched_priority
8765
[clinic start generated code]*/
8766
8767
static PyObject *
8768
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8769
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8770
0
{
8771
0
    PyObject *res;
8772
8773
0
    res = PyStructSequence_New(type);
8774
0
    if (!res)
8775
0
        return NULL;
8776
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8777
0
    return res;
8778
0
}
8779
8780
static PyObject *
8781
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8782
0
{
8783
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8784
0
}
8785
8786
static PyMethodDef os_sched_param_reduce_method = {
8787
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8788
};
8789
8790
PyDoc_VAR(os_sched_param__doc__);
8791
8792
static PyStructSequence_Field sched_param_fields[] = {
8793
    {"sched_priority", "the scheduling priority"},
8794
    {0}
8795
};
8796
8797
static PyStructSequence_Desc sched_param_desc = {
8798
    MODNAME ".sched_param", /* name */
8799
    os_sched_param__doc__, /* doc */
8800
    sched_param_fields,
8801
    1
8802
};
8803
8804
static int
8805
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8806
0
{
8807
0
    long priority;
8808
8809
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8810
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8811
0
        return 0;
8812
0
    }
8813
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8814
0
    if (priority == -1 && PyErr_Occurred())
8815
0
        return 0;
8816
0
    if (priority > INT_MAX || priority < INT_MIN) {
8817
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8818
0
        return 0;
8819
0
    }
8820
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8821
0
    return 1;
8822
0
}
8823
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8824
8825
8826
#ifdef HAVE_SCHED_SETSCHEDULER
8827
/*[clinic input]
8828
os.sched_setscheduler
8829
8830
    pid: pid_t
8831
    policy: int
8832
    param as param_obj: object
8833
    /
8834
8835
Set the scheduling policy for the process identified by pid.
8836
8837
If pid is 0, the calling process is changed.
8838
param is an instance of sched_param.
8839
[clinic start generated code]*/
8840
8841
static PyObject *
8842
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8843
                           PyObject *param_obj)
8844
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8845
0
{
8846
0
    struct sched_param param;
8847
0
    if (!convert_sched_param(module, param_obj, &param)) {
8848
0
        return NULL;
8849
0
    }
8850
8851
    /*
8852
    ** sched_setscheduler() returns 0 in Linux, but the previous
8853
    ** scheduling policy under Solaris/Illumos, and others.
8854
    ** On error, -1 is returned in all Operating Systems.
8855
    */
8856
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8857
0
        return posix_error();
8858
0
    Py_RETURN_NONE;
8859
0
}
8860
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8861
8862
8863
#ifdef HAVE_SCHED_SETPARAM
8864
/*[clinic input]
8865
os.sched_getparam
8866
    pid: pid_t
8867
    /
8868
8869
Returns scheduling parameters for the process identified by pid.
8870
8871
If pid is 0, returns parameters for the calling process.
8872
Return value is an instance of sched_param.
8873
[clinic start generated code]*/
8874
8875
static PyObject *
8876
os_sched_getparam_impl(PyObject *module, pid_t pid)
8877
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8878
0
{
8879
0
    struct sched_param param;
8880
0
    PyObject *result;
8881
0
    PyObject *priority;
8882
8883
0
    if (sched_getparam(pid, &param))
8884
0
        return posix_error();
8885
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8886
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8887
0
    if (!result)
8888
0
        return NULL;
8889
0
    priority = PyLong_FromLong(param.sched_priority);
8890
0
    if (!priority) {
8891
0
        Py_DECREF(result);
8892
0
        return NULL;
8893
0
    }
8894
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8895
0
    return result;
8896
0
}
8897
8898
8899
/*[clinic input]
8900
os.sched_setparam
8901
    pid: pid_t
8902
    param as param_obj: object
8903
    /
8904
8905
Set scheduling parameters for the process identified by pid.
8906
8907
If pid is 0, sets parameters for the calling process.
8908
param should be an instance of sched_param.
8909
[clinic start generated code]*/
8910
8911
static PyObject *
8912
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8913
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8914
0
{
8915
0
    struct sched_param param;
8916
0
    if (!convert_sched_param(module, param_obj, &param)) {
8917
0
        return NULL;
8918
0
    }
8919
8920
0
    if (sched_setparam(pid, &param))
8921
0
        return posix_error();
8922
0
    Py_RETURN_NONE;
8923
0
}
8924
#endif /* HAVE_SCHED_SETPARAM */
8925
8926
8927
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8928
/*[clinic input]
8929
@permit_long_summary
8930
os.sched_rr_get_interval -> double
8931
    pid: pid_t
8932
    /
8933
8934
Return the round-robin quantum for the process identified by pid, in seconds.
8935
8936
Value returned is a float.
8937
[clinic start generated code]*/
8938
8939
static double
8940
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8941
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8942
0
{
8943
0
    struct timespec interval;
8944
0
    if (sched_rr_get_interval(pid, &interval)) {
8945
0
        posix_error();
8946
0
        return -1.0;
8947
0
    }
8948
#ifdef _Py_MEMORY_SANITIZER
8949
    __msan_unpoison(&interval, sizeof(interval));
8950
#endif
8951
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8952
0
}
8953
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8954
8955
8956
/*[clinic input]
8957
os.sched_yield
8958
8959
Voluntarily relinquish the CPU.
8960
[clinic start generated code]*/
8961
8962
static PyObject *
8963
os_sched_yield_impl(PyObject *module)
8964
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8965
0
{
8966
0
    int result;
8967
0
    Py_BEGIN_ALLOW_THREADS
8968
0
    result = sched_yield();
8969
0
    Py_END_ALLOW_THREADS
8970
0
    if (result < 0) {
8971
0
        return posix_error();
8972
0
    }
8973
0
    Py_RETURN_NONE;
8974
0
}
8975
8976
#ifdef HAVE_SCHED_SETAFFINITY
8977
/* The minimum number of CPUs allocated in a cpu_set_t */
8978
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8979
8980
/*[clinic input]
8981
os.sched_setaffinity
8982
    pid: pid_t
8983
    mask : object
8984
    /
8985
8986
Set the CPU affinity of the process identified by pid to mask.
8987
8988
mask should be an iterable of integers identifying CPUs.
8989
[clinic start generated code]*/
8990
8991
static PyObject *
8992
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8993
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8994
0
{
8995
0
    int ncpus;
8996
0
    size_t setsize;
8997
0
    cpu_set_t *cpu_set = NULL;
8998
0
    PyObject *iterator = NULL, *item;
8999
9000
0
    iterator = PyObject_GetIter(mask);
9001
0
    if (iterator == NULL)
9002
0
        return NULL;
9003
9004
0
    ncpus = NCPUS_START;
9005
0
    setsize = CPU_ALLOC_SIZE(ncpus);
9006
0
    cpu_set = CPU_ALLOC(ncpus);
9007
0
    if (cpu_set == NULL) {
9008
0
        PyErr_NoMemory();
9009
0
        goto error;
9010
0
    }
9011
0
    CPU_ZERO_S(setsize, cpu_set);
9012
9013
0
    while ((item = PyIter_Next(iterator))) {
9014
0
        long cpu;
9015
0
        if (!PyIndex_Check(item)) {
9016
0
            PyErr_Format(PyExc_TypeError,
9017
0
                        "expected an iterator of ints, "
9018
0
                        "but iterator yielded %R",
9019
0
                        Py_TYPE(item));
9020
0
            Py_DECREF(item);
9021
0
            goto error;
9022
0
        }
9023
0
        cpu = PyLong_AsLong(item);
9024
0
        Py_DECREF(item);
9025
0
        if (cpu < 0) {
9026
0
            if (!PyErr_Occurred())
9027
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9028
0
            goto error;
9029
0
        }
9030
0
        if (cpu > INT_MAX - 1) {
9031
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9032
0
            goto error;
9033
0
        }
9034
0
        if (cpu >= ncpus) {
9035
            /* Grow CPU mask to fit the CPU number */
9036
0
            int newncpus = ncpus;
9037
0
            cpu_set_t *newmask;
9038
0
            size_t newsetsize;
9039
0
            while (newncpus <= cpu) {
9040
0
                if (newncpus > INT_MAX / 2)
9041
0
                    newncpus = cpu + 1;
9042
0
                else
9043
0
                    newncpus = newncpus * 2;
9044
0
            }
9045
0
            newmask = CPU_ALLOC(newncpus);
9046
0
            if (newmask == NULL) {
9047
0
                PyErr_NoMemory();
9048
0
                goto error;
9049
0
            }
9050
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9051
0
            CPU_ZERO_S(newsetsize, newmask);
9052
0
            memcpy(newmask, cpu_set, setsize);
9053
0
            CPU_FREE(cpu_set);
9054
0
            setsize = newsetsize;
9055
0
            cpu_set = newmask;
9056
0
            ncpus = newncpus;
9057
0
        }
9058
0
        CPU_SET_S(cpu, setsize, cpu_set);
9059
0
    }
9060
0
    if (PyErr_Occurred()) {
9061
0
        goto error;
9062
0
    }
9063
0
    Py_CLEAR(iterator);
9064
9065
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9066
0
        posix_error();
9067
0
        goto error;
9068
0
    }
9069
0
    CPU_FREE(cpu_set);
9070
0
    Py_RETURN_NONE;
9071
9072
0
error:
9073
0
    if (cpu_set)
9074
0
        CPU_FREE(cpu_set);
9075
0
    Py_XDECREF(iterator);
9076
0
    return NULL;
9077
0
}
9078
9079
9080
/*[clinic input]
9081
@permit_long_summary
9082
os.sched_getaffinity
9083
    pid: pid_t
9084
    /
9085
9086
Return the affinity of the process identified by pid (or the current process if zero).
9087
9088
The affinity is returned as a set of CPU identifiers.
9089
[clinic start generated code]*/
9090
9091
static PyObject *
9092
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9093
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9094
0
{
9095
0
    int ncpus = NCPUS_START;
9096
0
    size_t setsize;
9097
0
    cpu_set_t *mask;
9098
9099
0
    while (1) {
9100
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9101
0
        mask = CPU_ALLOC(ncpus);
9102
0
        if (mask == NULL) {
9103
0
            return PyErr_NoMemory();
9104
0
        }
9105
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9106
0
            break;
9107
0
        }
9108
0
        CPU_FREE(mask);
9109
0
        if (errno != EINVAL) {
9110
0
            return posix_error();
9111
0
        }
9112
0
        if (ncpus > INT_MAX / 2) {
9113
0
            PyErr_SetString(PyExc_OverflowError,
9114
0
                            "could not allocate a large enough CPU set");
9115
0
            return NULL;
9116
0
        }
9117
0
        ncpus *= 2;
9118
0
    }
9119
9120
0
    PyObject *res = PySet_New(NULL);
9121
0
    if (res == NULL) {
9122
0
        goto error;
9123
0
    }
9124
9125
0
    int cpu = 0;
9126
0
    int count = CPU_COUNT_S(setsize, mask);
9127
0
    for (; count; cpu++) {
9128
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9129
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9130
0
            --count;
9131
0
            if (cpu_num == NULL) {
9132
0
                goto error;
9133
0
            }
9134
0
            if (PySet_Add(res, cpu_num)) {
9135
0
                Py_DECREF(cpu_num);
9136
0
                goto error;
9137
0
            }
9138
0
            Py_DECREF(cpu_num);
9139
0
        }
9140
0
    }
9141
0
    CPU_FREE(mask);
9142
0
    return res;
9143
9144
0
error:
9145
0
    if (mask) {
9146
0
        CPU_FREE(mask);
9147
0
    }
9148
0
    Py_XDECREF(res);
9149
0
    return NULL;
9150
0
}
9151
#endif /* HAVE_SCHED_SETAFFINITY */
9152
9153
#endif /* HAVE_SCHED_H */
9154
9155
9156
#ifdef HAVE_POSIX_OPENPT
9157
/*[clinic input]
9158
os.posix_openpt -> int
9159
9160
    oflag: int
9161
    /
9162
9163
Open and return a file descriptor for a master pseudo-terminal device.
9164
9165
Performs a posix_openpt() C function call. The oflag argument is used to
9166
set file status flags and file access modes as specified in the manual
9167
page of posix_openpt() of your system.
9168
[clinic start generated code]*/
9169
9170
static int
9171
os_posix_openpt_impl(PyObject *module, int oflag)
9172
/*[clinic end generated code: output=ee0bc2624305fc79 input=3ce4eb297fa64307]*/
9173
0
{
9174
0
    int fd;
9175
9176
0
#if defined(O_CLOEXEC)
9177
0
    oflag |= O_CLOEXEC;
9178
0
#endif
9179
9180
0
    fd = posix_openpt(oflag);
9181
0
    if (fd == -1) {
9182
0
        posix_error();
9183
0
        return -1;
9184
0
    }
9185
9186
    // Just in case, likely a no-op given O_CLOEXEC above.
9187
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9188
0
        close(fd);
9189
0
        return -1;
9190
0
    }
9191
9192
0
    return fd;
9193
0
}
9194
#endif /* HAVE_POSIX_OPENPT */
9195
9196
#ifdef HAVE_GRANTPT
9197
/*[clinic input]
9198
os.grantpt
9199
9200
    fd: fildes
9201
        File descriptor of a master pseudo-terminal device.
9202
    /
9203
9204
Grant access to the slave pseudo-terminal device.
9205
9206
Performs a grantpt() C function call.
9207
[clinic start generated code]*/
9208
9209
static PyObject *
9210
os_grantpt_impl(PyObject *module, int fd)
9211
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9212
0
{
9213
0
    int ret;
9214
0
    int saved_errno;
9215
0
    PyOS_sighandler_t sig_saved;
9216
9217
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9218
9219
0
    ret = grantpt(fd);
9220
0
    if (ret == -1)
9221
0
        saved_errno = errno;
9222
9223
0
    PyOS_setsig(SIGCHLD, sig_saved);
9224
9225
0
    if (ret == -1) {
9226
0
        errno = saved_errno;
9227
0
        return posix_error();
9228
0
    }
9229
9230
0
    Py_RETURN_NONE;
9231
0
}
9232
#endif /* HAVE_GRANTPT */
9233
9234
#ifdef HAVE_UNLOCKPT
9235
/*[clinic input]
9236
os.unlockpt
9237
9238
    fd: fildes
9239
        File descriptor of a master pseudo-terminal device.
9240
    /
9241
9242
Unlock a pseudo-terminal master/slave pair.
9243
9244
Performs an unlockpt() C function call.
9245
[clinic start generated code]*/
9246
9247
static PyObject *
9248
os_unlockpt_impl(PyObject *module, int fd)
9249
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9250
0
{
9251
0
    if (unlockpt(fd) == -1)
9252
0
        return posix_error();
9253
9254
0
    Py_RETURN_NONE;
9255
0
}
9256
#endif /* HAVE_UNLOCKPT */
9257
9258
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9259
static PyObject *
9260
py_ptsname(int fd)
9261
0
{
9262
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9263
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9264
0
    errno = 0;
9265
0
    char *name = ptsname(fd);
9266
0
    if (name == NULL) {
9267
0
        return posix_error();
9268
0
    }
9269
0
    return PyUnicode_DecodeFSDefault(name);
9270
0
}
9271
9272
/*[clinic input]
9273
os.ptsname
9274
9275
    fd: fildes
9276
        File descriptor of a master pseudo-terminal device.
9277
    /
9278
9279
Return the name of the slave pseudo-terminal device.
9280
9281
If the ptsname_r() C function is available, it is called;
9282
otherwise, performs a ptsname() C function call.
9283
[clinic start generated code]*/
9284
9285
static PyObject *
9286
os_ptsname_impl(PyObject *module, int fd)
9287
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9288
0
{
9289
0
#ifdef HAVE_PTSNAME_R
9290
0
    int ret;
9291
0
    char name[MAXPATHLEN+1];
9292
9293
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9294
0
        ret = ptsname_r(fd, name, sizeof(name));
9295
0
    }
9296
0
    else {
9297
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9298
0
        return py_ptsname(fd);
9299
0
    }
9300
0
    if (ret != 0) {
9301
0
        errno = ret;
9302
0
        return posix_error();
9303
0
    }
9304
9305
0
    return PyUnicode_DecodeFSDefault(name);
9306
#else
9307
    return py_ptsname(fd);
9308
#endif /* HAVE_PTSNAME_R */
9309
0
}
9310
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9311
9312
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9313
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9314
#  define DEV_PTY_FILE "/dev/ptc"
9315
#  define HAVE_DEV_PTMX
9316
#else
9317
#  define DEV_PTY_FILE "/dev/ptmx"
9318
#endif
9319
9320
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9321
#ifdef HAVE_PTY_H
9322
#include <pty.h>
9323
#elif defined(HAVE_LIBUTIL_H)
9324
#include <libutil.h>
9325
#elif defined(HAVE_UTIL_H)
9326
#include <util.h>
9327
#endif /* HAVE_PTY_H */
9328
#ifdef HAVE_UTMP_H
9329
#include <utmp.h>
9330
#endif /* HAVE_UTMP_H */
9331
#ifdef HAVE_STROPTS_H
9332
#include <stropts.h>
9333
#endif
9334
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9335
9336
9337
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9338
/*[clinic input]
9339
os.openpty
9340
9341
Open a pseudo-terminal.
9342
9343
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9344
for both the master and slave ends.
9345
[clinic start generated code]*/
9346
9347
static PyObject *
9348
os_openpty_impl(PyObject *module)
9349
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9350
0
{
9351
0
    int master_fd = -1, slave_fd = -1;
9352
#ifndef HAVE_OPENPTY
9353
    char * slave_name;
9354
#endif
9355
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9356
    PyOS_sighandler_t sig_saved;
9357
#if defined(__sun) && defined(__SVR4)
9358
    extern char *ptsname(int fildes);
9359
#endif
9360
#endif
9361
9362
0
#ifdef HAVE_OPENPTY
9363
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9364
0
        goto posix_error;
9365
9366
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9367
0
        goto error;
9368
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9369
0
        goto error;
9370
9371
#elif defined(HAVE__GETPTY)
9372
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9373
    if (slave_name == NULL)
9374
        goto posix_error;
9375
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9376
        goto error;
9377
9378
    slave_fd = _Py_open(slave_name, O_RDWR);
9379
    if (slave_fd < 0)
9380
        goto error;
9381
9382
#else
9383
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9384
    if (master_fd < 0)
9385
        goto posix_error;
9386
9387
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9388
9389
    /* change permission of slave */
9390
    if (grantpt(master_fd) < 0) {
9391
        int saved_errno = errno;
9392
        PyOS_setsig(SIGCHLD, sig_saved);
9393
        errno = saved_errno;
9394
        goto posix_error;
9395
    }
9396
9397
    /* unlock slave */
9398
    if (unlockpt(master_fd) < 0) {
9399
        int saved_errno = errno;
9400
        PyOS_setsig(SIGCHLD, sig_saved);
9401
        errno = saved_errno;
9402
        goto posix_error;
9403
    }
9404
9405
    PyOS_setsig(SIGCHLD, sig_saved);
9406
9407
    slave_name = ptsname(master_fd); /* get name of slave */
9408
    if (slave_name == NULL)
9409
        goto posix_error;
9410
9411
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9412
    if (slave_fd == -1)
9413
        goto error;
9414
9415
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9416
        goto posix_error;
9417
9418
#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC)
9419
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9420
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9421
#ifndef __hpux
9422
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9423
#endif /* __hpux */
9424
#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
9425
#endif /* HAVE_OPENPTY */
9426
9427
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9428
9429
0
posix_error:
9430
0
    posix_error();
9431
0
error:
9432
0
    if (master_fd != -1)
9433
0
        close(master_fd);
9434
0
    if (slave_fd != -1)
9435
0
        close(slave_fd);
9436
0
    return NULL;
9437
0
}
9438
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9439
9440
9441
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9442
#define HAVE_FALLBACK_LOGIN_TTY 1
9443
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9444
9445
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9446
/*[clinic input]
9447
@permit_long_summary
9448
os.login_tty
9449
9450
    fd: fildes
9451
    /
9452
9453
Prepare the tty of which fd is a file descriptor for a new login session.
9454
9455
Make the calling process a session leader; make the tty the
9456
controlling tty, the stdin, the stdout, and the stderr of the
9457
calling process; close fd.
9458
[clinic start generated code]*/
9459
9460
static PyObject *
9461
os_login_tty_impl(PyObject *module, int fd)
9462
/*[clinic end generated code: output=495a79911b4cc1bc input=b102a7c36e8baf00]*/
9463
0
{
9464
0
#ifdef HAVE_LOGIN_TTY
9465
0
    if (login_tty(fd) == -1) {
9466
0
        return posix_error();
9467
0
    }
9468
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9469
    /* Establish a new session. */
9470
    if (setsid() == -1) {
9471
        return posix_error();
9472
    }
9473
9474
    /* The tty becomes the controlling terminal. */
9475
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9476
        return posix_error();
9477
    }
9478
9479
    /* The tty becomes stdin/stdout/stderr */
9480
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9481
        return posix_error();
9482
    }
9483
    if (fd > 2) {
9484
        close(fd);
9485
    }
9486
#endif /* HAVE_LOGIN_TTY */
9487
0
    Py_RETURN_NONE;
9488
0
}
9489
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9490
9491
9492
#ifdef HAVE_FORKPTY
9493
/*[clinic input]
9494
os.forkpty
9495
9496
Fork a new process with a new pseudo-terminal as controlling tty.
9497
9498
Returns a tuple of (pid, master_fd).
9499
Like fork(), return pid of 0 to the child process,
9500
and pid of child to the parent process.
9501
To both, return fd of newly opened pseudo-terminal.
9502
The master_fd is non-inheritable.
9503
[clinic start generated code]*/
9504
9505
static PyObject *
9506
os_forkpty_impl(PyObject *module)
9507
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9508
0
{
9509
0
    int master_fd = -1;
9510
0
    pid_t pid;
9511
9512
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9513
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9514
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9515
0
                        "can't fork at interpreter shutdown");
9516
0
        return NULL;
9517
0
    }
9518
0
    if (!_Py_IsMainInterpreter(interp)) {
9519
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9520
0
        return NULL;
9521
0
    }
9522
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9523
0
        return NULL;
9524
0
    }
9525
0
    PyOS_BeforeFork();
9526
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9527
0
    if (pid == 0) {
9528
        /* child: this clobbers and resets the import lock. */
9529
0
        PyOS_AfterFork_Child();
9530
0
    } else {
9531
        // Called before AfterFork_Parent in case those hooks start threads.
9532
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9533
        /* parent: release the import lock. */
9534
0
        PyOS_AfterFork_Parent();
9535
        /* set O_CLOEXEC on master_fd */
9536
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9537
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9538
0
                                   "non-inheritable in forkpty()");
9539
0
        }
9540
9541
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9542
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9543
0
            return NULL;
9544
0
    }
9545
0
    if (pid == -1) {
9546
0
        return posix_error();
9547
0
    }
9548
9549
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9550
0
}
9551
#endif /* HAVE_FORKPTY */
9552
9553
9554
#ifdef HAVE_GETEGID
9555
/*[clinic input]
9556
os.getegid
9557
9558
Return the current process's effective group id.
9559
[clinic start generated code]*/
9560
9561
static PyObject *
9562
os_getegid_impl(PyObject *module)
9563
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9564
37
{
9565
37
    return _PyLong_FromGid(getegid());
9566
37
}
9567
#endif /* HAVE_GETEGID */
9568
9569
9570
#ifdef HAVE_GETEUID
9571
/*[clinic input]
9572
os.geteuid
9573
9574
Return the current process's effective user id.
9575
[clinic start generated code]*/
9576
9577
static PyObject *
9578
os_geteuid_impl(PyObject *module)
9579
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9580
37
{
9581
37
    return _PyLong_FromUid(geteuid());
9582
37
}
9583
#endif /* HAVE_GETEUID */
9584
9585
9586
#ifdef HAVE_GETGID
9587
/*[clinic input]
9588
os.getgid
9589
9590
Return the current process's group id.
9591
[clinic start generated code]*/
9592
9593
static PyObject *
9594
os_getgid_impl(PyObject *module)
9595
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9596
37
{
9597
37
    return _PyLong_FromGid(getgid());
9598
37
}
9599
#endif /* HAVE_GETGID */
9600
9601
9602
#if defined(HAVE_GETPID)
9603
/*[clinic input]
9604
os.getpid
9605
9606
Return the current process id.
9607
[clinic start generated code]*/
9608
9609
static PyObject *
9610
os_getpid_impl(PyObject *module)
9611
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9612
4.48k
{
9613
4.48k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9614
4.48k
    return PyLong_FromPid(getpid());
9615
#else
9616
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9617
#endif
9618
4.48k
}
9619
#endif /* defined(HAVE_GETPID) */
9620
9621
#ifdef NGROUPS_MAX
9622
0
#define MAX_GROUPS NGROUPS_MAX
9623
#else
9624
    /* defined to be 16 on Solaris7, so this should be a small number */
9625
#define MAX_GROUPS 64
9626
#endif
9627
9628
#ifdef HAVE_GETGROUPLIST
9629
9630
#ifdef __APPLE__
9631
/*[clinic input]
9632
os.getgrouplist
9633
9634
    user: str
9635
        username to lookup
9636
    group as basegid: int
9637
        base group id of the user
9638
    /
9639
9640
Returns a list of groups to which a user belongs.
9641
[clinic start generated code]*/
9642
9643
static PyObject *
9644
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9645
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9646
#else
9647
/*[clinic input]
9648
os.getgrouplist
9649
9650
    user: str
9651
        username to lookup
9652
    group as basegid: gid_t
9653
        base group id of the user
9654
    /
9655
9656
Returns a list of groups to which a user belongs.
9657
[clinic start generated code]*/
9658
9659
static PyObject *
9660
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9661
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9662
#endif
9663
0
{
9664
0
    int i, ngroups;
9665
0
    PyObject *list;
9666
#ifdef __APPLE__
9667
    int *groups;
9668
#else
9669
0
    gid_t *groups;
9670
0
#endif
9671
9672
    /*
9673
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9674
     * number of supplemental groups a users can belong to.
9675
     * We have to increment it by one because
9676
     * getgrouplist() returns both the supplemental groups
9677
     * and the primary group, i.e. all of the groups the
9678
     * user belongs to.
9679
     */
9680
0
    ngroups = 1 + MAX_GROUPS;
9681
9682
0
    while (1) {
9683
#ifdef __APPLE__
9684
        groups = PyMem_New(int, ngroups);
9685
#else
9686
0
        groups = PyMem_New(gid_t, ngroups);
9687
0
#endif
9688
0
        if (groups == NULL) {
9689
0
            return PyErr_NoMemory();
9690
0
        }
9691
9692
0
        int old_ngroups = ngroups;
9693
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9694
            /* Success */
9695
0
            break;
9696
0
        }
9697
9698
        /* getgrouplist() fails if the group list is too small */
9699
0
        PyMem_Free(groups);
9700
9701
0
        if (ngroups > old_ngroups) {
9702
            /* If the group list is too small, the glibc implementation of
9703
               getgrouplist() sets ngroups to the total number of groups and
9704
               returns -1. */
9705
0
        }
9706
0
        else {
9707
            /* Double the group list size */
9708
0
            if (ngroups > INT_MAX / 2) {
9709
0
                return PyErr_NoMemory();
9710
0
            }
9711
0
            ngroups *= 2;
9712
0
        }
9713
9714
        /* Retry getgrouplist() with a larger group list */
9715
0
    }
9716
9717
#ifdef _Py_MEMORY_SANITIZER
9718
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9719
    __msan_unpoison(&ngroups, sizeof(ngroups));
9720
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9721
#endif
9722
9723
0
    list = PyList_New(ngroups);
9724
0
    if (list == NULL) {
9725
0
        PyMem_Free(groups);
9726
0
        return NULL;
9727
0
    }
9728
9729
0
    for (i = 0; i < ngroups; i++) {
9730
#ifdef __APPLE__
9731
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9732
#else
9733
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9734
0
#endif
9735
0
        if (o == NULL) {
9736
0
            Py_DECREF(list);
9737
0
            PyMem_Free(groups);
9738
0
            return NULL;
9739
0
        }
9740
0
        PyList_SET_ITEM(list, i, o);
9741
0
    }
9742
9743
0
    PyMem_Free(groups);
9744
9745
0
    return list;
9746
0
}
9747
#endif /* HAVE_GETGROUPLIST */
9748
9749
9750
#ifdef HAVE_GETGROUPS
9751
/*[clinic input]
9752
os.getgroups
9753
9754
Return list of supplemental group IDs for the process.
9755
[clinic start generated code]*/
9756
9757
static PyObject *
9758
os_getgroups_impl(PyObject *module)
9759
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9760
0
{
9761
    // Call getgroups with length 0 to get the actual number of groups
9762
0
    int n = getgroups(0, NULL);
9763
0
    if (n < 0) {
9764
0
        return posix_error();
9765
0
    }
9766
9767
0
    if (n == 0) {
9768
0
        return PyList_New(0);
9769
0
    }
9770
9771
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9772
0
    if (grouplist == NULL) {
9773
0
        return PyErr_NoMemory();
9774
0
    }
9775
9776
0
    n = getgroups(n, grouplist);
9777
0
    if (n == -1) {
9778
0
        posix_error();
9779
0
        PyMem_Free(grouplist);
9780
0
        return NULL;
9781
0
    }
9782
9783
0
    PyObject *result = PyList_New(n);
9784
0
    if (result == NULL) {
9785
0
        goto error;
9786
0
    }
9787
9788
0
    for (int i = 0; i < n; ++i) {
9789
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9790
0
        if (group == NULL) {
9791
0
            goto error;
9792
0
        }
9793
0
        PyList_SET_ITEM(result, i, group);
9794
0
    }
9795
0
    PyMem_Free(grouplist);
9796
9797
0
    return result;
9798
9799
0
error:
9800
0
    PyMem_Free(grouplist);
9801
0
    Py_XDECREF(result);
9802
0
    return NULL;
9803
0
}
9804
#endif /* HAVE_GETGROUPS */
9805
9806
#ifdef HAVE_INITGROUPS
9807
#ifdef __APPLE__
9808
/*[clinic input]
9809
os.initgroups
9810
9811
    username as oname: unicode_fs_encoded
9812
    gid: int
9813
    /
9814
9815
Initialize the group access list.
9816
9817
Call the system initgroups() to initialize the group access list with
9818
all of the groups of which the specified username is a member, plus the
9819
specified group id.
9820
[clinic start generated code]*/
9821
9822
static PyObject *
9823
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9824
/*[clinic end generated code: output=7f074d30a425fd3a input=35f2d4fb7fcc0bdf]*/
9825
#else
9826
/*[clinic input]
9827
os.initgroups
9828
9829
    username as oname: unicode_fs_encoded
9830
    gid: gid_t
9831
    /
9832
9833
Initialize the group access list.
9834
9835
Call the system initgroups() to initialize the group access list with
9836
all of the groups of which the specified username is a member, plus the
9837
specified group id.
9838
[clinic start generated code]*/
9839
9840
static PyObject *
9841
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9842
/*[clinic end generated code: output=59341244521a9e3f input=7e4514dff4526a95]*/
9843
#endif
9844
0
{
9845
0
    const char *username = PyBytes_AS_STRING(oname);
9846
9847
0
    if (initgroups(username, gid) == -1)
9848
0
        return PyErr_SetFromErrno(PyExc_OSError);
9849
9850
0
    Py_RETURN_NONE;
9851
0
}
9852
#endif /* HAVE_INITGROUPS */
9853
9854
9855
#ifdef HAVE_GETPGID
9856
/*[clinic input]
9857
os.getpgid
9858
9859
    pid: pid_t
9860
9861
Call the system call getpgid(), and return the result.
9862
[clinic start generated code]*/
9863
9864
static PyObject *
9865
os_getpgid_impl(PyObject *module, pid_t pid)
9866
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9867
0
{
9868
0
    pid_t pgid = getpgid(pid);
9869
0
    if (pgid < 0)
9870
0
        return posix_error();
9871
0
    return PyLong_FromPid(pgid);
9872
0
}
9873
#endif /* HAVE_GETPGID */
9874
9875
9876
#ifdef HAVE_GETPGRP
9877
/*[clinic input]
9878
os.getpgrp
9879
9880
Return the current process group id.
9881
[clinic start generated code]*/
9882
9883
static PyObject *
9884
os_getpgrp_impl(PyObject *module)
9885
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9886
0
{
9887
#ifdef GETPGRP_HAVE_ARG
9888
    return PyLong_FromPid(getpgrp(0));
9889
#else /* GETPGRP_HAVE_ARG */
9890
0
    return PyLong_FromPid(getpgrp());
9891
0
#endif /* GETPGRP_HAVE_ARG */
9892
0
}
9893
#endif /* HAVE_GETPGRP */
9894
9895
9896
#ifdef HAVE_SETPGRP
9897
/*[clinic input]
9898
os.setpgrp
9899
9900
Make the current process the leader of its process group.
9901
[clinic start generated code]*/
9902
9903
static PyObject *
9904
os_setpgrp_impl(PyObject *module)
9905
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9906
0
{
9907
#ifdef SETPGRP_HAVE_ARG
9908
    if (setpgrp(0, 0) < 0)
9909
#else /* SETPGRP_HAVE_ARG */
9910
0
    if (setpgrp() < 0)
9911
0
#endif /* SETPGRP_HAVE_ARG */
9912
0
        return posix_error();
9913
0
    Py_RETURN_NONE;
9914
0
}
9915
#endif /* HAVE_SETPGRP */
9916
9917
#ifdef HAVE_GETPPID
9918
9919
#ifdef MS_WINDOWS
9920
#include <winternl.h>
9921
#include <ProcessSnapshot.h>
9922
9923
// The structure definition in winternl.h may be incomplete.
9924
// This structure is the full version from the MSDN documentation.
9925
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9926
    NTSTATUS ExitStatus;
9927
    PVOID PebBaseAddress;
9928
    ULONG_PTR AffinityMask;
9929
    LONG BasePriority;
9930
    ULONG_PTR UniqueProcessId;
9931
    ULONG_PTR InheritedFromUniqueProcessId;
9932
} PROCESS_BASIC_INFORMATION_FULL;
9933
9934
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9935
    IN    HANDLE           ProcessHandle,
9936
    IN    PROCESSINFOCLASS ProcessInformationClass,
9937
    OUT   PVOID            ProcessInformation,
9938
    IN    ULONG            ProcessInformationLength,
9939
    OUT   PULONG           ReturnLength OPTIONAL);
9940
9941
// This function returns the process ID of the parent process.
9942
// Returns 0 on failure.
9943
static ULONG
9944
win32_getppid_fast(void)
9945
{
9946
    NTSTATUS status;
9947
    HMODULE ntdll;
9948
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9949
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9950
    static ULONG cached_ppid = 0;
9951
9952
    if (cached_ppid) {
9953
        // No need to query the kernel again.
9954
        return cached_ppid;
9955
    }
9956
9957
    ntdll = GetModuleHandleW(L"ntdll.dll");
9958
    if (!ntdll) {
9959
        return 0;
9960
    }
9961
9962
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9963
    if (!pNtQueryInformationProcess) {
9964
        return 0;
9965
    }
9966
9967
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9968
                                        ProcessBasicInformation,
9969
                                        &basic_information,
9970
                                        sizeof(basic_information),
9971
                                        NULL);
9972
9973
    if (!NT_SUCCESS(status)) {
9974
        return 0;
9975
    }
9976
9977
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9978
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9979
    // zero and (ULONG) -1.
9980
9981
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9982
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9983
    {
9984
        return 0;
9985
    }
9986
9987
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9988
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9989
    // process. This process ID will be correctly returned even if the parent process has
9990
    // exited or been terminated.
9991
9992
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9993
    return cached_ppid;
9994
}
9995
9996
static PyObject*
9997
win32_getppid(void)
9998
{
9999
    DWORD error;
10000
    PyObject* result = NULL;
10001
    HANDLE process = GetCurrentProcess();
10002
    HPSS snapshot = NULL;
10003
    ULONG pid;
10004
10005
    pid = win32_getppid_fast();
10006
    if (pid != 0) {
10007
        return PyLong_FromUnsignedLong(pid);
10008
    }
10009
10010
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
10011
10012
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
10013
    if (error != ERROR_SUCCESS) {
10014
        return PyErr_SetFromWindowsErr(error);
10015
    }
10016
10017
    PSS_PROCESS_INFORMATION info;
10018
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
10019
                             sizeof(info));
10020
    if (error == ERROR_SUCCESS) {
10021
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
10022
    }
10023
    else {
10024
        result = PyErr_SetFromWindowsErr(error);
10025
    }
10026
10027
    PssFreeSnapshot(process, snapshot);
10028
    return result;
10029
}
10030
#endif /*MS_WINDOWS*/
10031
10032
10033
/*[clinic input]
10034
os.getppid
10035
10036
Return the parent's process id.
10037
10038
If the parent process has already exited, Windows machines will still
10039
return its id; others systems will return the id of the 'init' proces
10040
(1).
10041
[clinic start generated code]*/
10042
10043
static PyObject *
10044
os_getppid_impl(PyObject *module)
10045
/*[clinic end generated code: output=43b2a946a8c603b4 input=e17c1de18f41316b]*/
10046
0
{
10047
#ifdef MS_WINDOWS
10048
    return win32_getppid();
10049
#else
10050
0
    return PyLong_FromPid(getppid());
10051
0
#endif
10052
0
}
10053
#endif /* HAVE_GETPPID */
10054
10055
10056
#ifdef HAVE_GETLOGIN
10057
/*[clinic input]
10058
os.getlogin
10059
10060
Return the actual login name.
10061
[clinic start generated code]*/
10062
10063
static PyObject *
10064
os_getlogin_impl(PyObject *module)
10065
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10066
0
{
10067
0
    PyObject *result = NULL;
10068
#ifdef MS_WINDOWS
10069
    wchar_t user_name[UNLEN + 1];
10070
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10071
10072
    if (GetUserNameW(user_name, &num_chars)) {
10073
        /* num_chars is the number of unicode chars plus null terminator */
10074
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10075
    }
10076
    else
10077
        result = PyErr_SetFromWindowsErr(GetLastError());
10078
#elif defined (HAVE_GETLOGIN_R)
10079
# if defined (HAVE_MAXLOGNAME)
10080
    char name[MAXLOGNAME + 1];
10081
# elif defined (HAVE_UT_NAMESIZE)
10082
    char name[UT_NAMESIZE + 1];
10083
# else
10084
    char name[256];
10085
# endif
10086
0
    int err = getlogin_r(name, sizeof(name));
10087
0
    if (err) {
10088
0
        int old_errno = errno;
10089
0
        errno = err;
10090
0
        posix_error();
10091
0
        errno = old_errno;
10092
0
    }
10093
0
    else {
10094
0
        result = PyUnicode_DecodeFSDefault(name);
10095
0
    }
10096
#else
10097
    char *name;
10098
    int old_errno = errno;
10099
10100
    errno = 0;
10101
    name = getlogin();
10102
    if (name == NULL) {
10103
        if (errno)
10104
            posix_error();
10105
        else
10106
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10107
    }
10108
    else
10109
        result = PyUnicode_DecodeFSDefault(name);
10110
    errno = old_errno;
10111
#endif
10112
0
    return result;
10113
0
}
10114
#endif /* HAVE_GETLOGIN */
10115
10116
10117
#ifdef HAVE_GETUID
10118
/*[clinic input]
10119
os.getuid
10120
10121
Return the current process's user id.
10122
[clinic start generated code]*/
10123
10124
static PyObject *
10125
os_getuid_impl(PyObject *module)
10126
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10127
37
{
10128
37
    return _PyLong_FromUid(getuid());
10129
37
}
10130
#endif /* HAVE_GETUID */
10131
10132
10133
#ifdef MS_WINDOWS
10134
#define HAVE_KILL
10135
#endif /* MS_WINDOWS */
10136
10137
#ifdef HAVE_KILL
10138
/*[clinic input]
10139
os.kill
10140
10141
    pid: pid_t
10142
    signal: Py_ssize_t
10143
    /
10144
10145
Kill a process with a signal.
10146
[clinic start generated code]*/
10147
10148
static PyObject *
10149
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10150
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10151
0
{
10152
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10153
0
        return NULL;
10154
0
    }
10155
0
#ifndef MS_WINDOWS
10156
0
    if (kill(pid, (int)signal) == -1) {
10157
0
        return posix_error();
10158
0
    }
10159
10160
    // Check immediately if the signal was sent to the current process.
10161
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10162
    // is cheap.
10163
0
    if (PyErr_CheckSignals()) {
10164
0
        return NULL;
10165
0
    }
10166
10167
0
    Py_RETURN_NONE;
10168
#else /* !MS_WINDOWS */
10169
    DWORD sig = (DWORD)signal;
10170
10171
#ifdef HAVE_WINDOWS_CONSOLE_IO
10172
    /* Console processes which share a common console can be sent CTRL+C or
10173
       CTRL+BREAK events, provided they handle said events. */
10174
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10175
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10176
            return PyErr_SetFromWindowsErr(0);
10177
        }
10178
        Py_RETURN_NONE;
10179
    }
10180
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10181
10182
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10183
       attempt to open and terminate the process. */
10184
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10185
    if (handle == NULL) {
10186
        return PyErr_SetFromWindowsErr(0);
10187
    }
10188
10189
    BOOL res = TerminateProcess(handle, sig);
10190
    CloseHandle(handle);
10191
    if (res == 0) {
10192
        return PyErr_SetFromWindowsErr(0);
10193
    }
10194
10195
    Py_RETURN_NONE;
10196
#endif /* !MS_WINDOWS */
10197
0
}
10198
#endif /* HAVE_KILL */
10199
10200
10201
#ifdef HAVE_KILLPG
10202
/*[clinic input]
10203
os.killpg
10204
10205
    pgid: pid_t
10206
    signal: int
10207
    /
10208
10209
Kill a process group with a signal.
10210
[clinic start generated code]*/
10211
10212
static PyObject *
10213
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10214
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10215
0
{
10216
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10217
0
        return NULL;
10218
0
    }
10219
    /* XXX some man pages make the `pgid` parameter an int, others
10220
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10221
       take the same type. Moreover, pid_t is always at least as wide as
10222
       int (else compilation of this module fails), which is safe. */
10223
0
    if (killpg(pgid, signal) == -1)
10224
0
        return posix_error();
10225
0
    Py_RETURN_NONE;
10226
0
}
10227
#endif /* HAVE_KILLPG */
10228
10229
10230
#ifdef HAVE_PLOCK
10231
#ifdef HAVE_SYS_LOCK_H
10232
#include <sys/lock.h>
10233
#endif
10234
10235
/*[clinic input]
10236
os.plock
10237
    op: int
10238
    /
10239
10240
Lock program segments into memory.");
10241
[clinic start generated code]*/
10242
10243
static PyObject *
10244
os_plock_impl(PyObject *module, int op)
10245
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10246
{
10247
    if (plock(op) == -1)
10248
        return posix_error();
10249
    Py_RETURN_NONE;
10250
}
10251
#endif /* HAVE_PLOCK */
10252
10253
10254
#ifdef HAVE_SETUID
10255
/*[clinic input]
10256
os.setuid
10257
10258
    uid: uid_t
10259
    /
10260
10261
Set the current process's user id.
10262
[clinic start generated code]*/
10263
10264
static PyObject *
10265
os_setuid_impl(PyObject *module, uid_t uid)
10266
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10267
0
{
10268
0
    if (setuid(uid) < 0)
10269
0
        return posix_error();
10270
0
    Py_RETURN_NONE;
10271
0
}
10272
#endif /* HAVE_SETUID */
10273
10274
10275
#ifdef HAVE_SETEUID
10276
/*[clinic input]
10277
os.seteuid
10278
10279
    euid: uid_t
10280
    /
10281
10282
Set the current process's effective user id.
10283
[clinic start generated code]*/
10284
10285
static PyObject *
10286
os_seteuid_impl(PyObject *module, uid_t euid)
10287
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10288
0
{
10289
0
    if (seteuid(euid) < 0)
10290
0
        return posix_error();
10291
0
    Py_RETURN_NONE;
10292
0
}
10293
#endif /* HAVE_SETEUID */
10294
10295
10296
#ifdef HAVE_SETEGID
10297
/*[clinic input]
10298
os.setegid
10299
10300
    egid: gid_t
10301
    /
10302
10303
Set the current process's effective group id.
10304
[clinic start generated code]*/
10305
10306
static PyObject *
10307
os_setegid_impl(PyObject *module, gid_t egid)
10308
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10309
0
{
10310
0
    if (setegid(egid) < 0)
10311
0
        return posix_error();
10312
0
    Py_RETURN_NONE;
10313
0
}
10314
#endif /* HAVE_SETEGID */
10315
10316
10317
#ifdef HAVE_SETREUID
10318
/*[clinic input]
10319
os.setreuid
10320
10321
    ruid: uid_t
10322
    euid: uid_t
10323
    /
10324
10325
Set the current process's real and effective user ids.
10326
[clinic start generated code]*/
10327
10328
static PyObject *
10329
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10330
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10331
0
{
10332
0
    if (setreuid(ruid, euid) < 0) {
10333
0
        return posix_error();
10334
0
    } else {
10335
0
        Py_RETURN_NONE;
10336
0
    }
10337
0
}
10338
#endif /* HAVE_SETREUID */
10339
10340
10341
#ifdef HAVE_SETREGID
10342
/*[clinic input]
10343
os.setregid
10344
10345
    rgid: gid_t
10346
    egid: gid_t
10347
    /
10348
10349
Set the current process's real and effective group ids.
10350
[clinic start generated code]*/
10351
10352
static PyObject *
10353
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10354
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10355
0
{
10356
0
    if (setregid(rgid, egid) < 0)
10357
0
        return posix_error();
10358
0
    Py_RETURN_NONE;
10359
0
}
10360
#endif /* HAVE_SETREGID */
10361
10362
10363
#ifdef HAVE_SETGID
10364
/*[clinic input]
10365
os.setgid
10366
    gid: gid_t
10367
    /
10368
10369
Set the current process's group id.
10370
[clinic start generated code]*/
10371
10372
static PyObject *
10373
os_setgid_impl(PyObject *module, gid_t gid)
10374
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10375
0
{
10376
0
    if (setgid(gid) < 0)
10377
0
        return posix_error();
10378
0
    Py_RETURN_NONE;
10379
0
}
10380
#endif /* HAVE_SETGID */
10381
10382
10383
#ifdef HAVE_SETGROUPS
10384
/*[clinic input]
10385
os.setgroups
10386
10387
    groups: object
10388
    /
10389
10390
Set the groups of the current process to list.
10391
[clinic start generated code]*/
10392
10393
static PyObject *
10394
os_setgroups(PyObject *module, PyObject *groups)
10395
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10396
0
{
10397
0
    if (!PySequence_Check(groups)) {
10398
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10399
0
        return NULL;
10400
0
    }
10401
0
    Py_ssize_t len = PySequence_Size(groups);
10402
0
    if (len < 0) {
10403
0
        return NULL;
10404
0
    }
10405
0
    if (len > MAX_GROUPS) {
10406
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10407
0
        return NULL;
10408
0
    }
10409
10410
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10411
0
    if (grouplist == NULL) {
10412
0
        PyErr_NoMemory();
10413
0
        return NULL;
10414
0
    }
10415
0
    for (Py_ssize_t i = 0; i < len; i++) {
10416
0
        PyObject *elem;
10417
0
        elem = PySequence_GetItem(groups, i);
10418
0
        if (!elem) {
10419
0
            PyMem_Free(grouplist);
10420
0
            return NULL;
10421
0
        }
10422
0
        if (!PyIndex_Check(elem)) {
10423
0
            PyErr_SetString(PyExc_TypeError,
10424
0
                            "groups must be integers");
10425
0
            Py_DECREF(elem);
10426
0
            PyMem_Free(grouplist);
10427
0
            return NULL;
10428
0
        } else {
10429
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10430
0
                Py_DECREF(elem);
10431
0
                PyMem_Free(grouplist);
10432
0
                return NULL;
10433
0
            }
10434
0
        }
10435
0
        Py_DECREF(elem);
10436
0
    }
10437
10438
0
    if (setgroups(len, grouplist) < 0) {
10439
0
        posix_error();
10440
0
        PyMem_Free(grouplist);
10441
0
        return NULL;
10442
0
    }
10443
0
    PyMem_Free(grouplist);
10444
0
    Py_RETURN_NONE;
10445
0
}
10446
#endif /* HAVE_SETGROUPS */
10447
10448
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10449
static PyObject *
10450
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10451
0
{
10452
0
    PyObject *result;
10453
0
    PyObject *struct_rusage;
10454
10455
0
    if (pid == -1)
10456
0
        return posix_error();
10457
10458
    // If wait succeeded but no child was ready to report status, ru will not
10459
    // have been populated.
10460
0
    if (pid == 0) {
10461
0
        memset(ru, 0, sizeof(*ru));
10462
0
    }
10463
10464
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10465
0
    if (struct_rusage == NULL)
10466
0
        return NULL;
10467
10468
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10469
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10470
0
    Py_DECREF(struct_rusage);
10471
0
    if (!result)
10472
0
        return NULL;
10473
10474
0
    int pos = 0;
10475
10476
0
#ifndef doubletime
10477
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10478
0
#endif
10479
10480
0
#define SET_RESULT(CALL)                                     \
10481
0
    do {                                                     \
10482
0
        PyObject *item = (CALL);                             \
10483
0
        if (item == NULL) {                                  \
10484
0
            Py_DECREF(result);                               \
10485
0
            return NULL;                                     \
10486
0
        }                                                    \
10487
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10488
0
    } while(0)
10489
10490
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10491
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10492
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10493
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10494
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10495
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10496
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10497
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10498
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10499
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10500
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10501
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10502
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10503
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10504
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10505
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10506
0
#undef SET_RESULT
10507
10508
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10509
0
}
10510
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10511
10512
10513
#ifdef HAVE_WAIT3
10514
/*[clinic input]
10515
os.wait3
10516
10517
    options: int
10518
Wait for completion of a child process.
10519
10520
Returns a tuple of information about the child process:
10521
  (pid, status, rusage)
10522
[clinic start generated code]*/
10523
10524
static PyObject *
10525
os_wait3_impl(PyObject *module, int options)
10526
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10527
0
{
10528
0
    pid_t pid;
10529
0
    struct rusage ru;
10530
0
    int async_err = 0;
10531
0
    WAIT_TYPE status;
10532
0
    WAIT_STATUS_INT(status) = 0;
10533
10534
0
    do {
10535
0
        Py_BEGIN_ALLOW_THREADS
10536
0
        pid = wait3(&status, options, &ru);
10537
0
        Py_END_ALLOW_THREADS
10538
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10539
0
    if (pid < 0)
10540
0
        return (!async_err) ? posix_error() : NULL;
10541
10542
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10543
0
}
10544
#endif /* HAVE_WAIT3 */
10545
10546
10547
#ifdef HAVE_WAIT4
10548
/*[clinic input]
10549
10550
os.wait4
10551
10552
    pid: pid_t
10553
    options: int
10554
10555
Wait for completion of a specific child process.
10556
10557
Returns a tuple of information about the child process:
10558
  (pid, status, rusage)
10559
[clinic start generated code]*/
10560
10561
static PyObject *
10562
os_wait4_impl(PyObject *module, pid_t pid, int options)
10563
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10564
0
{
10565
0
    pid_t res;
10566
0
    struct rusage ru;
10567
0
    int async_err = 0;
10568
0
    WAIT_TYPE status;
10569
0
    WAIT_STATUS_INT(status) = 0;
10570
10571
0
    do {
10572
0
        Py_BEGIN_ALLOW_THREADS
10573
0
        res = wait4(pid, &status, options, &ru);
10574
0
        Py_END_ALLOW_THREADS
10575
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10576
0
    if (res < 0)
10577
0
        return (!async_err) ? posix_error() : NULL;
10578
10579
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10580
0
}
10581
#endif /* HAVE_WAIT4 */
10582
10583
10584
#if defined(HAVE_WAITID)
10585
/*[clinic input]
10586
os.waitid
10587
10588
    idtype: idtype_t
10589
        Must be one of be P_PID, P_PGID or P_ALL.
10590
    id: id_t
10591
        The id to wait on.
10592
    options: int
10593
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10594
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10595
    /
10596
10597
Returns the result of waiting for a process or processes.
10598
10599
Returns either waitid_result or None if WNOHANG is specified and there
10600
are no children in a waitable state.
10601
[clinic start generated code]*/
10602
10603
static PyObject *
10604
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10605
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=14956bc8d102b5db]*/
10606
0
{
10607
0
    PyObject *result;
10608
0
    int res;
10609
0
    int async_err = 0;
10610
0
    siginfo_t si;
10611
0
    si.si_pid = 0;
10612
10613
0
    do {
10614
0
        Py_BEGIN_ALLOW_THREADS
10615
0
        res = waitid(idtype, id, &si, options);
10616
0
        Py_END_ALLOW_THREADS
10617
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10618
0
    if (res < 0)
10619
0
        return (!async_err) ? posix_error() : NULL;
10620
10621
0
    if (si.si_pid == 0)
10622
0
        Py_RETURN_NONE;
10623
10624
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10625
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10626
0
    if (!result)
10627
0
        return NULL;
10628
10629
0
    int pos = 0;
10630
10631
0
#define SET_RESULT(CALL)                                     \
10632
0
    do {                                                     \
10633
0
        PyObject *item = (CALL);                             \
10634
0
        if (item == NULL) {                                  \
10635
0
            Py_DECREF(result);                               \
10636
0
            return NULL;                                     \
10637
0
        }                                                    \
10638
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10639
0
    } while(0)
10640
10641
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10642
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10643
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10644
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10645
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10646
10647
0
#undef SET_RESULT
10648
10649
0
    return result;
10650
0
}
10651
#endif /* defined(HAVE_WAITID) */
10652
10653
10654
#if defined(HAVE_WAITPID)
10655
/*[clinic input]
10656
os.waitpid
10657
    pid: pid_t
10658
    options: int
10659
    /
10660
10661
Wait for completion of a given child process.
10662
10663
Returns a tuple of information regarding the child process:
10664
    (pid, status)
10665
10666
The options argument is ignored on Windows.
10667
[clinic start generated code]*/
10668
10669
static PyObject *
10670
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10671
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10672
0
{
10673
0
    pid_t res;
10674
0
    int async_err = 0;
10675
0
    WAIT_TYPE status;
10676
0
    WAIT_STATUS_INT(status) = 0;
10677
10678
0
    do {
10679
0
        Py_BEGIN_ALLOW_THREADS
10680
0
        res = waitpid(pid, &status, options);
10681
0
        Py_END_ALLOW_THREADS
10682
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10683
0
    if (res < 0)
10684
0
        return (!async_err) ? posix_error() : NULL;
10685
10686
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10687
0
}
10688
#elif defined(HAVE_CWAIT)
10689
/* MS C has a variant of waitpid() that's usable for most purposes. */
10690
/*[clinic input]
10691
os.waitpid
10692
    pid: intptr_t
10693
    options: int
10694
    /
10695
10696
Wait for completion of a given process.
10697
10698
Returns a tuple of information regarding the process:
10699
    (pid, status << 8)
10700
10701
The options argument is ignored on Windows.
10702
[clinic start generated code]*/
10703
10704
static PyObject *
10705
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10706
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10707
{
10708
    int status;
10709
    intptr_t res;
10710
    int async_err = 0;
10711
10712
    do {
10713
        Py_BEGIN_ALLOW_THREADS
10714
        _Py_BEGIN_SUPPRESS_IPH
10715
        res = _cwait(&status, pid, options);
10716
        _Py_END_SUPPRESS_IPH
10717
        Py_END_ALLOW_THREADS
10718
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10719
    if (res < 0)
10720
        return (!async_err) ? posix_error() : NULL;
10721
10722
    unsigned long long ustatus = (unsigned int)status;
10723
10724
    /* shift the status left a byte so this is more like the POSIX waitpid */
10725
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10726
}
10727
#endif
10728
10729
10730
#ifdef HAVE_WAIT
10731
/*[clinic input]
10732
os.wait
10733
10734
Wait for completion of a child process.
10735
10736
Returns a tuple of information about the child process:
10737
    (pid, status)
10738
[clinic start generated code]*/
10739
10740
static PyObject *
10741
os_wait_impl(PyObject *module)
10742
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10743
0
{
10744
0
    pid_t pid;
10745
0
    int async_err = 0;
10746
0
    WAIT_TYPE status;
10747
0
    WAIT_STATUS_INT(status) = 0;
10748
10749
0
    do {
10750
0
        Py_BEGIN_ALLOW_THREADS
10751
0
        pid = wait(&status);
10752
0
        Py_END_ALLOW_THREADS
10753
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10754
0
    if (pid < 0)
10755
0
        return (!async_err) ? posix_error() : NULL;
10756
10757
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10758
0
}
10759
#endif /* HAVE_WAIT */
10760
10761
10762
// This system call always crashes on older Android versions.
10763
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10764
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10765
/*[clinic input]
10766
os.pidfd_open
10767
  pid: pid_t
10768
  flags: unsigned_int = 0
10769
10770
Return a file descriptor referring to the process *pid*.
10771
10772
The descriptor can be used to perform process management without races
10773
and signals.
10774
[clinic start generated code]*/
10775
10776
static PyObject *
10777
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10778
/*[clinic end generated code: output=5c7252698947dc41 input=03058b32c389f874]*/
10779
4
{
10780
4
    int fd = syscall(__NR_pidfd_open, pid, flags);
10781
4
    if (fd < 0) {
10782
0
        return posix_error();
10783
0
    }
10784
4
    return PyLong_FromLong(fd);
10785
4
}
10786
#endif
10787
10788
10789
#if defined(__linux__) && defined(__NR_pidfd_getfd) && \
10790
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10791
/*[clinic input]
10792
os.pidfd_getfd
10793
  pidfd: int
10794
    A process file descriptor.
10795
  targetfd: int
10796
    The file descriptor to duplicate from the target process.
10797
  *
10798
  flags: unsigned_int = 0
10799
    Reserved, must be 0.
10800
10801
Duplicate a file descriptor from the process referred to by *pidfd*.
10802
[clinic start generated code]*/
10803
10804
static PyObject *
10805
os_pidfd_getfd_impl(PyObject *module, int pidfd, int targetfd,
10806
                    unsigned int flags)
10807
/*[clinic end generated code: output=e1a1415a13c7137f input=ef6417fb10deb1cc]*/
10808
{
10809
    int fd = syscall(__NR_pidfd_getfd, pidfd, targetfd, flags);
10810
    if (fd < 0) {
10811
        return posix_error();
10812
    }
10813
    return PyLong_FromLong(fd);
10814
}
10815
#endif
10816
10817
10818
#ifdef HAVE_SETNS
10819
/*[clinic input]
10820
os.setns
10821
  fd: fildes
10822
    A file descriptor to a namespace.
10823
  nstype: int = 0
10824
    Type of namespace.
10825
10826
Move the calling thread into different namespaces.
10827
[clinic start generated code]*/
10828
10829
static PyObject *
10830
os_setns_impl(PyObject *module, int fd, int nstype)
10831
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10832
0
{
10833
0
    int res;
10834
10835
0
    Py_BEGIN_ALLOW_THREADS
10836
0
    res = setns(fd, nstype);
10837
0
    Py_END_ALLOW_THREADS
10838
10839
0
    if (res != 0) {
10840
0
        return posix_error();
10841
0
    }
10842
10843
0
    Py_RETURN_NONE;
10844
0
}
10845
#endif
10846
10847
10848
#ifdef HAVE_UNSHARE
10849
/*[clinic input]
10850
os.unshare
10851
  flags: int
10852
    Namespaces to be unshared.
10853
10854
Disassociate parts of a process (or thread) execution context.
10855
[clinic start generated code]*/
10856
10857
static PyObject *
10858
os_unshare_impl(PyObject *module, int flags)
10859
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10860
0
{
10861
0
    int res;
10862
10863
0
    Py_BEGIN_ALLOW_THREADS
10864
0
    res = unshare(flags);
10865
0
    Py_END_ALLOW_THREADS
10866
10867
0
    if (res != 0) {
10868
0
        return posix_error();
10869
0
    }
10870
10871
0
    Py_RETURN_NONE;
10872
0
}
10873
#endif
10874
10875
10876
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10877
/*[clinic input]
10878
os.readlink
10879
10880
    path: path_t
10881
    *
10882
    dir_fd: dir_fd(requires='readlinkat') = None
10883
10884
Return a string representing the path to which the symbolic link points.
10885
10886
If dir_fd is not None, it should be a file descriptor open to
10887
a directory, and path should be relative; path will then be relative to
10888
that directory.
10889
10890
dir_fd may not be implemented on your platform.  If it is unavailable,
10891
using it will raise a NotImplementedError.
10892
[clinic start generated code]*/
10893
10894
static PyObject *
10895
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10896
/*[clinic end generated code: output=d21b732a2e814030 input=03d10130870dbca8]*/
10897
6
{
10898
6
#if defined(HAVE_READLINK)
10899
6
    char buffer[MAXPATHLEN+1];
10900
6
    ssize_t length;
10901
6
#ifdef HAVE_READLINKAT
10902
6
    int readlinkat_unavailable = 0;
10903
6
#endif
10904
10905
6
    Py_BEGIN_ALLOW_THREADS
10906
6
#ifdef HAVE_READLINKAT
10907
6
    if (dir_fd != DEFAULT_DIR_FD) {
10908
0
        if (HAVE_READLINKAT_RUNTIME) {
10909
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10910
0
        } else {
10911
0
            readlinkat_unavailable = 1;
10912
0
        }
10913
0
    } else
10914
6
#endif
10915
6
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10916
6
    Py_END_ALLOW_THREADS
10917
10918
6
#ifdef HAVE_READLINKAT
10919
6
    if (readlinkat_unavailable) {
10920
0
        argument_unavailable_error(NULL, "dir_fd");
10921
0
        return NULL;
10922
0
    }
10923
6
#endif
10924
10925
6
    if (length < 0) {
10926
0
        return path_error(path);
10927
0
    }
10928
6
    buffer[length] = '\0';
10929
10930
6
    if (PyUnicode_Check(path->object))
10931
6
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10932
0
    else
10933
0
        return PyBytes_FromStringAndSize(buffer, length);
10934
#elif defined(MS_WINDOWS)
10935
    DWORD n_bytes_returned;
10936
    DWORD io_result = 0;
10937
    HANDLE reparse_point_handle;
10938
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10939
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10940
    PyObject *result = NULL;
10941
10942
    /* First get a handle to the reparse point */
10943
    Py_BEGIN_ALLOW_THREADS
10944
    reparse_point_handle = CreateFileW(
10945
        path->wide,
10946
        0,
10947
        0,
10948
        0,
10949
        OPEN_EXISTING,
10950
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10951
        0);
10952
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10953
        /* New call DeviceIoControl to read the reparse point */
10954
        io_result = DeviceIoControl(
10955
            reparse_point_handle,
10956
            FSCTL_GET_REPARSE_POINT,
10957
            0, 0, /* in buffer */
10958
            target_buffer, sizeof(target_buffer),
10959
            &n_bytes_returned,
10960
            0 /* we're not using OVERLAPPED_IO */
10961
            );
10962
        CloseHandle(reparse_point_handle);
10963
    }
10964
    Py_END_ALLOW_THREADS
10965
10966
    if (io_result == 0) {
10967
        return path_error(path);
10968
    }
10969
10970
    wchar_t *name = NULL;
10971
    Py_ssize_t nameLen = 0;
10972
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10973
    {
10974
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10975
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10976
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10977
    }
10978
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10979
    {
10980
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10981
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10982
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10983
    }
10984
    else
10985
    {
10986
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10987
    }
10988
    if (name) {
10989
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10990
            /* Our buffer is mutable, so this is okay */
10991
            name[1] = L'\\';
10992
        }
10993
        result = PyUnicode_FromWideChar(name, nameLen);
10994
        if (result && PyBytes_Check(path->object)) {
10995
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10996
        }
10997
    }
10998
    return result;
10999
#endif
11000
6
}
11001
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
11002
11003
#if defined(MS_WINDOWS)
11004
11005
/* Remove the last portion of the path - return 0 on success */
11006
static int
11007
_dirnameW(WCHAR *path)
11008
{
11009
    WCHAR *ptr;
11010
    size_t length = wcsnlen_s(path, MAX_PATH);
11011
    if (length == MAX_PATH) {
11012
        return -1;
11013
    }
11014
11015
    /* walk the path from the end until a backslash is encountered */
11016
    for(ptr = path + length; ptr != path; ptr--) {
11017
        if (*ptr == L'\\' || *ptr == L'/') {
11018
            break;
11019
        }
11020
    }
11021
    *ptr = 0;
11022
    return 0;
11023
}
11024
11025
#endif
11026
11027
#ifdef HAVE_SYMLINK
11028
11029
#if defined(MS_WINDOWS)
11030
11031
/* Is this path absolute? */
11032
static int
11033
_is_absW(const WCHAR *path)
11034
{
11035
    return path[0] == L'\\' || path[0] == L'/' ||
11036
        (path[0] && path[1] == L':');
11037
}
11038
11039
/* join root and rest with a backslash - return 0 on success */
11040
static int
11041
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
11042
{
11043
    if (_is_absW(rest)) {
11044
        return wcscpy_s(dest_path, MAX_PATH, rest);
11045
    }
11046
11047
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
11048
        return -1;
11049
    }
11050
11051
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
11052
        return -1;
11053
    }
11054
11055
    return wcscat_s(dest_path, MAX_PATH, rest);
11056
}
11057
11058
/* Return True if the path at src relative to dest is a directory */
11059
static int
11060
_check_dirW(LPCWSTR src, LPCWSTR dest)
11061
{
11062
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11063
    WCHAR dest_parent[MAX_PATH];
11064
    WCHAR src_resolved[MAX_PATH] = L"";
11065
11066
    /* dest_parent = os.path.dirname(dest) */
11067
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11068
        _dirnameW(dest_parent)) {
11069
        return 0;
11070
    }
11071
    /* src_resolved = os.path.join(dest_parent, src) */
11072
    if (_joinW(src_resolved, dest_parent, src)) {
11073
        return 0;
11074
    }
11075
    return (
11076
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11077
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11078
    );
11079
}
11080
#endif
11081
11082
11083
/*[clinic input]
11084
os.symlink
11085
    src: path_t
11086
    dst: path_t
11087
    target_is_directory: bool = False
11088
    *
11089
    dir_fd: dir_fd(requires='symlinkat')=None
11090
11091
Create a symbolic link pointing to src named dst.
11092
11093
target_is_directory is required on Windows if the target is to be
11094
interpreted as a directory.  (On Windows, symlink requires Windows 6.0
11095
or greater, and raises a NotImplementedError otherwise.)
11096
target_is_directory is ignored on non-Windows platforms.
11097
11098
If dir_fd is not None, it should be a file descriptor open to
11099
a directory, and path should be relative; path will then be relative
11100
to that directory.
11101
dir_fd may not be implemented on your platform.  If it is unavailable,
11102
using it will raise a NotImplementedError.
11103
11104
[clinic start generated code]*/
11105
11106
static PyObject *
11107
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11108
                int target_is_directory, int dir_fd)
11109
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=71b75467b31c45f7]*/
11110
0
{
11111
#ifdef MS_WINDOWS
11112
    DWORD result;
11113
    DWORD flags = 0;
11114
11115
    /* Assumed true, set to false if detected to not be available. */
11116
    static int windows_has_symlink_unprivileged_flag = TRUE;
11117
#else
11118
0
    int result;
11119
0
#ifdef HAVE_SYMLINKAT
11120
0
    int symlinkat_unavailable = 0;
11121
0
#endif
11122
0
#endif
11123
11124
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11125
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11126
0
        return NULL;
11127
0
    }
11128
11129
#ifdef MS_WINDOWS
11130
11131
    if (windows_has_symlink_unprivileged_flag) {
11132
        /* Allow non-admin symlinks if system allows it. */
11133
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11134
    }
11135
11136
    Py_BEGIN_ALLOW_THREADS
11137
    _Py_BEGIN_SUPPRESS_IPH
11138
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11139
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11140
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11141
    }
11142
11143
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11144
    _Py_END_SUPPRESS_IPH
11145
    Py_END_ALLOW_THREADS
11146
11147
    if (windows_has_symlink_unprivileged_flag && !result &&
11148
        ERROR_INVALID_PARAMETER == GetLastError()) {
11149
11150
        Py_BEGIN_ALLOW_THREADS
11151
        _Py_BEGIN_SUPPRESS_IPH
11152
        /* This error might be caused by
11153
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11154
        Try again, and update windows_has_symlink_unprivileged_flag if we
11155
        are successful this time.
11156
11157
        NOTE: There is a risk of a race condition here if there are other
11158
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11159
        another process (or thread) changes that condition in between our
11160
        calls to CreateSymbolicLink.
11161
        */
11162
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11163
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11164
        _Py_END_SUPPRESS_IPH
11165
        Py_END_ALLOW_THREADS
11166
11167
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11168
            windows_has_symlink_unprivileged_flag = FALSE;
11169
        }
11170
    }
11171
11172
    if (!result)
11173
        return path_error2(src, dst);
11174
11175
#else
11176
11177
0
    Py_BEGIN_ALLOW_THREADS
11178
0
#ifdef HAVE_SYMLINKAT
11179
0
    if (dir_fd != DEFAULT_DIR_FD) {
11180
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11181
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11182
0
        } else {
11183
0
            symlinkat_unavailable = 1;
11184
0
        }
11185
0
    } else
11186
0
#endif
11187
0
        result = symlink(src->narrow, dst->narrow);
11188
0
    Py_END_ALLOW_THREADS
11189
11190
0
#ifdef HAVE_SYMLINKAT
11191
0
    if (symlinkat_unavailable) {
11192
0
          argument_unavailable_error(NULL, "dir_fd");
11193
0
          return NULL;
11194
0
    }
11195
0
#endif
11196
11197
0
    if (result)
11198
0
        return path_error2(src, dst);
11199
0
#endif
11200
11201
0
    Py_RETURN_NONE;
11202
0
}
11203
#endif /* HAVE_SYMLINK */
11204
11205
11206
static PyStructSequence_Field times_result_fields[] = {
11207
    {"user",    "user time"},
11208
    {"system",   "system time"},
11209
    {"children_user",    "user time of children"},
11210
    {"children_system",    "system time of children"},
11211
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11212
    {NULL}
11213
};
11214
11215
PyDoc_STRVAR(times_result__doc__,
11216
"times_result: Result from os.times().\n\n\
11217
This object may be accessed either as a tuple of\n\
11218
  (user, system, children_user, children_system, elapsed),\n\
11219
or via the attributes user, system, children_user, children_system,\n\
11220
and elapsed.\n\
11221
\n\
11222
See os.times for more information.");
11223
11224
static PyStructSequence_Desc times_result_desc = {
11225
    MODNAME ".times_result", /* name */
11226
    times_result__doc__, /* doc */
11227
    times_result_fields,
11228
    5
11229
};
11230
11231
static PyObject *
11232
build_times_result(PyObject *module, double user, double system,
11233
    double children_user, double children_system,
11234
    double elapsed)
11235
0
{
11236
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11237
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11238
0
    if (value == NULL)
11239
0
        return NULL;
11240
11241
0
#define SET(i, field) \
11242
0
    { \
11243
0
    PyObject *o = PyFloat_FromDouble(field); \
11244
0
    if (!o) { \
11245
0
        Py_DECREF(value); \
11246
0
        return NULL; \
11247
0
    } \
11248
0
    PyStructSequence_SET_ITEM(value, i, o); \
11249
0
    } \
11250
0
11251
0
    SET(0, user);
11252
0
    SET(1, system);
11253
0
    SET(2, children_user);
11254
0
    SET(3, children_system);
11255
0
    SET(4, elapsed);
11256
11257
0
#undef SET
11258
11259
0
    return value;
11260
0
}
11261
11262
11263
/*[clinic input]
11264
os.times
11265
11266
Return a collection containing process timing information.
11267
11268
The object returned behaves like a named tuple with these fields:
11269
  (utime, stime, cutime, cstime, elapsed_time)
11270
All fields are floating-point numbers.
11271
[clinic start generated code]*/
11272
11273
static PyObject *
11274
os_times_impl(PyObject *module)
11275
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11276
0
{
11277
#ifdef MS_WINDOWS
11278
    FILETIME create, exit, kernel, user;
11279
    HANDLE hProc;
11280
    hProc = GetCurrentProcess();
11281
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11282
    /* The fields of a FILETIME structure are the hi and lo part
11283
       of a 64-bit value expressed in 100 nanosecond units.
11284
       1e7 is one second in such units; 1e-7 the inverse.
11285
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11286
    */
11287
    return build_times_result(module,
11288
        (double)(user.dwHighDateTime*429.4967296 +
11289
                 user.dwLowDateTime*1e-7),
11290
        (double)(kernel.dwHighDateTime*429.4967296 +
11291
                 kernel.dwLowDateTime*1e-7),
11292
        (double)0,
11293
        (double)0,
11294
        (double)0);
11295
#else /* MS_WINDOWS */
11296
0
    _posixstate *state = get_posix_state(module);
11297
0
    long ticks_per_second = state->ticks_per_second;
11298
11299
0
    struct tms process;
11300
0
    clock_t elapsed;
11301
0
    errno = 0;
11302
0
    elapsed = times(&process);
11303
0
    if (elapsed == (clock_t) -1) {
11304
0
        return posix_error();
11305
0
    }
11306
11307
0
    return build_times_result(module,
11308
0
        (double)process.tms_utime / ticks_per_second,
11309
0
        (double)process.tms_stime / ticks_per_second,
11310
0
        (double)process.tms_cutime / ticks_per_second,
11311
0
        (double)process.tms_cstime / ticks_per_second,
11312
0
        (double)elapsed / ticks_per_second);
11313
0
#endif /* MS_WINDOWS */
11314
0
}
11315
11316
11317
#if defined(HAVE_TIMERFD_CREATE)
11318
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11319
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11320
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11321
11322
static PyObject *
11323
build_itimerspec(const struct itimerspec* curr_value)
11324
0
{
11325
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11326
0
                                                          curr_value->it_value.tv_nsec);
11327
0
    PyObject *value = PyFloat_FromDouble(_value);
11328
0
    if (value == NULL) {
11329
0
        return NULL;
11330
0
    }
11331
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11332
0
                                                   curr_value->it_interval.tv_nsec);
11333
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11334
0
    if (interval == NULL) {
11335
0
        Py_DECREF(value);
11336
0
        return NULL;
11337
0
    }
11338
0
    return _PyTuple_FromPairSteal(value, interval);
11339
0
}
11340
11341
static PyObject *
11342
build_itimerspec_ns(const struct itimerspec* curr_value)
11343
0
{
11344
0
    PyTime_t value, interval;
11345
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11346
0
        return NULL;
11347
0
    }
11348
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11349
0
        return NULL;
11350
0
    }
11351
0
    return Py_BuildValue("LL", value, interval);
11352
0
}
11353
11354
/*[clinic input]
11355
os.timerfd_create
11356
11357
    clockid: int
11358
        A valid clock ID constant as timer file descriptor.
11359
11360
        time.CLOCK_REALTIME
11361
        time.CLOCK_MONOTONIC
11362
        time.CLOCK_BOOTTIME
11363
    /
11364
    *
11365
    flags: int = 0
11366
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11367
11368
        os.TFD_NONBLOCK
11369
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11370
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11371
11372
        os.TFD_CLOEXEC
11373
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11374
11375
Create and return a timer file descriptor.
11376
[clinic start generated code]*/
11377
11378
static PyObject *
11379
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11380
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11381
11382
0
{
11383
0
    int fd;
11384
0
    Py_BEGIN_ALLOW_THREADS
11385
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11386
0
    fd = timerfd_create(clockid, flags);
11387
0
    Py_END_ALLOW_THREADS
11388
0
    if (fd == -1) {
11389
0
        return PyErr_SetFromErrno(PyExc_OSError);
11390
0
    }
11391
0
    return PyLong_FromLong(fd);
11392
0
}
11393
11394
/*[clinic input]
11395
os.timerfd_settime
11396
11397
    fd: fildes
11398
        A timer file descriptor.
11399
    /
11400
    *
11401
    flags: int = 0
11402
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11403
    initial as initial_double: double = 0.0
11404
        The initial expiration time, in seconds.
11405
    interval as interval_double: double = 0.0
11406
        The timer's interval, in seconds.
11407
11408
Alter a timer file descriptor's internal timer in seconds.
11409
[clinic start generated code]*/
11410
11411
static PyObject *
11412
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11413
                        double initial_double, double interval_double)
11414
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11415
0
{
11416
0
    PyTime_t initial, interval;
11417
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11418
0
                                  &initial) < 0) {
11419
0
        return NULL;
11420
0
    }
11421
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11422
0
                                  &interval) < 0) {
11423
0
        return NULL;
11424
0
    }
11425
11426
0
    struct itimerspec new_value, old_value;
11427
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11428
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11429
0
        return NULL;
11430
0
    }
11431
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11432
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11433
0
        return NULL;
11434
0
    }
11435
11436
0
    int result;
11437
0
    Py_BEGIN_ALLOW_THREADS
11438
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11439
0
    Py_END_ALLOW_THREADS
11440
0
    if (result == -1) {
11441
0
        return PyErr_SetFromErrno(PyExc_OSError);
11442
0
    }
11443
0
    return build_itimerspec(&old_value);
11444
0
}
11445
11446
11447
/*[clinic input]
11448
os.timerfd_settime_ns
11449
11450
    fd: fildes
11451
        A timer file descriptor.
11452
    /
11453
    *
11454
    flags: int = 0
11455
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11456
    initial: long_long = 0
11457
        initial expiration timing in seconds.
11458
    interval: long_long = 0
11459
        interval for the timer in seconds.
11460
11461
Alter a timer file descriptor's internal timer in nanoseconds.
11462
[clinic start generated code]*/
11463
11464
static PyObject *
11465
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11466
                           long long initial, long long interval)
11467
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11468
0
{
11469
0
    struct itimerspec new_value;
11470
0
    struct itimerspec old_value;
11471
0
    int result;
11472
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11473
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11474
0
        return NULL;
11475
0
    }
11476
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11477
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11478
0
        return NULL;
11479
0
    }
11480
0
    Py_BEGIN_ALLOW_THREADS
11481
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11482
0
    Py_END_ALLOW_THREADS
11483
0
    if (result == -1) {
11484
0
        return PyErr_SetFromErrno(PyExc_OSError);
11485
0
    }
11486
0
    return build_itimerspec_ns(&old_value);
11487
0
}
11488
11489
/*[clinic input]
11490
@permit_long_summary
11491
os.timerfd_gettime
11492
11493
    fd: fildes
11494
        A timer file descriptor.
11495
    /
11496
11497
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11498
[clinic start generated code]*/
11499
11500
static PyObject *
11501
os_timerfd_gettime_impl(PyObject *module, int fd)
11502
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11503
0
{
11504
0
    struct itimerspec curr_value;
11505
0
    int result;
11506
0
    Py_BEGIN_ALLOW_THREADS
11507
0
    result = timerfd_gettime(fd, &curr_value);
11508
0
    Py_END_ALLOW_THREADS
11509
0
    if (result == -1) {
11510
0
        return PyErr_SetFromErrno(PyExc_OSError);
11511
0
    }
11512
0
    return build_itimerspec(&curr_value);
11513
0
}
11514
11515
11516
/*[clinic input]
11517
@permit_long_summary
11518
os.timerfd_gettime_ns
11519
11520
    fd: fildes
11521
        A timer file descriptor.
11522
    /
11523
11524
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11525
[clinic start generated code]*/
11526
11527
static PyObject *
11528
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11529
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11530
0
{
11531
0
    struct itimerspec curr_value;
11532
0
    int result;
11533
0
    Py_BEGIN_ALLOW_THREADS
11534
0
    result = timerfd_gettime(fd, &curr_value);
11535
0
    Py_END_ALLOW_THREADS
11536
0
    if (result == -1) {
11537
0
        return PyErr_SetFromErrno(PyExc_OSError);
11538
0
    }
11539
0
    return build_itimerspec_ns(&curr_value);
11540
0
}
11541
11542
#undef ONE_SECOND_IN_NS
11543
#undef EXTRACT_NSEC
11544
11545
#endif  /* HAVE_TIMERFD_CREATE */
11546
11547
#ifdef HAVE_GETSID
11548
/*[clinic input]
11549
os.getsid
11550
11551
    pid: pid_t
11552
    /
11553
11554
Call the system call getsid(pid) and return the result.
11555
[clinic start generated code]*/
11556
11557
static PyObject *
11558
os_getsid_impl(PyObject *module, pid_t pid)
11559
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11560
0
{
11561
0
    int sid;
11562
0
    sid = getsid(pid);
11563
0
    if (sid < 0)
11564
0
        return posix_error();
11565
0
    return PyLong_FromLong((long)sid);
11566
0
}
11567
#endif /* HAVE_GETSID */
11568
11569
11570
#ifdef HAVE_SETSID
11571
/*[clinic input]
11572
os.setsid
11573
11574
Call the system call setsid().
11575
[clinic start generated code]*/
11576
11577
static PyObject *
11578
os_setsid_impl(PyObject *module)
11579
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11580
0
{
11581
0
    if (setsid() < 0)
11582
0
        return posix_error();
11583
0
    Py_RETURN_NONE;
11584
0
}
11585
#endif /* HAVE_SETSID */
11586
11587
11588
#ifdef HAVE_SETPGID
11589
/*[clinic input]
11590
os.setpgid
11591
11592
    pid: pid_t
11593
    pgrp: pid_t
11594
    /
11595
11596
Call the system call setpgid(pid, pgrp).
11597
[clinic start generated code]*/
11598
11599
static PyObject *
11600
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11601
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11602
0
{
11603
0
    if (setpgid(pid, pgrp) < 0)
11604
0
        return posix_error();
11605
0
    Py_RETURN_NONE;
11606
0
}
11607
#endif /* HAVE_SETPGID */
11608
11609
11610
#ifdef HAVE_TCGETPGRP
11611
/*[clinic input]
11612
os.tcgetpgrp
11613
11614
    fd: int
11615
    /
11616
11617
Return the process group associated with the terminal specified by fd.
11618
[clinic start generated code]*/
11619
11620
static PyObject *
11621
os_tcgetpgrp_impl(PyObject *module, int fd)
11622
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11623
0
{
11624
0
    pid_t pgid = tcgetpgrp(fd);
11625
0
    if (pgid < 0)
11626
0
        return posix_error();
11627
0
    return PyLong_FromPid(pgid);
11628
0
}
11629
#endif /* HAVE_TCGETPGRP */
11630
11631
11632
#ifdef HAVE_TCSETPGRP
11633
/*[clinic input]
11634
os.tcsetpgrp
11635
11636
    fd: int
11637
    pgid: pid_t
11638
    /
11639
11640
Set the process group associated with the terminal specified by fd.
11641
[clinic start generated code]*/
11642
11643
static PyObject *
11644
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11645
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11646
0
{
11647
0
    if (tcsetpgrp(fd, pgid) < 0)
11648
0
        return posix_error();
11649
0
    Py_RETURN_NONE;
11650
0
}
11651
#endif /* HAVE_TCSETPGRP */
11652
11653
/* Functions acting on file descriptors */
11654
11655
#ifdef O_CLOEXEC
11656
extern int _Py_open_cloexec_works;
11657
#endif
11658
11659
11660
/*[clinic input]
11661
os.open -> int
11662
    path: path_t
11663
    flags: int
11664
    mode: int = 0o777
11665
    *
11666
    dir_fd: dir_fd(requires='openat') = None
11667
11668
Open a file for low level IO.  Returns a file descriptor (integer).
11669
11670
If dir_fd is not None, it should be a file descriptor open to
11671
a directory, and path should be relative; path will then be relative to
11672
that directory.
11673
dir_fd may not be implemented on your platform.  If it is unavailable,
11674
using it will raise a NotImplementedError.
11675
[clinic start generated code]*/
11676
11677
static int
11678
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11679
/*[clinic end generated code: output=abc7227888c8bc73 input=75f7b4eaf92f2225]*/
11680
96.8k
{
11681
96.8k
    int fd;
11682
96.8k
    int async_err = 0;
11683
96.8k
#ifdef HAVE_OPENAT
11684
96.8k
    int openat_unavailable = 0;
11685
96.8k
#endif
11686
11687
96.8k
#ifdef O_CLOEXEC
11688
96.8k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11689
#elif !defined(MS_WINDOWS)
11690
    int *atomic_flag_works = NULL;
11691
#endif
11692
11693
#ifdef MS_WINDOWS
11694
    flags |= O_NOINHERIT;
11695
#elif defined(O_CLOEXEC)
11696
96.8k
    flags |= O_CLOEXEC;
11697
96.8k
#endif
11698
11699
96.8k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11700
0
        return -1;
11701
0
    }
11702
11703
96.8k
    _Py_BEGIN_SUPPRESS_IPH
11704
96.8k
    do {
11705
96.8k
        Py_BEGIN_ALLOW_THREADS
11706
#ifdef MS_WINDOWS
11707
        fd = _wopen(path->wide, flags, mode);
11708
#else
11709
96.8k
#ifdef HAVE_OPENAT
11710
96.8k
        if (dir_fd != DEFAULT_DIR_FD) {
11711
92.1k
            if (HAVE_OPENAT_RUNTIME) {
11712
92.1k
                fd = openat(dir_fd, path->narrow, flags, mode);
11713
11714
92.1k
            } else {
11715
0
                openat_unavailable = 1;
11716
0
                fd = -1;
11717
0
            }
11718
92.1k
        } else
11719
4.64k
#endif /* HAVE_OPENAT */
11720
4.64k
            fd = open(path->narrow, flags, mode);
11721
96.8k
#endif /* !MS_WINDOWS */
11722
96.8k
        Py_END_ALLOW_THREADS
11723
96.8k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11724
96.8k
    _Py_END_SUPPRESS_IPH
11725
11726
96.8k
#ifdef HAVE_OPENAT
11727
96.8k
    if (openat_unavailable) {
11728
0
        argument_unavailable_error(NULL, "dir_fd");
11729
0
        return -1;
11730
0
    }
11731
96.8k
#endif
11732
11733
96.8k
    if (fd < 0) {
11734
0
        if (!async_err)
11735
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11736
0
        return -1;
11737
0
    }
11738
11739
96.8k
#ifndef MS_WINDOWS
11740
96.8k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11741
0
        close(fd);
11742
0
        return -1;
11743
0
    }
11744
96.8k
#endif
11745
11746
96.8k
    return fd;
11747
96.8k
}
11748
11749
11750
/*[clinic input]
11751
os.close
11752
11753
    fd: int
11754
11755
Close a file descriptor.
11756
[clinic start generated code]*/
11757
11758
static PyObject *
11759
os_close_impl(PyObject *module, int fd)
11760
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11761
96.6k
{
11762
96.6k
    int res;
11763
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11764
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11765
     * for more details.
11766
     */
11767
96.6k
    Py_BEGIN_ALLOW_THREADS
11768
96.6k
    _Py_BEGIN_SUPPRESS_IPH
11769
96.6k
    res = close(fd);
11770
96.6k
    _Py_END_SUPPRESS_IPH
11771
96.6k
    Py_END_ALLOW_THREADS
11772
96.6k
    if (res < 0)
11773
0
        return posix_error();
11774
96.6k
    Py_RETURN_NONE;
11775
96.6k
}
11776
11777
/*[clinic input]
11778
os.closerange
11779
11780
    fd_low: int
11781
    fd_high: int
11782
    /
11783
11784
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11785
[clinic start generated code]*/
11786
11787
static PyObject *
11788
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11789
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11790
0
{
11791
0
    Py_BEGIN_ALLOW_THREADS
11792
0
    _Py_closerange(fd_low, fd_high - 1);
11793
0
    Py_END_ALLOW_THREADS
11794
0
    Py_RETURN_NONE;
11795
0
}
11796
11797
11798
/*[clinic input]
11799
os.dup -> int
11800
11801
    fd: int
11802
    /
11803
11804
Return a duplicate of a file descriptor.
11805
[clinic start generated code]*/
11806
11807
static int
11808
os_dup_impl(PyObject *module, int fd)
11809
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11810
0
{
11811
0
    return _Py_dup(fd);
11812
0
}
11813
11814
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11815
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11816
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11817
/*[clinic input]
11818
os.dup2 -> int
11819
    fd: int
11820
    fd2: int
11821
    inheritable: bool=True
11822
11823
Duplicate file descriptor.
11824
[clinic start generated code]*/
11825
11826
static int
11827
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11828
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11829
0
{
11830
0
    int res = 0;
11831
0
#if defined(HAVE_DUP3) && \
11832
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11833
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11834
0
    static int dup3_works = -1;
11835
0
#endif
11836
11837
    /* dup2() can fail with EINTR if the target FD is already open, because it
11838
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11839
     * upon close(), and therefore below.
11840
     */
11841
#ifdef MS_WINDOWS
11842
    Py_BEGIN_ALLOW_THREADS
11843
    _Py_BEGIN_SUPPRESS_IPH
11844
    res = dup2(fd, fd2);
11845
    _Py_END_SUPPRESS_IPH
11846
    Py_END_ALLOW_THREADS
11847
    if (res < 0) {
11848
        posix_error();
11849
        return -1;
11850
    }
11851
    res = fd2; // msvcrt dup2 returns 0 on success.
11852
11853
    /* Character files like console cannot be make non-inheritable */
11854
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11855
        close(fd2);
11856
        return -1;
11857
    }
11858
11859
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11860
    Py_BEGIN_ALLOW_THREADS
11861
    if (!inheritable)
11862
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11863
    else
11864
        res = dup2(fd, fd2);
11865
    Py_END_ALLOW_THREADS
11866
    if (res < 0) {
11867
        posix_error();
11868
        return -1;
11869
    }
11870
11871
#else
11872
11873
0
#ifdef HAVE_DUP3
11874
0
    if (!inheritable && dup3_works != 0) {
11875
0
        Py_BEGIN_ALLOW_THREADS
11876
0
        res = dup3(fd, fd2, O_CLOEXEC);
11877
0
        Py_END_ALLOW_THREADS
11878
0
        if (res < 0) {
11879
0
            if (dup3_works == -1)
11880
0
                dup3_works = (errno != ENOSYS);
11881
0
            if (dup3_works) {
11882
0
                posix_error();
11883
0
                return -1;
11884
0
            }
11885
0
        }
11886
0
    }
11887
11888
0
    if (inheritable || dup3_works == 0)
11889
0
    {
11890
0
#endif
11891
0
        Py_BEGIN_ALLOW_THREADS
11892
0
        res = dup2(fd, fd2);
11893
0
        Py_END_ALLOW_THREADS
11894
0
        if (res < 0) {
11895
0
            posix_error();
11896
0
            return -1;
11897
0
        }
11898
11899
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11900
0
            close(fd2);
11901
0
            return -1;
11902
0
        }
11903
0
#ifdef HAVE_DUP3
11904
0
    }
11905
0
#endif
11906
11907
0
#endif
11908
11909
0
    return res;
11910
0
}
11911
#endif
11912
11913
11914
#ifdef HAVE_LOCKF
11915
/*[clinic input]
11916
os.lockf
11917
11918
    fd: int
11919
        An open file descriptor.
11920
    command: int
11921
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11922
    length: Py_off_t
11923
        The number of bytes to lock, starting at the current position.
11924
    /
11925
11926
Apply, test or remove a POSIX lock on an open file descriptor.
11927
11928
[clinic start generated code]*/
11929
11930
static PyObject *
11931
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11932
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11933
0
{
11934
0
    int res;
11935
11936
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11937
0
        return NULL;
11938
0
    }
11939
11940
0
    Py_BEGIN_ALLOW_THREADS
11941
0
    res = lockf(fd, command, length);
11942
0
    Py_END_ALLOW_THREADS
11943
11944
0
    if (res < 0)
11945
0
        return posix_error();
11946
11947
0
    Py_RETURN_NONE;
11948
0
}
11949
#endif /* HAVE_LOCKF */
11950
11951
11952
/*[clinic input]
11953
os.lseek -> Py_off_t
11954
11955
    fd: int
11956
        An open file descriptor, as returned by os.open().
11957
    position: Py_off_t
11958
        Position, interpreted relative to 'whence'.
11959
    whence as how: int
11960
        The relative position to seek from. Valid values are:
11961
        - SEEK_SET: seek from the start of the file.
11962
        - SEEK_CUR: seek from the current file position.
11963
        - SEEK_END: seek from the end of the file.
11964
    /
11965
11966
Set the position of a file descriptor.  Return the new position.
11967
11968
The return value is the number of bytes relative to the beginning of
11969
the file.
11970
[clinic start generated code]*/
11971
11972
static Py_off_t
11973
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11974
/*[clinic end generated code: output=971e1efb6b30bd2f input=32ea0788da7cb44b]*/
11975
0
{
11976
0
    Py_off_t result;
11977
11978
0
#ifdef SEEK_SET
11979
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11980
0
    switch (how) {
11981
0
        case 0: how = SEEK_SET; break;
11982
0
        case 1: how = SEEK_CUR; break;
11983
0
        case 2: how = SEEK_END; break;
11984
0
    }
11985
0
#endif /* SEEK_END */
11986
11987
0
    Py_BEGIN_ALLOW_THREADS
11988
0
    _Py_BEGIN_SUPPRESS_IPH
11989
#ifdef MS_WINDOWS
11990
    result = _lseeki64(fd, position, how);
11991
#else
11992
0
    result = lseek(fd, position, how);
11993
0
#endif
11994
0
    _Py_END_SUPPRESS_IPH
11995
0
    Py_END_ALLOW_THREADS
11996
0
    if (result < 0)
11997
0
        posix_error();
11998
11999
0
    return result;
12000
0
}
12001
12002
12003
/*[clinic input]
12004
os.read
12005
    fd: int
12006
    length: Py_ssize_t
12007
    /
12008
12009
Read from a file descriptor.  Returns a bytes object.
12010
[clinic start generated code]*/
12011
12012
static PyObject *
12013
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
12014
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
12015
0
{
12016
0
    if (length < 0) {
12017
0
        errno = EINVAL;
12018
0
        return posix_error();
12019
0
    }
12020
12021
0
    length = Py_MIN(length, _PY_READ_MAX);
12022
12023
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12024
0
    if (writer == NULL) {
12025
0
        return NULL;
12026
0
    }
12027
12028
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
12029
0
    if (n == -1) {
12030
0
        PyBytesWriter_Discard(writer);
12031
0
        return NULL;
12032
0
    }
12033
12034
0
    return PyBytesWriter_FinishWithSize(writer, n);
12035
0
}
12036
12037
/*[clinic input]
12038
os.readinto -> Py_ssize_t
12039
    fd: int
12040
    buffer: Py_buffer(accept={rwbuffer})
12041
    /
12042
12043
Read into a buffer object from a file descriptor.
12044
12045
The buffer should be mutable and bytes-like.  On success, returns the
12046
number of bytes read.  Less bytes may be read than the size of the
12047
buffer.  The underlying system call will be retried when interrupted by
12048
a signal, unless the signal handler raises an exception.  Other errors
12049
will not be retried and an error will be raised.
12050
12051
Returns 0 if *fd* is at end of file or if the provided *buffer* has
12052
length 0 (which can be used to check for errors without reading data).
12053
Never returns negative.
12054
[clinic start generated code]*/
12055
12056
static Py_ssize_t
12057
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12058
/*[clinic end generated code: output=8091a3513c683a80 input=2a5f8b212cb5730c]*/
12059
0
{
12060
0
    assert(buffer->len >= 0);
12061
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12062
    /* Ensure negative is never returned without an error. Simplifies calling
12063
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12064
        error. */
12065
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12066
0
    return result;
12067
0
}
12068
12069
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12070
                                || defined(__APPLE__))) \
12071
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12072
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12073
static int
12074
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12075
0
{
12076
0
    Py_ssize_t i, j;
12077
12078
0
    *iov = PyMem_New(struct iovec, cnt);
12079
0
    if (*iov == NULL) {
12080
0
        PyErr_NoMemory();
12081
0
        return -1;
12082
0
    }
12083
12084
0
    *buf = PyMem_New(Py_buffer, cnt);
12085
0
    if (*buf == NULL) {
12086
0
        PyMem_Free(*iov);
12087
0
        PyErr_NoMemory();
12088
0
        return -1;
12089
0
    }
12090
12091
0
    for (i = 0; i < cnt; i++) {
12092
0
        PyObject *item = PySequence_GetItem(seq, i);
12093
0
        if (item == NULL)
12094
0
            goto fail;
12095
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12096
0
            Py_DECREF(item);
12097
0
            goto fail;
12098
0
        }
12099
0
        Py_DECREF(item);
12100
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12101
0
        (*iov)[i].iov_len = (*buf)[i].len;
12102
0
    }
12103
0
    return 0;
12104
12105
0
fail:
12106
0
    PyMem_Free(*iov);
12107
0
    for (j = 0; j < i; j++) {
12108
0
        PyBuffer_Release(&(*buf)[j]);
12109
0
    }
12110
0
    PyMem_Free(*buf);
12111
0
    return -1;
12112
0
}
12113
12114
static void
12115
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12116
0
{
12117
0
    int i;
12118
0
    PyMem_Free(iov);
12119
0
    for (i = 0; i < cnt; i++) {
12120
0
        PyBuffer_Release(&buf[i]);
12121
0
    }
12122
0
    PyMem_Free(buf);
12123
0
}
12124
#endif
12125
12126
12127
#ifdef HAVE_READV
12128
/*[clinic input]
12129
os.readv -> Py_ssize_t
12130
12131
    fd: int
12132
    buffers: object
12133
    /
12134
12135
Read from a file descriptor fd into an iterable of buffers.
12136
12137
The buffers should be mutable buffers accepting bytes.
12138
readv will transfer data into each buffer until it is full
12139
and then move on to the next buffer in the sequence to hold
12140
the rest of the data.
12141
12142
readv returns the total number of bytes read,
12143
which may be less than the total capacity of all the buffers.
12144
[clinic start generated code]*/
12145
12146
static Py_ssize_t
12147
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12148
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12149
0
{
12150
0
    Py_ssize_t cnt, n;
12151
0
    int async_err = 0;
12152
0
    struct iovec *iov;
12153
0
    Py_buffer *buf;
12154
12155
0
    if (!PySequence_Check(buffers)) {
12156
0
        PyErr_SetString(PyExc_TypeError,
12157
0
            "readv() arg 2 must be a sequence");
12158
0
        return -1;
12159
0
    }
12160
12161
0
    cnt = PySequence_Size(buffers);
12162
0
    if (cnt < 0)
12163
0
        return -1;
12164
12165
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12166
0
        return -1;
12167
12168
0
    do {
12169
0
        Py_BEGIN_ALLOW_THREADS
12170
0
        n = readv(fd, iov, cnt);
12171
0
        Py_END_ALLOW_THREADS
12172
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12173
12174
0
    int saved_errno = errno;
12175
0
    iov_cleanup(iov, buf, cnt);
12176
0
    if (n < 0) {
12177
0
        if (!async_err) {
12178
0
            errno = saved_errno;
12179
0
            posix_error();
12180
0
        }
12181
0
        return -1;
12182
0
    }
12183
12184
0
    return n;
12185
0
}
12186
#endif /* HAVE_READV */
12187
12188
12189
#ifdef HAVE_PREAD
12190
/*[clinic input]
12191
@permit_long_summary
12192
os.pread
12193
12194
    fd: int
12195
    length: Py_ssize_t
12196
    offset: Py_off_t
12197
    /
12198
12199
Read a number of bytes from a file descriptor starting at a particular offset.
12200
12201
Read length bytes from file descriptor fd, starting at offset bytes from
12202
the beginning of the file.  The file offset remains unchanged.
12203
[clinic start generated code]*/
12204
12205
static PyObject *
12206
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12207
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12208
0
{
12209
0
    Py_ssize_t n;
12210
0
    int async_err = 0;
12211
12212
0
    if (length < 0) {
12213
0
        errno = EINVAL;
12214
0
        return posix_error();
12215
0
    }
12216
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12217
0
    if (writer == NULL) {
12218
0
        return NULL;
12219
0
    }
12220
12221
0
    do {
12222
0
        Py_BEGIN_ALLOW_THREADS
12223
0
        _Py_BEGIN_SUPPRESS_IPH
12224
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12225
0
        _Py_END_SUPPRESS_IPH
12226
0
        Py_END_ALLOW_THREADS
12227
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12228
12229
0
    if (n < 0) {
12230
0
        if (!async_err) {
12231
0
            posix_error();
12232
0
        }
12233
0
        PyBytesWriter_Discard(writer);
12234
0
        return NULL;
12235
0
    }
12236
0
    return PyBytesWriter_FinishWithSize(writer, n);
12237
0
}
12238
#endif /* HAVE_PREAD */
12239
12240
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12241
/*[clinic input]
12242
@permit_long_summary
12243
os.preadv -> Py_ssize_t
12244
12245
    fd: int
12246
    buffers: object
12247
    offset: Py_off_t
12248
    flags: int = 0
12249
    /
12250
12251
Reads from a file descriptor into a number of mutable bytes-like objects.
12252
12253
Combines the functionality of readv() and pread().  As readv(), it will
12254
transfer data into each buffer until it is full and then move on to the
12255
next buffer in the sequence to hold the rest of the data.  Its fourth
12256
argument, specifies the file offset at which the input operation is to
12257
be performed.  It will return the total number of bytes read (which can
12258
be less than the total capacity of all the objects).
12259
12260
The flags argument contains a bitwise OR of zero or more of the
12261
following flags:
12262
12263
- RWF_HIPRI
12264
- RWF_NOWAIT
12265
- RWF_DONTCACHE
12266
12267
Using non-zero flags requires Linux 4.6 or newer.
12268
[clinic start generated code]*/
12269
12270
static Py_ssize_t
12271
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12272
               int flags)
12273
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=bbc70c63b4f4e877]*/
12274
0
{
12275
0
    Py_ssize_t cnt, n;
12276
0
    int async_err = 0;
12277
0
    struct iovec *iov;
12278
0
    Py_buffer *buf;
12279
12280
0
    if (!PySequence_Check(buffers)) {
12281
0
        PyErr_SetString(PyExc_TypeError,
12282
0
            "preadv2() arg 2 must be a sequence");
12283
0
        return -1;
12284
0
    }
12285
12286
0
    cnt = PySequence_Size(buffers);
12287
0
    if (cnt < 0) {
12288
0
        return -1;
12289
0
    }
12290
12291
#ifndef HAVE_PREADV2
12292
    if(flags != 0) {
12293
        argument_unavailable_error("preadv2", "flags");
12294
        return -1;
12295
    }
12296
#endif
12297
12298
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12299
0
        return -1;
12300
0
    }
12301
0
#ifdef HAVE_PREADV2
12302
0
    do {
12303
0
        Py_BEGIN_ALLOW_THREADS
12304
0
        _Py_BEGIN_SUPPRESS_IPH
12305
0
        n = preadv2(fd, iov, cnt, offset, flags);
12306
0
        _Py_END_SUPPRESS_IPH
12307
0
        Py_END_ALLOW_THREADS
12308
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12309
#else
12310
    do {
12311
#if defined(__APPLE__) && defined(__clang__)
12312
/* This entire function will be removed from the module dict when the API
12313
 * is not available.
12314
 */
12315
#pragma clang diagnostic push
12316
#pragma clang diagnostic ignored "-Wunguarded-availability"
12317
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12318
#endif
12319
        Py_BEGIN_ALLOW_THREADS
12320
        _Py_BEGIN_SUPPRESS_IPH
12321
        n = preadv(fd, iov, cnt, offset);
12322
        _Py_END_SUPPRESS_IPH
12323
        Py_END_ALLOW_THREADS
12324
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12325
12326
#if defined(__APPLE__) && defined(__clang__)
12327
#pragma clang diagnostic pop
12328
#endif
12329
12330
#endif
12331
12332
0
    int saved_errno = errno;
12333
0
    iov_cleanup(iov, buf, cnt);
12334
0
    if (n < 0) {
12335
0
        if (!async_err) {
12336
0
            errno = saved_errno;
12337
0
            posix_error();
12338
0
        }
12339
0
        return -1;
12340
0
    }
12341
12342
0
    return n;
12343
0
}
12344
#endif /* HAVE_PREADV */
12345
12346
12347
/*[clinic input]
12348
os.write -> Py_ssize_t
12349
12350
    fd: int
12351
    data: Py_buffer
12352
    /
12353
12354
Write a bytes object to a file descriptor.
12355
[clinic start generated code]*/
12356
12357
static Py_ssize_t
12358
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12359
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12360
2
{
12361
2
    return _Py_write(fd, data->buf, data->len);
12362
2
}
12363
12364
#ifdef HAVE_SENDFILE
12365
#ifdef __APPLE__
12366
/*[clinic input]
12367
os.sendfile
12368
12369
    out_fd: int
12370
    in_fd: int
12371
    offset: Py_off_t
12372
    count as sbytes: Py_off_t
12373
    headers: object(c_default="NULL") = ()
12374
    trailers: object(c_default="NULL") = ()
12375
    flags: int = 0
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, Py_off_t offset,
12382
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12383
                 int flags)
12384
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12385
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12386
/*[clinic input]
12387
os.sendfile
12388
12389
    out_fd: int
12390
    in_fd: int
12391
    offset: Py_off_t
12392
    count: Py_ssize_t(allow_negative=False)
12393
    headers: object(c_default="NULL") = ()
12394
    trailers: object(c_default="NULL") = ()
12395
    flags: int = 0
12396
12397
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12398
[clinic start generated code]*/
12399
12400
static PyObject *
12401
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12402
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12403
                 int flags)
12404
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12405
#else
12406
/*[clinic input]
12407
os.sendfile
12408
12409
    out_fd: int
12410
    in_fd: int
12411
    offset as offobj: object
12412
    count: Py_ssize_t(allow_negative=False)
12413
12414
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12415
[clinic start generated code]*/
12416
12417
static PyObject *
12418
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12419
                 Py_ssize_t count)
12420
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12421
#endif
12422
0
{
12423
0
    Py_ssize_t ret;
12424
0
    int async_err = 0;
12425
12426
#ifdef __APPLE__
12427
    if(sbytes < 0) {
12428
        PyErr_SetString(PyExc_ValueError,
12429
                        "count cannot be negative");
12430
        return NULL;
12431
    }
12432
#else
12433
0
    assert(count >= 0);
12434
0
#endif
12435
12436
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12437
#ifndef __APPLE__
12438
    off_t sbytes;
12439
#endif
12440
    Py_buffer *hbuf, *tbuf;
12441
    struct sf_hdtr sf;
12442
12443
    sf.headers = NULL;
12444
    sf.trailers = NULL;
12445
12446
    if (headers != NULL) {
12447
        if (!PySequence_Check(headers)) {
12448
            PyErr_SetString(PyExc_TypeError,
12449
                "sendfile() headers must be a sequence");
12450
            return NULL;
12451
        } else {
12452
            Py_ssize_t i = PySequence_Size(headers);
12453
            if (i < 0)
12454
                return NULL;
12455
            if (i > INT_MAX) {
12456
                PyErr_SetString(PyExc_OverflowError,
12457
                    "sendfile() header is too large");
12458
                return NULL;
12459
            }
12460
            if (i > 0) {
12461
                sf.hdr_cnt = (int)i;
12462
                if (iov_setup(&(sf.headers), &hbuf,
12463
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12464
                    return NULL;
12465
#ifdef __APPLE__
12466
                for (i = 0; i < sf.hdr_cnt; i++) {
12467
                    Py_ssize_t blen = sf.headers[i].iov_len;
12468
# define OFF_T_MAX 0x7fffffffffffffff
12469
                    if (sbytes >= OFF_T_MAX - blen) {
12470
                        PyErr_SetString(PyExc_OverflowError,
12471
                            "sendfile() header is too large");
12472
                        return NULL;
12473
                    }
12474
                    sbytes += blen;
12475
                }
12476
#endif
12477
            }
12478
        }
12479
    }
12480
    if (trailers != NULL) {
12481
        if (!PySequence_Check(trailers)) {
12482
            PyErr_SetString(PyExc_TypeError,
12483
                "sendfile() trailers must be a sequence");
12484
            return NULL;
12485
        } else {
12486
            Py_ssize_t i = PySequence_Size(trailers);
12487
            if (i < 0)
12488
                return NULL;
12489
            if (i > INT_MAX) {
12490
                PyErr_SetString(PyExc_OverflowError,
12491
                    "sendfile() trailer is too large");
12492
                return NULL;
12493
            }
12494
            if (i > 0) {
12495
                sf.trl_cnt = (int)i;
12496
                if (iov_setup(&(sf.trailers), &tbuf,
12497
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12498
                    return NULL;
12499
            }
12500
        }
12501
    }
12502
12503
    _Py_BEGIN_SUPPRESS_IPH
12504
    do {
12505
        Py_BEGIN_ALLOW_THREADS
12506
#ifdef __APPLE__
12507
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12508
#else
12509
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12510
#endif
12511
        Py_END_ALLOW_THREADS
12512
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12513
    _Py_END_SUPPRESS_IPH
12514
12515
    int saved_errno = errno;
12516
    if (sf.headers != NULL)
12517
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12518
    if (sf.trailers != NULL)
12519
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12520
12521
    if (ret < 0) {
12522
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12523
            if (sbytes != 0) {
12524
                // some data has been sent
12525
                goto done;
12526
            }
12527
            // no data has been sent; upper application is supposed
12528
            // to retry on EAGAIN or EBUSY
12529
        }
12530
        if (!async_err) {
12531
            errno = saved_errno;
12532
            posix_error();
12533
        }
12534
        return NULL;
12535
    }
12536
    goto done;
12537
12538
done:
12539
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12540
        return PyLong_FromLong(sbytes);
12541
    #else
12542
        return PyLong_FromLongLong(sbytes);
12543
    #endif
12544
12545
#else
12546
0
#ifdef __linux__
12547
0
    if (offobj == Py_None) {
12548
0
        do {
12549
0
            Py_BEGIN_ALLOW_THREADS
12550
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12551
0
            Py_END_ALLOW_THREADS
12552
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12553
0
        if (ret < 0)
12554
0
            return (!async_err) ? posix_error() : NULL;
12555
0
        return PyLong_FromSsize_t(ret);
12556
0
    }
12557
0
#endif
12558
0
    off_t offset;
12559
0
    if (!Py_off_t_converter(offobj, &offset))
12560
0
        return NULL;
12561
12562
#if defined(__sun) && defined(__SVR4)
12563
    // On Solaris, sendfile raises EINVAL rather than returning 0
12564
    // when the offset is equal or bigger than the in_fd size.
12565
    struct stat st;
12566
12567
    do {
12568
        Py_BEGIN_ALLOW_THREADS
12569
        ret = fstat(in_fd, &st);
12570
        Py_END_ALLOW_THREADS
12571
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12572
    if (ret < 0)
12573
        return (!async_err) ? posix_error() : NULL;
12574
12575
    if (offset >= st.st_size) {
12576
        return PyLong_FromLong(0);
12577
    }
12578
12579
    // On illumos specifically sendfile() may perform a partial write but
12580
    // return -1/an error (in one confirmed case the destination socket
12581
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12582
    // code to check if the offset parameter was modified by sendfile().
12583
    //
12584
    // We need this variable to track said change.
12585
    off_t original_offset = offset;
12586
#endif
12587
12588
0
    do {
12589
0
        Py_BEGIN_ALLOW_THREADS
12590
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12591
#if defined(__sun) && defined(__SVR4)
12592
        // This handles illumos-specific sendfile() partial write behavior,
12593
        // see a comment above for more details.
12594
        if (ret < 0 && offset != original_offset) {
12595
            ret = offset - original_offset;
12596
        }
12597
#endif
12598
0
        Py_END_ALLOW_THREADS
12599
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12600
0
    if (ret < 0)
12601
0
        return (!async_err) ? posix_error() : NULL;
12602
0
    return PyLong_FromSsize_t(ret);
12603
0
#endif
12604
0
}
12605
#endif /* HAVE_SENDFILE */
12606
12607
12608
#if defined(__APPLE__)
12609
/*[clinic input]
12610
@permit_long_summary
12611
os._fcopyfile
12612
12613
    in_fd: int
12614
    out_fd: int
12615
    flags: int
12616
    /
12617
12618
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12619
[clinic start generated code]*/
12620
12621
static PyObject *
12622
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12623
/*[clinic end generated code: output=c9d1a35a992e401b input=80b53ad8863c9101]*/
12624
{
12625
    int ret;
12626
12627
    Py_BEGIN_ALLOW_THREADS
12628
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12629
    Py_END_ALLOW_THREADS
12630
    if (ret < 0)
12631
        return posix_error();
12632
    Py_RETURN_NONE;
12633
}
12634
#endif
12635
12636
12637
/*[clinic input]
12638
os.fstat
12639
12640
    fd : int
12641
12642
Perform a stat system call on the given file descriptor.
12643
12644
Like stat(), but for an open file descriptor.
12645
Equivalent to os.stat(fd).
12646
[clinic start generated code]*/
12647
12648
static PyObject *
12649
os_fstat_impl(PyObject *module, int fd)
12650
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12651
96.6k
{
12652
96.6k
    STRUCT_STAT st;
12653
96.6k
    int res;
12654
96.6k
    int async_err = 0;
12655
12656
96.6k
    do {
12657
96.6k
        Py_BEGIN_ALLOW_THREADS
12658
96.6k
        res = FSTAT(fd, &st);
12659
96.6k
        Py_END_ALLOW_THREADS
12660
96.6k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12661
96.6k
    if (res != 0) {
12662
#ifdef MS_WINDOWS
12663
        return PyErr_SetFromWindowsErr(0);
12664
#else
12665
0
        return (!async_err) ? posix_error() : NULL;
12666
0
#endif
12667
0
    }
12668
12669
96.6k
    return _pystat_fromstructstat(module, &st);
12670
96.6k
}
12671
12672
12673
/*[clinic input]
12674
os.isatty -> bool
12675
    fd: int
12676
    /
12677
12678
Return True if the fd is connected to a terminal.
12679
12680
Return True if the file descriptor is an open file descriptor
12681
connected to the slave end of a terminal.
12682
[clinic start generated code]*/
12683
12684
static int
12685
os_isatty_impl(PyObject *module, int fd)
12686
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12687
0
{
12688
0
    int return_value;
12689
0
    Py_BEGIN_ALLOW_THREADS
12690
0
    _Py_BEGIN_SUPPRESS_IPH
12691
0
    return_value = isatty(fd);
12692
0
    _Py_END_SUPPRESS_IPH
12693
0
    Py_END_ALLOW_THREADS
12694
0
    return return_value;
12695
0
}
12696
12697
12698
#ifdef HAVE_PIPE
12699
/*[clinic input]
12700
os.pipe
12701
12702
Create a pipe.
12703
12704
Returns a tuple of two file descriptors:
12705
  (read_fd, write_fd)
12706
[clinic start generated code]*/
12707
12708
static PyObject *
12709
os_pipe_impl(PyObject *module)
12710
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12711
0
{
12712
0
    int fds[2];
12713
#ifdef MS_WINDOWS
12714
    HANDLE read, write;
12715
    SECURITY_ATTRIBUTES attr;
12716
    BOOL ok;
12717
#else
12718
0
    int res;
12719
0
#endif
12720
12721
#ifdef MS_WINDOWS
12722
    attr.nLength = sizeof(attr);
12723
    attr.lpSecurityDescriptor = NULL;
12724
    attr.bInheritHandle = FALSE;
12725
12726
    Py_BEGIN_ALLOW_THREADS
12727
    ok = CreatePipe(&read, &write, &attr, 0);
12728
    if (ok) {
12729
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12730
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12731
        if (fds[0] == -1 || fds[1] == -1) {
12732
            CloseHandle(read);
12733
            CloseHandle(write);
12734
            ok = 0;
12735
        }
12736
    }
12737
    Py_END_ALLOW_THREADS
12738
12739
    if (!ok)
12740
        return PyErr_SetFromWindowsErr(0);
12741
#else
12742
12743
0
#ifdef HAVE_PIPE2
12744
0
    Py_BEGIN_ALLOW_THREADS
12745
0
    res = pipe2(fds, O_CLOEXEC);
12746
0
    Py_END_ALLOW_THREADS
12747
12748
0
    if (res != 0 && errno == ENOSYS)
12749
0
    {
12750
0
#endif
12751
0
        Py_BEGIN_ALLOW_THREADS
12752
0
        res = pipe(fds);
12753
0
        Py_END_ALLOW_THREADS
12754
12755
0
        if (res == 0) {
12756
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12757
0
                close(fds[0]);
12758
0
                close(fds[1]);
12759
0
                return NULL;
12760
0
            }
12761
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12762
0
                close(fds[0]);
12763
0
                close(fds[1]);
12764
0
                return NULL;
12765
0
            }
12766
0
        }
12767
0
#ifdef HAVE_PIPE2
12768
0
    }
12769
0
#endif
12770
12771
0
    if (res != 0)
12772
0
        return PyErr_SetFromErrno(PyExc_OSError);
12773
0
#endif /* !MS_WINDOWS */
12774
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12775
0
}
12776
#endif  /* HAVE_PIPE */
12777
12778
12779
#ifdef HAVE_PIPE2
12780
/*[clinic input]
12781
os.pipe2
12782
12783
    flags: int
12784
    /
12785
12786
Create a pipe with flags set atomically.
12787
12788
Returns a tuple of two file descriptors:
12789
  (read_fd, write_fd)
12790
12791
flags can be constructed by ORing together one or more of these values:
12792
O_NONBLOCK, O_CLOEXEC.
12793
[clinic start generated code]*/
12794
12795
static PyObject *
12796
os_pipe2_impl(PyObject *module, int flags)
12797
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12798
0
{
12799
0
    int fds[2];
12800
0
    int res;
12801
12802
0
    res = pipe2(fds, flags);
12803
0
    if (res != 0)
12804
0
        return posix_error();
12805
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12806
0
}
12807
#endif /* HAVE_PIPE2 */
12808
12809
12810
#ifdef HAVE_WRITEV
12811
/*[clinic input]
12812
@permit_long_summary
12813
os.writev -> Py_ssize_t
12814
    fd: int
12815
    buffers: object
12816
    /
12817
12818
Iterate over buffers, and write the contents of each to a file descriptor.
12819
12820
Returns the total number of bytes written.
12821
buffers must be a sequence of bytes-like objects.
12822
[clinic start generated code]*/
12823
12824
static Py_ssize_t
12825
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12826
/*[clinic end generated code: output=56565cfac3aac15b input=5771a0f0c2b326f2]*/
12827
0
{
12828
0
    Py_ssize_t cnt;
12829
0
    Py_ssize_t result;
12830
0
    int async_err = 0;
12831
0
    struct iovec *iov;
12832
0
    Py_buffer *buf;
12833
12834
0
    if (!PySequence_Check(buffers)) {
12835
0
        PyErr_SetString(PyExc_TypeError,
12836
0
            "writev() arg 2 must be a sequence");
12837
0
        return -1;
12838
0
    }
12839
0
    cnt = PySequence_Size(buffers);
12840
0
    if (cnt < 0)
12841
0
        return -1;
12842
12843
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12844
0
        return -1;
12845
0
    }
12846
12847
0
    do {
12848
0
        Py_BEGIN_ALLOW_THREADS
12849
0
        result = writev(fd, iov, cnt);
12850
0
        Py_END_ALLOW_THREADS
12851
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12852
12853
0
    if (result < 0 && !async_err)
12854
0
        posix_error();
12855
12856
0
    iov_cleanup(iov, buf, cnt);
12857
0
    return result;
12858
0
}
12859
#endif /* HAVE_WRITEV */
12860
12861
12862
#ifdef HAVE_PWRITE
12863
/*[clinic input]
12864
os.pwrite -> Py_ssize_t
12865
12866
    fd: int
12867
    buffer: Py_buffer
12868
    offset: Py_off_t
12869
    /
12870
12871
Write bytes to a file descriptor starting at a particular offset.
12872
12873
Write buffer to fd, starting at offset bytes from the beginning of
12874
the file.  Returns the number of bytes written.  Does not change the
12875
current file offset.
12876
[clinic start generated code]*/
12877
12878
static Py_ssize_t
12879
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12880
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12881
0
{
12882
0
    Py_ssize_t size;
12883
0
    int async_err = 0;
12884
12885
0
    do {
12886
0
        Py_BEGIN_ALLOW_THREADS
12887
0
        _Py_BEGIN_SUPPRESS_IPH
12888
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12889
0
        _Py_END_SUPPRESS_IPH
12890
0
        Py_END_ALLOW_THREADS
12891
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12892
12893
0
    if (size < 0 && !async_err)
12894
0
        posix_error();
12895
0
    return size;
12896
0
}
12897
#endif /* HAVE_PWRITE */
12898
12899
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12900
/*[clinic input]
12901
@permit_long_summary
12902
os.pwritev -> Py_ssize_t
12903
12904
    fd: int
12905
    buffers: object
12906
    offset: Py_off_t
12907
    flags: int = 0
12908
    /
12909
12910
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12911
12912
Combines the functionality of writev() and pwrite(). All buffers must be
12913
a sequence of bytes-like objects.  Buffers are processed in array order.
12914
Entire contents of first buffer is written before proceeding to second,
12915
and so on. The operating system may set a limit (sysconf() value
12916
SC_IOV_MAX) on the number of buffers that can be used.
12917
This function writes the contents of each object to the file descriptor
12918
and returns the total number of bytes written.
12919
12920
The flags argument contains a bitwise OR of zero or more of the
12921
following flags:
12922
12923
- RWF_DSYNC
12924
- RWF_SYNC
12925
- RWF_APPEND
12926
- RWF_DONTCACHE
12927
- RWF_ATOMIC
12928
12929
Using non-zero flags requires Linux 4.7 or newer.
12930
[clinic start generated code]*/
12931
12932
static Py_ssize_t
12933
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12934
                int flags)
12935
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=b2e352a22f030e9a]*/
12936
0
{
12937
0
    Py_ssize_t cnt;
12938
0
    Py_ssize_t result;
12939
0
    int async_err = 0;
12940
0
    struct iovec *iov;
12941
0
    Py_buffer *buf;
12942
12943
0
    if (!PySequence_Check(buffers)) {
12944
0
        PyErr_SetString(PyExc_TypeError,
12945
0
            "pwritev() arg 2 must be a sequence");
12946
0
        return -1;
12947
0
    }
12948
12949
0
    cnt = PySequence_Size(buffers);
12950
0
    if (cnt < 0) {
12951
0
        return -1;
12952
0
    }
12953
12954
#ifndef HAVE_PWRITEV2
12955
    if(flags != 0) {
12956
        argument_unavailable_error("pwritev2", "flags");
12957
        return -1;
12958
    }
12959
#endif
12960
12961
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12962
0
        return -1;
12963
0
    }
12964
0
#ifdef HAVE_PWRITEV2
12965
0
    do {
12966
0
        Py_BEGIN_ALLOW_THREADS
12967
0
        _Py_BEGIN_SUPPRESS_IPH
12968
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12969
0
        _Py_END_SUPPRESS_IPH
12970
0
        Py_END_ALLOW_THREADS
12971
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12972
#else
12973
12974
#if defined(__APPLE__) && defined(__clang__)
12975
/* This entire function will be removed from the module dict when the API
12976
 * is not available.
12977
 */
12978
#pragma clang diagnostic push
12979
#pragma clang diagnostic ignored "-Wunguarded-availability"
12980
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12981
#endif
12982
    do {
12983
        Py_BEGIN_ALLOW_THREADS
12984
        _Py_BEGIN_SUPPRESS_IPH
12985
        result = pwritev(fd, iov, cnt, offset);
12986
        _Py_END_SUPPRESS_IPH
12987
        Py_END_ALLOW_THREADS
12988
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12989
12990
#if defined(__APPLE__) && defined(__clang__)
12991
#pragma clang diagnostic pop
12992
#endif
12993
12994
#endif
12995
12996
0
    if (result < 0) {
12997
0
        if (!async_err) {
12998
0
            posix_error();
12999
0
        }
13000
0
        result = -1;
13001
0
    }
13002
0
    iov_cleanup(iov, buf, cnt);
13003
13004
0
    return result;
13005
0
}
13006
#endif /* HAVE_PWRITEV */
13007
13008
#ifdef HAVE_COPY_FILE_RANGE
13009
/*[clinic input]
13010
13011
os.copy_file_range
13012
    src: int
13013
        Source file descriptor.
13014
    dst: int
13015
        Destination file descriptor.
13016
    count: Py_ssize_t(allow_negative=False)
13017
        Number of bytes to copy.
13018
    offset_src: object = None
13019
        Starting offset in src.
13020
    offset_dst: object = None
13021
        Starting offset in dst.
13022
13023
Copy count bytes from one file descriptor to another.
13024
13025
If offset_src is None, then src is read from the current position;
13026
respectively for offset_dst.
13027
[clinic start generated code]*/
13028
13029
static PyObject *
13030
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13031
                        PyObject *offset_src, PyObject *offset_dst)
13032
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
13033
0
{
13034
0
    off_t offset_src_val, offset_dst_val;
13035
0
    off_t *p_offset_src = NULL;
13036
0
    off_t *p_offset_dst = NULL;
13037
0
    Py_ssize_t ret;
13038
0
    int async_err = 0;
13039
    /* The flags argument is provided to allow
13040
     * for future extensions and currently must be to 0. */
13041
0
    int flags = 0;
13042
13043
13044
0
    if (offset_src != Py_None) {
13045
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13046
0
            return NULL;
13047
0
        }
13048
0
        p_offset_src = &offset_src_val;
13049
0
    }
13050
13051
0
    if (offset_dst != Py_None) {
13052
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13053
0
            return NULL;
13054
0
        }
13055
0
        p_offset_dst = &offset_dst_val;
13056
0
    }
13057
13058
0
    do {
13059
0
        Py_BEGIN_ALLOW_THREADS
13060
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13061
0
        Py_END_ALLOW_THREADS
13062
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13063
13064
0
    if (ret < 0) {
13065
0
        return (!async_err) ? posix_error() : NULL;
13066
0
    }
13067
13068
0
    return PyLong_FromSsize_t(ret);
13069
0
}
13070
#endif /* HAVE_COPY_FILE_RANGE*/
13071
13072
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13073
/*[clinic input]
13074
13075
os.splice
13076
    src: int
13077
        Source file descriptor.
13078
    dst: int
13079
        Destination file descriptor.
13080
    count: Py_ssize_t(allow_negative=False)
13081
        Number of bytes to copy.
13082
    offset_src: object = None
13083
        Starting offset in src.
13084
    offset_dst: object = None
13085
        Starting offset in dst.
13086
    flags: unsigned_int = 0
13087
        Flags to modify the semantics of the call.
13088
13089
Transfer count bytes from one pipe to a descriptor or vice versa.
13090
13091
If offset_src is None, then src is read from the current position;
13092
respectively for offset_dst. The offset associated to the file
13093
descriptor that refers to a pipe must be None.
13094
[clinic start generated code]*/
13095
13096
static PyObject *
13097
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13098
               PyObject *offset_src, PyObject *offset_dst,
13099
               unsigned int flags)
13100
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13101
0
{
13102
0
    off_t offset_src_val, offset_dst_val;
13103
0
    off_t *p_offset_src = NULL;
13104
0
    off_t *p_offset_dst = NULL;
13105
0
    Py_ssize_t ret;
13106
0
    int async_err = 0;
13107
13108
13109
0
    if (offset_src != Py_None) {
13110
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13111
0
            return NULL;
13112
0
        }
13113
0
        p_offset_src = &offset_src_val;
13114
0
    }
13115
13116
0
    if (offset_dst != Py_None) {
13117
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13118
0
            return NULL;
13119
0
        }
13120
0
        p_offset_dst = &offset_dst_val;
13121
0
    }
13122
13123
0
    do {
13124
0
        Py_BEGIN_ALLOW_THREADS
13125
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13126
0
        Py_END_ALLOW_THREADS
13127
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13128
13129
0
    if (ret < 0) {
13130
0
        return (!async_err) ? posix_error() : NULL;
13131
0
    }
13132
13133
0
    return PyLong_FromSsize_t(ret);
13134
0
}
13135
#endif /* HAVE_SPLICE*/
13136
13137
#ifdef HAVE_MKFIFO
13138
/*[clinic input]
13139
os.mkfifo
13140
13141
    path: path_t
13142
    mode: int=0o666
13143
    *
13144
    dir_fd: dir_fd(requires='mkfifoat')=None
13145
13146
Create a "fifo" (a POSIX named pipe).
13147
13148
If dir_fd is not None, it should be a file descriptor open to
13149
a directory, and path should be relative; path will then be relative to
13150
that directory.
13151
dir_fd may not be implemented on your platform.  If it is unavailable,
13152
using it will raise a NotImplementedError.
13153
[clinic start generated code]*/
13154
13155
static PyObject *
13156
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13157
/*[clinic end generated code: output=ce41cfad0e68c940 input=d2fb917c01e888d6]*/
13158
0
{
13159
0
    int result;
13160
0
    int async_err = 0;
13161
0
#ifdef HAVE_MKFIFOAT
13162
0
    int mkfifoat_unavailable = 0;
13163
0
#endif
13164
13165
0
    do {
13166
0
        Py_BEGIN_ALLOW_THREADS
13167
0
#ifdef HAVE_MKFIFOAT
13168
0
        if (dir_fd != DEFAULT_DIR_FD) {
13169
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13170
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13171
13172
0
            } else {
13173
0
                mkfifoat_unavailable = 1;
13174
0
                result = 0;
13175
0
            }
13176
0
        } else
13177
0
#endif
13178
0
            result = mkfifo(path->narrow, mode);
13179
0
        Py_END_ALLOW_THREADS
13180
0
    } while (result != 0 && errno == EINTR &&
13181
0
             !(async_err = PyErr_CheckSignals()));
13182
13183
0
#ifdef HAVE_MKFIFOAT
13184
0
    if (mkfifoat_unavailable) {
13185
0
        argument_unavailable_error(NULL, "dir_fd");
13186
0
        return NULL;
13187
0
    }
13188
0
#endif
13189
13190
0
    if (result != 0)
13191
0
        return (!async_err) ? posix_error() : NULL;
13192
13193
0
    Py_RETURN_NONE;
13194
0
}
13195
#endif /* HAVE_MKFIFO */
13196
13197
13198
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13199
/*[clinic input]
13200
os.mknod
13201
13202
    path: path_t
13203
    mode: int=0o600
13204
    device: dev_t=0
13205
    *
13206
    dir_fd: dir_fd(requires='mknodat')=None
13207
13208
Create a node in the file system.
13209
13210
Create a node in the file system (file, device special file or named
13211
pipe) at path.  mode specifies both the permissions to use and the
13212
type of node to be created, being combined (bitwise OR) with one of
13213
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set
13214
on mode, device defines the newly created device special file (probably
13215
using os.makedev()).  Otherwise device is ignored.
13216
13217
If dir_fd is not None, it should be a file descriptor open to
13218
a directory, and path should be relative; path will then be relative
13219
to that directory.
13220
dir_fd may not be implemented on your platform.  If it is unavailable,
13221
using it will raise a NotImplementedError.
13222
[clinic start generated code]*/
13223
13224
static PyObject *
13225
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13226
              int dir_fd)
13227
/*[clinic end generated code: output=92e55d3ca8917461 input=7d0099e85c6b4cba]*/
13228
0
{
13229
0
    int result;
13230
0
    int async_err = 0;
13231
0
#ifdef HAVE_MKNODAT
13232
0
    int mknodat_unavailable = 0;
13233
0
#endif
13234
13235
0
    do {
13236
0
        Py_BEGIN_ALLOW_THREADS
13237
0
#ifdef HAVE_MKNODAT
13238
0
        if (dir_fd != DEFAULT_DIR_FD) {
13239
0
            if (HAVE_MKNODAT_RUNTIME) {
13240
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13241
13242
0
            } else {
13243
0
                mknodat_unavailable = 1;
13244
0
                result = 0;
13245
0
            }
13246
0
        } else
13247
0
#endif
13248
0
            result = mknod(path->narrow, mode, device);
13249
0
        Py_END_ALLOW_THREADS
13250
0
    } while (result != 0 && errno == EINTR &&
13251
0
             !(async_err = PyErr_CheckSignals()));
13252
0
#ifdef HAVE_MKNODAT
13253
0
    if (mknodat_unavailable) {
13254
0
        argument_unavailable_error(NULL, "dir_fd");
13255
0
        return NULL;
13256
0
    }
13257
0
#endif
13258
0
    if (result != 0)
13259
0
        return (!async_err) ? posix_error() : NULL;
13260
13261
0
    Py_RETURN_NONE;
13262
0
}
13263
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13264
13265
13266
#ifdef HAVE_DEVICE_MACROS
13267
static PyObject *
13268
major_minor_conv(unsigned int value)
13269
0
{
13270
0
#ifdef NODEV
13271
0
    if (value == (unsigned int)NODEV) {
13272
0
        return PyLong_FromLong((int)NODEV);
13273
0
    }
13274
0
#endif
13275
0
    return PyLong_FromUnsignedLong(value);
13276
0
}
13277
13278
static int
13279
major_minor_check(dev_t value)
13280
0
{
13281
0
#ifdef NODEV
13282
0
    if (value == NODEV) {
13283
0
        return 1;
13284
0
    }
13285
0
#endif
13286
0
    return (dev_t)(unsigned int)value == value;
13287
0
}
13288
13289
/*[clinic input]
13290
os.major
13291
13292
    device: dev_t
13293
    /
13294
13295
Extracts a device major number from a raw device number.
13296
[clinic start generated code]*/
13297
13298
static PyObject *
13299
os_major_impl(PyObject *module, dev_t device)
13300
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13301
0
{
13302
0
    return major_minor_conv(major(device));
13303
0
}
13304
13305
13306
/*[clinic input]
13307
os.minor
13308
13309
    device: dev_t
13310
    /
13311
13312
Extracts a device minor number from a raw device number.
13313
[clinic start generated code]*/
13314
13315
static PyObject *
13316
os_minor_impl(PyObject *module, dev_t device)
13317
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13318
0
{
13319
0
    return major_minor_conv(minor(device));
13320
0
}
13321
13322
13323
/*[clinic input]
13324
os.makedev -> dev_t
13325
13326
    major: dev_t
13327
    minor: dev_t
13328
    /
13329
13330
Composes a raw device number from the major and minor device numbers.
13331
[clinic start generated code]*/
13332
13333
static dev_t
13334
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13335
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13336
0
{
13337
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13338
0
        PyErr_SetString(PyExc_OverflowError,
13339
0
                        "Python int too large to convert to C unsigned int");
13340
0
        return (dev_t)-1;
13341
0
    }
13342
0
    return makedev(major, minor);
13343
0
}
13344
#endif /* HAVE_DEVICE_MACROS */
13345
13346
13347
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13348
/*[clinic input]
13349
os.ftruncate
13350
13351
    fd: int
13352
    length: Py_off_t
13353
    /
13354
13355
Truncate a file, specified by file descriptor, to a specific length.
13356
[clinic start generated code]*/
13357
13358
static PyObject *
13359
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13360
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13361
0
{
13362
0
    int result;
13363
0
    int async_err = 0;
13364
13365
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13366
0
        return NULL;
13367
0
    }
13368
13369
0
    do {
13370
0
        Py_BEGIN_ALLOW_THREADS
13371
0
        _Py_BEGIN_SUPPRESS_IPH
13372
#ifdef MS_WINDOWS
13373
        result = _chsize_s(fd, length);
13374
#else
13375
0
        result = ftruncate(fd, length);
13376
0
#endif
13377
0
        _Py_END_SUPPRESS_IPH
13378
0
        Py_END_ALLOW_THREADS
13379
0
    } while (result != 0 && errno == EINTR &&
13380
0
             !(async_err = PyErr_CheckSignals()));
13381
0
    if (result != 0)
13382
0
        return (!async_err) ? posix_error() : NULL;
13383
0
    Py_RETURN_NONE;
13384
0
}
13385
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13386
13387
13388
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13389
/*[clinic input]
13390
os.truncate
13391
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13392
    length: Py_off_t
13393
13394
Truncate a file, specified by path, to a specific length.
13395
13396
On some platforms, path may also be specified as an open file
13397
descriptor.  If this functionality is unavailable, using it raises
13398
an exception.
13399
[clinic start generated code]*/
13400
13401
static PyObject *
13402
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13403
/*[clinic end generated code: output=43009c8df5c0a12b input=ce33fd7808a511c4]*/
13404
0
{
13405
0
    int result;
13406
#ifdef MS_WINDOWS
13407
    int fd;
13408
#endif
13409
13410
0
    if (path->is_fd)
13411
0
        return os_ftruncate_impl(module, path->fd, length);
13412
13413
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13414
0
        return NULL;
13415
0
    }
13416
13417
0
    Py_BEGIN_ALLOW_THREADS
13418
0
    _Py_BEGIN_SUPPRESS_IPH
13419
#ifdef MS_WINDOWS
13420
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13421
    if (fd < 0)
13422
        result = -1;
13423
    else {
13424
        result = _chsize_s(fd, length);
13425
        close(fd);
13426
        if (result < 0)
13427
            errno = result;
13428
    }
13429
#else
13430
0
    result = truncate(path->narrow, length);
13431
0
#endif
13432
0
    _Py_END_SUPPRESS_IPH
13433
0
    Py_END_ALLOW_THREADS
13434
0
    if (result < 0)
13435
0
        return posix_path_error(path);
13436
13437
0
    Py_RETURN_NONE;
13438
0
}
13439
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13440
13441
13442
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13443
   OSs, support was dropped in WASI preview2. */
13444
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13445
/*[clinic input]
13446
@permit_long_summary
13447
os.posix_fallocate
13448
13449
    fd: int
13450
    offset: Py_off_t
13451
    length: Py_off_t
13452
    /
13453
13454
Ensure a file has allocated at least a particular number of bytes on disk.
13455
13456
Ensure that the file specified by fd encompasses a range of bytes
13457
starting at offset bytes from the beginning and continuing for length
13458
bytes.
13459
[clinic start generated code]*/
13460
13461
static PyObject *
13462
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13463
                        Py_off_t length)
13464
/*[clinic end generated code: output=73f107139564aa9d input=c718971d18b96896]*/
13465
0
{
13466
0
    int result;
13467
0
    int async_err = 0;
13468
13469
0
    do {
13470
0
        Py_BEGIN_ALLOW_THREADS
13471
0
        result = posix_fallocate(fd, offset, length);
13472
0
        Py_END_ALLOW_THREADS
13473
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13474
13475
0
    if (result == 0)
13476
0
        Py_RETURN_NONE;
13477
13478
0
    if (async_err)
13479
0
        return NULL;
13480
13481
0
    errno = result;
13482
0
    return posix_error();
13483
0
}
13484
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13485
13486
13487
#if defined(HAVE_POSIX_FADVISE)
13488
/*[clinic input]
13489
os.posix_fadvise
13490
13491
    fd: int
13492
    offset: Py_off_t
13493
    length: Py_off_t
13494
    advice: int
13495
    /
13496
13497
Announce an intention to access data in a specific pattern.
13498
13499
Announce an intention to access data in a specific pattern, thus
13500
allowing the kernel to make optimizations.
13501
The advice applies to the region of the file specified by fd starting at
13502
offset and continuing for length bytes.
13503
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13504
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13505
POSIX_FADV_DONTNEED.
13506
[clinic start generated code]*/
13507
13508
static PyObject *
13509
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13510
                      Py_off_t length, int advice)
13511
/*[clinic end generated code: output=412ef4aa70c98642 input=961b01a4518ef727]*/
13512
0
{
13513
0
    int result;
13514
0
    int async_err = 0;
13515
13516
0
    do {
13517
0
        Py_BEGIN_ALLOW_THREADS
13518
0
        result = posix_fadvise(fd, offset, length, advice);
13519
0
        Py_END_ALLOW_THREADS
13520
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13521
13522
0
    if (result == 0)
13523
0
        Py_RETURN_NONE;
13524
13525
0
    if (async_err)
13526
0
        return NULL;
13527
13528
0
    errno = result;
13529
0
    return posix_error();
13530
0
}
13531
#endif /* HAVE_POSIX_FADVISE */
13532
13533
13534
#ifdef MS_WINDOWS
13535
static PyObject*
13536
win32_putenv(PyObject *name, PyObject *value)
13537
{
13538
    /* Search from index 1 because on Windows starting '=' is allowed for
13539
       defining hidden environment variables. */
13540
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13541
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13542
    {
13543
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13544
        return NULL;
13545
    }
13546
    PyObject *unicode;
13547
    if (value != NULL) {
13548
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13549
    }
13550
    else {
13551
        unicode = PyUnicode_FromFormat("%U=", name);
13552
    }
13553
    if (unicode == NULL) {
13554
        return NULL;
13555
    }
13556
13557
    Py_ssize_t size;
13558
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13559
    Py_DECREF(unicode);
13560
13561
    if (env == NULL) {
13562
        return NULL;
13563
    }
13564
    if (size > _MAX_ENV) {
13565
        PyErr_Format(PyExc_ValueError,
13566
                     "the environment variable is longer than %u characters",
13567
                     _MAX_ENV);
13568
        PyMem_Free(env);
13569
        return NULL;
13570
    }
13571
    if (wcslen(env) != (size_t)size) {
13572
        PyErr_SetString(PyExc_ValueError,
13573
                        "embedded null character");
13574
        PyMem_Free(env);
13575
        return NULL;
13576
    }
13577
13578
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13579
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13580
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13581
13582
       Prefer _wputenv() to be compatible with C libraries using CRT
13583
       variables and CRT functions using these variables (ex: getenv()). */
13584
    int err = _wputenv(env);
13585
13586
    if (err) {
13587
        posix_error();
13588
        PyMem_Free(env);
13589
        return NULL;
13590
    }
13591
    PyMem_Free(env);
13592
13593
    Py_RETURN_NONE;
13594
}
13595
#endif
13596
13597
13598
#ifdef MS_WINDOWS
13599
/*[clinic input]
13600
os.putenv
13601
13602
    name: unicode
13603
    value: unicode
13604
    /
13605
13606
Change or add an environment variable.
13607
[clinic start generated code]*/
13608
13609
static PyObject *
13610
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13611
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13612
{
13613
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13614
        return NULL;
13615
    }
13616
    return win32_putenv(name, value);
13617
}
13618
#else
13619
/*[clinic input]
13620
os.putenv
13621
13622
    name: unicode_fs_encoded
13623
    value: unicode_fs_encoded
13624
    /
13625
13626
Change or add an environment variable.
13627
[clinic start generated code]*/
13628
13629
static PyObject *
13630
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13631
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13632
0
{
13633
0
    const char *name_string = PyBytes_AS_STRING(name);
13634
0
    const char *value_string = PyBytes_AS_STRING(value);
13635
13636
0
    if (strchr(name_string, '=') != NULL) {
13637
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13638
0
        return NULL;
13639
0
    }
13640
13641
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13642
0
        return NULL;
13643
0
    }
13644
13645
0
    if (setenv(name_string, value_string, 1)) {
13646
0
        return posix_error();
13647
0
    }
13648
0
    Py_RETURN_NONE;
13649
0
}
13650
#endif  /* !defined(MS_WINDOWS) */
13651
13652
13653
#ifdef MS_WINDOWS
13654
/*[clinic input]
13655
os.unsetenv
13656
    name: unicode
13657
    /
13658
13659
Delete an environment variable.
13660
[clinic start generated code]*/
13661
13662
static PyObject *
13663
os_unsetenv_impl(PyObject *module, PyObject *name)
13664
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13665
{
13666
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13667
        return NULL;
13668
    }
13669
    return win32_putenv(name, NULL);
13670
}
13671
#else
13672
/*[clinic input]
13673
os.unsetenv
13674
    name: unicode_fs_encoded
13675
    /
13676
13677
Delete an environment variable.
13678
[clinic start generated code]*/
13679
13680
static PyObject *
13681
os_unsetenv_impl(PyObject *module, PyObject *name)
13682
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13683
0
{
13684
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13685
0
        return NULL;
13686
0
    }
13687
#ifdef HAVE_BROKEN_UNSETENV
13688
    unsetenv(PyBytes_AS_STRING(name));
13689
#else
13690
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13691
0
    if (err) {
13692
0
        return posix_error();
13693
0
    }
13694
0
#endif
13695
13696
0
    Py_RETURN_NONE;
13697
0
}
13698
#endif /* !MS_WINDOWS */
13699
13700
13701
#ifdef HAVE_CLEARENV
13702
/*[clinic input]
13703
os._clearenv
13704
[clinic start generated code]*/
13705
13706
static PyObject *
13707
os__clearenv_impl(PyObject *module)
13708
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13709
0
{
13710
0
    if (PySys_Audit("os._clearenv", NULL) < 0) {
13711
0
        return NULL;
13712
0
    }
13713
13714
0
    errno = 0;
13715
0
    int err = clearenv();
13716
0
    if (err) {
13717
0
        return posix_error();
13718
0
    }
13719
0
    Py_RETURN_NONE;
13720
0
}
13721
#endif
13722
13723
13724
/*[clinic input]
13725
os.strerror
13726
13727
    code: int
13728
    /
13729
13730
Translate an error code to a message string.
13731
[clinic start generated code]*/
13732
13733
static PyObject *
13734
os_strerror_impl(PyObject *module, int code)
13735
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13736
0
{
13737
0
    char *message = strerror(code);
13738
0
    if (message == NULL) {
13739
0
        PyErr_SetString(PyExc_ValueError,
13740
0
                        "strerror() argument out of range");
13741
0
        return NULL;
13742
0
    }
13743
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13744
0
}
13745
13746
13747
#ifdef HAVE_SYS_WAIT_H
13748
#ifdef WCOREDUMP
13749
/*[clinic input]
13750
os.WCOREDUMP -> bool
13751
13752
    status: int
13753
    /
13754
13755
Return True if the process returning status was dumped to a core file.
13756
[clinic start generated code]*/
13757
13758
static int
13759
os_WCOREDUMP_impl(PyObject *module, int status)
13760
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13761
0
{
13762
0
    WAIT_TYPE wait_status;
13763
0
    WAIT_STATUS_INT(wait_status) = status;
13764
0
    return WCOREDUMP(wait_status);
13765
0
}
13766
#endif /* WCOREDUMP */
13767
13768
13769
#ifdef WIFCONTINUED
13770
/*[clinic input]
13771
@permit_long_summary
13772
os.WIFCONTINUED -> bool
13773
13774
    status: int
13775
13776
Return True if a particular process was continued from a job control stop.
13777
13778
Return True if the process returning status was continued from a
13779
job control stop.
13780
[clinic start generated code]*/
13781
13782
static int
13783
os_WIFCONTINUED_impl(PyObject *module, int status)
13784
/*[clinic end generated code: output=1e35295d844364bd input=7b577845a0f8b12f]*/
13785
0
{
13786
0
    WAIT_TYPE wait_status;
13787
0
    WAIT_STATUS_INT(wait_status) = status;
13788
0
    return WIFCONTINUED(wait_status);
13789
0
}
13790
#endif /* WIFCONTINUED */
13791
13792
13793
#ifdef WIFSTOPPED
13794
/*[clinic input]
13795
os.WIFSTOPPED -> bool
13796
13797
    status: int
13798
13799
Return True if the process returning status was stopped.
13800
[clinic start generated code]*/
13801
13802
static int
13803
os_WIFSTOPPED_impl(PyObject *module, int status)
13804
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13805
0
{
13806
0
    WAIT_TYPE wait_status;
13807
0
    WAIT_STATUS_INT(wait_status) = status;
13808
0
    return WIFSTOPPED(wait_status);
13809
0
}
13810
#endif /* WIFSTOPPED */
13811
13812
13813
#ifdef WIFSIGNALED
13814
/*[clinic input]
13815
os.WIFSIGNALED -> bool
13816
13817
    status: int
13818
13819
Return True if the process returning status was terminated by a signal.
13820
[clinic start generated code]*/
13821
13822
static int
13823
os_WIFSIGNALED_impl(PyObject *module, int status)
13824
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13825
0
{
13826
0
    WAIT_TYPE wait_status;
13827
0
    WAIT_STATUS_INT(wait_status) = status;
13828
0
    return WIFSIGNALED(wait_status);
13829
0
}
13830
#endif /* WIFSIGNALED */
13831
13832
13833
#ifdef WIFEXITED
13834
/*[clinic input]
13835
@permit_long_summary
13836
os.WIFEXITED -> bool
13837
13838
    status: int
13839
13840
Return True if the process returning status exited via the exit() system call.
13841
[clinic start generated code]*/
13842
13843
static int
13844
os_WIFEXITED_impl(PyObject *module, int status)
13845
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13846
0
{
13847
0
    WAIT_TYPE wait_status;
13848
0
    WAIT_STATUS_INT(wait_status) = status;
13849
0
    return WIFEXITED(wait_status);
13850
0
}
13851
#endif /* WIFEXITED */
13852
13853
13854
#ifdef WEXITSTATUS
13855
/*[clinic input]
13856
os.WEXITSTATUS -> int
13857
13858
    status: int
13859
13860
Return the process return code from status.
13861
[clinic start generated code]*/
13862
13863
static int
13864
os_WEXITSTATUS_impl(PyObject *module, int status)
13865
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13866
0
{
13867
0
    WAIT_TYPE wait_status;
13868
0
    WAIT_STATUS_INT(wait_status) = status;
13869
0
    return WEXITSTATUS(wait_status);
13870
0
}
13871
#endif /* WEXITSTATUS */
13872
13873
13874
#ifdef WTERMSIG
13875
/*[clinic input]
13876
@permit_long_summary
13877
os.WTERMSIG -> int
13878
13879
    status: int
13880
13881
Return the signal that terminated the process that provided the status value.
13882
[clinic start generated code]*/
13883
13884
static int
13885
os_WTERMSIG_impl(PyObject *module, int status)
13886
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13887
0
{
13888
0
    WAIT_TYPE wait_status;
13889
0
    WAIT_STATUS_INT(wait_status) = status;
13890
0
    return WTERMSIG(wait_status);
13891
0
}
13892
#endif /* WTERMSIG */
13893
13894
13895
#ifdef WSTOPSIG
13896
/*[clinic input]
13897
@permit_long_summary
13898
os.WSTOPSIG -> int
13899
13900
    status: int
13901
13902
Return the signal that stopped the process that provided the status value.
13903
[clinic start generated code]*/
13904
13905
static int
13906
os_WSTOPSIG_impl(PyObject *module, int status)
13907
/*[clinic end generated code: output=0ab7586396f5d82b input=4698db1a6a320433]*/
13908
0
{
13909
0
    WAIT_TYPE wait_status;
13910
0
    WAIT_STATUS_INT(wait_status) = status;
13911
0
    return WSTOPSIG(wait_status);
13912
0
}
13913
#endif /* WSTOPSIG */
13914
#endif /* HAVE_SYS_WAIT_H */
13915
13916
13917
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13918
#ifdef _SCO_DS
13919
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13920
   needed definitions in sys/statvfs.h */
13921
#define _SVID3
13922
#endif
13923
#include <sys/statvfs.h>
13924
13925
#ifdef __APPLE__
13926
/* On macOS struct statvfs uses 32-bit integers for block counts,
13927
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13928
 * os.statvfs is implemented in terms of statfs(2).
13929
 */
13930
13931
static PyObject*
13932
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13933
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13934
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13935
    if (v == NULL) {
13936
        return NULL;
13937
    }
13938
13939
    long flags = 0;
13940
    if (st.f_flags & MNT_RDONLY) {
13941
        flags |= ST_RDONLY;
13942
    }
13943
    if (st.f_flags & MNT_NOSUID) {
13944
        flags |= ST_NOSUID;
13945
    }
13946
13947
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13948
13949
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13950
    do {                                                 \
13951
        PyObject *obj = (EXPR);                          \
13952
        if (obj == NULL) {                               \
13953
            Py_DECREF((SEQ));                            \
13954
            return NULL;                                 \
13955
        }                                                \
13956
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13957
    } while (0)
13958
13959
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13960
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13961
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13962
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13963
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13964
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13965
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13966
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13967
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13968
13969
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13970
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13971
13972
#undef SET_ITEM
13973
13974
    return v;
13975
}
13976
13977
#else
13978
13979
13980
13981
static PyObject*
13982
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13983
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13984
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13985
0
    if (v == NULL)
13986
0
        return NULL;
13987
13988
0
    int pos = 0;
13989
13990
0
#define SET_RESULT(CALL)                                     \
13991
0
    do {                                                     \
13992
0
        PyObject *item = (CALL);                             \
13993
0
        if (item == NULL) {                                  \
13994
0
            Py_DECREF(v);                                    \
13995
0
            return NULL;                                     \
13996
0
        }                                                    \
13997
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13998
0
    } while(0)
13999
14000
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
14001
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
14002
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
14003
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
14004
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
14005
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
14006
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
14007
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
14008
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
14009
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
14010
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
14011
#else
14012
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
14013
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
14014
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
14015
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
14016
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
14017
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
14018
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
14019
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
14020
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
14021
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
14022
#endif
14023
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
14024
 * (issue #32390). */
14025
#if defined(_AIX) && defined(_ALL_SOURCE)
14026
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
14027
#else
14028
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
14029
0
#endif
14030
14031
0
#undef SET_RESULT
14032
14033
0
    return v;
14034
0
}
14035
14036
#endif
14037
14038
14039
/*[clinic input]
14040
os.fstatvfs
14041
    fd: int
14042
    /
14043
14044
Perform an fstatvfs system call on the given fd.
14045
14046
Equivalent to statvfs(fd).
14047
[clinic start generated code]*/
14048
14049
static PyObject *
14050
os_fstatvfs_impl(PyObject *module, int fd)
14051
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
14052
0
{
14053
0
    int result;
14054
0
    int async_err = 0;
14055
#ifdef __APPLE__
14056
    struct statfs st;
14057
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
14058
     * the former uses 32-bit values for block counts.
14059
     */
14060
    do {
14061
        Py_BEGIN_ALLOW_THREADS
14062
        result = fstatfs(fd, &st);
14063
        Py_END_ALLOW_THREADS
14064
    } while (result != 0 && errno == EINTR &&
14065
             !(async_err = PyErr_CheckSignals()));
14066
    if (result != 0)
14067
        return (!async_err) ? posix_error() : NULL;
14068
14069
    return _pystatvfs_fromstructstatfs(module, st);
14070
#else
14071
0
    struct statvfs st;
14072
14073
0
    do {
14074
0
        Py_BEGIN_ALLOW_THREADS
14075
0
        result = fstatvfs(fd, &st);
14076
0
        Py_END_ALLOW_THREADS
14077
0
    } while (result != 0 && errno == EINTR &&
14078
0
             !(async_err = PyErr_CheckSignals()));
14079
0
    if (result != 0)
14080
0
        return (!async_err) ? posix_error() : NULL;
14081
14082
0
    return _pystatvfs_fromstructstatvfs(module, st);
14083
0
#endif
14084
0
}
14085
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14086
14087
14088
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14089
#include <sys/statvfs.h>
14090
/*[clinic input]
14091
os.statvfs
14092
14093
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14094
14095
Perform a statvfs system call on the given path.
14096
14097
path may always be specified as a string.
14098
On some platforms, path may also be specified as an open file
14099
descriptor.  If this functionality is unavailable, using it raises
14100
an exception.
14101
[clinic start generated code]*/
14102
14103
static PyObject *
14104
os_statvfs_impl(PyObject *module, path_t *path)
14105
/*[clinic end generated code: output=87106dd1beb8556e input=1cfd9a4fd36f7425]*/
14106
0
{
14107
0
    int result;
14108
14109
#ifdef __APPLE__
14110
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14111
     * the former uses 32-bit values for block counts.
14112
     */
14113
    struct statfs st;
14114
14115
    Py_BEGIN_ALLOW_THREADS
14116
    if (path->is_fd) {
14117
        result = fstatfs(path->fd, &st);
14118
    }
14119
    else
14120
        result = statfs(path->narrow, &st);
14121
    Py_END_ALLOW_THREADS
14122
14123
    if (result) {
14124
        return path_error(path);
14125
    }
14126
14127
    return _pystatvfs_fromstructstatfs(module, st);
14128
14129
#else
14130
0
    struct statvfs st;
14131
14132
0
    Py_BEGIN_ALLOW_THREADS
14133
0
#ifdef HAVE_FSTATVFS
14134
0
    if (path->is_fd) {
14135
0
        result = fstatvfs(path->fd, &st);
14136
0
    }
14137
0
    else
14138
0
#endif
14139
0
        result = statvfs(path->narrow, &st);
14140
0
    Py_END_ALLOW_THREADS
14141
14142
0
    if (result) {
14143
0
        return path_error(path);
14144
0
    }
14145
14146
0
    return _pystatvfs_fromstructstatvfs(module, st);
14147
0
#endif
14148
0
}
14149
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14150
14151
14152
#ifdef MS_WINDOWS
14153
/*[clinic input]
14154
@permit_long_summary
14155
os._getdiskusage
14156
14157
    path: path_t
14158
14159
Return disk usage statistics about the given path as a (total, free) tuple.
14160
[clinic start generated code]*/
14161
14162
static PyObject *
14163
os__getdiskusage_impl(PyObject *module, path_t *path)
14164
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=aee7e38bc3e7fb08]*/
14165
{
14166
    BOOL retval;
14167
    ULARGE_INTEGER _, total, free;
14168
    DWORD err = 0;
14169
14170
    Py_BEGIN_ALLOW_THREADS
14171
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14172
    Py_END_ALLOW_THREADS
14173
    if (retval == 0) {
14174
        if (GetLastError() == ERROR_DIRECTORY) {
14175
            wchar_t *dir_path = NULL;
14176
14177
            dir_path = PyMem_New(wchar_t, path->length + 1);
14178
            if (dir_path == NULL) {
14179
                return PyErr_NoMemory();
14180
            }
14181
14182
            wcscpy_s(dir_path, path->length + 1, path->wide);
14183
14184
            if (_dirnameW(dir_path) != -1) {
14185
                Py_BEGIN_ALLOW_THREADS
14186
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14187
                Py_END_ALLOW_THREADS
14188
            }
14189
            /* Record the last error in case it's modified by PyMem_Free. */
14190
            err = GetLastError();
14191
            PyMem_Free(dir_path);
14192
            if (retval) {
14193
                goto success;
14194
            }
14195
        }
14196
        return PyErr_SetFromWindowsErr(err);
14197
    }
14198
14199
success:
14200
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14201
}
14202
#endif /* MS_WINDOWS */
14203
14204
14205
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14206
 * It maps strings representing configuration variable names to
14207
 * integer values, allowing those functions to be called with the
14208
 * magic names instead of polluting the module's namespace with tons of
14209
 * rarely-used constants.  There are three separate tables that use
14210
 * these definitions.
14211
 *
14212
 * This code is always included, even if none of the interfaces that
14213
 * need it are included.  The #if hackery needed to avoid it would be
14214
 * sufficiently pervasive that it's not worth the loss of readability.
14215
 */
14216
struct constdef {
14217
    const char *name;
14218
    int value;
14219
};
14220
14221
static int
14222
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14223
8
{
14224
8
    if (PyUnicode_Check(arg)) {
14225
8
        PyObject *table = PyObject_GetAttrString(module, tablename);
14226
8
        if (table == NULL) {
14227
0
            return 0;
14228
0
        }
14229
14230
8
        arg = PyObject_GetItem(table, arg);
14231
8
        Py_DECREF(table);
14232
8
        if (arg == NULL) {
14233
0
            PyErr_SetString(
14234
0
                PyExc_ValueError, "unrecognized configuration name");
14235
0
            return 0;
14236
0
        }
14237
8
    } else {
14238
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14239
0
    }
14240
14241
8
    int success = 0;
14242
8
    if (!PyIndex_Check(arg)) {
14243
0
        PyErr_SetString(PyExc_TypeError,
14244
0
            "configuration names must be strings or integers");
14245
8
    } else {
14246
8
        int value = PyLong_AsInt(arg);
14247
8
        if (!(value == -1 && PyErr_Occurred())) {
14248
8
            *valuep = value;
14249
8
            success = 1;
14250
8
        }
14251
8
    }
14252
8
    Py_DECREF(arg);
14253
8
    return success;
14254
8
}
14255
14256
14257
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14258
static struct constdef  posix_constants_pathconf[] = {
14259
#ifdef _PC_ABI_AIO_XFER_MAX
14260
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14261
#endif
14262
#ifdef _PC_ABI_ASYNC_IO
14263
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14264
#endif
14265
#ifdef _PC_ASYNC_IO
14266
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14267
#endif
14268
#ifdef _PC_CHOWN_RESTRICTED
14269
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14270
#endif
14271
#ifdef _PC_FILESIZEBITS
14272
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14273
#endif
14274
#ifdef _PC_LAST
14275
    {"PC_LAST", _PC_LAST},
14276
#endif
14277
#ifdef _PC_LINK_MAX
14278
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14279
#endif
14280
#ifdef _PC_MAX_CANON
14281
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14282
#endif
14283
#ifdef _PC_MAX_INPUT
14284
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14285
#endif
14286
#ifdef _PC_NAME_MAX
14287
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14288
#endif
14289
#ifdef _PC_NO_TRUNC
14290
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14291
#endif
14292
#ifdef _PC_PATH_MAX
14293
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14294
#endif
14295
#ifdef _PC_PIPE_BUF
14296
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14297
#endif
14298
#ifdef _PC_PRIO_IO
14299
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14300
#endif
14301
#ifdef _PC_SOCK_MAXBUF
14302
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14303
#endif
14304
#ifdef _PC_SYNC_IO
14305
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14306
#endif
14307
#ifdef _PC_VDISABLE
14308
    {"PC_VDISABLE",     _PC_VDISABLE},
14309
#endif
14310
#ifdef _PC_ACL_ENABLED
14311
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14312
#endif
14313
#ifdef _PC_MIN_HOLE_SIZE
14314
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14315
#endif
14316
#ifdef _PC_ALLOC_SIZE_MIN
14317
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14318
#endif
14319
#ifdef _PC_REC_INCR_XFER_SIZE
14320
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14321
#endif
14322
#ifdef _PC_REC_MAX_XFER_SIZE
14323
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14324
#endif
14325
#ifdef _PC_REC_MIN_XFER_SIZE
14326
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14327
#endif
14328
#ifdef _PC_REC_XFER_ALIGN
14329
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14330
#endif
14331
#ifdef _PC_SYMLINK_MAX
14332
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14333
#endif
14334
#ifdef _PC_XATTR_ENABLED
14335
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14336
#endif
14337
#ifdef _PC_XATTR_EXISTS
14338
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14339
#endif
14340
#ifdef _PC_TIMESTAMP_RESOLUTION
14341
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14342
#endif
14343
};
14344
#endif
14345
14346
14347
#ifdef HAVE_FPATHCONF
14348
/*[clinic input]
14349
os.fpathconf -> long
14350
14351
    fd: fildes
14352
    name: confname(table="pathconf_names")
14353
    /
14354
14355
Return the configuration limit name for the file descriptor fd.
14356
14357
If there is no limit, return -1.
14358
[clinic start generated code]*/
14359
14360
static long
14361
os_fpathconf_impl(PyObject *module, int fd, int name)
14362
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14363
0
{
14364
0
    long limit;
14365
14366
0
    errno = 0;
14367
0
    limit = fpathconf(fd, name);
14368
0
    if (limit == -1 && errno != 0)
14369
0
        posix_error();
14370
14371
0
    return limit;
14372
0
}
14373
#endif /* HAVE_FPATHCONF */
14374
14375
14376
#ifdef HAVE_PATHCONF
14377
/*[clinic input]
14378
os.pathconf -> long
14379
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14380
    name: confname(table="pathconf_names")
14381
14382
Return the configuration limit name for the file or directory path.
14383
14384
If there is no limit, return -1.
14385
On some platforms, path may also be specified as an open file
14386
descriptor.  If this functionality is unavailable, using it raises
14387
an exception.
14388
[clinic start generated code]*/
14389
14390
static long
14391
os_pathconf_impl(PyObject *module, path_t *path, int name)
14392
/*[clinic end generated code: output=5bedee35b293a089 input=e86f6eacfa006426]*/
14393
0
{
14394
0
    long limit;
14395
14396
0
    errno = 0;
14397
0
#ifdef HAVE_FPATHCONF
14398
0
    if (path->is_fd) {
14399
0
        limit = fpathconf(path->fd, name);
14400
0
    }
14401
0
    else
14402
0
#endif
14403
0
        limit = pathconf(path->narrow, name);
14404
0
    if (limit == -1 && errno != 0) {
14405
0
        if (errno == EINVAL)
14406
            /* could be a path or name problem */
14407
0
            posix_error();
14408
0
        else
14409
0
            path_error(path);
14410
0
    }
14411
14412
0
    return limit;
14413
0
}
14414
#endif /* HAVE_PATHCONF */
14415
14416
#ifdef HAVE_CONFSTR
14417
static struct constdef posix_constants_confstr[] = {
14418
#ifdef _CS_ARCHITECTURE
14419
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14420
#endif
14421
#ifdef _CS_GNU_LIBC_VERSION
14422
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14423
#endif
14424
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14425
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14426
#endif
14427
#ifdef _CS_HOSTNAME
14428
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14429
#endif
14430
#ifdef _CS_HW_PROVIDER
14431
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14432
#endif
14433
#ifdef _CS_HW_SERIAL
14434
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14435
#endif
14436
#ifdef _CS_INITTAB_NAME
14437
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14438
#endif
14439
#ifdef _CS_LFS64_CFLAGS
14440
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14441
#endif
14442
#ifdef _CS_LFS64_LDFLAGS
14443
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14444
#endif
14445
#ifdef _CS_LFS64_LIBS
14446
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14447
#endif
14448
#ifdef _CS_LFS64_LINTFLAGS
14449
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14450
#endif
14451
#ifdef _CS_LFS_CFLAGS
14452
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14453
#endif
14454
#ifdef _CS_LFS_LDFLAGS
14455
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14456
#endif
14457
#ifdef _CS_LFS_LIBS
14458
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14459
#endif
14460
#ifdef _CS_LFS_LINTFLAGS
14461
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14462
#endif
14463
#ifdef _CS_MACHINE
14464
    {"CS_MACHINE",      _CS_MACHINE},
14465
#endif
14466
#ifdef _CS_PATH
14467
    {"CS_PATH", _CS_PATH},
14468
#endif
14469
#ifdef _CS_RELEASE
14470
    {"CS_RELEASE",      _CS_RELEASE},
14471
#endif
14472
#ifdef _CS_SRPC_DOMAIN
14473
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14474
#endif
14475
#ifdef _CS_SYSNAME
14476
    {"CS_SYSNAME",      _CS_SYSNAME},
14477
#endif
14478
#ifdef _CS_VERSION
14479
    {"CS_VERSION",      _CS_VERSION},
14480
#endif
14481
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14482
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14483
#endif
14484
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14485
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14486
#endif
14487
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14488
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14489
#endif
14490
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14491
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14492
#endif
14493
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14494
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14495
#endif
14496
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14497
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14498
#endif
14499
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14500
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14501
#endif
14502
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14503
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14504
#endif
14505
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14506
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14507
#endif
14508
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14509
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14510
#endif
14511
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14512
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14513
#endif
14514
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14515
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14516
#endif
14517
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14518
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14519
#endif
14520
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14521
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14522
#endif
14523
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14524
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14525
#endif
14526
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14527
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14528
#endif
14529
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14530
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14531
#endif
14532
#ifdef _MIPS_CS_BASE
14533
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14534
#endif
14535
#ifdef _MIPS_CS_HOSTID
14536
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14537
#endif
14538
#ifdef _MIPS_CS_HW_NAME
14539
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14540
#endif
14541
#ifdef _MIPS_CS_NUM_PROCESSORS
14542
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14543
#endif
14544
#ifdef _MIPS_CS_OSREL_MAJ
14545
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14546
#endif
14547
#ifdef _MIPS_CS_OSREL_MIN
14548
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14549
#endif
14550
#ifdef _MIPS_CS_OSREL_PATCH
14551
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14552
#endif
14553
#ifdef _MIPS_CS_OS_NAME
14554
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14555
#endif
14556
#ifdef _MIPS_CS_OS_PROVIDER
14557
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14558
#endif
14559
#ifdef _MIPS_CS_PROCESSORS
14560
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14561
#endif
14562
#ifdef _MIPS_CS_SERIAL
14563
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14564
#endif
14565
#ifdef _MIPS_CS_VENDOR
14566
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14567
#endif
14568
};
14569
14570
14571
/*[clinic input]
14572
os.confstr
14573
14574
    name: confname(table="confstr_names")
14575
    /
14576
14577
Return a string-valued system configuration variable.
14578
[clinic start generated code]*/
14579
14580
static PyObject *
14581
os_confstr_impl(PyObject *module, int name)
14582
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14583
4
{
14584
4
    PyObject *result = NULL;
14585
4
    char buffer[255];
14586
4
    size_t len;
14587
14588
4
    errno = 0;
14589
4
    len = confstr(name, buffer, sizeof(buffer));
14590
4
    if (len == 0) {
14591
0
        if (errno) {
14592
0
            posix_error();
14593
0
            return NULL;
14594
0
        }
14595
0
        else {
14596
0
            Py_RETURN_NONE;
14597
0
        }
14598
0
    }
14599
14600
4
    if (len >= sizeof(buffer)) {
14601
0
        size_t len2;
14602
0
        char *buf = PyMem_Malloc(len);
14603
0
        if (buf == NULL)
14604
0
            return PyErr_NoMemory();
14605
0
        len2 = confstr(name, buf, len);
14606
0
        assert(len == len2);
14607
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14608
0
        PyMem_Free(buf);
14609
0
    }
14610
4
    else
14611
4
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14612
4
    return result;
14613
4
}
14614
#endif /* HAVE_CONFSTR */
14615
14616
14617
#ifdef HAVE_SYSCONF
14618
static struct constdef posix_constants_sysconf[] = {
14619
#ifdef _SC_2_CHAR_TERM
14620
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14621
#endif
14622
#ifdef _SC_2_C_BIND
14623
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14624
#endif
14625
#ifdef _SC_2_C_DEV
14626
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14627
#endif
14628
#ifdef _SC_2_C_VERSION
14629
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14630
#endif
14631
#ifdef _SC_2_FORT_DEV
14632
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14633
#endif
14634
#ifdef _SC_2_FORT_RUN
14635
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14636
#endif
14637
#ifdef _SC_2_LOCALEDEF
14638
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14639
#endif
14640
#ifdef _SC_2_SW_DEV
14641
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14642
#endif
14643
#ifdef _SC_2_UPE
14644
    {"SC_2_UPE",        _SC_2_UPE},
14645
#endif
14646
#ifdef _SC_2_VERSION
14647
    {"SC_2_VERSION",    _SC_2_VERSION},
14648
#endif
14649
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14650
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14651
#endif
14652
#ifdef _SC_ACL
14653
    {"SC_ACL",  _SC_ACL},
14654
#endif
14655
#ifdef _SC_AIO_LISTIO_MAX
14656
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14657
#endif
14658
#ifdef _SC_AIO_MAX
14659
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14660
#endif
14661
#ifdef _SC_AIO_PRIO_DELTA_MAX
14662
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14663
#endif
14664
#ifdef _SC_ARG_MAX
14665
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14666
#endif
14667
#ifdef _SC_ASYNCHRONOUS_IO
14668
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14669
#endif
14670
#ifdef _SC_ATEXIT_MAX
14671
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14672
#endif
14673
#ifdef _SC_AUDIT
14674
    {"SC_AUDIT",        _SC_AUDIT},
14675
#endif
14676
#ifdef _SC_AVPHYS_PAGES
14677
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14678
#endif
14679
#ifdef _SC_BC_BASE_MAX
14680
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14681
#endif
14682
#ifdef _SC_BC_DIM_MAX
14683
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14684
#endif
14685
#ifdef _SC_BC_SCALE_MAX
14686
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14687
#endif
14688
#ifdef _SC_BC_STRING_MAX
14689
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14690
#endif
14691
#ifdef _SC_CAP
14692
    {"SC_CAP",  _SC_CAP},
14693
#endif
14694
#ifdef _SC_CHARCLASS_NAME_MAX
14695
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14696
#endif
14697
#ifdef _SC_CHAR_BIT
14698
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14699
#endif
14700
#ifdef _SC_CHAR_MAX
14701
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14702
#endif
14703
#ifdef _SC_CHAR_MIN
14704
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14705
#endif
14706
#ifdef _SC_CHILD_MAX
14707
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14708
#endif
14709
#ifdef _SC_CLK_TCK
14710
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14711
#endif
14712
#ifdef _SC_COHER_BLKSZ
14713
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14714
#endif
14715
#ifdef _SC_COLL_WEIGHTS_MAX
14716
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14717
#endif
14718
#ifdef _SC_DCACHE_ASSOC
14719
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14720
#endif
14721
#ifdef _SC_DCACHE_BLKSZ
14722
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14723
#endif
14724
#ifdef _SC_DCACHE_LINESZ
14725
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14726
#endif
14727
#ifdef _SC_DCACHE_SZ
14728
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14729
#endif
14730
#ifdef _SC_DCACHE_TBLKSZ
14731
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14732
#endif
14733
#ifdef _SC_DELAYTIMER_MAX
14734
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14735
#endif
14736
#ifdef _SC_EQUIV_CLASS_MAX
14737
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14738
#endif
14739
#ifdef _SC_EXPR_NEST_MAX
14740
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14741
#endif
14742
#ifdef _SC_FSYNC
14743
    {"SC_FSYNC",        _SC_FSYNC},
14744
#endif
14745
#ifdef _SC_GETGR_R_SIZE_MAX
14746
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14747
#endif
14748
#ifdef _SC_GETPW_R_SIZE_MAX
14749
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14750
#endif
14751
#ifdef _SC_ICACHE_ASSOC
14752
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14753
#endif
14754
#ifdef _SC_ICACHE_BLKSZ
14755
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14756
#endif
14757
#ifdef _SC_ICACHE_LINESZ
14758
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14759
#endif
14760
#ifdef _SC_ICACHE_SZ
14761
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14762
#endif
14763
#ifdef _SC_INF
14764
    {"SC_INF",  _SC_INF},
14765
#endif
14766
#ifdef _SC_INT_MAX
14767
    {"SC_INT_MAX",      _SC_INT_MAX},
14768
#endif
14769
#ifdef _SC_INT_MIN
14770
    {"SC_INT_MIN",      _SC_INT_MIN},
14771
#endif
14772
#ifdef _SC_IOV_MAX
14773
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14774
#endif
14775
#ifdef _SC_IP_SECOPTS
14776
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14777
#endif
14778
#ifdef _SC_JOB_CONTROL
14779
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14780
#endif
14781
#ifdef _SC_KERN_POINTERS
14782
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14783
#endif
14784
#ifdef _SC_KERN_SIM
14785
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14786
#endif
14787
#ifdef _SC_LINE_MAX
14788
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14789
#endif
14790
#ifdef _SC_LOGIN_NAME_MAX
14791
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14792
#endif
14793
#ifdef _SC_LOGNAME_MAX
14794
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14795
#endif
14796
#ifdef _SC_LONG_BIT
14797
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14798
#endif
14799
#ifdef _SC_MAC
14800
    {"SC_MAC",  _SC_MAC},
14801
#endif
14802
#ifdef _SC_MAPPED_FILES
14803
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14804
#endif
14805
#ifdef _SC_MAXPID
14806
    {"SC_MAXPID",       _SC_MAXPID},
14807
#endif
14808
#ifdef _SC_MB_LEN_MAX
14809
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14810
#endif
14811
#ifdef _SC_MEMLOCK
14812
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14813
#endif
14814
#ifdef _SC_MEMLOCK_RANGE
14815
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14816
#endif
14817
#ifdef _SC_MEMORY_PROTECTION
14818
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14819
#endif
14820
#ifdef _SC_MESSAGE_PASSING
14821
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14822
#endif
14823
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14824
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14825
#endif
14826
#ifdef _SC_MQ_OPEN_MAX
14827
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14828
#endif
14829
#ifdef _SC_MQ_PRIO_MAX
14830
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14831
#endif
14832
#ifdef _SC_NACLS_MAX
14833
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14834
#endif
14835
#ifdef _SC_NGROUPS_MAX
14836
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14837
#endif
14838
#ifdef _SC_NL_ARGMAX
14839
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14840
#endif
14841
#ifdef _SC_NL_LANGMAX
14842
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14843
#endif
14844
#ifdef _SC_NL_MSGMAX
14845
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14846
#endif
14847
#ifdef _SC_NL_NMAX
14848
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14849
#endif
14850
#ifdef _SC_NL_SETMAX
14851
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14852
#endif
14853
#ifdef _SC_NL_TEXTMAX
14854
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14855
#endif
14856
#ifdef _SC_NPROCESSORS_CONF
14857
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14858
#endif
14859
#ifdef _SC_NPROCESSORS_ONLN
14860
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14861
#endif
14862
#ifdef _SC_NPROC_CONF
14863
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14864
#endif
14865
#ifdef _SC_NPROC_ONLN
14866
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14867
#endif
14868
#ifdef _SC_NZERO
14869
    {"SC_NZERO",        _SC_NZERO},
14870
#endif
14871
#ifdef _SC_OPEN_MAX
14872
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14873
#endif
14874
#ifdef _SC_PAGESIZE
14875
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14876
#endif
14877
#ifdef _SC_PAGE_SIZE
14878
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14879
#endif
14880
#ifdef _SC_AIX_REALMEM
14881
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14882
#endif
14883
#ifdef _SC_PASS_MAX
14884
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14885
#endif
14886
#ifdef _SC_PHYS_PAGES
14887
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14888
#endif
14889
#ifdef _SC_PII
14890
    {"SC_PII",  _SC_PII},
14891
#endif
14892
#ifdef _SC_PII_INTERNET
14893
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14894
#endif
14895
#ifdef _SC_PII_INTERNET_DGRAM
14896
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14897
#endif
14898
#ifdef _SC_PII_INTERNET_STREAM
14899
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14900
#endif
14901
#ifdef _SC_PII_OSI
14902
    {"SC_PII_OSI",      _SC_PII_OSI},
14903
#endif
14904
#ifdef _SC_PII_OSI_CLTS
14905
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14906
#endif
14907
#ifdef _SC_PII_OSI_COTS
14908
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14909
#endif
14910
#ifdef _SC_PII_OSI_M
14911
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14912
#endif
14913
#ifdef _SC_PII_SOCKET
14914
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14915
#endif
14916
#ifdef _SC_PII_XTI
14917
    {"SC_PII_XTI",      _SC_PII_XTI},
14918
#endif
14919
#ifdef _SC_POLL
14920
    {"SC_POLL", _SC_POLL},
14921
#endif
14922
#ifdef _SC_PRIORITIZED_IO
14923
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14924
#endif
14925
#ifdef _SC_PRIORITY_SCHEDULING
14926
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14927
#endif
14928
#ifdef _SC_REALTIME_SIGNALS
14929
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14930
#endif
14931
#ifdef _SC_RE_DUP_MAX
14932
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14933
#endif
14934
#ifdef _SC_RTSIG_MAX
14935
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14936
#endif
14937
#ifdef _SC_SAVED_IDS
14938
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14939
#endif
14940
#ifdef _SC_SCHAR_MAX
14941
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14942
#endif
14943
#ifdef _SC_SCHAR_MIN
14944
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14945
#endif
14946
#ifdef _SC_SELECT
14947
    {"SC_SELECT",       _SC_SELECT},
14948
#endif
14949
#ifdef _SC_SEMAPHORES
14950
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14951
#endif
14952
#ifdef _SC_SEM_NSEMS_MAX
14953
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14954
#endif
14955
#ifdef _SC_SEM_VALUE_MAX
14956
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14957
#endif
14958
#ifdef _SC_SHARED_MEMORY_OBJECTS
14959
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14960
#endif
14961
#ifdef _SC_SHRT_MAX
14962
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14963
#endif
14964
#ifdef _SC_SHRT_MIN
14965
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14966
#endif
14967
#ifdef _SC_SIGQUEUE_MAX
14968
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14969
#endif
14970
#ifdef _SC_SIGRT_MAX
14971
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14972
#endif
14973
#ifdef _SC_SIGRT_MIN
14974
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14975
#endif
14976
#ifdef _SC_SOFTPOWER
14977
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14978
#endif
14979
#ifdef _SC_SPLIT_CACHE
14980
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14981
#endif
14982
#ifdef _SC_SSIZE_MAX
14983
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14984
#endif
14985
#ifdef _SC_STACK_PROT
14986
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14987
#endif
14988
#ifdef _SC_STREAM_MAX
14989
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14990
#endif
14991
#ifdef _SC_SYNCHRONIZED_IO
14992
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14993
#endif
14994
#ifdef _SC_THREADS
14995
    {"SC_THREADS",      _SC_THREADS},
14996
#endif
14997
#ifdef _SC_THREAD_ATTR_STACKADDR
14998
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14999
#endif
15000
#ifdef _SC_THREAD_ATTR_STACKSIZE
15001
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
15002
#endif
15003
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
15004
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
15005
#endif
15006
#ifdef _SC_THREAD_KEYS_MAX
15007
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
15008
#endif
15009
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
15010
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
15011
#endif
15012
#ifdef _SC_THREAD_PRIO_INHERIT
15013
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
15014
#endif
15015
#ifdef _SC_THREAD_PRIO_PROTECT
15016
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
15017
#endif
15018
#ifdef _SC_THREAD_PROCESS_SHARED
15019
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
15020
#endif
15021
#ifdef _SC_THREAD_SAFE_FUNCTIONS
15022
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
15023
#endif
15024
#ifdef _SC_THREAD_STACK_MIN
15025
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
15026
#endif
15027
#ifdef _SC_THREAD_THREADS_MAX
15028
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
15029
#endif
15030
#ifdef _SC_TIMERS
15031
    {"SC_TIMERS",       _SC_TIMERS},
15032
#endif
15033
#ifdef _SC_TIMER_MAX
15034
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
15035
#endif
15036
#ifdef _SC_TTY_NAME_MAX
15037
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
15038
#endif
15039
#ifdef _SC_TZNAME_MAX
15040
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
15041
#endif
15042
#ifdef _SC_T_IOV_MAX
15043
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
15044
#endif
15045
#ifdef _SC_UCHAR_MAX
15046
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
15047
#endif
15048
#ifdef _SC_UINT_MAX
15049
    {"SC_UINT_MAX",     _SC_UINT_MAX},
15050
#endif
15051
#ifdef _SC_UIO_MAXIOV
15052
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
15053
#endif
15054
#ifdef _SC_ULONG_MAX
15055
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
15056
#endif
15057
#ifdef _SC_USHRT_MAX
15058
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
15059
#endif
15060
#ifdef _SC_VERSION
15061
    {"SC_VERSION",      _SC_VERSION},
15062
#endif
15063
#ifdef _SC_WORD_BIT
15064
    {"SC_WORD_BIT",     _SC_WORD_BIT},
15065
#endif
15066
#ifdef _SC_XBS5_ILP32_OFF32
15067
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15068
#endif
15069
#ifdef _SC_XBS5_ILP32_OFFBIG
15070
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15071
#endif
15072
#ifdef _SC_XBS5_LP64_OFF64
15073
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15074
#endif
15075
#ifdef _SC_XBS5_LPBIG_OFFBIG
15076
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15077
#endif
15078
#ifdef _SC_XOPEN_CRYPT
15079
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15080
#endif
15081
#ifdef _SC_XOPEN_ENH_I18N
15082
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15083
#endif
15084
#ifdef _SC_XOPEN_LEGACY
15085
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15086
#endif
15087
#ifdef _SC_XOPEN_REALTIME
15088
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15089
#endif
15090
#ifdef _SC_XOPEN_REALTIME_THREADS
15091
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15092
#endif
15093
#ifdef _SC_XOPEN_SHM
15094
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15095
#endif
15096
#ifdef _SC_XOPEN_UNIX
15097
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15098
#endif
15099
#ifdef _SC_XOPEN_VERSION
15100
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15101
#endif
15102
#ifdef _SC_XOPEN_XCU_VERSION
15103
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15104
#endif
15105
#ifdef _SC_XOPEN_XPG2
15106
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15107
#endif
15108
#ifdef _SC_XOPEN_XPG3
15109
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15110
#endif
15111
#ifdef _SC_XOPEN_XPG4
15112
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15113
#endif
15114
#ifdef _SC_MINSIGSTKSZ
15115
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15116
#endif
15117
};
15118
15119
15120
/*[clinic input]
15121
os.sysconf -> long
15122
    name: confname(table="sysconf_names")
15123
    /
15124
15125
Return an integer-valued system configuration variable.
15126
[clinic start generated code]*/
15127
15128
static long
15129
os_sysconf_impl(PyObject *module, int name)
15130
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15131
4
{
15132
4
    long value;
15133
15134
4
    errno = 0;
15135
4
    value = sysconf(name);
15136
4
    if (value == -1 && errno != 0)
15137
0
        posix_error();
15138
4
    return value;
15139
4
}
15140
#endif /* HAVE_SYSCONF */
15141
15142
15143
static int
15144
setup_confname_table(struct constdef *table, size_t tablesize,
15145
                     const char *tablename, PyObject *module)
15146
111
{
15147
111
    PyObject *d = PyDict_New();
15148
111
    if (d == NULL)
15149
0
        return -1;
15150
15151
6.80k
    for (size_t i=0; i < tablesize; ++i) {
15152
6.69k
        PyObject *o = PyLong_FromLong(table[i].value);
15153
6.69k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15154
0
            Py_XDECREF(o);
15155
0
            Py_DECREF(d);
15156
0
            return -1;
15157
0
        }
15158
6.69k
        Py_DECREF(o);
15159
6.69k
    }
15160
111
    return PyModule_Add(module, tablename, d);
15161
111
}
15162
15163
/* Return -1 on failure, 0 on success. */
15164
static int
15165
setup_confname_tables(PyObject *module)
15166
37
{
15167
37
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15168
37
    if (setup_confname_table(posix_constants_pathconf,
15169
37
                             sizeof(posix_constants_pathconf)
15170
37
                               / sizeof(struct constdef),
15171
37
                             "pathconf_names", module))
15172
0
        return -1;
15173
37
#endif
15174
37
#ifdef HAVE_CONFSTR
15175
37
    if (setup_confname_table(posix_constants_confstr,
15176
37
                             sizeof(posix_constants_confstr)
15177
37
                               / sizeof(struct constdef),
15178
37
                             "confstr_names", module))
15179
0
        return -1;
15180
37
#endif
15181
37
#ifdef HAVE_SYSCONF
15182
37
    if (setup_confname_table(posix_constants_sysconf,
15183
37
                             sizeof(posix_constants_sysconf)
15184
37
                               / sizeof(struct constdef),
15185
37
                             "sysconf_names", module))
15186
0
        return -1;
15187
37
#endif
15188
37
    return 0;
15189
37
}
15190
15191
15192
/*[clinic input]
15193
os.abort
15194
15195
Abort the interpreter immediately.
15196
15197
This function 'dumps core' or otherwise fails in the hardest way
15198
possible on the hosting operating system.  This function never returns.
15199
[clinic start generated code]*/
15200
15201
static PyObject *
15202
os_abort_impl(PyObject *module)
15203
/*[clinic end generated code: output=dcf52586dad2467c input=ee8bd0ed690440ab]*/
15204
0
{
15205
0
    abort();
15206
    /*NOTREACHED*/
15207
#ifndef __clang__
15208
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15209
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15210
       is smarter and emits a warning on the return. */
15211
    Py_FatalError("abort() called from Python code didn't abort!");
15212
    return NULL;
15213
#endif
15214
0
}
15215
15216
#ifdef MS_WINDOWS
15217
/* Grab ShellExecute dynamically from shell32 */
15218
static int has_ShellExecute = -1;
15219
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15220
                                              LPCWSTR, INT);
15221
static int
15222
check_ShellExecute(void)
15223
{
15224
    HINSTANCE hShell32;
15225
15226
    /* only recheck */
15227
    if (-1 == has_ShellExecute) {
15228
        Py_BEGIN_ALLOW_THREADS
15229
        /* Security note: this call is not vulnerable to "DLL hijacking".
15230
           SHELL32 is part of "KnownDLLs" and so Windows always load
15231
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15232
           in the DLL search path. */
15233
        hShell32 = LoadLibraryW(L"SHELL32");
15234
        if (hShell32) {
15235
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15236
                                            "ShellExecuteW");
15237
            has_ShellExecute = Py_ShellExecuteW != NULL;
15238
        } else {
15239
            has_ShellExecute = 0;
15240
        }
15241
        Py_END_ALLOW_THREADS
15242
    }
15243
    return has_ShellExecute;
15244
}
15245
15246
15247
/*[clinic input]
15248
os.startfile
15249
    filepath: path_t
15250
    operation: Py_UNICODE = NULL
15251
    arguments: Py_UNICODE = NULL
15252
    cwd: path_t(nullable=True) = None
15253
    show_cmd: int = 1
15254
15255
Start a file with its associated application.
15256
15257
When "operation" is not specified or "open", this acts like
15258
double-clicking the file in Explorer, or giving the file name as an
15259
argument to the DOS "start" command: the file is opened with whatever
15260
application (if any) its extension is associated.
15261
When another "operation" is given, it specifies what should be done with
15262
the file.  A typical operation is "print".
15263
15264
"arguments" is passed to the application, but should be omitted if the
15265
file is a document.
15266
15267
"cwd" is the working directory for the operation. If "filepath" is
15268
relative, it will be resolved against this directory. This argument
15269
should usually be an absolute path.
15270
15271
"show_cmd" can be used to override the recommended visibility option.
15272
See the Windows ShellExecute documentation for values.
15273
15274
startfile returns as soon as the associated application is launched.
15275
There is no option to wait for the application to close, and no way
15276
to retrieve the application's exit status.
15277
15278
The filepath is relative to the current directory.  If you want to use
15279
an absolute path, make sure the first character is not a slash ("/");
15280
the underlying Win32 ShellExecute function doesn't work if it is.
15281
[clinic start generated code]*/
15282
15283
static PyObject *
15284
os_startfile_impl(PyObject *module, path_t *filepath,
15285
                  const wchar_t *operation, const wchar_t *arguments,
15286
                  path_t *cwd, int show_cmd)
15287
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15288
{
15289
    HINSTANCE rc;
15290
15291
    if(!check_ShellExecute()) {
15292
        /* If the OS doesn't have ShellExecute, return a
15293
           NotImplementedError. */
15294
        return PyErr_Format(PyExc_NotImplementedError,
15295
            "startfile not available on this platform");
15296
    }
15297
15298
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15299
        return NULL;
15300
    }
15301
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15302
                    arguments, cwd->object ? cwd->object : Py_None,
15303
                    show_cmd) < 0) {
15304
        return NULL;
15305
    }
15306
15307
    Py_BEGIN_ALLOW_THREADS
15308
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15309
                          arguments, cwd->wide, show_cmd);
15310
    Py_END_ALLOW_THREADS
15311
15312
    if (rc <= (HINSTANCE)32) {
15313
        win32_error_object("startfile", filepath->object);
15314
        return NULL;
15315
    }
15316
    Py_RETURN_NONE;
15317
}
15318
#endif /* MS_WINDOWS */
15319
15320
15321
#ifdef HAVE_GETLOADAVG
15322
/*[clinic input]
15323
os.getloadavg
15324
15325
Return average recent system load information.
15326
15327
Return the number of processes in the system run queue averaged over
15328
the last 1, 5, and 15 minutes as a tuple of three floats.
15329
Raises OSError if the load average was unobtainable.
15330
[clinic start generated code]*/
15331
15332
static PyObject *
15333
os_getloadavg_impl(PyObject *module)
15334
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15335
0
{
15336
0
    double loadavg[3];
15337
0
    if (getloadavg(loadavg, 3)!=3) {
15338
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15339
0
        return NULL;
15340
0
    } else
15341
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15342
0
}
15343
#endif /* HAVE_GETLOADAVG */
15344
15345
15346
/*[clinic input]
15347
os.device_encoding
15348
    fd: int
15349
15350
Return a string describing the encoding of a terminal's file descriptor.
15351
15352
The file descriptor must be attached to a terminal.
15353
If the device is not a terminal, return None.
15354
[clinic start generated code]*/
15355
15356
static PyObject *
15357
os_device_encoding_impl(PyObject *module, int fd)
15358
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15359
0
{
15360
0
    return _Py_device_encoding(fd);
15361
0
}
15362
15363
15364
#ifdef HAVE_SETRESUID
15365
/*[clinic input]
15366
os.setresuid
15367
15368
    ruid: uid_t
15369
    euid: uid_t
15370
    suid: uid_t
15371
    /
15372
15373
Set the current process's real, effective, and saved user ids.
15374
[clinic start generated code]*/
15375
15376
static PyObject *
15377
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15378
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15379
0
{
15380
0
    if (setresuid(ruid, euid, suid) < 0)
15381
0
        return posix_error();
15382
0
    Py_RETURN_NONE;
15383
0
}
15384
#endif /* HAVE_SETRESUID */
15385
15386
15387
#ifdef HAVE_SETRESGID
15388
/*[clinic input]
15389
os.setresgid
15390
15391
    rgid: gid_t
15392
    egid: gid_t
15393
    sgid: gid_t
15394
    /
15395
15396
Set the current process's real, effective, and saved group ids.
15397
[clinic start generated code]*/
15398
15399
static PyObject *
15400
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15401
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15402
0
{
15403
0
    if (setresgid(rgid, egid, sgid) < 0)
15404
0
        return posix_error();
15405
0
    Py_RETURN_NONE;
15406
0
}
15407
#endif /* HAVE_SETRESGID */
15408
15409
15410
#ifdef HAVE_GETRESUID
15411
/*[clinic input]
15412
@permit_long_summary
15413
os.getresuid
15414
15415
Return a tuple of the current process's real, effective, and saved user ids.
15416
[clinic start generated code]*/
15417
15418
static PyObject *
15419
os_getresuid_impl(PyObject *module)
15420
/*[clinic end generated code: output=8e0becff5dece5bf input=ddf95881f492cb97]*/
15421
0
{
15422
0
    uid_t ruid, euid, suid;
15423
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15424
0
        return posix_error();
15425
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15426
0
                                  _PyLong_FromUid(euid),
15427
0
                                  _PyLong_FromUid(suid));
15428
0
}
15429
#endif /* HAVE_GETRESUID */
15430
15431
15432
#ifdef HAVE_GETRESGID
15433
/*[clinic input]
15434
@permit_long_summary
15435
os.getresgid
15436
15437
Return a tuple of the current process's real, effective, and saved group ids.
15438
[clinic start generated code]*/
15439
15440
static PyObject *
15441
os_getresgid_impl(PyObject *module)
15442
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15443
0
{
15444
0
    gid_t rgid, egid, sgid;
15445
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15446
0
        return posix_error();
15447
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15448
0
                                  _PyLong_FromGid(egid),
15449
0
                                  _PyLong_FromGid(sgid));
15450
0
}
15451
#endif /* HAVE_GETRESGID */
15452
15453
15454
#ifdef USE_XATTRS
15455
/*[clinic input]
15456
os.getxattr
15457
15458
    path: path_t(allow_fd=True)
15459
    attribute: path_t
15460
    *
15461
    follow_symlinks: bool = True
15462
15463
Return the value of extended attribute attribute on path.
15464
15465
path may be either a string, a path-like object, or an open file
15466
descriptor.
15467
If follow_symlinks is False, and the last element of the path is
15468
a symbolic link, getxattr will examine the symbolic link itself
15469
instead of the file the link points to.
15470
15471
[clinic start generated code]*/
15472
15473
static PyObject *
15474
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15475
                 int follow_symlinks)
15476
/*[clinic end generated code: output=5f2f44200a43cff2 input=db1021ed738d9754]*/
15477
0
{
15478
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
15479
0
        return NULL;
15480
15481
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15482
0
        return NULL;
15483
0
    }
15484
15485
0
    for (Py_ssize_t i = 0; ; i++) {
15486
0
        ssize_t result;
15487
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15488
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15489
0
        if (!buffer_size) {
15490
0
            path_error(path);
15491
0
            return NULL;
15492
0
        }
15493
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15494
0
        if (writer == NULL) {
15495
0
            return NULL;
15496
0
        }
15497
0
        void *ptr = PyBytesWriter_GetData(writer);
15498
15499
0
        Py_BEGIN_ALLOW_THREADS;
15500
0
        if (path->is_fd)
15501
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15502
0
        else if (follow_symlinks)
15503
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15504
0
        else
15505
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15506
0
        Py_END_ALLOW_THREADS;
15507
15508
0
        if (result < 0) {
15509
0
            PyBytesWriter_Discard(writer);
15510
0
            if (errno == ERANGE) {
15511
0
                continue;
15512
0
            }
15513
0
            path_error(path);
15514
0
            return NULL;
15515
0
        }
15516
15517
0
        return PyBytesWriter_FinishWithSize(writer, result);
15518
0
    }
15519
0
}
15520
15521
15522
/*[clinic input]
15523
os.setxattr
15524
15525
    path: path_t(allow_fd=True)
15526
    attribute: path_t
15527
    value: Py_buffer
15528
    flags: int = 0
15529
    *
15530
    follow_symlinks: bool = True
15531
15532
Set extended attribute attribute on path to value.
15533
15534
path may be either a string, a path-like object,  or an open file
15535
descriptor.
15536
If follow_symlinks is False, and the last element of the path is
15537
a symbolic link, setxattr will modify the symbolic link itself instead
15538
of the file the link points to.
15539
15540
[clinic start generated code]*/
15541
15542
static PyObject *
15543
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15544
                 Py_buffer *value, int flags, int follow_symlinks)
15545
/*[clinic end generated code: output=98b83f63fdde26bb input=6c4ee6724e8947a4]*/
15546
0
{
15547
0
    ssize_t result;
15548
15549
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
15550
0
        return NULL;
15551
15552
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15553
0
                    value->buf, value->len, flags) < 0) {
15554
0
        return NULL;
15555
0
    }
15556
15557
0
    Py_BEGIN_ALLOW_THREADS;
15558
0
    if (path->is_fd)
15559
0
        result = fsetxattr(path->fd, attribute->narrow,
15560
0
                           value->buf, value->len, flags);
15561
0
    else if (follow_symlinks)
15562
0
        result = setxattr(path->narrow, attribute->narrow,
15563
0
                           value->buf, value->len, flags);
15564
0
    else
15565
0
        result = lsetxattr(path->narrow, attribute->narrow,
15566
0
                           value->buf, value->len, flags);
15567
0
    Py_END_ALLOW_THREADS;
15568
15569
0
    if (result) {
15570
0
        path_error(path);
15571
0
        return NULL;
15572
0
    }
15573
15574
0
    Py_RETURN_NONE;
15575
0
}
15576
15577
15578
/*[clinic input]
15579
os.removexattr
15580
15581
    path: path_t(allow_fd=True)
15582
    attribute: path_t
15583
    *
15584
    follow_symlinks: bool = True
15585
15586
Remove extended attribute attribute on path.
15587
15588
path may be either a string, a path-like object, or an open file
15589
descriptor.
15590
If follow_symlinks is False, and the last element of the path is
15591
a symbolic link, removexattr will modify the symbolic link itself
15592
instead of the file the link points to.
15593
15594
[clinic start generated code]*/
15595
15596
static PyObject *
15597
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15598
                    int follow_symlinks)
15599
/*[clinic end generated code: output=521a51817980cda6 input=a7ec62a86aa83f01]*/
15600
0
{
15601
0
    ssize_t result;
15602
15603
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
15604
0
        return NULL;
15605
15606
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15607
0
        return NULL;
15608
0
    }
15609
15610
0
    Py_BEGIN_ALLOW_THREADS;
15611
0
    if (path->is_fd)
15612
0
        result = fremovexattr(path->fd, attribute->narrow);
15613
0
    else if (follow_symlinks)
15614
0
        result = removexattr(path->narrow, attribute->narrow);
15615
0
    else
15616
0
        result = lremovexattr(path->narrow, attribute->narrow);
15617
0
    Py_END_ALLOW_THREADS;
15618
15619
0
    if (result) {
15620
0
        return path_error(path);
15621
0
    }
15622
15623
0
    Py_RETURN_NONE;
15624
0
}
15625
15626
15627
/*[clinic input]
15628
os.listxattr
15629
15630
    path: path_t(allow_fd=True, nullable=True) = None
15631
    *
15632
    follow_symlinks: bool = True
15633
15634
Return a list of extended attributes on path.
15635
15636
path may be either None, a string, a path-like object, or an open file
15637
descriptor.  If path is None, listxattr will examine the current
15638
directory.
15639
If follow_symlinks is False, and the last element of the path is
15640
a symbolic link, listxattr will examine the symbolic link itself instead
15641
of the file the link points to.
15642
[clinic start generated code]*/
15643
15644
static PyObject *
15645
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15646
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=cb4a6414afaa99bd]*/
15647
0
{
15648
0
    Py_ssize_t i;
15649
0
    PyObject *result = NULL;
15650
0
    const char *name;
15651
0
    char *buffer = NULL;
15652
15653
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
15654
0
        goto exit;
15655
15656
0
    if (PySys_Audit("os.listxattr", "(O)",
15657
0
                    path->object ? path->object : Py_None) < 0) {
15658
0
        return NULL;
15659
0
    }
15660
15661
0
    name = path->narrow ? path->narrow : ".";
15662
15663
0
    for (i = 0; ; i++) {
15664
0
        const char *start, *trace, *end;
15665
0
        ssize_t length;
15666
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15667
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15668
0
        if (!buffer_size) {
15669
            /* ERANGE */
15670
0
            path_error(path);
15671
0
            break;
15672
0
        }
15673
0
        buffer = PyMem_Malloc(buffer_size);
15674
0
        if (!buffer) {
15675
0
            PyErr_NoMemory();
15676
0
            break;
15677
0
        }
15678
15679
0
        Py_BEGIN_ALLOW_THREADS;
15680
0
        if (path->is_fd)
15681
0
            length = flistxattr(path->fd, buffer, buffer_size);
15682
0
        else if (follow_symlinks)
15683
0
            length = listxattr(name, buffer, buffer_size);
15684
0
        else
15685
0
            length = llistxattr(name, buffer, buffer_size);
15686
0
        Py_END_ALLOW_THREADS;
15687
15688
0
        if (length < 0) {
15689
0
            if (errno == ERANGE) {
15690
0
                PyMem_Free(buffer);
15691
0
                buffer = NULL;
15692
0
                continue;
15693
0
            }
15694
0
            path_error(path);
15695
0
            break;
15696
0
        }
15697
15698
0
        result = PyList_New(0);
15699
0
        if (!result) {
15700
0
            goto exit;
15701
0
        }
15702
15703
0
        end = buffer + length;
15704
0
        for (trace = start = buffer; trace != end; trace++) {
15705
0
            if (!*trace) {
15706
0
                int error;
15707
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15708
0
                                                                 trace - start);
15709
0
                if (!attribute) {
15710
0
                    Py_SETREF(result, NULL);
15711
0
                    goto exit;
15712
0
                }
15713
0
                error = PyList_Append(result, attribute);
15714
0
                Py_DECREF(attribute);
15715
0
                if (error) {
15716
0
                    Py_SETREF(result, NULL);
15717
0
                    goto exit;
15718
0
                }
15719
0
                start = trace + 1;
15720
0
            }
15721
0
        }
15722
0
    break;
15723
0
    }
15724
0
exit:
15725
0
    if (buffer)
15726
0
        PyMem_Free(buffer);
15727
0
    return result;
15728
0
}
15729
#endif /* USE_XATTRS */
15730
15731
15732
/*[clinic input]
15733
@permit_long_summary
15734
os.urandom
15735
15736
    size: Py_ssize_t(allow_negative=False)
15737
    /
15738
15739
Return a bytes object containing random bytes suitable for cryptographic use.
15740
[clinic start generated code]*/
15741
15742
static PyObject *
15743
os_urandom_impl(PyObject *module, Py_ssize_t size)
15744
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15745
0
{
15746
0
    if (size < 0) {
15747
0
        return PyErr_Format(PyExc_ValueError,
15748
0
                            "negative argument not allowed");
15749
0
    }
15750
15751
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15752
0
    if (writer == NULL) {
15753
0
        return NULL;
15754
0
    }
15755
15756
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15757
0
    if (result == -1) {
15758
0
        PyBytesWriter_Discard(writer);
15759
0
        return NULL;
15760
0
    }
15761
0
    return PyBytesWriter_Finish(writer);
15762
0
}
15763
15764
#ifdef HAVE_MEMFD_CREATE
15765
/*[clinic input]
15766
os.memfd_create
15767
15768
    name: unicode_fs_encoded
15769
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15770
15771
[clinic start generated code]*/
15772
15773
static PyObject *
15774
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15775
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15776
0
{
15777
0
    int fd;
15778
0
    const char *bytes = PyBytes_AS_STRING(name);
15779
0
    Py_BEGIN_ALLOW_THREADS
15780
0
    fd = memfd_create(bytes, flags);
15781
0
    Py_END_ALLOW_THREADS
15782
0
    if (fd == -1) {
15783
0
        return PyErr_SetFromErrno(PyExc_OSError);
15784
0
    }
15785
0
    return PyLong_FromLong(fd);
15786
0
}
15787
#endif
15788
15789
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15790
/*[clinic input]
15791
os.eventfd
15792
15793
    initval: unsigned_int
15794
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15795
15796
Creates and returns an event notification file descriptor.
15797
[clinic start generated code]*/
15798
15799
static PyObject *
15800
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15801
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15802
15803
0
{
15804
    /* initval is limited to uint32_t, internal counter is uint64_t */
15805
0
    int fd;
15806
0
    Py_BEGIN_ALLOW_THREADS
15807
0
    fd = eventfd(initval, flags);
15808
0
    Py_END_ALLOW_THREADS
15809
0
    if (fd == -1) {
15810
0
        return PyErr_SetFromErrno(PyExc_OSError);
15811
0
    }
15812
0
    return PyLong_FromLong(fd);
15813
0
}
15814
15815
/*[clinic input]
15816
os.eventfd_read
15817
15818
    fd: fildes
15819
15820
Read eventfd value
15821
[clinic start generated code]*/
15822
15823
static PyObject *
15824
os_eventfd_read_impl(PyObject *module, int fd)
15825
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15826
0
{
15827
0
    eventfd_t value;
15828
0
    int result;
15829
0
    Py_BEGIN_ALLOW_THREADS
15830
0
    result = eventfd_read(fd, &value);
15831
0
    Py_END_ALLOW_THREADS
15832
0
    if (result == -1) {
15833
0
        return PyErr_SetFromErrno(PyExc_OSError);
15834
0
    }
15835
0
    return PyLong_FromUnsignedLongLong(value);
15836
0
}
15837
15838
/*[clinic input]
15839
os.eventfd_write
15840
15841
    fd: fildes
15842
    value: unsigned_long_long
15843
15844
Write eventfd value.
15845
[clinic start generated code]*/
15846
15847
static PyObject *
15848
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15849
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15850
0
{
15851
0
    int result;
15852
0
    Py_BEGIN_ALLOW_THREADS
15853
0
    result = eventfd_write(fd, value);
15854
0
    Py_END_ALLOW_THREADS
15855
0
    if (result == -1) {
15856
0
        return PyErr_SetFromErrno(PyExc_OSError);
15857
0
    }
15858
0
    Py_RETURN_NONE;
15859
0
}
15860
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15861
15862
/* Terminal size querying */
15863
15864
PyDoc_STRVAR(TerminalSize_docstring,
15865
    "A tuple of (columns, lines) for holding terminal window size");
15866
15867
static PyStructSequence_Field TerminalSize_fields[] = {
15868
    {"columns", "width of the terminal window in characters"},
15869
    {"lines", "height of the terminal window in characters"},
15870
    {NULL, NULL}
15871
};
15872
15873
static PyStructSequence_Desc TerminalSize_desc = {
15874
    "os.terminal_size",
15875
    TerminalSize_docstring,
15876
    TerminalSize_fields,
15877
    2,
15878
};
15879
15880
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15881
/*[clinic input]
15882
os.get_terminal_size
15883
15884
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15885
    /
15886
15887
Return the size of the terminal window as (columns, lines).
15888
15889
The optional argument fd (default standard output) specifies
15890
which file descriptor should be queried.
15891
15892
If the file descriptor is not connected to a terminal, an OSError
15893
is thrown.
15894
15895
This function will only be defined if an implementation is
15896
available for this system.
15897
15898
shutil.get_terminal_size is the high-level function which should
15899
normally be used, os.get_terminal_size is the low-level implementation.
15900
[clinic start generated code]*/
15901
15902
static PyObject *
15903
os_get_terminal_size_impl(PyObject *module, int fd)
15904
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15905
0
{
15906
0
    int columns, lines;
15907
0
    PyObject *termsize;
15908
15909
    /* Under some conditions stdout may not be connected and
15910
     * fileno(stdout) may point to an invalid file descriptor. For example
15911
     * GUI apps don't have valid standard streams by default.
15912
     *
15913
     * If this happens, and the optional fd argument is not present,
15914
     * the ioctl below will fail returning EBADF. This is what we want.
15915
     */
15916
15917
0
#ifdef TERMSIZE_USE_IOCTL
15918
0
    {
15919
0
        struct winsize w;
15920
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15921
0
            return PyErr_SetFromErrno(PyExc_OSError);
15922
0
        columns = w.ws_col;
15923
0
        lines = w.ws_row;
15924
0
    }
15925
0
#endif /* TERMSIZE_USE_IOCTL */
15926
15927
#ifdef TERMSIZE_USE_CONIO
15928
    {
15929
        HANDLE handle;
15930
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15931
        handle = _Py_get_osfhandle(fd);
15932
        if (handle == INVALID_HANDLE_VALUE)
15933
            return NULL;
15934
15935
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15936
            return PyErr_SetFromWindowsErr(0);
15937
15938
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15939
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15940
    }
15941
#endif /* TERMSIZE_USE_CONIO */
15942
15943
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15944
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15945
0
    if (termsize == NULL)
15946
0
        return NULL;
15947
15948
0
    int pos = 0;
15949
15950
0
#define SET_TERMSIZE(CALL)                                   \
15951
0
    do {                                                     \
15952
0
        PyObject *item = (CALL);                             \
15953
0
        if (item == NULL) {                                  \
15954
0
            Py_DECREF(termsize);                             \
15955
0
            return NULL;                                     \
15956
0
        }                                                    \
15957
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15958
0
    } while(0)
15959
15960
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15961
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15962
0
#undef SET_TERMSIZE
15963
15964
0
    return termsize;
15965
0
}
15966
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15967
15968
/*[clinic input]
15969
os.cpu_count
15970
15971
Return the number of logical CPUs in the system.
15972
15973
Return None if indeterminable.
15974
[clinic start generated code]*/
15975
15976
static PyObject *
15977
os_cpu_count_impl(PyObject *module)
15978
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15979
0
{
15980
0
    const PyConfig *config = _Py_GetConfig();
15981
0
    if (config->cpu_count > 0) {
15982
0
        return PyLong_FromLong(config->cpu_count);
15983
0
    }
15984
15985
0
    int ncpu = 0;
15986
#ifdef MS_WINDOWS
15987
# ifdef MS_WINDOWS_DESKTOP
15988
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15989
# else
15990
    ncpu = 0;
15991
# endif
15992
15993
#elif defined(__hpux)
15994
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15995
15996
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15997
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15998
15999
#elif defined(__VXWORKS__)
16000
    ncpu = _Py_popcount32(vxCpuEnabledGet());
16001
16002
#elif defined(__DragonFly__) || \
16003
      defined(__OpenBSD__)   || \
16004
      defined(__FreeBSD__)   || \
16005
      defined(__NetBSD__)    || \
16006
      defined(__APPLE__)
16007
    ncpu = 0;
16008
    size_t len = sizeof(ncpu);
16009
    int mib[2] = {CTL_HW, HW_NCPU};
16010
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
16011
        ncpu = 0;
16012
    }
16013
#endif
16014
16015
0
    if (ncpu < 1) {
16016
0
        Py_RETURN_NONE;
16017
0
    }
16018
0
    return PyLong_FromLong(ncpu);
16019
0
}
16020
16021
16022
/*[clinic input]
16023
os.get_inheritable -> bool
16024
16025
    fd: int
16026
    /
16027
16028
Get the close-on-exe flag of the specified file descriptor.
16029
[clinic start generated code]*/
16030
16031
static int
16032
os_get_inheritable_impl(PyObject *module, int fd)
16033
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
16034
0
{
16035
0
    int return_value;
16036
0
    _Py_BEGIN_SUPPRESS_IPH
16037
0
    return_value = _Py_get_inheritable(fd);
16038
0
    _Py_END_SUPPRESS_IPH
16039
0
    return return_value;
16040
0
}
16041
16042
16043
/*[clinic input]
16044
os.set_inheritable
16045
    fd: int
16046
    inheritable: int
16047
    /
16048
16049
Set the inheritable flag of the specified file descriptor.
16050
[clinic start generated code]*/
16051
16052
static PyObject *
16053
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
16054
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
16055
0
{
16056
0
    int result;
16057
16058
0
    _Py_BEGIN_SUPPRESS_IPH
16059
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
16060
0
    _Py_END_SUPPRESS_IPH
16061
0
    if (result < 0)
16062
0
        return NULL;
16063
0
    Py_RETURN_NONE;
16064
0
}
16065
16066
16067
#ifdef MS_WINDOWS
16068
#ifndef HANDLE_FLAG_INHERIT
16069
#define HANDLE_FLAG_INHERIT 0x00000001
16070
#endif
16071
16072
/*[clinic input]
16073
os.get_handle_inheritable -> bool
16074
    handle: intptr_t
16075
    /
16076
16077
Get the close-on-exe flag of the specified file descriptor.
16078
[clinic start generated code]*/
16079
16080
static int
16081
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16082
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16083
{
16084
    DWORD flags;
16085
16086
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16087
        PyErr_SetFromWindowsErr(0);
16088
        return -1;
16089
    }
16090
16091
    return flags & HANDLE_FLAG_INHERIT;
16092
}
16093
16094
16095
/*[clinic input]
16096
os.set_handle_inheritable
16097
    handle: intptr_t
16098
    inheritable: bool
16099
    /
16100
16101
Set the inheritable flag of the specified handle.
16102
[clinic start generated code]*/
16103
16104
static PyObject *
16105
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16106
                               int inheritable)
16107
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16108
{
16109
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16110
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16111
        PyErr_SetFromWindowsErr(0);
16112
        return NULL;
16113
    }
16114
    Py_RETURN_NONE;
16115
}
16116
#endif /* MS_WINDOWS */
16117
16118
/*[clinic input]
16119
os.get_blocking -> bool
16120
    fd: int
16121
    /
16122
16123
Get the blocking mode of the file descriptor.
16124
16125
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16126
[clinic start generated code]*/
16127
16128
static int
16129
os_get_blocking_impl(PyObject *module, int fd)
16130
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16131
0
{
16132
0
    int blocking;
16133
16134
0
    _Py_BEGIN_SUPPRESS_IPH
16135
0
    blocking = _Py_get_blocking(fd);
16136
0
    _Py_END_SUPPRESS_IPH
16137
0
    return blocking;
16138
0
}
16139
16140
/*[clinic input]
16141
os.set_blocking
16142
    fd: int
16143
    blocking: bool
16144
    /
16145
16146
Set the blocking mode of the specified file descriptor.
16147
16148
Set the O_NONBLOCK flag if blocking is False,
16149
clear the O_NONBLOCK flag otherwise.
16150
[clinic start generated code]*/
16151
16152
static PyObject *
16153
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16154
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16155
0
{
16156
0
    int result;
16157
16158
0
    _Py_BEGIN_SUPPRESS_IPH
16159
0
    result = _Py_set_blocking(fd, blocking);
16160
0
    _Py_END_SUPPRESS_IPH
16161
0
    if (result < 0)
16162
0
        return NULL;
16163
0
    Py_RETURN_NONE;
16164
0
}
16165
16166
16167
/*[clinic input]
16168
class os.DirEntry "DirEntry *" "DirEntryType"
16169
[clinic start generated code]*/
16170
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16171
16172
typedef struct {
16173
    PyObject_HEAD
16174
    PyObject *name;
16175
    PyObject *path;
16176
    PyObject *stat;
16177
    PyObject *lstat;
16178
#ifdef MS_WINDOWS
16179
    struct _Py_stat_struct win32_lstat;
16180
    uint64_t win32_file_index;
16181
    uint64_t win32_file_index_high;
16182
    int got_file_index;
16183
#else /* POSIX */
16184
#ifdef HAVE_DIRENT_D_TYPE
16185
    unsigned char d_type;
16186
#endif
16187
    ino_t d_ino;
16188
    int dir_fd;
16189
#endif
16190
} DirEntry;
16191
16192
113k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16193
16194
static void
16195
DirEntry_dealloc(PyObject *op)
16196
113k
{
16197
113k
    DirEntry *entry = DirEntry_CAST(op);
16198
113k
    PyTypeObject *tp = Py_TYPE(entry);
16199
113k
    Py_XDECREF(entry->name);
16200
113k
    Py_XDECREF(entry->path);
16201
113k
    Py_XDECREF(entry->stat);
16202
113k
    Py_XDECREF(entry->lstat);
16203
113k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16204
113k
    free_func(entry);
16205
113k
    Py_DECREF(tp);
16206
113k
}
16207
16208
/* Forward reference */
16209
static int
16210
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16211
                   int follow_symlinks, unsigned short mode_bits);
16212
16213
/*[clinic input]
16214
os.DirEntry.is_symlink -> bool
16215
    defining_class: defining_class
16216
    /
16217
16218
Return True if the entry is a symbolic link; cached per entry.
16219
[clinic start generated code]*/
16220
16221
static int
16222
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16223
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16224
0
{
16225
#ifdef MS_WINDOWS
16226
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16227
#elif defined(HAVE_DIRENT_D_TYPE)
16228
    /* POSIX */
16229
0
    if (self->d_type != DT_UNKNOWN)
16230
0
        return self->d_type == DT_LNK;
16231
0
    else
16232
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16233
#else
16234
    /* POSIX without d_type */
16235
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16236
#endif
16237
0
}
16238
16239
/*[clinic input]
16240
os.DirEntry.is_junction -> bool
16241
16242
Return True if the entry is a junction; cached per entry.
16243
[clinic start generated code]*/
16244
16245
static int
16246
os_DirEntry_is_junction_impl(DirEntry *self)
16247
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16248
0
{
16249
#ifdef MS_WINDOWS
16250
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16251
#else
16252
0
    return 0;
16253
0
#endif
16254
0
}
16255
16256
static PyObject *
16257
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16258
92.1k
{
16259
92.1k
    int result;
16260
92.1k
    STRUCT_STAT st;
16261
92.1k
    PyObject *ub;
16262
16263
#ifdef MS_WINDOWS
16264
    if (!PyUnicode_FSDecoder(self->path, &ub))
16265
        return NULL;
16266
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16267
    Py_DECREF(ub);
16268
#else /* POSIX */
16269
92.1k
    if (!PyUnicode_FSConverter(self->path, &ub))
16270
0
        return NULL;
16271
92.1k
    const char *path = PyBytes_AS_STRING(ub);
16272
92.1k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16273
92.1k
#ifdef HAVE_FSTATAT
16274
92.1k
      if (HAVE_FSTATAT_RUNTIME) {
16275
92.1k
        Py_BEGIN_ALLOW_THREADS
16276
92.1k
        result = fstatat(self->dir_fd, path, &st,
16277
92.1k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16278
92.1k
        Py_END_ALLOW_THREADS
16279
92.1k
      } else
16280
16281
0
#endif /* HAVE_FSTATAT */
16282
0
      {
16283
0
        Py_DECREF(ub);
16284
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16285
0
        return NULL;
16286
0
      }
16287
92.1k
    }
16288
0
    else
16289
0
#endif
16290
0
    {
16291
0
        Py_BEGIN_ALLOW_THREADS
16292
0
        if (follow_symlinks) {
16293
0
            result = STAT(path, &st);
16294
0
        }
16295
0
        else {
16296
0
            result = LSTAT(path, &st);
16297
0
        }
16298
0
        Py_END_ALLOW_THREADS
16299
0
    }
16300
16301
92.1k
    int saved_errno = errno;
16302
#if defined(MS_WINDOWS)
16303
    PyMem_Free(path);
16304
#else
16305
92.1k
    Py_DECREF(ub);
16306
92.1k
#endif
16307
16308
92.1k
    if (result != 0) {
16309
0
        errno = saved_errno;
16310
0
        path_object_error(self->path);
16311
0
        return NULL;
16312
0
    }
16313
16314
92.1k
    return _pystat_fromstructstat(module, &st);
16315
92.1k
}
16316
16317
static PyObject *
16318
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16319
92.1k
{
16320
92.1k
    if (!self->lstat) {
16321
92.1k
        PyObject *module = PyType_GetModule(defining_class);
16322
#ifdef MS_WINDOWS
16323
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16324
#else /* POSIX */
16325
92.1k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16326
92.1k
#endif
16327
92.1k
    }
16328
92.1k
    return Py_XNewRef(self->lstat);
16329
92.1k
}
16330
16331
/*[clinic input]
16332
os.DirEntry.stat
16333
    defining_class: defining_class
16334
    /
16335
    *
16336
    follow_symlinks: bool = True
16337
16338
Return stat_result object for the entry; cached per entry.
16339
[clinic start generated code]*/
16340
16341
static PyObject *
16342
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16343
                      int follow_symlinks)
16344
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16345
92.1k
{
16346
92.1k
    if (!follow_symlinks) {
16347
92.1k
        return DirEntry_get_lstat(defining_class, self);
16348
92.1k
    }
16349
16350
0
    if (!self->stat) {
16351
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16352
0
        if (result == -1) {
16353
0
            return NULL;
16354
0
        }
16355
0
        if (result) {
16356
0
            PyObject *module = PyType_GetModule(defining_class);
16357
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16358
0
        }
16359
0
        else {
16360
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16361
0
        }
16362
0
    }
16363
16364
0
    return Py_XNewRef(self->stat);
16365
0
}
16366
16367
/* Set exception and return -1 on error, 0 for False, 1 for True */
16368
static int
16369
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16370
                   int follow_symlinks, unsigned short mode_bits)
16371
113k
{
16372
113k
    PyObject *stat = NULL;
16373
113k
    PyObject *st_mode = NULL;
16374
113k
    long mode;
16375
113k
    int result;
16376
113k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16377
113k
    int is_symlink;
16378
113k
    int need_stat;
16379
113k
#endif
16380
#ifdef MS_WINDOWS
16381
    unsigned long dir_bits;
16382
#endif
16383
16384
#ifdef MS_WINDOWS
16385
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16386
    need_stat = follow_symlinks && is_symlink;
16387
#elif defined(HAVE_DIRENT_D_TYPE)
16388
113k
    is_symlink = self->d_type == DT_LNK;
16389
113k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16390
113k
#endif
16391
16392
113k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16393
113k
    if (need_stat) {
16394
0
#endif
16395
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16396
0
        if (!stat) {
16397
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16398
                /* If file doesn't exist (anymore), then return False
16399
                   (i.e., say it's not a file/directory) */
16400
0
                PyErr_Clear();
16401
0
                return 0;
16402
0
            }
16403
0
            goto error;
16404
0
        }
16405
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16406
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16407
0
        if (!st_mode)
16408
0
            goto error;
16409
16410
0
        mode = PyLong_AsLong(st_mode);
16411
0
        if (mode == -1 && PyErr_Occurred())
16412
0
            goto error;
16413
0
        Py_CLEAR(st_mode);
16414
0
        Py_CLEAR(stat);
16415
0
        result = (mode & S_IFMT) == mode_bits;
16416
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16417
0
    }
16418
113k
    else if (is_symlink) {
16419
0
        assert(mode_bits != S_IFLNK);
16420
0
        result = 0;
16421
0
    }
16422
113k
    else {
16423
113k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16424
#ifdef MS_WINDOWS
16425
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16426
        if (mode_bits == S_IFDIR)
16427
            result = dir_bits != 0;
16428
        else
16429
            result = dir_bits == 0;
16430
#else /* POSIX */
16431
113k
        if (mode_bits == S_IFDIR)
16432
113k
            result = self->d_type == DT_DIR;
16433
0
        else
16434
0
            result = self->d_type == DT_REG;
16435
113k
#endif
16436
113k
    }
16437
113k
#endif
16438
16439
113k
    return result;
16440
16441
0
error:
16442
0
    Py_XDECREF(st_mode);
16443
0
    Py_XDECREF(stat);
16444
0
    return -1;
16445
113k
}
16446
16447
/*[clinic input]
16448
os.DirEntry.is_dir -> bool
16449
    defining_class: defining_class
16450
    /
16451
    *
16452
    follow_symlinks: bool = True
16453
16454
Return True if the entry is a directory; cached per entry.
16455
[clinic start generated code]*/
16456
16457
static int
16458
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16459
                        int follow_symlinks)
16460
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16461
113k
{
16462
113k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16463
113k
}
16464
16465
/*[clinic input]
16466
os.DirEntry.is_file -> bool
16467
    defining_class: defining_class
16468
    /
16469
    *
16470
    follow_symlinks: bool = True
16471
16472
Return True if the entry is a file; cached per entry.
16473
[clinic start generated code]*/
16474
16475
static int
16476
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16477
                         int follow_symlinks)
16478
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16479
0
{
16480
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16481
0
}
16482
16483
/*[clinic input]
16484
os.DirEntry.inode
16485
16486
Return inode of the entry; cached per entry.
16487
[clinic start generated code]*/
16488
16489
static PyObject *
16490
os_DirEntry_inode_impl(DirEntry *self)
16491
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16492
0
{
16493
#ifdef MS_WINDOWS
16494
    if (!self->got_file_index) {
16495
        PyObject *unicode;
16496
        STRUCT_STAT stat;
16497
        int result;
16498
16499
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16500
            return NULL;
16501
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16502
        Py_DECREF(unicode);
16503
        result = LSTAT(path, &stat);
16504
16505
        int saved_errno = errno;
16506
        PyMem_Free(path);
16507
16508
        if (result != 0) {
16509
            errno = saved_errno;
16510
            return path_object_error(self->path);
16511
        }
16512
16513
        self->win32_file_index = stat.st_ino;
16514
        self->win32_file_index_high = stat.st_ino_high;
16515
        self->got_file_index = 1;
16516
    }
16517
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16518
#else /* POSIX */
16519
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16520
0
                  "DirEntry.d_ino is larger than unsigned long long");
16521
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16522
0
#endif
16523
0
}
16524
16525
static PyObject *
16526
DirEntry_repr(PyObject *op)
16527
0
{
16528
0
    DirEntry *self = DirEntry_CAST(op);
16529
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16530
0
}
16531
16532
/*[clinic input]
16533
os.DirEntry.__fspath__
16534
16535
Returns the path for the entry.
16536
[clinic start generated code]*/
16537
16538
static PyObject *
16539
os_DirEntry___fspath___impl(DirEntry *self)
16540
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16541
0
{
16542
0
    return Py_NewRef(self->path);
16543
0
}
16544
16545
static PyMemberDef DirEntry_members[] = {
16546
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16547
     "the entry's base filename, relative to scandir() \"path\" argument"},
16548
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16549
     "the entry's full path name; equivalent to\nos.path.join(scandir_path, entry.name)"},
16550
    {NULL}
16551
};
16552
16553
#include "clinic/posixmodule.c.h"
16554
16555
static PyMethodDef DirEntry_methods[] = {
16556
    OS_DIRENTRY_IS_DIR_METHODDEF
16557
    OS_DIRENTRY_IS_FILE_METHODDEF
16558
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16559
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16560
    OS_DIRENTRY_STAT_METHODDEF
16561
    OS_DIRENTRY_INODE_METHODDEF
16562
    OS_DIRENTRY___FSPATH___METHODDEF
16563
    {"__class_getitem__",       Py_GenericAlias,
16564
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16565
    {NULL}
16566
};
16567
16568
static PyType_Slot DirEntryType_slots[] = {
16569
    {Py_tp_dealloc, DirEntry_dealloc},
16570
    {Py_tp_repr, DirEntry_repr},
16571
    {Py_tp_methods, DirEntry_methods},
16572
    {Py_tp_members, DirEntry_members},
16573
    {0, 0},
16574
};
16575
16576
static PyType_Spec DirEntryType_spec = {
16577
    .name = MODNAME ".DirEntry",
16578
    .basicsize = sizeof(DirEntry),
16579
    .flags = (
16580
        Py_TPFLAGS_DEFAULT
16581
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16582
        | Py_TPFLAGS_IMMUTABLETYPE
16583
    ),
16584
    .slots = DirEntryType_slots
16585
};
16586
16587
16588
#ifdef MS_WINDOWS
16589
16590
static wchar_t *
16591
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16592
{
16593
    Py_ssize_t path_len;
16594
    Py_ssize_t size;
16595
    wchar_t *result;
16596
    wchar_t ch;
16597
16598
    if (!path_wide) { /* Default arg: "." */
16599
        path_wide = L".";
16600
        path_len = 1;
16601
    }
16602
    else {
16603
        path_len = wcslen(path_wide);
16604
    }
16605
16606
    /* The +1's are for the path separator and the NUL */
16607
    size = path_len + 1 + wcslen(filename) + 1;
16608
    result = PyMem_New(wchar_t, size);
16609
    if (!result) {
16610
        PyErr_NoMemory();
16611
        return NULL;
16612
    }
16613
    wcscpy(result, path_wide);
16614
    if (path_len > 0) {
16615
        ch = result[path_len - 1];
16616
        if (ch != SEP && ch != ALTSEP && ch != L':')
16617
            result[path_len++] = SEP;
16618
        wcscpy(result + path_len, filename);
16619
    }
16620
    return result;
16621
}
16622
16623
static PyObject *
16624
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16625
{
16626
    DirEntry *entry;
16627
    BY_HANDLE_FILE_INFORMATION file_info;
16628
    ULONG reparse_tag;
16629
    wchar_t *joined_path;
16630
16631
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16632
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16633
    if (!entry)
16634
        return NULL;
16635
    entry->name = NULL;
16636
    entry->path = NULL;
16637
    entry->stat = NULL;
16638
    entry->lstat = NULL;
16639
    entry->got_file_index = 0;
16640
16641
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16642
    if (!entry->name)
16643
        goto error;
16644
    int return_bytes = path->wide && PyBytes_Check(path->object);
16645
    if (return_bytes) {
16646
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16647
        if (!entry->name)
16648
            goto error;
16649
    }
16650
16651
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16652
    if (!joined_path)
16653
        goto error;
16654
16655
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16656
    PyMem_Free(joined_path);
16657
    if (!entry->path)
16658
        goto error;
16659
    if (return_bytes) {
16660
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16661
        if (!entry->path)
16662
            goto error;
16663
    }
16664
16665
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16666
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16667
16668
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16669
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16670
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16671
16672
    return (PyObject *)entry;
16673
16674
error:
16675
    Py_DECREF(entry);
16676
    return NULL;
16677
}
16678
16679
#else /* POSIX */
16680
16681
static char *
16682
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16683
0
{
16684
0
    Py_ssize_t path_len;
16685
0
    Py_ssize_t size;
16686
0
    char *result;
16687
16688
0
    if (!path_narrow) { /* Default arg: "." */
16689
0
        path_narrow = ".";
16690
0
        path_len = 1;
16691
0
    }
16692
0
    else {
16693
0
        path_len = strlen(path_narrow);
16694
0
    }
16695
16696
0
    if (filename_len == -1)
16697
0
        filename_len = strlen(filename);
16698
16699
    /* The +1's are for the path separator and the NUL */
16700
0
    size = path_len + 1 + filename_len + 1;
16701
0
    result = PyMem_New(char, size);
16702
0
    if (!result) {
16703
0
        PyErr_NoMemory();
16704
0
        return NULL;
16705
0
    }
16706
0
    strcpy(result, path_narrow);
16707
0
    if (path_len > 0 && result[path_len - 1] != '/')
16708
0
        result[path_len++] = '/';
16709
0
    strcpy(result + path_len, filename);
16710
0
    return result;
16711
0
}
16712
16713
static PyObject *
16714
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16715
                         Py_ssize_t name_len, ino_t d_ino
16716
#ifdef HAVE_DIRENT_D_TYPE
16717
                         , unsigned char d_type
16718
#endif
16719
                         )
16720
113k
{
16721
113k
    DirEntry *entry;
16722
113k
    char *joined_path;
16723
16724
113k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16725
113k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16726
113k
    if (!entry)
16727
0
        return NULL;
16728
113k
    entry->name = NULL;
16729
113k
    entry->path = NULL;
16730
113k
    entry->stat = NULL;
16731
113k
    entry->lstat = NULL;
16732
16733
113k
    if (path->is_fd) {
16734
113k
        entry->dir_fd = path->fd;
16735
113k
        joined_path = NULL;
16736
113k
    }
16737
0
    else {
16738
0
        entry->dir_fd = DEFAULT_DIR_FD;
16739
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16740
0
        if (!joined_path)
16741
0
            goto error;
16742
0
    }
16743
16744
113k
    if (!path->narrow || !PyBytes_Check(path->object)) {
16745
113k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16746
113k
        if (joined_path)
16747
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16748
113k
    }
16749
0
    else {
16750
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16751
0
        if (joined_path)
16752
0
            entry->path = PyBytes_FromString(joined_path);
16753
0
    }
16754
113k
    PyMem_Free(joined_path);
16755
113k
    if (!entry->name)
16756
0
        goto error;
16757
16758
113k
    if (path->is_fd) {
16759
113k
        entry->path = Py_NewRef(entry->name);
16760
113k
    }
16761
0
    else if (!entry->path)
16762
0
        goto error;
16763
16764
113k
#ifdef HAVE_DIRENT_D_TYPE
16765
113k
    entry->d_type = d_type;
16766
113k
#endif
16767
113k
    entry->d_ino = d_ino;
16768
16769
113k
    return (PyObject *)entry;
16770
16771
0
error:
16772
0
    Py_XDECREF(entry);
16773
0
    return NULL;
16774
113k
}
16775
16776
#endif
16777
16778
16779
typedef struct {
16780
    PyObject_HEAD
16781
    path_t path;
16782
#ifdef MS_WINDOWS
16783
    HANDLE handle;
16784
    WIN32_FIND_DATAW file_data;
16785
    int first_time;
16786
#else /* POSIX */
16787
    DIR *dirp;
16788
#endif
16789
#ifdef HAVE_FDOPENDIR
16790
    int fd;
16791
#endif
16792
} ScandirIterator;
16793
16794
403k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16795
16796
#ifdef MS_WINDOWS
16797
16798
static int
16799
ScandirIterator_is_closed(ScandirIterator *iterator)
16800
{
16801
    return iterator->handle == INVALID_HANDLE_VALUE;
16802
}
16803
16804
static void
16805
ScandirIterator_closedir(ScandirIterator *iterator)
16806
{
16807
    HANDLE handle = iterator->handle;
16808
16809
    if (handle == INVALID_HANDLE_VALUE)
16810
        return;
16811
16812
    iterator->handle = INVALID_HANDLE_VALUE;
16813
    Py_BEGIN_ALLOW_THREADS
16814
    FindClose(handle);
16815
    Py_END_ALLOW_THREADS
16816
}
16817
16818
static PyObject *
16819
ScandirIterator_iternext(PyObject *op)
16820
{
16821
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16822
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16823
    BOOL success;
16824
    PyObject *entry;
16825
16826
    /* Happens if the iterator is iterated twice, or closed explicitly */
16827
    if (iterator->handle == INVALID_HANDLE_VALUE)
16828
        return NULL;
16829
16830
    while (1) {
16831
        if (!iterator->first_time) {
16832
            Py_BEGIN_ALLOW_THREADS
16833
            success = FindNextFileW(iterator->handle, file_data);
16834
            Py_END_ALLOW_THREADS
16835
            if (!success) {
16836
                /* Error or no more files */
16837
                if (GetLastError() != ERROR_NO_MORE_FILES)
16838
                    path_error(&iterator->path);
16839
                break;
16840
            }
16841
        }
16842
        iterator->first_time = 0;
16843
16844
        /* Skip over . and .. */
16845
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16846
            wcscmp(file_data->cFileName, L"..") != 0)
16847
        {
16848
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16849
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16850
            if (!entry)
16851
                break;
16852
            return entry;
16853
        }
16854
16855
        /* Loop till we get a non-dot directory or finish iterating */
16856
    }
16857
16858
    /* Error or no more files */
16859
    ScandirIterator_closedir(iterator);
16860
    return NULL;
16861
}
16862
16863
#else /* POSIX */
16864
16865
static int
16866
ScandirIterator_is_closed(ScandirIterator *iterator)
16867
96.6k
{
16868
96.6k
    return !iterator->dirp;
16869
96.6k
}
16870
16871
static void
16872
ScandirIterator_closedir(ScandirIterator *iterator)
16873
193k
{
16874
193k
    DIR *dirp = iterator->dirp;
16875
16876
193k
    if (!dirp)
16877
96.6k
        return;
16878
16879
96.6k
    iterator->dirp = NULL;
16880
96.6k
    Py_BEGIN_ALLOW_THREADS
16881
96.6k
#ifdef HAVE_FDOPENDIR
16882
96.6k
    if (iterator->path.is_fd) {
16883
96.6k
        rewinddir(dirp);
16884
96.6k
    }
16885
96.6k
#endif
16886
96.6k
    closedir(dirp);
16887
96.6k
    Py_END_ALLOW_THREADS
16888
96.6k
    return;
16889
193k
}
16890
16891
static PyObject *
16892
ScandirIterator_iternext(PyObject *op)
16893
209k
{
16894
209k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16895
209k
    struct dirent *direntp;
16896
209k
    Py_ssize_t name_len;
16897
209k
    int is_dot;
16898
209k
    PyObject *entry;
16899
16900
    /* Happens if the iterator is iterated twice, or closed explicitly */
16901
209k
    if (!iterator->dirp)
16902
0
        return NULL;
16903
16904
403k
    while (1) {
16905
403k
        errno = 0;
16906
403k
        Py_BEGIN_ALLOW_THREADS
16907
403k
        direntp = readdir(iterator->dirp);
16908
403k
        Py_END_ALLOW_THREADS
16909
16910
403k
        if (!direntp) {
16911
            /* Error or no more files */
16912
96.6k
            if (errno != 0)
16913
0
                path_error(&iterator->path);
16914
96.6k
            break;
16915
96.6k
        }
16916
16917
        /* Skip over . and .. */
16918
306k
        name_len = NAMLEN(direntp);
16919
306k
        is_dot = direntp->d_name[0] == '.' &&
16920
194k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16921
306k
        if (!is_dot) {
16922
113k
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16923
113k
            entry = DirEntry_from_posix_info(module,
16924
113k
                                             &iterator->path, direntp->d_name,
16925
113k
                                             name_len, direntp->d_ino
16926
113k
#ifdef HAVE_DIRENT_D_TYPE
16927
113k
                                             , direntp->d_type
16928
113k
#endif
16929
113k
                                            );
16930
113k
            if (!entry)
16931
0
                break;
16932
113k
            return entry;
16933
113k
        }
16934
16935
        /* Loop till we get a non-dot directory or finish iterating */
16936
306k
    }
16937
16938
    /* Error or no more files */
16939
96.6k
    ScandirIterator_closedir(iterator);
16940
96.6k
    return NULL;
16941
209k
}
16942
16943
#endif
16944
16945
static PyObject *
16946
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16947
0
{
16948
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16949
0
    ScandirIterator_closedir(self);
16950
0
    Py_RETURN_NONE;
16951
0
}
16952
16953
static PyObject *
16954
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16955
96.6k
{
16956
96.6k
    return Py_NewRef(self);
16957
96.6k
}
16958
16959
static PyObject *
16960
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16961
96.6k
{
16962
96.6k
    ScandirIterator *self = ScandirIterator_CAST(op);
16963
96.6k
    ScandirIterator_closedir(self);
16964
96.6k
    Py_RETURN_NONE;
16965
96.6k
}
16966
16967
static void
16968
ScandirIterator_finalize(PyObject *op)
16969
96.6k
{
16970
96.6k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16971
    /* Save the current exception, if any. */
16972
96.6k
    PyObject *exc = PyErr_GetRaisedException();
16973
16974
96.6k
    if (!ScandirIterator_is_closed(iterator)) {
16975
0
        ScandirIterator_closedir(iterator);
16976
16977
0
        if (PyErr_ResourceWarning(op, 1,
16978
0
                                  "unclosed scandir iterator %R", iterator))
16979
0
        {
16980
            /* Spurious errors can appear at shutdown */
16981
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16982
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16983
0
                                       "scandir iterator %R", iterator);
16984
0
            }
16985
0
        }
16986
0
    }
16987
16988
96.6k
    path_cleanup(&iterator->path);
16989
16990
    /* Restore the saved exception. */
16991
96.6k
    PyErr_SetRaisedException(exc);
16992
96.6k
}
16993
16994
static void
16995
ScandirIterator_dealloc(PyObject *op)
16996
96.6k
{
16997
96.6k
    PyTypeObject *tp = Py_TYPE(op);
16998
96.6k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16999
0
        return;
17000
17001
96.6k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
17002
96.6k
    free_func(op);
17003
96.6k
    Py_DECREF(tp);
17004
96.6k
}
17005
17006
static PyMethodDef ScandirIterator_methods[] = {
17007
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
17008
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
17009
    {"close", ScandirIterator_close, METH_NOARGS},
17010
    {NULL}
17011
};
17012
17013
static PyType_Slot ScandirIteratorType_slots[] = {
17014
    {Py_tp_dealloc, ScandirIterator_dealloc},
17015
    {Py_tp_finalize, ScandirIterator_finalize},
17016
    {Py_tp_iter, PyObject_SelfIter},
17017
    {Py_tp_iternext, ScandirIterator_iternext},
17018
    {Py_tp_methods, ScandirIterator_methods},
17019
    {0, 0},
17020
};
17021
17022
static PyType_Spec ScandirIteratorType_spec = {
17023
    .name = MODNAME ".ScandirIterator",
17024
    .basicsize = sizeof(ScandirIterator),
17025
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
17026
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
17027
    .flags = (
17028
        Py_TPFLAGS_DEFAULT
17029
        | Py_TPFLAGS_HAVE_FINALIZE
17030
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
17031
        | Py_TPFLAGS_IMMUTABLETYPE
17032
    ),
17033
    .slots = ScandirIteratorType_slots
17034
};
17035
17036
/*[clinic input]
17037
os.scandir
17038
17039
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
17040
17041
Return an iterator of DirEntry objects for given path.
17042
17043
path can be specified as either str, bytes, or a path-like object.  If
17044
path is bytes, the names of yielded DirEntry objects will also be bytes;
17045
in all other circumstances they will be str.
17046
17047
If path is None, uses the path='.'.
17048
[clinic start generated code]*/
17049
17050
static PyObject *
17051
os_scandir_impl(PyObject *module, path_t *path)
17052
/*[clinic end generated code: output=6eb2668b675ca89e input=6ab9600993f51577]*/
17053
96.6k
{
17054
96.6k
    ScandirIterator *iterator;
17055
#ifdef MS_WINDOWS
17056
    wchar_t *path_strW;
17057
#else
17058
96.6k
    const char *path_str;
17059
96.6k
#ifdef HAVE_FDOPENDIR
17060
96.6k
    int fd = -1;
17061
96.6k
#endif
17062
96.6k
#endif
17063
17064
96.6k
    if (PySys_Audit("os.scandir", "O",
17065
96.6k
                    path->object ? path->object : Py_None) < 0) {
17066
0
        return NULL;
17067
0
    }
17068
17069
96.6k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
17070
96.6k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
17071
96.6k
    if (!iterator)
17072
0
        return NULL;
17073
17074
#ifdef MS_WINDOWS
17075
    iterator->handle = INVALID_HANDLE_VALUE;
17076
#else
17077
96.6k
    iterator->dirp = NULL;
17078
96.6k
#endif
17079
17080
    /* Move the ownership to iterator->path */
17081
96.6k
    memcpy(&iterator->path, path, sizeof(path_t));
17082
96.6k
    memset(path, 0, sizeof(path_t));
17083
17084
#ifdef MS_WINDOWS
17085
    iterator->first_time = 1;
17086
17087
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
17088
    if (!path_strW)
17089
        goto error;
17090
17091
    Py_BEGIN_ALLOW_THREADS
17092
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17093
    Py_END_ALLOW_THREADS
17094
17095
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17096
        path_error(&iterator->path);
17097
        PyMem_Free(path_strW);
17098
        goto error;
17099
    }
17100
    PyMem_Free(path_strW);
17101
#else /* POSIX */
17102
96.6k
    errno = 0;
17103
96.6k
#ifdef HAVE_FDOPENDIR
17104
96.6k
    if (iterator->path.is_fd) {
17105
96.6k
      if (HAVE_FDOPENDIR_RUNTIME) {
17106
        /* closedir() closes the FD, so we duplicate it */
17107
96.6k
        fd = _Py_dup(iterator->path.fd);
17108
96.6k
        if (fd == -1)
17109
0
            goto error;
17110
17111
96.6k
        Py_BEGIN_ALLOW_THREADS
17112
96.6k
        iterator->dirp = fdopendir(fd);
17113
96.6k
        Py_END_ALLOW_THREADS
17114
96.6k
      } else {
17115
0
        PyErr_SetString(PyExc_TypeError,
17116
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17117
0
        return NULL;
17118
0
      }
17119
96.6k
    }
17120
0
    else
17121
0
#endif
17122
0
    {
17123
0
        if (iterator->path.narrow)
17124
0
            path_str = iterator->path.narrow;
17125
0
        else
17126
0
            path_str = ".";
17127
17128
0
        Py_BEGIN_ALLOW_THREADS
17129
0
        iterator->dirp = opendir(path_str);
17130
0
        Py_END_ALLOW_THREADS
17131
0
    }
17132
17133
96.6k
    if (!iterator->dirp) {
17134
0
        path_error(&iterator->path);
17135
0
#ifdef HAVE_FDOPENDIR
17136
0
        if (fd != -1) {
17137
0
            Py_BEGIN_ALLOW_THREADS
17138
0
            close(fd);
17139
0
            Py_END_ALLOW_THREADS
17140
0
        }
17141
0
#endif
17142
0
        goto error;
17143
0
    }
17144
96.6k
#endif
17145
17146
96.6k
    return (PyObject *)iterator;
17147
17148
0
error:
17149
0
    Py_DECREF(iterator);
17150
0
    return NULL;
17151
96.6k
}
17152
17153
/*
17154
    Return the file system path representation of the object.
17155
17156
    If the object is str or bytes, then allow it to pass through with
17157
    an incremented refcount. If the object defines __fspath__(), then
17158
    return the result of that method. All other types raise a TypeError.
17159
*/
17160
PyObject *
17161
PyOS_FSPath(PyObject *path)
17162
1.05M
{
17163
    /* For error message reasons, this function is manually inlined in
17164
       path_converter(). */
17165
1.05M
    PyObject *func = NULL;
17166
1.05M
    PyObject *path_repr = NULL;
17167
17168
1.05M
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17169
1.05M
        return Py_NewRef(path);
17170
1.05M
    }
17171
17172
275
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17173
275
    if ((NULL == func) || (func == Py_None)) {
17174
0
        return PyErr_Format(PyExc_TypeError,
17175
0
                            "expected str, bytes or os.PathLike object, "
17176
0
                            "not %.200s",
17177
0
                            _PyType_Name(Py_TYPE(path)));
17178
0
    }
17179
17180
275
    path_repr = _PyObject_CallNoArgs(func);
17181
275
    Py_DECREF(func);
17182
275
    if (NULL == path_repr) {
17183
0
        return NULL;
17184
0
    }
17185
17186
275
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17187
0
        PyErr_Format(PyExc_TypeError,
17188
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17189
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17190
0
                     _PyType_Name(Py_TYPE(path_repr)));
17191
0
        Py_DECREF(path_repr);
17192
0
        return NULL;
17193
0
    }
17194
17195
275
    return path_repr;
17196
275
}
17197
17198
/*[clinic input]
17199
os.fspath
17200
17201
    path: object
17202
17203
Return the file system path representation of the object.
17204
17205
If the object is str or bytes, then allow it to pass through as-is.  If
17206
the object defines __fspath__(), then return the result of that method.
17207
All other types raise a TypeError.
17208
[clinic start generated code]*/
17209
17210
static PyObject *
17211
os_fspath_impl(PyObject *module, PyObject *path)
17212
/*[clinic end generated code: output=c3c3b78ecff2914f input=d3c54404240d5da0]*/
17213
724k
{
17214
724k
    return PyOS_FSPath(path);
17215
724k
}
17216
17217
#ifdef HAVE_GETRANDOM_SYSCALL
17218
/*[clinic input]
17219
os.getrandom
17220
17221
    size: Py_ssize_t
17222
    flags: int=0
17223
17224
Obtain a series of random bytes.
17225
[clinic start generated code]*/
17226
17227
static PyObject *
17228
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17229
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17230
0
{
17231
0
    if (size < 0) {
17232
0
        errno = EINVAL;
17233
0
        return posix_error();
17234
0
    }
17235
17236
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17237
0
    if (writer == NULL) {
17238
0
        return NULL;
17239
0
    }
17240
0
    void *data = PyBytesWriter_GetData(writer);
17241
17242
0
    Py_ssize_t n;
17243
0
    while (1) {
17244
0
        n = syscall(SYS_getrandom, data, size, flags);
17245
0
        if (n < 0 && errno == EINTR) {
17246
0
            if (PyErr_CheckSignals() < 0) {
17247
0
                goto error;
17248
0
            }
17249
17250
            /* getrandom() was interrupted by a signal: retry */
17251
0
            continue;
17252
0
        }
17253
0
        break;
17254
0
    }
17255
17256
0
    if (n < 0) {
17257
0
        PyErr_SetFromErrno(PyExc_OSError);
17258
0
        goto error;
17259
0
    }
17260
17261
0
    _Py_MSAN_UNPOISON(data, size);
17262
17263
0
    return PyBytesWriter_FinishWithSize(writer, n);
17264
17265
0
error:
17266
0
    PyBytesWriter_Discard(writer);
17267
0
    return NULL;
17268
0
}
17269
#endif   /* HAVE_GETRANDOM_SYSCALL */
17270
17271
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17272
17273
/* bpo-36085: Helper functions for managing DLL search directories
17274
 * on win32
17275
 */
17276
17277
/*[clinic input]
17278
os._add_dll_directory
17279
17280
    path: path_t
17281
17282
Add a path to the DLL search path.
17283
17284
This search path is used when resolving dependencies for imported
17285
extension modules (the module itself is resolved through sys.path),
17286
and also by ctypes.
17287
17288
Returns an opaque value that may be passed to os.remove_dll_directory
17289
to remove this directory from the search path.
17290
[clinic start generated code]*/
17291
17292
static PyObject *
17293
os__add_dll_directory_impl(PyObject *module, path_t *path)
17294
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17295
{
17296
    DLL_DIRECTORY_COOKIE cookie = 0;
17297
    DWORD err = 0;
17298
17299
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17300
        return NULL;
17301
    }
17302
17303
    Py_BEGIN_ALLOW_THREADS
17304
    if (!(cookie = AddDllDirectory(path->wide))) {
17305
        err = GetLastError();
17306
    }
17307
    Py_END_ALLOW_THREADS
17308
17309
    if (err) {
17310
        return win32_error_object_err("add_dll_directory",
17311
                                      path->object, err);
17312
    }
17313
17314
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17315
}
17316
17317
/*[clinic input]
17318
os._remove_dll_directory
17319
17320
    cookie: object
17321
17322
Removes a path from the DLL search path.
17323
17324
The parameter is an opaque value that was returned from
17325
os.add_dll_directory. You can only remove directories that you added
17326
yourself.
17327
[clinic start generated code]*/
17328
17329
static PyObject *
17330
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17331
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17332
{
17333
    DLL_DIRECTORY_COOKIE cookieValue;
17334
    DWORD err = 0;
17335
17336
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17337
        PyErr_SetString(PyExc_TypeError,
17338
            "Provided cookie was not returned from os.add_dll_directory");
17339
        return NULL;
17340
    }
17341
17342
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17343
        cookie, "DLL directory cookie");
17344
17345
    Py_BEGIN_ALLOW_THREADS
17346
    if (!RemoveDllDirectory(cookieValue)) {
17347
        err = GetLastError();
17348
    }
17349
    Py_END_ALLOW_THREADS
17350
17351
    if (err) {
17352
        return win32_error_object_err("remove_dll_directory",
17353
                                      NULL, err);
17354
    }
17355
17356
    if (PyCapsule_SetName(cookie, NULL)) {
17357
        return NULL;
17358
    }
17359
17360
    Py_RETURN_NONE;
17361
}
17362
17363
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17364
17365
17366
/* Only check if WIFEXITED is available: expect that it comes
17367
   with WEXITSTATUS, WIFSIGNALED, etc.
17368
17369
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17370
   subprocess can safely call it during late Python finalization without
17371
   risking that used os attributes were set to None by finalize_modules(). */
17372
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17373
/*[clinic input]
17374
os.waitstatus_to_exitcode
17375
17376
    status as status_obj: object
17377
17378
Convert a wait status to an exit code.
17379
17380
On Unix:
17381
17382
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17383
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17384
* Otherwise, raise a ValueError.
17385
17386
On Windows, return status shifted right by 8 bits.
17387
17388
On Unix, if the process is being traced or if waitpid() was called with
17389
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is
17390
true.  This function must not be called if WIFSTOPPED(status) is true.
17391
[clinic start generated code]*/
17392
17393
static PyObject *
17394
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17395
/*[clinic end generated code: output=db50b1b0ba3c7153 input=3b44a23f5090006c]*/
17396
0
{
17397
0
#ifndef MS_WINDOWS
17398
0
    int status = PyLong_AsInt(status_obj);
17399
0
    if (status == -1 && PyErr_Occurred()) {
17400
0
        return NULL;
17401
0
    }
17402
17403
0
    WAIT_TYPE wait_status;
17404
0
    WAIT_STATUS_INT(wait_status) = status;
17405
0
    int exitcode;
17406
0
    if (WIFEXITED(wait_status)) {
17407
0
        exitcode = WEXITSTATUS(wait_status);
17408
        /* Sanity check to provide warranty on the function behavior.
17409
           It should not occur in practice */
17410
0
        if (exitcode < 0) {
17411
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17412
0
            return NULL;
17413
0
        }
17414
0
    }
17415
0
    else if (WIFSIGNALED(wait_status)) {
17416
0
        int signum = WTERMSIG(wait_status);
17417
        /* Sanity check to provide warranty on the function behavior.
17418
           It should not occurs in practice */
17419
0
        if (signum <= 0) {
17420
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17421
0
            return NULL;
17422
0
        }
17423
0
        exitcode = -signum;
17424
0
    } else if (WIFSTOPPED(wait_status)) {
17425
        /* Status only received if the process is being traced
17426
           or if waitpid() was called with WUNTRACED option. */
17427
0
        int signum = WSTOPSIG(wait_status);
17428
0
        PyErr_Format(PyExc_ValueError,
17429
0
                     "process stopped by delivery of signal %i",
17430
0
                     signum);
17431
0
        return NULL;
17432
0
    }
17433
0
    else {
17434
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17435
0
        return NULL;
17436
0
    }
17437
0
    return PyLong_FromLong(exitcode);
17438
#else
17439
    /* Windows implementation: see os.waitpid() implementation
17440
       which uses _cwait(). */
17441
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17442
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17443
        return NULL;
17444
    }
17445
17446
    unsigned long long exitcode = (status >> 8);
17447
    /* ExitProcess() accepts an UINT type:
17448
       reject exit code which doesn't fit in an UINT */
17449
    if (exitcode > UINT_MAX) {
17450
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17451
        return NULL;
17452
    }
17453
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17454
#endif
17455
0
}
17456
#endif
17457
17458
#if defined(MS_WINDOWS)
17459
/*[clinic input]
17460
os._supports_virtual_terminal
17461
17462
Checks if virtual terminal is supported in windows
17463
[clinic start generated code]*/
17464
17465
static PyObject *
17466
os__supports_virtual_terminal_impl(PyObject *module)
17467
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17468
{
17469
#ifdef HAVE_WINDOWS_CONSOLE_IO
17470
    DWORD mode = 0;
17471
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17472
    if (!GetConsoleMode(handle, &mode)) {
17473
        Py_RETURN_FALSE;
17474
    }
17475
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17476
#else
17477
    Py_RETURN_FALSE;
17478
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17479
}
17480
#endif
17481
17482
/*[clinic input]
17483
os._inputhook
17484
17485
Calls PyOS_InputHook dropping the GIL first
17486
[clinic start generated code]*/
17487
17488
static PyObject *
17489
os__inputhook_impl(PyObject *module)
17490
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17491
0
{
17492
0
     int result = 0;
17493
0
     if (PyOS_InputHook) {
17494
0
         Py_BEGIN_ALLOW_THREADS;
17495
0
         result = PyOS_InputHook();
17496
0
         Py_END_ALLOW_THREADS;
17497
0
     }
17498
0
     return PyLong_FromLong(result);
17499
0
}
17500
17501
/*[clinic input]
17502
os._is_inputhook_installed
17503
17504
Checks if PyOS_InputHook is set
17505
[clinic start generated code]*/
17506
17507
static PyObject *
17508
os__is_inputhook_installed_impl(PyObject *module)
17509
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17510
0
{
17511
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17512
0
}
17513
17514
/*[clinic input]
17515
os._create_environ
17516
17517
Create the environment dictionary.
17518
[clinic start generated code]*/
17519
17520
static PyObject *
17521
os__create_environ_impl(PyObject *module)
17522
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17523
0
{
17524
0
    return convertenviron();
17525
0
}
17526
17527
17528
#ifdef __EMSCRIPTEN__
17529
/*[clinic input]
17530
os._emscripten_debugger
17531
17532
Create a breakpoint for the JavaScript debugger. Emscripten only.
17533
[clinic start generated code]*/
17534
17535
static PyObject *
17536
os__emscripten_debugger_impl(PyObject *module)
17537
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17538
{
17539
    emscripten_debugger();
17540
    Py_RETURN_NONE;
17541
}
17542
17543
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17544
    console.warn(UTF8ToString(arg));
17545
});
17546
17547
/*[clinic input]
17548
os._emscripten_log
17549
   arg: str
17550
17551
Log something to the JS console. Emscripten only.
17552
[clinic start generated code]*/
17553
17554
static PyObject *
17555
os__emscripten_log_impl(PyObject *module, const char *arg)
17556
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17557
{
17558
    emscripten_log_impl_js(arg);
17559
    Py_RETURN_NONE;
17560
}
17561
#endif /* __EMSCRIPTEN__ */
17562
17563
17564
static PyMethodDef posix_methods[] = {
17565
    OS_STAT_METHODDEF
17566
    OS_STATX_METHODDEF
17567
    OS_ACCESS_METHODDEF
17568
    OS_TTYNAME_METHODDEF
17569
    OS_CHDIR_METHODDEF
17570
    OS_CHFLAGS_METHODDEF
17571
    OS_CHMOD_METHODDEF
17572
    OS_FCHMOD_METHODDEF
17573
    OS_LCHMOD_METHODDEF
17574
    OS_CHOWN_METHODDEF
17575
    OS_FCHOWN_METHODDEF
17576
    OS_LCHOWN_METHODDEF
17577
    OS_LCHFLAGS_METHODDEF
17578
    OS_CHROOT_METHODDEF
17579
    OS_CTERMID_METHODDEF
17580
    OS_GETCWD_METHODDEF
17581
    OS_GETCWDB_METHODDEF
17582
    OS_LINK_METHODDEF
17583
    OS_LISTDIR_METHODDEF
17584
    OS_LISTDRIVES_METHODDEF
17585
    OS_LISTMOUNTS_METHODDEF
17586
    OS_LISTVOLUMES_METHODDEF
17587
    OS_LSTAT_METHODDEF
17588
    OS_MKDIR_METHODDEF
17589
    OS_NICE_METHODDEF
17590
    OS_GETPRIORITY_METHODDEF
17591
    OS_SETPRIORITY_METHODDEF
17592
    OS_POSIX_SPAWN_METHODDEF
17593
    OS_POSIX_SPAWNP_METHODDEF
17594
    OS_READLINK_METHODDEF
17595
    OS_COPY_FILE_RANGE_METHODDEF
17596
    OS_SPLICE_METHODDEF
17597
    OS_RENAME_METHODDEF
17598
    OS_REPLACE_METHODDEF
17599
    OS_RMDIR_METHODDEF
17600
    OS_SYMLINK_METHODDEF
17601
    OS_SYSTEM_METHODDEF
17602
    OS_UMASK_METHODDEF
17603
    OS_UNAME_METHODDEF
17604
    OS_UNLINK_METHODDEF
17605
    OS_REMOVE_METHODDEF
17606
    OS_UTIME_METHODDEF
17607
    OS_TIMES_METHODDEF
17608
    OS__EXIT_METHODDEF
17609
    OS__FCOPYFILE_METHODDEF
17610
    OS_EXECV_METHODDEF
17611
    OS_EXECVE_METHODDEF
17612
    OS_SPAWNV_METHODDEF
17613
    OS_SPAWNVE_METHODDEF
17614
    OS_FORK1_METHODDEF
17615
    OS_FORK_METHODDEF
17616
    OS_REGISTER_AT_FORK_METHODDEF
17617
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17618
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17619
    OS_SCHED_GETPARAM_METHODDEF
17620
    OS_SCHED_GETSCHEDULER_METHODDEF
17621
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17622
    OS_SCHED_SETPARAM_METHODDEF
17623
    OS_SCHED_SETSCHEDULER_METHODDEF
17624
    OS_SCHED_YIELD_METHODDEF
17625
    OS_SCHED_SETAFFINITY_METHODDEF
17626
    OS_SCHED_GETAFFINITY_METHODDEF
17627
    OS_POSIX_OPENPT_METHODDEF
17628
    OS_GRANTPT_METHODDEF
17629
    OS_UNLOCKPT_METHODDEF
17630
    OS_PTSNAME_METHODDEF
17631
    OS_OPENPTY_METHODDEF
17632
    OS_LOGIN_TTY_METHODDEF
17633
    OS_FORKPTY_METHODDEF
17634
    OS_GETEGID_METHODDEF
17635
    OS_GETEUID_METHODDEF
17636
    OS_GETGID_METHODDEF
17637
    OS_GETGROUPLIST_METHODDEF
17638
    OS_GETGROUPS_METHODDEF
17639
    OS_GETPID_METHODDEF
17640
    OS_GETPGRP_METHODDEF
17641
    OS_GETPPID_METHODDEF
17642
    OS_GETUID_METHODDEF
17643
    OS_GETLOGIN_METHODDEF
17644
    OS_KILL_METHODDEF
17645
    OS_KILLPG_METHODDEF
17646
    OS_PLOCK_METHODDEF
17647
    OS_STARTFILE_METHODDEF
17648
    OS_SETUID_METHODDEF
17649
    OS_SETEUID_METHODDEF
17650
    OS_SETREUID_METHODDEF
17651
    OS_SETGID_METHODDEF
17652
    OS_SETEGID_METHODDEF
17653
    OS_SETREGID_METHODDEF
17654
    OS_SETGROUPS_METHODDEF
17655
    OS_INITGROUPS_METHODDEF
17656
    OS_GETPGID_METHODDEF
17657
    OS_SETPGRP_METHODDEF
17658
    OS_WAIT_METHODDEF
17659
    OS_WAIT3_METHODDEF
17660
    OS_WAIT4_METHODDEF
17661
    OS_WAITID_METHODDEF
17662
    OS_WAITPID_METHODDEF
17663
    OS_PIDFD_OPEN_METHODDEF
17664
    OS_PIDFD_GETFD_METHODDEF
17665
    OS_GETSID_METHODDEF
17666
    OS_SETSID_METHODDEF
17667
    OS_SETPGID_METHODDEF
17668
    OS_TCGETPGRP_METHODDEF
17669
    OS_TCSETPGRP_METHODDEF
17670
    OS_OPEN_METHODDEF
17671
    OS_CLOSE_METHODDEF
17672
    OS_CLOSERANGE_METHODDEF
17673
    OS_DEVICE_ENCODING_METHODDEF
17674
    OS_DUP_METHODDEF
17675
    OS_DUP2_METHODDEF
17676
    OS_LOCKF_METHODDEF
17677
    OS_LSEEK_METHODDEF
17678
    OS_READ_METHODDEF
17679
    OS_READINTO_METHODDEF
17680
    OS_READV_METHODDEF
17681
    OS_PREAD_METHODDEF
17682
    OS_PREADV_METHODDEF
17683
    OS_WRITE_METHODDEF
17684
    OS_WRITEV_METHODDEF
17685
    OS_PWRITE_METHODDEF
17686
    OS_PWRITEV_METHODDEF
17687
    OS_SENDFILE_METHODDEF
17688
    OS_FSTAT_METHODDEF
17689
    OS_ISATTY_METHODDEF
17690
    OS_PIPE_METHODDEF
17691
    OS_PIPE2_METHODDEF
17692
    OS_MKFIFO_METHODDEF
17693
    OS_MKNOD_METHODDEF
17694
    OS_MAJOR_METHODDEF
17695
    OS_MINOR_METHODDEF
17696
    OS_MAKEDEV_METHODDEF
17697
    OS_FTRUNCATE_METHODDEF
17698
    OS_TRUNCATE_METHODDEF
17699
    OS_POSIX_FALLOCATE_METHODDEF
17700
    OS_POSIX_FADVISE_METHODDEF
17701
    OS_PUTENV_METHODDEF
17702
    OS_UNSETENV_METHODDEF
17703
    OS__CLEARENV_METHODDEF
17704
    OS_STRERROR_METHODDEF
17705
    OS_FCHDIR_METHODDEF
17706
    OS_FSYNC_METHODDEF
17707
    OS_SYNC_METHODDEF
17708
    OS_FDATASYNC_METHODDEF
17709
    OS_WCOREDUMP_METHODDEF
17710
    OS_WIFCONTINUED_METHODDEF
17711
    OS_WIFSTOPPED_METHODDEF
17712
    OS_WIFSIGNALED_METHODDEF
17713
    OS_WIFEXITED_METHODDEF
17714
    OS_WEXITSTATUS_METHODDEF
17715
    OS_WTERMSIG_METHODDEF
17716
    OS_WSTOPSIG_METHODDEF
17717
    OS_FSTATVFS_METHODDEF
17718
    OS_STATVFS_METHODDEF
17719
    OS_CONFSTR_METHODDEF
17720
    OS_SYSCONF_METHODDEF
17721
    OS_FPATHCONF_METHODDEF
17722
    OS_PATHCONF_METHODDEF
17723
    OS_ABORT_METHODDEF
17724
    OS__GETFULLPATHNAME_METHODDEF
17725
    OS__GETDISKUSAGE_METHODDEF
17726
    OS__GETFINALPATHNAME_METHODDEF
17727
    OS__FINDFIRSTFILE_METHODDEF
17728
    OS__GETVOLUMEPATHNAME_METHODDEF
17729
    OS__PATH_SPLITROOT_METHODDEF
17730
    OS__PATH_SPLITROOT_EX_METHODDEF
17731
    OS__PATH_NORMPATH_METHODDEF
17732
    OS_GETLOADAVG_METHODDEF
17733
    OS_URANDOM_METHODDEF
17734
    OS_SETRESUID_METHODDEF
17735
    OS_SETRESGID_METHODDEF
17736
    OS_GETRESUID_METHODDEF
17737
    OS_GETRESGID_METHODDEF
17738
17739
    OS_GETXATTR_METHODDEF
17740
    OS_SETXATTR_METHODDEF
17741
    OS_REMOVEXATTR_METHODDEF
17742
    OS_LISTXATTR_METHODDEF
17743
17744
    OS_GET_TERMINAL_SIZE_METHODDEF
17745
    OS_CPU_COUNT_METHODDEF
17746
    OS_GET_INHERITABLE_METHODDEF
17747
    OS_SET_INHERITABLE_METHODDEF
17748
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17749
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17750
    OS_GET_BLOCKING_METHODDEF
17751
    OS_SET_BLOCKING_METHODDEF
17752
    OS_SCANDIR_METHODDEF
17753
    OS_FSPATH_METHODDEF
17754
    OS_GETRANDOM_METHODDEF
17755
    OS_MEMFD_CREATE_METHODDEF
17756
    OS_EVENTFD_METHODDEF
17757
    OS_EVENTFD_READ_METHODDEF
17758
    OS_EVENTFD_WRITE_METHODDEF
17759
    OS__ADD_DLL_DIRECTORY_METHODDEF
17760
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17761
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17762
    OS_SETNS_METHODDEF
17763
    OS_UNSHARE_METHODDEF
17764
    OS_TIMERFD_CREATE_METHODDEF
17765
    OS_TIMERFD_SETTIME_METHODDEF
17766
    OS_TIMERFD_SETTIME_NS_METHODDEF
17767
    OS_TIMERFD_GETTIME_METHODDEF
17768
    OS_TIMERFD_GETTIME_NS_METHODDEF
17769
17770
    OS__PATH_ISDEVDRIVE_METHODDEF
17771
    OS__PATH_ISDIR_METHODDEF
17772
    OS__PATH_ISFILE_METHODDEF
17773
    OS__PATH_ISLINK_METHODDEF
17774
    OS__PATH_ISJUNCTION_METHODDEF
17775
    OS__PATH_EXISTS_METHODDEF
17776
    OS__PATH_LEXISTS_METHODDEF
17777
17778
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17779
    OS__INPUTHOOK_METHODDEF
17780
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17781
    OS__CREATE_ENVIRON_METHODDEF
17782
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17783
    OS__EMSCRIPTEN_LOG_METHODDEF
17784
    {NULL,              NULL}            /* Sentinel */
17785
};
17786
17787
static int
17788
all_ins(PyObject *m)
17789
37
{
17790
37
#ifdef F_OK
17791
37
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17792
37
#endif
17793
37
#ifdef R_OK
17794
37
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17795
37
#endif
17796
37
#ifdef W_OK
17797
37
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17798
37
#endif
17799
37
#ifdef X_OK
17800
37
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17801
37
#endif
17802
37
#ifdef NGROUPS_MAX
17803
37
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17804
37
#endif
17805
37
#ifdef TMP_MAX
17806
37
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17807
37
#endif
17808
37
#ifdef WCONTINUED
17809
37
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17810
37
#endif
17811
37
#ifdef WNOHANG
17812
37
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17813
37
#endif
17814
37
#ifdef WUNTRACED
17815
37
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17816
37
#endif
17817
37
#ifdef O_RDONLY
17818
37
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17819
37
#endif
17820
37
#ifdef O_WRONLY
17821
37
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17822
37
#endif
17823
37
#ifdef O_RDWR
17824
37
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17825
37
#endif
17826
37
#ifdef O_NDELAY
17827
37
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17828
37
#endif
17829
37
#ifdef O_NONBLOCK
17830
37
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17831
37
#endif
17832
37
#ifdef O_APPEND
17833
37
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17834
37
#endif
17835
37
#ifdef O_DSYNC
17836
37
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17837
37
#endif
17838
37
#ifdef O_RSYNC
17839
37
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17840
37
#endif
17841
37
#ifdef O_SYNC
17842
37
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17843
37
#endif
17844
37
#ifdef O_NOCTTY
17845
37
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17846
37
#endif
17847
37
#ifdef O_CREAT
17848
37
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17849
37
#endif
17850
37
#ifdef O_EXCL
17851
37
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17852
37
#endif
17853
37
#ifdef O_TRUNC
17854
37
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17855
37
#endif
17856
#ifdef O_BINARY
17857
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17858
#endif
17859
#ifdef O_TEXT
17860
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17861
#endif
17862
#ifdef O_XATTR
17863
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17864
#endif
17865
37
#ifdef O_LARGEFILE
17866
37
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17867
37
#endif
17868
37
#ifndef __GNU__
17869
#ifdef O_SHLOCK
17870
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17871
#endif
17872
#ifdef O_EXLOCK
17873
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17874
#endif
17875
37
#endif
17876
#ifdef O_EXEC
17877
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17878
#endif
17879
#ifdef O_SEARCH
17880
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17881
#endif
17882
37
#ifdef O_PATH
17883
37
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17884
37
#endif
17885
#ifdef O_TTY_INIT
17886
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17887
#endif
17888
37
#ifdef O_TMPFILE
17889
37
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17890
37
#endif
17891
37
#ifdef PRIO_PROCESS
17892
37
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17893
37
#endif
17894
37
#ifdef PRIO_PGRP
17895
37
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17896
37
#endif
17897
37
#ifdef PRIO_USER
17898
37
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17899
37
#endif
17900
#ifdef PRIO_DARWIN_THREAD
17901
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17902
#endif
17903
#ifdef PRIO_DARWIN_PROCESS
17904
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17905
#endif
17906
#ifdef PRIO_DARWIN_BG
17907
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17908
#endif
17909
#ifdef PRIO_DARWIN_NONUI
17910
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17911
#endif
17912
37
#ifdef O_CLOEXEC
17913
37
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17914
37
#endif
17915
37
#ifdef O_ACCMODE
17916
37
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17917
37
#endif
17918
#ifdef O_EVTONLY
17919
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17920
#endif
17921
37
#ifdef O_FSYNC
17922
37
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17923
37
#endif
17924
#ifdef O_SYMLINK
17925
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17926
#endif
17927
17928
37
#ifdef SEEK_HOLE
17929
37
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17930
37
#endif
17931
37
#ifdef SEEK_DATA
17932
37
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17933
37
#endif
17934
17935
/* MS Windows */
17936
#ifdef O_NOINHERIT
17937
    /* Don't inherit in child processes. */
17938
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17939
#endif
17940
#ifdef _O_SHORT_LIVED
17941
    /* Optimize for short life (keep in memory). */
17942
    /* MS forgot to define this one with a non-underscore form too. */
17943
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17944
#endif
17945
#ifdef O_TEMPORARY
17946
    /* Automatically delete when last handle is closed. */
17947
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17948
#endif
17949
#ifdef O_RANDOM
17950
    /* Optimize for random access. */
17951
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17952
#endif
17953
#ifdef O_SEQUENTIAL
17954
    /* Optimize for sequential access. */
17955
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17956
#endif
17957
17958
/* GNU extensions. */
17959
37
#ifdef O_ASYNC
17960
    /* Send a SIGIO signal whenever input or output
17961
       becomes available on file descriptor */
17962
37
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17963
37
#endif
17964
37
#ifdef O_DIRECT
17965
    /* Direct disk access. */
17966
37
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17967
37
#endif
17968
37
#ifdef O_DIRECTORY
17969
    /* Must be a directory.      */
17970
37
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17971
37
#endif
17972
37
#ifdef O_NOFOLLOW
17973
    /* Do not follow links.      */
17974
37
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17975
37
#endif
17976
#ifdef O_NOFOLLOW_ANY
17977
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17978
#endif
17979
#ifdef O_NOLINKS
17980
    /* Fails if link count of the named file is greater than 1 */
17981
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17982
#endif
17983
37
#ifdef O_NOATIME
17984
    /* Do not update the access time. */
17985
37
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17986
37
#endif
17987
17988
    /* These come from sysexits.h */
17989
37
#ifdef EX_OK
17990
37
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17991
37
#endif /* EX_OK */
17992
37
#ifdef EX_USAGE
17993
37
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17994
37
#endif /* EX_USAGE */
17995
37
#ifdef EX_DATAERR
17996
37
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17997
37
#endif /* EX_DATAERR */
17998
37
#ifdef EX_NOINPUT
17999
37
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
18000
37
#endif /* EX_NOINPUT */
18001
37
#ifdef EX_NOUSER
18002
37
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
18003
37
#endif /* EX_NOUSER */
18004
37
#ifdef EX_NOHOST
18005
37
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
18006
37
#endif /* EX_NOHOST */
18007
37
#ifdef EX_UNAVAILABLE
18008
37
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
18009
37
#endif /* EX_UNAVAILABLE */
18010
37
#ifdef EX_SOFTWARE
18011
37
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
18012
37
#endif /* EX_SOFTWARE */
18013
37
#ifdef EX_OSERR
18014
37
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
18015
37
#endif /* EX_OSERR */
18016
37
#ifdef EX_OSFILE
18017
37
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
18018
37
#endif /* EX_OSFILE */
18019
37
#ifdef EX_CANTCREAT
18020
37
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
18021
37
#endif /* EX_CANTCREAT */
18022
37
#ifdef EX_IOERR
18023
37
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
18024
37
#endif /* EX_IOERR */
18025
37
#ifdef EX_TEMPFAIL
18026
37
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
18027
37
#endif /* EX_TEMPFAIL */
18028
37
#ifdef EX_PROTOCOL
18029
37
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
18030
37
#endif /* EX_PROTOCOL */
18031
37
#ifdef EX_NOPERM
18032
37
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
18033
37
#endif /* EX_NOPERM */
18034
37
#ifdef EX_CONFIG
18035
37
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
18036
37
#endif /* EX_CONFIG */
18037
#ifdef EX_NOTFOUND
18038
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
18039
#endif /* EX_NOTFOUND */
18040
18041
    /* statvfs */
18042
37
#ifdef ST_RDONLY
18043
37
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
18044
37
#endif /* ST_RDONLY */
18045
37
#ifdef ST_NOSUID
18046
37
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
18047
37
#endif /* ST_NOSUID */
18048
18049
       /* GNU extensions */
18050
37
#ifdef ST_NODEV
18051
37
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
18052
37
#endif /* ST_NODEV */
18053
37
#ifdef ST_NOEXEC
18054
37
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
18055
37
#endif /* ST_NOEXEC */
18056
37
#ifdef ST_SYNCHRONOUS
18057
37
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
18058
37
#endif /* ST_SYNCHRONOUS */
18059
37
#ifdef ST_MANDLOCK
18060
37
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
18061
37
#endif /* ST_MANDLOCK */
18062
37
#ifdef ST_WRITE
18063
37
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
18064
37
#endif /* ST_WRITE */
18065
37
#ifdef ST_APPEND
18066
37
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
18067
37
#endif /* ST_APPEND */
18068
37
#ifdef ST_NOATIME
18069
37
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
18070
37
#endif /* ST_NOATIME */
18071
37
#ifdef ST_NODIRATIME
18072
37
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
18073
37
#endif /* ST_NODIRATIME */
18074
37
#ifdef ST_RELATIME
18075
37
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18076
37
#endif /* ST_RELATIME */
18077
18078
    /* FreeBSD sendfile() constants */
18079
#ifdef SF_NODISKIO
18080
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18081
#endif
18082
    /* is obsolete since the 11.x release */
18083
#ifdef SF_MNOWAIT
18084
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18085
#endif
18086
#ifdef SF_SYNC
18087
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18088
#endif
18089
#ifdef SF_NOCACHE
18090
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18091
#endif
18092
18093
37
#ifdef TFD_NONBLOCK
18094
37
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18095
37
#endif
18096
37
#ifdef TFD_CLOEXEC
18097
37
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18098
37
#endif
18099
37
#ifdef TFD_TIMER_ABSTIME
18100
37
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18101
37
#endif
18102
37
#ifdef TFD_TIMER_CANCEL_ON_SET
18103
37
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18104
37
#endif
18105
18106
    /* constants for posix_fadvise */
18107
37
#ifdef POSIX_FADV_NORMAL
18108
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18109
37
#endif
18110
37
#ifdef POSIX_FADV_SEQUENTIAL
18111
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18112
37
#endif
18113
37
#ifdef POSIX_FADV_RANDOM
18114
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18115
37
#endif
18116
37
#ifdef POSIX_FADV_NOREUSE
18117
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18118
37
#endif
18119
37
#ifdef POSIX_FADV_WILLNEED
18120
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18121
37
#endif
18122
37
#ifdef POSIX_FADV_DONTNEED
18123
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18124
37
#endif
18125
18126
    /* constants for waitid */
18127
37
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18128
37
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18129
37
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18130
37
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18131
37
#ifdef P_PIDFD
18132
37
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18133
37
#endif
18134
#ifdef PIDFD_NONBLOCK
18135
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18136
#endif
18137
37
#endif
18138
37
#ifdef WEXITED
18139
37
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18140
37
#endif
18141
37
#ifdef WNOWAIT
18142
37
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18143
37
#endif
18144
37
#ifdef WSTOPPED
18145
37
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18146
37
#endif
18147
37
#ifdef CLD_EXITED
18148
37
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18149
37
#endif
18150
37
#ifdef CLD_KILLED
18151
37
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18152
37
#endif
18153
37
#ifdef CLD_DUMPED
18154
37
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18155
37
#endif
18156
37
#ifdef CLD_TRAPPED
18157
37
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18158
37
#endif
18159
37
#ifdef CLD_STOPPED
18160
37
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18161
37
#endif
18162
37
#ifdef CLD_CONTINUED
18163
37
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18164
37
#endif
18165
18166
    /* constants for lockf */
18167
37
#ifdef F_LOCK
18168
37
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18169
37
#endif
18170
37
#ifdef F_TLOCK
18171
37
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18172
37
#endif
18173
37
#ifdef F_ULOCK
18174
37
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18175
37
#endif
18176
37
#ifdef F_TEST
18177
37
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18178
37
#endif
18179
18180
37
#ifdef RWF_DSYNC
18181
37
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18182
37
#endif
18183
37
#ifdef RWF_HIPRI
18184
37
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18185
37
#endif
18186
37
#ifdef RWF_SYNC
18187
37
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18188
37
#endif
18189
37
#ifdef RWF_NOWAIT
18190
37
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18191
37
#endif
18192
#ifdef RWF_DONTCACHE
18193
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18194
#endif
18195
#ifdef RWF_ATOMIC
18196
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18197
#endif
18198
37
#ifdef RWF_APPEND
18199
37
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18200
37
#endif
18201
18202
/* constants for splice */
18203
37
#if defined(HAVE_SPLICE) && defined(__linux__)
18204
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18205
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18206
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18207
37
#endif
18208
18209
/* constants for posix_spawn */
18210
37
#ifdef HAVE_POSIX_SPAWN
18211
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18212
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18213
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18214
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18215
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18216
#endif
18217
37
#endif
18218
18219
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18220
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18221
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18222
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18223
#endif
18224
#ifdef HAVE_SPAWNV
18225
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18226
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18227
#endif
18228
18229
37
#ifdef HAVE_SCHED_H
18230
37
#ifdef SCHED_OTHER
18231
37
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18232
37
#endif
18233
37
#ifdef SCHED_DEADLINE
18234
37
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18235
37
#endif
18236
37
#ifdef SCHED_FIFO
18237
37
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18238
37
#endif
18239
37
#ifdef SCHED_NORMAL
18240
37
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18241
37
#endif
18242
37
#ifdef SCHED_RR
18243
37
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18244
37
#endif
18245
#ifdef SCHED_SPORADIC
18246
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18247
#endif
18248
37
#ifdef SCHED_BATCH
18249
37
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18250
37
#endif
18251
37
#ifdef SCHED_IDLE
18252
37
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18253
37
#endif
18254
37
#ifdef SCHED_RESET_ON_FORK
18255
37
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18256
37
#endif
18257
#ifdef SCHED_SYS
18258
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18259
#endif
18260
#ifdef SCHED_IA
18261
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18262
#endif
18263
#ifdef SCHED_FSS
18264
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18265
#endif
18266
#ifdef SCHED_FX
18267
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18268
#endif
18269
18270
/* constants for namespaces */
18271
37
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18272
37
#ifdef CLONE_FS
18273
37
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18274
37
#endif
18275
37
#ifdef CLONE_FILES
18276
37
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18277
37
#endif
18278
37
#ifdef CLONE_NEWNS
18279
37
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18280
37
#endif
18281
37
#ifdef CLONE_NEWCGROUP
18282
37
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18283
37
#endif
18284
37
#ifdef CLONE_NEWUTS
18285
37
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18286
37
#endif
18287
37
#ifdef CLONE_NEWIPC
18288
37
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18289
37
#endif
18290
37
#ifdef CLONE_NEWUSER
18291
37
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18292
37
#endif
18293
37
#ifdef CLONE_NEWPID
18294
37
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18295
37
#endif
18296
37
#ifdef CLONE_NEWNET
18297
37
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18298
37
#endif
18299
#ifdef CLONE_NEWTIME
18300
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18301
#endif
18302
37
#ifdef CLONE_SYSVSEM
18303
37
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18304
37
#endif
18305
37
#ifdef CLONE_THREAD
18306
37
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18307
37
#endif
18308
37
#ifdef CLONE_SIGHAND
18309
37
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18310
37
#endif
18311
37
#ifdef CLONE_VM
18312
37
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18313
37
#endif
18314
37
#endif
18315
18316
37
#endif
18317
18318
37
#ifdef USE_XATTRS
18319
37
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18320
37
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18321
37
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18322
37
#endif
18323
18324
37
#if HAVE_DECL_RTLD_LAZY
18325
37
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18326
37
#endif
18327
37
#if HAVE_DECL_RTLD_NOW
18328
37
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18329
37
#endif
18330
37
#if HAVE_DECL_RTLD_GLOBAL
18331
37
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18332
37
#endif
18333
37
#if HAVE_DECL_RTLD_LOCAL
18334
37
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18335
37
#endif
18336
37
#if HAVE_DECL_RTLD_NODELETE
18337
37
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18338
37
#endif
18339
37
#if HAVE_DECL_RTLD_NOLOAD
18340
37
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18341
37
#endif
18342
37
#if HAVE_DECL_RTLD_DEEPBIND
18343
37
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18344
37
#endif
18345
#if HAVE_DECL_RTLD_MEMBER
18346
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18347
#endif
18348
18349
37
#ifdef HAVE_GETRANDOM_SYSCALL
18350
37
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18351
37
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18352
37
#endif
18353
37
#ifdef HAVE_MEMFD_CREATE
18354
37
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18355
37
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18356
37
#ifdef MFD_HUGETLB
18357
37
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18358
37
#endif
18359
37
#ifdef MFD_HUGE_SHIFT
18360
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18361
37
#endif
18362
37
#ifdef MFD_HUGE_MASK
18363
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18364
37
#endif
18365
37
#ifdef MFD_HUGE_64KB
18366
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18367
37
#endif
18368
37
#ifdef MFD_HUGE_512KB
18369
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18370
37
#endif
18371
37
#ifdef MFD_HUGE_1MB
18372
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18373
37
#endif
18374
37
#ifdef MFD_HUGE_2MB
18375
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18376
37
#endif
18377
37
#ifdef MFD_HUGE_8MB
18378
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18379
37
#endif
18380
37
#ifdef MFD_HUGE_16MB
18381
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18382
37
#endif
18383
37
#ifdef MFD_HUGE_32MB
18384
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18385
37
#endif
18386
37
#ifdef MFD_HUGE_256MB
18387
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18388
37
#endif
18389
37
#ifdef MFD_HUGE_512MB
18390
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18391
37
#endif
18392
37
#ifdef MFD_HUGE_1GB
18393
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18394
37
#endif
18395
37
#ifdef MFD_HUGE_2GB
18396
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18397
37
#endif
18398
37
#ifdef MFD_HUGE_16GB
18399
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18400
37
#endif
18401
37
#endif /* HAVE_MEMFD_CREATE */
18402
18403
37
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18404
37
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18405
37
#ifdef EFD_NONBLOCK
18406
37
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18407
37
#endif
18408
37
#ifdef EFD_SEMAPHORE
18409
37
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18410
37
#endif
18411
37
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18412
18413
37
#ifdef NODEV
18414
37
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18415
37
#endif
18416
18417
37
#ifdef AT_NO_AUTOMOUNT
18418
37
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18419
37
#endif
18420
18421
37
#ifdef HAVE_STATX
18422
37
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18423
37
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18424
37
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18425
37
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18426
37
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18427
37
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18428
37
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18429
37
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18430
37
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18431
37
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18432
37
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18433
37
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18434
37
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18435
#ifdef STATX_MNT_ID
18436
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18437
#endif
18438
#ifdef STATX_DIOALIGN
18439
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18440
#endif
18441
#ifdef STATX_MNT_ID_UNIQUE
18442
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18443
#endif
18444
#ifdef STATX_SUBVOL
18445
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18446
#endif
18447
#ifdef STATX_WRITE_ATOMIC
18448
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18449
#endif
18450
#ifdef STATX_DIO_READ_ALIGN
18451
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18452
#endif
18453
    /* STATX_ALL intentionally omitted because it is deprecated */
18454
37
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18455
37
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18456
37
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18457
    /* STATX_ATTR_* constants are in the stat module */
18458
37
#endif /* HAVE_STATX */
18459
18460
#if defined(__APPLE__)
18461
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18462
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18463
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18464
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18465
#endif
18466
18467
#ifdef MS_WINDOWS
18468
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18469
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18470
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18471
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18472
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18473
#endif
18474
18475
37
    return 0;
18476
37
}
18477
18478
18479
18480
#define PROBE(name, test) \
18481
   static int name(void)  \
18482
629
   {                      \
18483
629
      if (test) {        \
18484
629
          return 1;       \
18485
629
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
629
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_futimens
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_linkat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_openat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_renameat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18482
37
   {                      \
18483
37
      if (test) {        \
18484
37
          return 1;       \
18485
37
      } else {            \
18486
0
          return 0;       \
18487
0
      }                   \
18488
37
   }
18489
18490
#ifdef HAVE_FSTATAT
18491
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18492
#endif
18493
18494
#ifdef HAVE_FACCESSAT
18495
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18496
#endif
18497
18498
#ifdef HAVE_FCHMODAT
18499
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18500
#endif
18501
18502
#ifdef HAVE_FCHOWNAT
18503
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18504
#endif
18505
18506
#ifdef HAVE_LINKAT
18507
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18508
#endif
18509
18510
#ifdef HAVE_FDOPENDIR
18511
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18512
#endif
18513
18514
#ifdef HAVE_MKDIRAT
18515
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18516
#endif
18517
18518
#ifdef HAVE_MKFIFOAT
18519
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18520
#endif
18521
18522
#ifdef HAVE_MKNODAT
18523
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18524
#endif
18525
18526
#ifdef HAVE_RENAMEAT
18527
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18528
#endif
18529
18530
#ifdef HAVE_UNLINKAT
18531
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18532
#endif
18533
18534
#ifdef HAVE_OPENAT
18535
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18536
#endif
18537
18538
#ifdef HAVE_READLINKAT
18539
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18540
#endif
18541
18542
#ifdef HAVE_SYMLINKAT
18543
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18544
#endif
18545
18546
#ifdef HAVE_FUTIMENS
18547
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18548
#endif
18549
18550
#ifdef HAVE_UTIMENSAT
18551
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18552
#endif
18553
18554
#ifdef HAVE_PTSNAME_R
18555
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18556
#endif
18557
18558
18559
18560
static const struct have_function {
18561
    const char * const label;
18562
    int (*probe)(void);
18563
} have_functions[] = {
18564
18565
#ifdef HAVE_EVENTFD
18566
    {"HAVE_EVENTFD", NULL},
18567
#endif
18568
18569
#ifdef HAVE_TIMERFD_CREATE
18570
    {"HAVE_TIMERFD_CREATE", NULL},
18571
#endif
18572
18573
#ifdef HAVE_FACCESSAT
18574
    { "HAVE_FACCESSAT", probe_faccessat },
18575
#endif
18576
18577
#ifdef HAVE_FCHDIR
18578
    { "HAVE_FCHDIR", NULL },
18579
#endif
18580
18581
#ifdef HAVE_FCHMOD
18582
    { "HAVE_FCHMOD", NULL },
18583
#endif
18584
18585
#ifdef HAVE_FCHMODAT
18586
    { "HAVE_FCHMODAT", probe_fchmodat },
18587
#endif
18588
18589
#ifdef HAVE_FCHOWN
18590
    { "HAVE_FCHOWN", NULL },
18591
#endif
18592
18593
#ifdef HAVE_FCHOWNAT
18594
    { "HAVE_FCHOWNAT", probe_fchownat },
18595
#endif
18596
18597
#ifdef HAVE_FEXECVE
18598
    { "HAVE_FEXECVE", NULL },
18599
#endif
18600
18601
#ifdef HAVE_FDOPENDIR
18602
    { "HAVE_FDOPENDIR", probe_fdopendir },
18603
#endif
18604
18605
#ifdef HAVE_FPATHCONF
18606
    { "HAVE_FPATHCONF", NULL },
18607
#endif
18608
18609
#ifdef HAVE_FSTATAT
18610
    { "HAVE_FSTATAT", probe_fstatat },
18611
#endif
18612
18613
#ifdef HAVE_FSTATVFS
18614
    { "HAVE_FSTATVFS", NULL },
18615
#endif
18616
18617
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18618
    { "HAVE_FTRUNCATE", NULL },
18619
#endif
18620
18621
#ifdef HAVE_FUTIMENS
18622
    { "HAVE_FUTIMENS", probe_futimens },
18623
#endif
18624
18625
#ifdef HAVE_FUTIMES
18626
    { "HAVE_FUTIMES", NULL },
18627
#endif
18628
18629
#ifdef HAVE_FUTIMESAT
18630
    { "HAVE_FUTIMESAT", NULL },
18631
#endif
18632
18633
#ifdef HAVE_LINKAT
18634
    { "HAVE_LINKAT", probe_linkat },
18635
#endif
18636
18637
#ifdef HAVE_LCHFLAGS
18638
    { "HAVE_LCHFLAGS", NULL },
18639
#endif
18640
18641
#ifdef HAVE_LCHMOD
18642
    { "HAVE_LCHMOD", NULL },
18643
#endif
18644
18645
#ifdef HAVE_LCHOWN
18646
    { "HAVE_LCHOWN", NULL },
18647
#endif
18648
18649
#ifdef HAVE_LSTAT
18650
    { "HAVE_LSTAT", NULL },
18651
#endif
18652
18653
#ifdef HAVE_LUTIMES
18654
    { "HAVE_LUTIMES", NULL },
18655
#endif
18656
18657
#ifdef HAVE_MEMFD_CREATE
18658
    { "HAVE_MEMFD_CREATE", NULL },
18659
#endif
18660
18661
#ifdef HAVE_MKDIRAT
18662
    { "HAVE_MKDIRAT", probe_mkdirat },
18663
#endif
18664
18665
#ifdef HAVE_MKFIFOAT
18666
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18667
#endif
18668
18669
#ifdef HAVE_MKNODAT
18670
    { "HAVE_MKNODAT", probe_mknodat },
18671
#endif
18672
18673
#ifdef HAVE_OPENAT
18674
    { "HAVE_OPENAT", probe_openat },
18675
#endif
18676
18677
#ifdef HAVE_READLINKAT
18678
    { "HAVE_READLINKAT", probe_readlinkat },
18679
#endif
18680
18681
#ifdef HAVE_RENAMEAT
18682
    { "HAVE_RENAMEAT", probe_renameat },
18683
#endif
18684
18685
#ifdef HAVE_SYMLINKAT
18686
    { "HAVE_SYMLINKAT", probe_symlinkat },
18687
#endif
18688
18689
#ifdef HAVE_UNLINKAT
18690
    { "HAVE_UNLINKAT", probe_unlinkat },
18691
#endif
18692
18693
#ifdef HAVE_UTIMENSAT
18694
    { "HAVE_UTIMENSAT", probe_utimensat },
18695
#endif
18696
18697
#ifdef HAVE_PTSNAME_R
18698
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18699
#endif
18700
18701
#ifdef MS_WINDOWS
18702
    { "MS_WINDOWS", NULL },
18703
#endif
18704
18705
    { NULL, NULL }
18706
};
18707
18708
18709
static int
18710
posixmodule_exec(PyObject *m)
18711
37
{
18712
37
    _posixstate *state = get_posix_state(m);
18713
18714
37
#if defined(HAVE_PWRITEV)
18715
37
    if (HAVE_PWRITEV_RUNTIME) {} else {
18716
0
        PyObject* dct = PyModule_GetDict(m);
18717
18718
0
        if (dct == NULL) {
18719
0
            return -1;
18720
0
        }
18721
18722
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18723
0
            return -1;
18724
0
        }
18725
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18726
0
            return -1;
18727
0
        }
18728
0
    }
18729
37
#endif
18730
18731
37
#ifdef HAVE_STATX
18732
37
    if (statx == NULL) {
18733
0
        PyObject* dct = PyModule_GetDict(m);
18734
0
        if (dct == NULL) {
18735
0
            return -1;
18736
0
        }
18737
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18738
0
            return -1;
18739
0
        }
18740
0
    }
18741
37
    else {
18742
37
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18743
37
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18744
0
            return -1;
18745
0
        }
18746
37
    }
18747
37
#endif
18748
18749
    /* Initialize environ dictionary */
18750
37
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18751
0
        return -1;
18752
0
    }
18753
18754
37
    if (all_ins(m))
18755
0
        return -1;
18756
18757
37
    if (setup_confname_tables(m))
18758
0
        return -1;
18759
18760
37
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18761
0
        return -1;
18762
0
    }
18763
18764
37
#if defined(HAVE_WAITID)
18765
37
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18766
37
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18767
0
        return -1;
18768
0
    }
18769
37
#endif
18770
18771
37
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18772
37
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18773
37
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18774
37
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18775
37
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18776
0
        return -1;
18777
0
    }
18778
37
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18779
37
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18780
18781
37
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18782
37
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18783
0
        return -1;
18784
0
    }
18785
18786
37
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18787
37
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18788
37
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18789
0
        return -1;
18790
0
    }
18791
37
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18792
37
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18793
37
                          &os_sched_param_reduce_method) < 0)
18794
0
    {
18795
0
        return -1;
18796
0
    }
18797
37
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18798
37
#endif
18799
18800
    /* initialize TerminalSize_info */
18801
37
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18802
37
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18803
0
        return -1;
18804
0
    }
18805
18806
    /* initialize scandir types */
18807
37
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18808
37
    if (ScandirIteratorType == NULL) {
18809
0
        return -1;
18810
0
    }
18811
37
    state->ScandirIteratorType = ScandirIteratorType;
18812
18813
37
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18814
37
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18815
0
        return -1;
18816
0
    }
18817
18818
37
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18819
37
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18820
0
        return -1;
18821
0
    }
18822
18823
37
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18824
37
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18825
0
        return -1;
18826
0
    }
18827
18828
37
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18829
0
        return -1;
18830
37
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18831
37
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18832
37
    if (state->struct_rusage == NULL)
18833
0
        return -1;
18834
37
#endif
18835
37
    state->st_mode = PyUnicode_InternFromString("st_mode");
18836
37
    if (state->st_mode == NULL)
18837
0
        return -1;
18838
18839
    /* suppress "function not used" warnings */
18840
37
    {
18841
37
    int ignored;
18842
37
    fd_specified("", -1);
18843
37
    follow_symlinks_specified("", 1);
18844
37
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18845
37
    dir_fd_converter(Py_None, &ignored);
18846
37
    dir_fd_unavailable(Py_None, &ignored);
18847
37
    }
18848
18849
    /*
18850
     * provide list of locally available functions
18851
     * so os.py can populate support_* lists
18852
     */
18853
37
    PyObject *list = PyList_New(0);
18854
37
    if (!list) {
18855
0
        return -1;
18856
0
    }
18857
1.22k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18858
1.18k
        PyObject *unicode;
18859
1.18k
        if (trace->probe && !trace->probe()) continue;
18860
1.18k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18861
1.18k
        if (!unicode)
18862
0
            return -1;
18863
1.18k
        if (PyList_Append(list, unicode))
18864
0
            return -1;
18865
1.18k
        Py_DECREF(unicode);
18866
1.18k
    }
18867
18868
37
#ifndef MS_WINDOWS
18869
37
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18870
0
        PyErr_SetString(PyExc_RuntimeError,
18871
0
                        "cannot read ticks_per_second");
18872
0
        return -1;
18873
0
    }
18874
37
    assert(state->ticks_per_second >= 1);
18875
37
#endif
18876
18877
37
    return PyModule_Add(m, "_have_functions", list);
18878
37
}
18879
18880
18881
static PyModuleDef_Slot posixmodile_slots[] = {
18882
    _Py_ABI_SLOT,
18883
    {Py_mod_exec, posixmodule_exec},
18884
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18885
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18886
    {0, NULL}
18887
};
18888
18889
static struct PyModuleDef posixmodule = {
18890
    PyModuleDef_HEAD_INIT,
18891
    .m_name = MODNAME,
18892
    .m_doc = posix__doc__,
18893
    .m_size = sizeof(_posixstate),
18894
    .m_methods = posix_methods,
18895
    .m_slots = posixmodile_slots,
18896
    .m_traverse = _posix_traverse,
18897
    .m_clear = _posix_clear,
18898
    .m_free = _posix_free,
18899
};
18900
18901
PyMODINIT_FUNC
18902
INITFUNC(void)
18903
37
{
18904
37
    return PyModuleDef_Init(&posixmodule);
18905
37
}