Coverage Report

Created: 2025-11-02 06:30

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_long.h"          // _PyLong_IsNegative()
24
#include "pycore_moduleobject.h"  // _PyModule_GetState()
25
#include "pycore_object.h"        // _PyObject_LookupSpecial()
26
#include "pycore_pylifecycle.h"   // _PyOS_URandom()
27
#include "pycore_pystate.h"       // _PyInterpreterState_GET()
28
#include "pycore_signal.h"        // Py_NSIG
29
#include "pycore_time.h"          // _PyLong_FromTime_t()
30
#include "pycore_typeobject.h"    // _PyType_AddMethod()
31
32
#ifndef MS_WINDOWS
33
#  include "posixmodule.h"        // _PyLong_FromUid()
34
#else
35
#  include "pycore_fileutils_windows.h" // _Py_GetFileInformationByName()
36
#  include "osdefs.h"             // SEP
37
#  include "winreparse.h"         // _Py_REPARSE_DATA_BUFFER
38
#endif
39
40
41
// --- System includes ------------------------------------------------------
42
43
#include <stddef.h>               // offsetof()
44
#include <stdio.h>                // ctermid()
45
#include <stdlib.h>               // system()
46
47
#ifdef HAVE_UNISTD_H
48
#  include <unistd.h>             // symlink()
49
#endif
50
51
#ifdef __APPLE__
52
   /* Needed for the implementation of os.statvfs */
53
#  include <sys/param.h>
54
#  include <sys/mount.h>
55
#endif
56
57
#ifdef HAVE_SYS_TIME_H
58
#  include <sys/time.h>           // futimes()
59
#endif
60
61
#ifdef HAVE_SYS_PIDFD_H
62
#  include <sys/pidfd.h>          // PIDFD_NONBLOCK
63
#endif
64
65
#ifdef __EMSCRIPTEN__
66
#  include "emscripten.h"         // emscripten_debugger()
67
#endif
68
69
#ifdef HAVE_SYS_UIO_H
70
#  include <sys/uio.h>
71
#endif
72
73
#ifdef HAVE_SYS_TYPES_H
74
   /* Should be included before <sys/sysmacros.h> on HP-UX v3 */
75
#  include <sys/types.h>
76
#endif
77
#ifdef HAVE_SYS_SYSMACROS_H
78
   /* GNU C Library: major(), minor(), makedev() */
79
#  include <sys/sysmacros.h>
80
#endif
81
82
#ifdef HAVE_SYS_STAT_H
83
#  include <sys/stat.h>
84
#endif
85
86
#ifdef HAVE_SYS_WAIT_H
87
#  include <sys/wait.h>           // WNOHANG
88
#endif
89
90
#ifdef HAVE_LINUX_WAIT_H
91
#  include <linux/wait.h>         // P_PIDFD
92
#endif
93
94
#ifdef HAVE_SIGNAL_H
95
#  include <signal.h>
96
#endif
97
98
#ifdef HAVE_FCNTL_H
99
#  include <fcntl.h>              // fcntl()
100
#endif
101
102
#ifdef HAVE_GRP_H
103
#  include <grp.h>                // setgroups()
104
#endif
105
106
#ifdef HAVE_SYSEXITS_H
107
#  include <sysexits.h>           // EX_OK
108
#endif
109
110
#ifdef HAVE_SYS_LOADAVG_H
111
#  include <sys/loadavg.h>        // getloadavg()
112
#endif
113
114
#ifdef HAVE_SYS_SENDFILE_H
115
#  include <sys/sendfile.h>       // sendfile()
116
#endif
117
118
#if defined(__APPLE__)
119
#  include <copyfile.h>           // fcopyfile()
120
#endif
121
122
#ifdef HAVE_SCHED_H
123
#  include <sched.h>              // sched_setscheduler()
124
#endif
125
#ifdef HAVE_LINUX_SCHED_H
126
#  include <linux/sched.h>        // SCHED_IDLE, SCHED_RR
127
#endif
128
129
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
130
#  ifdef HAVE_SYS_SOCKET_H
131
#    include <sys/socket.h>
132
#  endif
133
#endif
134
135
#ifdef HAVE_DLFCN_H
136
#  include <dlfcn.h>
137
#endif
138
139
#ifdef __hpux
140
#  include <sys/mpctl.h>
141
#endif
142
143
#if defined(__DragonFly__) || \
144
    defined(__OpenBSD__)   || \
145
    defined(__FreeBSD__)   || \
146
    defined(__NetBSD__)    || \
147
    defined(__APPLE__)
148
#  include <sys/sysctl.h>
149
#endif
150
151
#ifdef HAVE_LINUX_RANDOM_H
152
#  include <linux/random.h>       // GRND_RANDOM
153
#endif
154
#ifdef HAVE_GETRANDOM_SYSCALL
155
#  include <sys/syscall.h>        // syscall()
156
#endif
157
158
#ifdef HAVE_POSIX_SPAWN
159
#  include <spawn.h>              // posix_spawn()
160
#endif
161
162
#ifdef HAVE_UTIME_H
163
#  include <utime.h>              // utime()
164
#endif
165
166
#ifdef HAVE_SYS_UTIME_H
167
#  include <sys/utime.h>
168
#  define HAVE_UTIME_H /* pretend we do for the rest of this file */
169
#endif
170
171
#ifdef HAVE_SYS_TIMES_H
172
#  include <sys/times.h>          // times()
173
#endif
174
175
#ifdef HAVE_SYS_PARAM_H
176
#  include <sys/param.h>
177
#endif
178
179
#ifdef HAVE_SYS_UTSNAME_H
180
#  include <sys/utsname.h>        // uname()
181
#endif
182
183
/* memfd_create is either defined in sys/mman.h or sys/memfd.h
184
 * linux/memfd.h defines additional flags
185
 */
186
#ifdef HAVE_SYS_MMAN_H
187
#  include <sys/mman.h>           // memfd_create()
188
#endif
189
#ifdef HAVE_SYS_MEMFD_H
190
#  include <sys/memfd.h>          // memfd_create()
191
#endif
192
#ifdef HAVE_LINUX_MEMFD_H
193
#  include <linux/memfd.h>        // memfd_create(), MFD_CLOEXEC
194
#endif
195
196
#ifdef HAVE_SYS_EVENTFD_H
197
#  include <sys/eventfd.h>        // eventfd()
198
#endif
199
200
#ifdef HAVE_SYS_TIMERFD_H
201
#  include <sys/timerfd.h>        // timerfd_create()
202
#endif
203
204
#ifdef _Py_MEMORY_SANITIZER
205
#  include <sanitizer/msan_interface.h> // __msan_unpoison()
206
#endif
207
208
209
// --- More complex system includes -----------------------------------------
210
211
#ifdef MS_WINDOWS
212
#  include <windows.h>
213
#  if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP)
214
#    include <pathcch.h>          // PathCchSkipRoot()
215
#  endif
216
#  include <aclapi.h>             // SetEntriesInAcl
217
#  include <lmcons.h>             // UNLEN
218
#  include <sddl.h>               // SDDL_REVISION_1
219
#  include <winioctl.h>           // FSCTL_GET_REPARSE_POINT
220
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
221
#    define HAVE_SYMLINK
222
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
223
#endif
224
225
226
#ifdef _MSC_VER
227
#  ifdef HAVE_DIRECT_H
228
#    include <direct.h>
229
#  endif
230
#  ifdef HAVE_IO_H
231
#    include <io.h>
232
#  endif
233
#  ifdef HAVE_PROCESS_H
234
#    include <process.h>          // getpid(), _cwait()
235
#  endif
236
#  include <malloc.h>
237
#endif /* _MSC_VER */
238
239
240
#ifdef HAVE__GETPTY
241
#  include <sys/types.h>          // mode_t
242
   // SGI apparently needs this forward declaration
243
   extern char * _getpty(int *, int, mode_t, int);
244
#endif
245
246
247
#if defined(HAVE_SYS_XATTR_H)
248
#  if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
249
#    define USE_XATTRS
250
#    include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
251
#  endif
252
#  if defined(__CYGWIN__)
253
#    define USE_XATTRS
254
#    include <cygwin/limits.h>  // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX.
255
#  endif
256
#endif
257
#ifdef USE_XATTRS
258
#  include <sys/xattr.h>          // fgetxattr()
259
#endif
260
261
262
#ifdef HAVE_WINDOWS_CONSOLE_IO
263
#  define TERMSIZE_USE_CONIO
264
#elif defined(HAVE_SYS_IOCTL_H)
265
#  include <sys/ioctl.h>          // ioctl(), TIOCGWINSZ
266
#  if defined(HAVE_TERMIOS_H)
267
#    include <termios.h>
268
#  endif
269
#  if defined(TIOCGWINSZ)
270
#    define TERMSIZE_USE_IOCTL
271
#  endif
272
#endif
273
274
275
/* Various compilers have only certain posix functions */
276
/* XXX Gosh I wish these were all moved into pyconfig.h */
277
#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
278
#  define HAVE_OPENDIR    1
279
#  define HAVE_SYSTEM     1
280
#  include <process.h>
281
#elif defined( _MSC_VER)
282
  /* Microsoft compiler */
283
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
284
#    define HAVE_GETPPID    1
285
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */
286
#  if defined(MS_WINDOWS_DESKTOP)
287
#    define HAVE_GETLOGIN   1
288
#  endif /* MS_WINDOWS_DESKTOP */
289
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
290
#    define HAVE_SPAWNV     1
291
#    define HAVE_EXECV      1
292
#    define HAVE_WSPAWNV    1
293
#    define HAVE_WEXECV     1
294
#    define HAVE_SYSTEM     1
295
#    define HAVE_CWAIT      1
296
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
297
#  define HAVE_PIPE       1
298
#  define HAVE_FSYNC      1
299
#  define fsync _commit
300
#endif
301
302
303
#if !defined(_MSC_VER) && defined(__sgi) && _COMPILER_VERSION>=700
304
/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
305
   (default) */
306
extern char *ctermid_r(char *);
307
#endif
308
309
310
#if defined(__VXWORKS__)
311
#  include <vxCpuLib.h>
312
#  include <rtpLib.h>
313
#  include <wait.h>
314
#  include <taskLib.h>
315
#  ifndef _P_WAIT
316
#    define _P_WAIT          0
317
#    define _P_NOWAIT        1
318
#    define _P_NOWAITO       1
319
#  endif
320
#endif /* __VXWORKS__ */
321
322
323
#ifdef HAVE_DIRENT_H
324
#  include <dirent.h>             // opendir()
325
7.08k
#  define NAMLEN(dirent) strlen((dirent)->d_name)
326
#else
327
#  if defined(__WATCOMC__) && !defined(__QNX__)
328
#    include <direct.h>
329
#    define NAMLEN(dirent) strlen((dirent)->d_name)
330
#  else
331
#    define dirent direct
332
#    define NAMLEN(dirent) (dirent)->d_namlen
333
#  endif
334
#  ifdef HAVE_SYS_NDIR_H
335
#    include <sys/ndir.h>
336
#  endif
337
#  ifdef HAVE_SYS_DIR_H
338
#    include <sys/dir.h>
339
#  endif
340
#  ifdef HAVE_NDIR_H
341
#    include <ndir.h>
342
#  endif
343
#endif
344
345
346
#if defined(MAJOR_IN_MKDEV)
347
#  include <sys/mkdev.h>
348
#else
349
#  if defined(MAJOR_IN_SYSMACROS)
350
#    include <sys/sysmacros.h>
351
#  endif
352
#  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
353
#    include <sys/mkdev.h>
354
#  endif
355
#endif
356
357
358
// --- Macros ---------------------------------------------------------------
359
360
#ifndef MAXPATHLEN
361
#  if defined(PATH_MAX) && PATH_MAX > 1024
362
#    define MAXPATHLEN PATH_MAX
363
#  else
364
#    define MAXPATHLEN 1024
365
#  endif
366
#endif /* MAXPATHLEN */
367
368
369
#ifdef UNION_WAIT
370
   /* Emulate some macros on systems that have a union instead of macros */
371
#  ifndef WIFEXITED
372
#    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
373
#  endif
374
#  ifndef WEXITSTATUS
375
#    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
376
#  endif
377
#  ifndef WTERMSIG
378
#    define WTERMSIG(u_wait) ((u_wait).w_termsig)
379
#  endif
380
#  define WAIT_TYPE union wait
381
#  define WAIT_STATUS_INT(s) (s.w_status)
382
#else
383
   /* !UNION_WAIT */
384
0
#  define WAIT_TYPE int
385
0
#  define WAIT_STATUS_INT(s) (s)
386
#endif /* UNION_WAIT */
387
388
389
/* Don't use the "_r" form if we don't need it (also, won't have a
390
   prototype for it, at least on Solaris -- maybe others as well?). */
391
#if defined(HAVE_CTERMID_R)
392
#  define USE_CTERMID_R
393
#endif
394
395
396
/* choose the appropriate stat and fstat functions and return structs */
397
#undef STAT
398
#undef FSTAT
399
#undef STRUCT_STAT
400
#ifdef MS_WINDOWS
401
#  define STAT win32_stat
402
#  define LSTAT win32_lstat
403
#  define FSTAT _Py_fstat_noraise
404
#  define STRUCT_STAT struct _Py_stat_struct
405
#else
406
5.31k
#  define STAT stat
407
0
#  define LSTAT lstat
408
0
#  define FSTAT fstat
409
5.31k
#  define STRUCT_STAT struct stat
410
#endif
411
412
#ifdef HAVE_STATX
413
/* until we can assume glibc 2.28 at runtime, we must weakly link */
414
#  pragma weak statx
415
static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
416
#ifdef STATX_MNT_ID
417
                                             | STATX_MNT_ID
418
#endif
419
#ifdef STATX_DIOALIGN
420
                                             | STATX_DIOALIGN
421
#endif
422
#ifdef STATX_MNT_ID_UNIQUE
423
                                             | STATX_MNT_ID_UNIQUE
424
#endif
425
#ifdef STATX_SUBVOL
426
                                             | STATX_SUBVOL
427
#endif
428
#ifdef STATX_WRITE_ATOMIC
429
                                             | STATX_WRITE_ATOMIC
430
#endif
431
#ifdef STATX_DIO_READ_ALIGN
432
                                             | STATX_DIO_READ_ALIGN
433
#endif
434
                                            );
435
#endif /* HAVE_STATX */
436
437
438
#if !defined(EX_OK) && defined(EXIT_SUCCESS)
439
#  define EX_OK EXIT_SUCCESS
440
#endif
441
442
#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
443
#  undef HAVE_SCHED_SETAFFINITY
444
#endif
445
446
/* On android API level 21, 'AT_EACCESS' is not declared although
447
 * HAVE_FACCESSAT is defined. */
448
#ifdef __ANDROID__
449
#  undef HAVE_FACCESSAT
450
#endif
451
452
#if defined(__sun)
453
/* Something to implement in autoconf, not present in autoconf 2.69 */
454
#  define HAVE_STRUCT_STAT_ST_FSTYPE 1
455
#endif
456
457
458
// --- Apple __builtin_available() macros -----------------------------------
459
460
/*
461
 * A number of APIs are available on macOS from a certain macOS version.
462
 * To support building with a new SDK while deploying to older versions
463
 * the availability test is split into two:
464
 *   - HAVE_<FUNCTION>:  The configure check for compile time availability
465
 *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
466
 *
467
 * The latter is always true when not on macOS, or when using a compiler
468
 * that does not support __has_builtin (older versions of Xcode).
469
 *
470
 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
471
 *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
472
 *
473
 * In mixing the test with other tests or using negations will result in compile
474
 * errors.
475
 */
476
#if defined(__APPLE__)
477
478
#include <mach/mach.h>
479
480
#if defined(__has_builtin)
481
#if __has_builtin(__builtin_available)
482
#define HAVE_BUILTIN_AVAILABLE 1
483
#endif
484
#endif
485
486
#ifdef HAVE_BUILTIN_AVAILABLE
487
#  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
488
#  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
489
#  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
490
#  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
491
#  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
492
#  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
493
#  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
494
#  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
495
#  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
496
#  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
497
#  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
498
#  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
499
#  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
500
#  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
501
#  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
502
#  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
503
#  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
504
#  define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
505
506
#  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
507
508
#else /* Xcode 8 or earlier */
509
510
   /* __builtin_available is not present in these compilers, but
511
    * some of the symbols might be weak linked (10.10 SDK or later
512
    * deploying on 10.9.
513
    *
514
    * Fall back to the older style of availability checking for
515
    * symbols introduced in macOS 10.10.
516
    */
517
518
#  ifdef HAVE_FSTATAT
519
#    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
520
#  endif
521
522
#  ifdef HAVE_FACCESSAT
523
#    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
524
#  endif
525
526
#  ifdef HAVE_FCHMODAT
527
#    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
528
#  endif
529
530
#  ifdef HAVE_FCHOWNAT
531
#    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
532
#  endif
533
534
#  ifdef HAVE_LINKAT
535
#    define HAVE_LINKAT_RUNTIME (linkat != NULL)
536
#  endif
537
538
#  ifdef HAVE_FDOPENDIR
539
#    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
540
#  endif
541
542
#  ifdef HAVE_MKDIRAT
543
#    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
544
#  endif
545
546
#  ifdef HAVE_RENAMEAT
547
#    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
548
#  endif
549
550
#  ifdef HAVE_UNLINKAT
551
#    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
552
#  endif
553
554
#  ifdef HAVE_OPENAT
555
#    define HAVE_OPENAT_RUNTIME (openat != NULL)
556
#  endif
557
558
#  ifdef HAVE_READLINKAT
559
#    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
560
#  endif
561
562
#  ifdef HAVE_SYMLINKAT
563
#    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
564
#  endif
565
566
#  ifdef HAVE_UTIMENSAT
567
#    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
568
#  endif
569
570
#  ifdef HAVE_FUTIMENS
571
#    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
572
#  endif
573
574
#  ifdef HAVE_PWRITEV
575
#    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
576
#  endif
577
578
#  ifdef HAVE_MKFIFOAT
579
#    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
580
#  endif
581
582
#  ifdef HAVE_MKNODAT
583
#    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
584
#  endif
585
586
#  ifdef HAVE_PTSNAME_R
587
#    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
588
#  endif
589
590
#endif
591
592
#ifdef HAVE_FUTIMESAT
593
/* Some of the logic for weak linking depends on this assertion */
594
# error "HAVE_FUTIMESAT unexpectedly defined"
595
#endif
596
597
#else
598
0
#  define HAVE_FSTATAT_RUNTIME 1
599
0
#  define HAVE_FACCESSAT_RUNTIME 1
600
0
#  define HAVE_FCHMODAT_RUNTIME 1
601
0
#  define HAVE_FCHOWNAT_RUNTIME 1
602
#ifdef __wasi__
603
#  define HAVE_LINKAT_RUNTIME 0
604
# else
605
0
#  define HAVE_LINKAT_RUNTIME 1
606
# endif
607
0
#  define HAVE_FDOPENDIR_RUNTIME 1
608
0
#  define HAVE_MKDIRAT_RUNTIME 1
609
0
#  define HAVE_RENAMEAT_RUNTIME 1
610
0
#  define HAVE_UNLINKAT_RUNTIME 1
611
0
#  define HAVE_OPENAT_RUNTIME 1
612
0
#  define HAVE_READLINKAT_RUNTIME 1
613
0
#  define HAVE_SYMLINKAT_RUNTIME 1
614
0
#  define HAVE_FUTIMENS_RUNTIME 1
615
0
#  define HAVE_UTIMENSAT_RUNTIME 1
616
16
#  define HAVE_PWRITEV_RUNTIME 1
617
0
#  define HAVE_MKFIFOAT_RUNTIME 1
618
0
#  define HAVE_MKNODAT_RUNTIME 1
619
0
#  define HAVE_PTSNAME_R_RUNTIME 1
620
#endif
621
622
623
// --- os module ------------------------------------------------------------
624
625
#ifdef MS_WINDOWS
626
#  define INITFUNC PyInit_nt
627
#  define MODNAME "nt"
628
#  define MODNAME_OBJ &_Py_ID(nt)
629
#else
630
#  define INITFUNC PyInit_posix
631
#  define MODNAME "posix"
632
0
#  define MODNAME_OBJ &_Py_ID(posix)
633
#endif
634
635
/*[clinic input]
636
# one of the few times we lie about this name!
637
module os
638
[clinic start generated code]*/
639
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
640
641
PyDoc_STRVAR(posix__doc__,
642
"This module provides access to operating system functionality that is\n\
643
standardized by the C Standard and the POSIX standard (a thinly\n\
644
disguised Unix interface).  Refer to the library manual and\n\
645
corresponding Unix manual entries for more information on calls.");
646
647
648
// --- Functions ------------------------------------------------------------
649
650
#ifdef HAVE_FORK
651
static void
652
run_at_forkers(PyObject *lst, int reverse)
653
0
{
654
0
    Py_ssize_t i;
655
0
    PyObject *cpy;
656
657
0
    if (lst != NULL) {
658
0
        assert(PyList_CheckExact(lst));
659
660
        /* Use a list copy in case register_at_fork() is called from
661
         * one of the callbacks.
662
         */
663
0
        cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
664
0
        if (cpy == NULL) {
665
0
            PyErr_FormatUnraisable("Exception ignored in atfork callback "
666
0
                                   "while copying list %R", lst);
667
0
        }
668
0
        else {
669
0
            if (reverse)
670
0
                PyList_Reverse(cpy);
671
0
            for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
672
0
                PyObject *func, *res;
673
0
                func = PyList_GET_ITEM(cpy, i);
674
0
                res = _PyObject_CallNoArgs(func);
675
0
                if (res == NULL) {
676
0
                    PyErr_FormatUnraisable("Exception ignored "
677
0
                                           "in atfork callback %R", func);
678
0
                }
679
0
                else {
680
0
                    Py_DECREF(res);
681
0
                }
682
0
            }
683
0
            Py_DECREF(cpy);
684
0
        }
685
0
    }
686
0
}
687
688
void
689
PyOS_BeforeFork(void)
690
0
{
691
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
692
0
    run_at_forkers(interp->before_forkers, 1);
693
694
0
    _PyImport_AcquireLock(interp);
695
0
    _PyEval_StopTheWorldAll(&_PyRuntime);
696
0
    HEAD_LOCK(&_PyRuntime);
697
0
}
698
699
void
700
PyOS_AfterFork_Parent(void)
701
0
{
702
0
    HEAD_UNLOCK(&_PyRuntime);
703
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
704
705
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
706
0
    _PyImport_ReleaseLock(interp);
707
0
    run_at_forkers(interp->after_forkers_parent, 0);
708
0
}
709
710
static void
711
reset_remotedebug_data(PyThreadState *tstate)
712
0
{
713
0
    tstate->remote_debugger_support.debugger_pending_call = 0;
714
0
    memset(tstate->remote_debugger_support.debugger_script_path, 0,
715
0
           _Py_MAX_SCRIPT_PATH_SIZE);
716
0
}
717
718
static void
719
reset_asyncio_state(_PyThreadStateImpl *tstate)
720
0
{
721
0
    llist_init(&tstate->asyncio_tasks_head);
722
0
    tstate->asyncio_running_loop = NULL;
723
0
    tstate->asyncio_running_task = NULL;
724
0
}
725
726
727
void
728
PyOS_AfterFork_Child(void)
729
0
{
730
0
    PyStatus status;
731
0
    _PyRuntimeState *runtime = &_PyRuntime;
732
733
    // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
734
0
    status = _PyRuntimeState_ReInitThreads(runtime);
735
0
    if (_PyStatus_EXCEPTION(status)) {
736
0
        goto fatal_error;
737
0
    }
738
739
0
    PyThreadState *tstate = _PyThreadState_GET();
740
0
    _Py_EnsureTstateNotNULL(tstate);
741
742
0
    assert(tstate->thread_id == PyThread_get_thread_ident());
743
0
#ifdef PY_HAVE_THREAD_NATIVE_ID
744
0
    tstate->native_thread_id = PyThread_get_thread_native_id();
745
0
#endif
746
747
#ifdef Py_GIL_DISABLED
748
    _Py_brc_after_fork(tstate->interp);
749
    _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
750
#endif
751
752
    // Ideally we could guarantee tstate is running main.
753
0
    _PyInterpreterState_ReinitRunningMain(tstate);
754
755
0
    status = _PyEval_ReInitThreads(tstate);
756
0
    if (_PyStatus_EXCEPTION(status)) {
757
0
        goto fatal_error;
758
0
    }
759
760
0
    reset_remotedebug_data(tstate);
761
762
0
    reset_asyncio_state((_PyThreadStateImpl *)tstate);
763
764
    // Remove the dead thread states. We "start the world" once we are the only
765
    // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
766
    // That needs to happen before `_PyThreadState_DeleteList`, because that
767
    // may call destructors.
768
0
    PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
769
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
770
0
    _PyThreadState_DeleteList(list, /*is_after_fork=*/1);
771
772
0
    _PyImport_ReInitLock(tstate->interp);
773
0
    _PyImport_ReleaseLock(tstate->interp);
774
775
0
    _PySignal_AfterFork();
776
777
0
    status = _PyInterpreterState_DeleteExceptMain(runtime);
778
0
    if (_PyStatus_EXCEPTION(status)) {
779
0
        goto fatal_error;
780
0
    }
781
0
    assert(_PyThreadState_GET() == tstate);
782
783
0
    status = _PyPerfTrampoline_AfterFork_Child();
784
0
    if (_PyStatus_EXCEPTION(status)) {
785
0
        goto fatal_error;
786
0
    }
787
788
0
    run_at_forkers(tstate->interp->after_forkers_child, 0);
789
0
    return;
790
791
0
fatal_error:
792
0
    Py_ExitStatusException(status);
793
0
}
794
795
static int
796
register_at_forker(PyObject **lst, PyObject *func)
797
6
{
798
6
    if (func == NULL)  /* nothing to register? do nothing. */
799
4
        return 0;
800
2
    if (*lst == NULL) {
801
2
        *lst = PyList_New(0);
802
2
        if (*lst == NULL)
803
0
            return -1;
804
2
    }
805
2
    return PyList_Append(*lst, func);
806
2
}
807
#endif  /* HAVE_FORK */
808
809
810
/* Legacy wrapper */
811
void
812
PyOS_AfterFork(void)
813
0
{
814
0
#ifdef HAVE_FORK
815
0
    PyOS_AfterFork_Child();
816
0
#endif
817
0
}
818
819
820
#ifdef MS_WINDOWS
821
/* defined in fileutils.c */
822
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
823
void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
824
                                FILE_BASIC_INFO *, FILE_ID_INFO *,
825
                                struct _Py_stat_struct *);
826
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
827
                                 struct _Py_stat_struct *);
828
#endif
829
830
831
#ifndef MS_WINDOWS
832
PyObject *
833
_PyLong_FromUid(uid_t uid)
834
5.03k
{
835
5.03k
    if (uid == (uid_t)-1)
836
0
        return PyLong_FromLong(-1);
837
5.03k
    return PyLong_FromUnsignedLong(uid);
838
5.03k
}
839
840
PyObject *
841
_PyLong_FromGid(gid_t gid)
842
5.03k
{
843
5.03k
    if (gid == (gid_t)-1)
844
0
        return PyLong_FromLong(-1);
845
5.03k
    return PyLong_FromUnsignedLong(gid);
846
5.03k
}
847
848
int
849
_Py_Uid_Converter(PyObject *obj, uid_t *p)
850
0
{
851
0
    uid_t uid;
852
0
    PyObject *index;
853
0
    int overflow;
854
0
    long result;
855
0
    unsigned long uresult;
856
857
0
    index = _PyNumber_Index(obj);
858
0
    if (index == NULL) {
859
0
        PyErr_Format(PyExc_TypeError,
860
0
                     "uid should be integer, not %.200s",
861
0
                     _PyType_Name(Py_TYPE(obj)));
862
0
        return 0;
863
0
    }
864
865
    /*
866
     * Handling uid_t is complicated for two reasons:
867
     *  * Although uid_t is (always?) unsigned, it still
868
     *    accepts -1.
869
     *  * We don't know its size in advance--it may be
870
     *    bigger than an int, or it may be smaller than
871
     *    a long.
872
     *
873
     * So a bit of defensive programming is in order.
874
     * Start with interpreting the value passed
875
     * in as a signed long and see if it works.
876
     */
877
878
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
879
880
0
    if (!overflow) {
881
0
        uid = (uid_t)result;
882
883
0
        if (result == -1) {
884
0
            if (PyErr_Occurred())
885
0
                goto fail;
886
            /* It's a legitimate -1, we're done. */
887
0
            goto success;
888
0
        }
889
890
        /* Any other negative number is disallowed. */
891
0
        if (result < 0)
892
0
            goto underflow;
893
894
        /* Ensure the value wasn't truncated. */
895
0
        if (sizeof(uid_t) < sizeof(long) &&
896
0
            (long)uid != result)
897
0
            goto underflow;
898
0
        goto success;
899
0
    }
900
901
0
    if (overflow < 0)
902
0
        goto underflow;
903
904
    /*
905
     * Okay, the value overflowed a signed long.  If it
906
     * fits in an *unsigned* long, it may still be okay,
907
     * as uid_t may be unsigned long on this platform.
908
     */
909
0
    uresult = PyLong_AsUnsignedLong(index);
910
0
    if (PyErr_Occurred()) {
911
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
912
0
            goto overflow;
913
0
        goto fail;
914
0
    }
915
916
0
    uid = (uid_t)uresult;
917
918
    /*
919
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
920
     * but this value would get interpreted as (uid_t)-1  by chown
921
     * and its siblings.   That's not what the user meant!  So we
922
     * throw an overflow exception instead.   (We already
923
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
924
     */
925
0
    if (uid == (uid_t)-1)
926
0
        goto overflow;
927
928
    /* Ensure the value wasn't truncated. */
929
0
    if (sizeof(uid_t) < sizeof(long) &&
930
0
        (unsigned long)uid != uresult)
931
0
        goto overflow;
932
    /* fallthrough */
933
934
0
success:
935
0
    Py_DECREF(index);
936
0
    *p = uid;
937
0
    return 1;
938
939
0
underflow:
940
0
    PyErr_SetString(PyExc_OverflowError,
941
0
                    "uid is less than minimum");
942
0
    goto fail;
943
944
0
overflow:
945
0
    PyErr_SetString(PyExc_OverflowError,
946
0
                    "uid is greater than maximum");
947
    /* fallthrough */
948
949
0
fail:
950
0
    Py_DECREF(index);
951
0
    return 0;
952
0
}
953
954
int
955
_Py_Gid_Converter(PyObject *obj, gid_t *p)
956
0
{
957
0
    gid_t gid;
958
0
    PyObject *index;
959
0
    int overflow;
960
0
    long result;
961
0
    unsigned long uresult;
962
963
0
    index = _PyNumber_Index(obj);
964
0
    if (index == NULL) {
965
0
        PyErr_Format(PyExc_TypeError,
966
0
                     "gid should be integer, not %.200s",
967
0
                     _PyType_Name(Py_TYPE(obj)));
968
0
        return 0;
969
0
    }
970
971
    /*
972
     * Handling gid_t is complicated for two reasons:
973
     *  * Although gid_t is (always?) unsigned, it still
974
     *    accepts -1.
975
     *  * We don't know its size in advance--it may be
976
     *    bigger than an int, or it may be smaller than
977
     *    a long.
978
     *
979
     * So a bit of defensive programming is in order.
980
     * Start with interpreting the value passed
981
     * in as a signed long and see if it works.
982
     */
983
984
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
985
986
0
    if (!overflow) {
987
0
        gid = (gid_t)result;
988
989
0
        if (result == -1) {
990
0
            if (PyErr_Occurred())
991
0
                goto fail;
992
            /* It's a legitimate -1, we're done. */
993
0
            goto success;
994
0
        }
995
996
        /* Any other negative number is disallowed. */
997
0
        if (result < 0) {
998
0
            goto underflow;
999
0
        }
1000
1001
        /* Ensure the value wasn't truncated. */
1002
0
        if (sizeof(gid_t) < sizeof(long) &&
1003
0
            (long)gid != result)
1004
0
            goto underflow;
1005
0
        goto success;
1006
0
    }
1007
1008
0
    if (overflow < 0)
1009
0
        goto underflow;
1010
1011
    /*
1012
     * Okay, the value overflowed a signed long.  If it
1013
     * fits in an *unsigned* long, it may still be okay,
1014
     * as gid_t may be unsigned long on this platform.
1015
     */
1016
0
    uresult = PyLong_AsUnsignedLong(index);
1017
0
    if (PyErr_Occurred()) {
1018
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1019
0
            goto overflow;
1020
0
        goto fail;
1021
0
    }
1022
1023
0
    gid = (gid_t)uresult;
1024
1025
    /*
1026
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
1027
     * but this value would get interpreted as (gid_t)-1  by chown
1028
     * and its siblings.   That's not what the user meant!  So we
1029
     * throw an overflow exception instead.   (We already
1030
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
1031
     */
1032
0
    if (gid == (gid_t)-1)
1033
0
        goto overflow;
1034
1035
    /* Ensure the value wasn't truncated. */
1036
0
    if (sizeof(gid_t) < sizeof(long) &&
1037
0
        (unsigned long)gid != uresult)
1038
0
        goto overflow;
1039
    /* fallthrough */
1040
1041
0
success:
1042
0
    Py_DECREF(index);
1043
0
    *p = gid;
1044
0
    return 1;
1045
1046
0
underflow:
1047
0
    PyErr_SetString(PyExc_OverflowError,
1048
0
                    "gid is less than minimum");
1049
0
    goto fail;
1050
1051
0
overflow:
1052
0
    PyErr_SetString(PyExc_OverflowError,
1053
0
                    "gid is greater than maximum");
1054
    /* fallthrough */
1055
1056
0
fail:
1057
0
    Py_DECREF(index);
1058
0
    return 0;
1059
0
}
1060
#endif /* MS_WINDOWS */
1061
1062
1063
static PyObject *
1064
_PyLong_FromDev(dev_t dev)
1065
10.0k
{
1066
10.0k
#ifdef NODEV
1067
10.0k
    if (dev == NODEV) {
1068
16
        return PyLong_FromLongLong((long long)dev);
1069
16
    }
1070
10.0k
#endif
1071
10.0k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1072
10.0k
}
1073
1074
1075
#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
1076
static int
1077
_Py_Dev_Converter(PyObject *obj, void *p)
1078
0
{
1079
0
    if (!PyLong_Check(obj)) {
1080
0
        obj = _PyNumber_Index(obj);
1081
0
        if (obj == NULL) {
1082
0
            return 0;
1083
0
        }
1084
0
    }
1085
0
    else {
1086
0
        Py_INCREF(obj);
1087
0
    }
1088
0
    assert(PyLong_Check(obj));
1089
0
#ifdef NODEV
1090
0
    if (_PyLong_IsNegative((PyLongObject *)obj)) {
1091
0
        int overflow;
1092
0
        long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
1093
0
        if (result == -1 && PyErr_Occurred()) {
1094
0
            Py_DECREF(obj);
1095
0
            return 0;
1096
0
        }
1097
0
        if (!overflow && result == (long long)NODEV) {
1098
0
            *((dev_t *)p) = NODEV;
1099
0
            Py_DECREF(obj);
1100
0
            return 1;
1101
0
        }
1102
0
    }
1103
0
#endif
1104
1105
0
    unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1106
0
    Py_DECREF(obj);
1107
0
    if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1108
0
        return 0;
1109
0
    }
1110
0
    if ((unsigned long long)(dev_t)result != result) {
1111
0
        PyErr_SetString(PyExc_OverflowError,
1112
0
                        "Python int too large to convert to C dev_t");
1113
0
        return 0;
1114
0
    }
1115
0
    *((dev_t *)p) = (dev_t)result;
1116
0
    return 1;
1117
0
}
1118
#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1119
1120
1121
#ifdef AT_FDCWD
1122
/*
1123
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1124
 * without the int cast, the value gets interpreted as uint (4291925331),
1125
 * which doesn't play nicely with all the initializer lines in this file that
1126
 * look like this:
1127
 *      int dir_fd = DEFAULT_DIR_FD;
1128
 */
1129
23.2k
#define DEFAULT_DIR_FD (int)AT_FDCWD
1130
#else
1131
#define DEFAULT_DIR_FD (-100)
1132
#endif
1133
1134
static int
1135
_fd_converter(PyObject *o, int *p)
1136
0
{
1137
0
    int overflow;
1138
0
    long long_value;
1139
1140
0
    if (PyBool_Check(o)) {
1141
0
        if (PyErr_WarnEx(PyExc_RuntimeWarning,
1142
0
                "bool is used as a file descriptor", 1))
1143
0
        {
1144
0
            return 0;
1145
0
        }
1146
0
    }
1147
0
    PyObject *index = _PyNumber_Index(o);
1148
0
    if (index == NULL) {
1149
0
        return 0;
1150
0
    }
1151
1152
0
    assert(PyLong_Check(index));
1153
0
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1154
0
    Py_DECREF(index);
1155
0
    assert(!PyErr_Occurred());
1156
0
    if (overflow > 0 || long_value > INT_MAX) {
1157
0
        PyErr_SetString(PyExc_OverflowError,
1158
0
                        "fd is greater than maximum");
1159
0
        return 0;
1160
0
    }
1161
0
    if (overflow < 0 || long_value < INT_MIN) {
1162
0
        PyErr_SetString(PyExc_OverflowError,
1163
0
                        "fd is less than minimum");
1164
0
        return 0;
1165
0
    }
1166
1167
0
    *p = (int)long_value;
1168
0
    return 1;
1169
0
}
1170
1171
static int
1172
dir_fd_converter(PyObject *o, void *p)
1173
32
{
1174
32
    if (o == Py_None) {
1175
32
        *(int *)p = DEFAULT_DIR_FD;
1176
32
        return 1;
1177
32
    }
1178
0
    else if (PyIndex_Check(o)) {
1179
0
        return _fd_converter(o, (int *)p);
1180
0
    }
1181
0
    else {
1182
0
        PyErr_Format(PyExc_TypeError,
1183
0
                     "argument should be integer or None, not %.200s",
1184
0
                     _PyType_Name(Py_TYPE(o)));
1185
0
        return 0;
1186
0
    }
1187
32
}
1188
1189
typedef struct {
1190
    PyObject *billion;
1191
    PyObject *DirEntryType;
1192
    PyObject *ScandirIteratorType;
1193
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1194
    PyObject *SchedParamType;
1195
#endif
1196
    newfunc statresult_new_orig;
1197
    PyObject *StatResultType;
1198
#ifdef HAVE_STATX
1199
    PyObject *StatxResultType;
1200
#endif
1201
    PyObject *StatVFSResultType;
1202
    PyObject *TerminalSizeType;
1203
    PyObject *TimesResultType;
1204
    PyObject *UnameResultType;
1205
#if defined(HAVE_WAITID)
1206
    PyObject *WaitidResultType;
1207
#endif
1208
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1209
    PyObject *struct_rusage;
1210
#endif
1211
    PyObject *st_mode;
1212
#ifndef MS_WINDOWS
1213
    // times() clock frequency in hertz; used by os.times()
1214
    long ticks_per_second;
1215
#endif
1216
} _posixstate;
1217
1218
1219
static inline _posixstate*
1220
get_posix_state(PyObject *module)
1221
5.88k
{
1222
5.88k
    void *state = _PyModule_GetState(module);
1223
5.88k
    assert(state != NULL);
1224
5.88k
    return (_posixstate *)state;
1225
5.88k
}
1226
1227
/*
1228
 * A PyArg_ParseTuple "converter" function
1229
 * that handles filesystem paths in the manner
1230
 * preferred by the os module.
1231
 *
1232
 * path_converter accepts (Unicode) strings and their
1233
 * subclasses, and bytes and their subclasses.  What
1234
 * it does with the argument depends on path.make_wide:
1235
 *
1236
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1237
 *     string we extract the wchar_t * and return it; if we
1238
 *     get bytes we decode to wchar_t * and return that.
1239
 *
1240
 *   * If path.make_wide is zero, if we get bytes we extract
1241
 *     the char_t * and return it; if we get a (Unicode)
1242
 *     string we encode to char_t * and return that.
1243
 *
1244
 * path_converter also optionally accepts signed
1245
 * integers (representing open file descriptors) instead
1246
 * of path strings.
1247
 *
1248
 * Input fields:
1249
 *   path.nullable
1250
 *     If nonzero, the path is permitted to be None.
1251
 *   path.nonstrict
1252
 *     If nonzero, the path is permitted to contain
1253
 *     embedded null characters and have any length.
1254
 *   path.make_wide
1255
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1256
 *     it always uses narrow, encoding if necessary. The default value is
1257
 *     nonzero on Windows, else zero.
1258
 *   path.suppress_value_error
1259
 *     If nonzero, raising ValueError is suppressed.
1260
 *   path.allow_fd
1261
 *     If nonzero, the path is permitted to be a file handle
1262
 *     (a signed int) instead of a string.
1263
 *   path.function_name
1264
 *     If non-NULL, path_converter will use that as the name
1265
 *     of the function in error messages.
1266
 *     (If path.function_name is NULL it omits the function name.)
1267
 *   path.argument_name
1268
 *     If non-NULL, path_converter will use that as the name
1269
 *     of the parameter in error messages.
1270
 *     (If path.argument_name is NULL it uses "path".)
1271
 *
1272
 * Output fields:
1273
 *   path.wide
1274
 *     Points to the path if it was expressed as Unicode
1275
 *     or if it was bytes and decoded to Unicode.
1276
 *   path.narrow
1277
 *     Points to the path if it was expressed as bytes,
1278
 *     or if it was Unicode and encoded to bytes.
1279
 *   path.fd
1280
 *     Contains a file descriptor if path.accept_fd was true
1281
 *     and the caller provided a signed integer instead of any
1282
 *     sort of string.
1283
 *
1284
 *     WARNING: if your "path" parameter is optional, and is
1285
 *     unspecified, path_converter will never get called.
1286
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1287
 *     yourself!
1288
 *   path.value_error
1289
 *     If nonzero, then suppress_value_error was specified and a ValueError
1290
 *     occurred.
1291
 *   path.length
1292
 *     The length of the path in characters, if specified as
1293
 *     a string.
1294
 *   path.object
1295
 *     The original object passed in (if get a PathLike object,
1296
 *     the result of PyOS_FSPath() is treated as the original object).
1297
 *     Own a reference to the object.
1298
 *   path.cleanup
1299
 *     For internal use only.  May point to a temporary object.
1300
 *     (Pay no attention to the man behind the curtain.)
1301
 *
1302
 *   At most one of path.wide or path.narrow will be non-NULL.
1303
 *   If path was None and path.nullable was set,
1304
 *     or if path was an integer and path.allow_fd was set,
1305
 *     both path.wide and path.narrow will be NULL
1306
 *     and path.length will be 0.
1307
 *
1308
 *   path_converter takes care to not write to the path_t
1309
 *   unless it's successful.  However it must reset the
1310
 *   "cleanup" field each time it's called.
1311
 *
1312
 * Use as follows:
1313
 *      path_t path;
1314
 *      memset(&path, 0, sizeof(path));
1315
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1316
 *      // ... use values from path ...
1317
 *      path_cleanup(&path);
1318
 *
1319
 * (Note that if PyArg_Parse fails you don't need to call
1320
 * path_cleanup().  However it is safe to do so.)
1321
 */
1322
typedef struct {
1323
    // Input fields
1324
    const char *function_name;
1325
    const char *argument_name;
1326
    int nullable;
1327
    int nonstrict;
1328
    int make_wide;
1329
    int suppress_value_error;
1330
    int allow_fd;
1331
    // Output fields
1332
    const wchar_t *wide;
1333
    const char *narrow;
1334
    int fd;
1335
    int value_error;
1336
    Py_ssize_t length;
1337
    PyObject *object;
1338
    PyObject *cleanup;
1339
} path_t;
1340
1341
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1342
                          make_wide, suppress_value_error, allow_fd) \
1343
6.23k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1344
6.23k
     suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL}
1345
#ifdef MS_WINDOWS
1346
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1347
                            nonstrict, suppress_value_error, allow_fd) \
1348
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1349
                      suppress_value_error, allow_fd)
1350
#else
1351
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1352
                            nonstrict, suppress_value_error, allow_fd) \
1353
6.15k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1354
6.15k
                      suppress_value_error, allow_fd)
1355
#endif
1356
1357
static void
1358
path_cleanup(path_t *path)
1359
6.23k
{
1360
6.23k
    wchar_t *wide = (wchar_t *)path->wide;
1361
6.23k
    path->wide = NULL;
1362
6.23k
    PyMem_Free(wide);
1363
6.23k
    Py_CLEAR(path->object);
1364
6.23k
    Py_CLEAR(path->cleanup);
1365
6.23k
}
1366
1367
static int
1368
path_converter(PyObject *o, void *p)
1369
6.23k
{
1370
6.23k
    path_t *path = (path_t *)p;
1371
6.23k
    PyObject *bytes = NULL;
1372
6.23k
    Py_ssize_t length = 0;
1373
6.23k
    int is_index, is_bytes, is_unicode;
1374
6.23k
    const char *narrow;
1375
6.23k
    PyObject *wo = NULL;
1376
6.23k
    wchar_t *wide = NULL;
1377
1378
6.23k
#define FORMAT_EXCEPTION(exc, fmt) \
1379
6.23k
    PyErr_Format(exc, "%s%s" fmt, \
1380
0
        path->function_name ? path->function_name : "", \
1381
0
        path->function_name ? ": "                : "", \
1382
0
        path->argument_name ? path->argument_name : "path")
1383
1384
    /* Py_CLEANUP_SUPPORTED support */
1385
6.23k
    if (o == NULL) {
1386
0
        path_cleanup(path);
1387
0
        return 1;
1388
0
    }
1389
1390
    /* Ensure it's always safe to call path_cleanup(). */
1391
6.23k
    path->object = path->cleanup = NULL;
1392
    /* path->object owns a reference to the original object */
1393
6.23k
    Py_INCREF(o);
1394
1395
6.23k
    if ((o == Py_None) && path->nullable) {
1396
0
        path->wide = NULL;
1397
0
        path->narrow = NULL;
1398
0
        path->fd = -1;
1399
0
        goto success_exit;
1400
0
    }
1401
1402
    /* Only call this here so that we don't treat the return value of
1403
       os.fspath() as an fd or buffer. */
1404
6.23k
    is_index = path->allow_fd && PyIndex_Check(o);
1405
6.23k
    is_bytes = PyBytes_Check(o);
1406
6.23k
    is_unicode = PyUnicode_Check(o);
1407
1408
6.23k
    if (!is_index && !is_unicode && !is_bytes) {
1409
        /* Inline PyOS_FSPath() for better error messages. */
1410
0
        PyObject *func, *res;
1411
1412
0
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1413
0
        if ((NULL == func) || (func == Py_None)) {
1414
0
            goto error_format;
1415
0
        }
1416
0
        res = _PyObject_CallNoArgs(func);
1417
0
        Py_DECREF(func);
1418
0
        if (NULL == res) {
1419
0
            goto error_exit;
1420
0
        }
1421
0
        else if (PyUnicode_Check(res)) {
1422
0
            is_unicode = 1;
1423
0
        }
1424
0
        else if (PyBytes_Check(res)) {
1425
0
            is_bytes = 1;
1426
0
        }
1427
0
        else {
1428
0
            PyErr_Format(PyExc_TypeError,
1429
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1430
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1431
0
                 _PyType_Name(Py_TYPE(res)));
1432
0
            Py_DECREF(res);
1433
0
            goto error_exit;
1434
0
        }
1435
1436
        /* still owns a reference to the original object */
1437
0
        Py_SETREF(o, res);
1438
0
    }
1439
1440
6.23k
    if (is_unicode) {
1441
6.23k
        if (path->make_wide) {
1442
80
            wide = PyUnicode_AsWideCharString(o, &length);
1443
80
            if (!wide) {
1444
0
                goto error_exit;
1445
0
            }
1446
#ifdef MS_WINDOWS
1447
            if (!path->nonstrict && length > 32767) {
1448
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1449
                goto error_exit;
1450
            }
1451
#endif
1452
80
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1453
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1454
0
                                 "embedded null character in %s");
1455
0
                goto error_exit;
1456
0
            }
1457
1458
80
            path->wide = wide;
1459
80
            path->narrow = NULL;
1460
80
            path->fd = -1;
1461
80
            wide = NULL;
1462
80
            goto success_exit;
1463
80
        }
1464
6.15k
        bytes = PyUnicode_EncodeFSDefault(o);
1465
6.15k
        if (!bytes) {
1466
0
            goto error_exit;
1467
0
        }
1468
6.15k
    }
1469
0
    else if (is_bytes) {
1470
0
        bytes = Py_NewRef(o);
1471
0
    }
1472
0
    else if (is_index) {
1473
0
        if (!_fd_converter(o, &path->fd)) {
1474
0
            goto error_exit;
1475
0
        }
1476
0
        path->wide = NULL;
1477
0
        path->narrow = NULL;
1478
0
        goto success_exit;
1479
0
    }
1480
0
    else {
1481
0
 error_format:
1482
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1483
0
            path->function_name ? path->function_name : "",
1484
0
            path->function_name ? ": "                : "",
1485
0
            path->argument_name ? path->argument_name : "path",
1486
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1487
0
                                               "integer or None" :
1488
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1489
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1490
0
                             "string, bytes or os.PathLike",
1491
0
            _PyType_Name(Py_TYPE(o)));
1492
0
        goto error_exit;
1493
0
    }
1494
1495
6.15k
    length = PyBytes_GET_SIZE(bytes);
1496
6.15k
    narrow = PyBytes_AS_STRING(bytes);
1497
6.15k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1498
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1499
0
        goto error_exit;
1500
0
    }
1501
1502
6.15k
    if (path->make_wide) {
1503
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1504
0
        if (!wo) {
1505
0
            goto error_exit;
1506
0
        }
1507
1508
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1509
0
        Py_DECREF(wo);
1510
0
        if (!wide) {
1511
0
            goto error_exit;
1512
0
        }
1513
#ifdef MS_WINDOWS
1514
        if (!path->nonstrict && length > 32767) {
1515
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1516
            goto error_exit;
1517
        }
1518
#endif
1519
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1520
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1521
0
                             "embedded null character in %s");
1522
0
            goto error_exit;
1523
0
        }
1524
0
        path->wide = wide;
1525
0
        path->narrow = NULL;
1526
0
        Py_DECREF(bytes);
1527
0
        wide = NULL;
1528
0
    }
1529
6.15k
    else {
1530
6.15k
        path->wide = NULL;
1531
6.15k
        path->narrow = narrow;
1532
6.15k
        if (bytes == o) {
1533
            /* Still a reference owned by path->object, don't have to
1534
            worry about path->narrow is used after free. */
1535
0
            Py_DECREF(bytes);
1536
0
        }
1537
6.15k
        else {
1538
6.15k
            path->cleanup = bytes;
1539
6.15k
        }
1540
6.15k
    }
1541
6.15k
    path->fd = -1;
1542
1543
6.23k
 success_exit:
1544
6.23k
    path->value_error = 0;
1545
6.23k
    path->length = length;
1546
6.23k
    path->object = o;
1547
6.23k
    return Py_CLEANUP_SUPPORTED;
1548
1549
0
 error_exit:
1550
0
    Py_XDECREF(o);
1551
0
    Py_XDECREF(bytes);
1552
0
    PyMem_Free(wide);
1553
0
    if (!path->suppress_value_error ||
1554
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1555
0
    {
1556
0
        return 0;
1557
0
    }
1558
0
    PyErr_Clear();
1559
0
    path->wide = NULL;
1560
0
    path->narrow = NULL;
1561
0
    path->fd = -1;
1562
0
    path->value_error = 1;
1563
0
    path->length = 0;
1564
0
    path->object = NULL;
1565
0
    return Py_CLEANUP_SUPPORTED;
1566
0
}
1567
1568
static void
1569
argument_unavailable_error(const char *function_name, const char *argument_name)
1570
0
{
1571
0
    PyErr_Format(PyExc_NotImplementedError,
1572
0
        "%s%s%s unavailable on this platform",
1573
0
        (function_name != NULL) ? function_name : "",
1574
0
        (function_name != NULL) ? ": ": "",
1575
0
        argument_name);
1576
0
}
1577
1578
static int
1579
dir_fd_unavailable(PyObject *o, void *p)
1580
16
{
1581
16
    int dir_fd;
1582
16
    if (!dir_fd_converter(o, &dir_fd))
1583
0
        return 0;
1584
16
    if (dir_fd != DEFAULT_DIR_FD) {
1585
0
        argument_unavailable_error(NULL, "dir_fd");
1586
0
        return 0;
1587
0
    }
1588
16
    *(int *)p = dir_fd;
1589
16
    return 1;
1590
16
}
1591
1592
static int
1593
fd_specified(const char *function_name, int fd)
1594
16
{
1595
16
    if (fd == -1)
1596
16
        return 0;
1597
1598
0
    argument_unavailable_error(function_name, "fd");
1599
0
    return 1;
1600
16
}
1601
1602
static int
1603
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1604
16
{
1605
16
    if (follow_symlinks)
1606
16
        return 0;
1607
1608
0
    argument_unavailable_error(function_name, "follow_symlinks");
1609
0
    return 1;
1610
16
}
1611
1612
static int
1613
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1614
5.31k
{
1615
5.31k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1616
0
        PyErr_Format(PyExc_ValueError,
1617
0
                     "%s: can't specify dir_fd without matching path",
1618
0
                     function_name);
1619
0
        return 1;
1620
0
    }
1621
5.31k
    return 0;
1622
5.31k
}
1623
1624
static int
1625
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1626
5.31k
{
1627
5.31k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1628
0
        PyErr_Format(PyExc_ValueError,
1629
0
                     "%s: can't specify both dir_fd and fd",
1630
0
                     function_name);
1631
0
        return 1;
1632
0
    }
1633
5.31k
    return 0;
1634
5.31k
}
1635
1636
static int
1637
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1638
                               int follow_symlinks)
1639
5.31k
{
1640
5.31k
    if ((fd > 0) && (!follow_symlinks)) {
1641
0
        PyErr_Format(PyExc_ValueError,
1642
0
                     "%s: cannot use fd and follow_symlinks together",
1643
0
                     function_name);
1644
0
        return 1;
1645
0
    }
1646
5.31k
    return 0;
1647
5.31k
}
1648
1649
static int
1650
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1651
                                   int follow_symlinks)
1652
16
{
1653
16
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1654
0
        PyErr_Format(PyExc_ValueError,
1655
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1656
0
                     function_name);
1657
0
        return 1;
1658
0
    }
1659
16
    return 0;
1660
16
}
1661
1662
#if defined(HAVE_WAITID)
1663
static int
1664
idtype_t_converter(PyObject *arg, void *addr)
1665
0
{
1666
0
    int value = PyLong_AsInt(arg);
1667
0
    if (value == -1 && PyErr_Occurred()) {
1668
0
        return 0;
1669
0
    }
1670
0
    *((idtype_t *)addr) = (idtype_t)(value);
1671
0
    return 1;
1672
0
}
1673
#endif
1674
1675
#ifdef MS_WINDOWS
1676
    typedef long long Py_off_t;
1677
#else
1678
    typedef off_t Py_off_t;
1679
#endif
1680
1681
static int
1682
Py_off_t_converter(PyObject *arg, void *addr)
1683
0
{
1684
#ifdef HAVE_LARGEFILE_SUPPORT
1685
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1686
#else
1687
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1688
0
#endif
1689
0
    if (PyErr_Occurred())
1690
0
        return 0;
1691
0
    return 1;
1692
0
}
1693
1694
static PyObject *
1695
PyLong_FromPy_off_t(Py_off_t offset)
1696
0
{
1697
#ifdef HAVE_LARGEFILE_SUPPORT
1698
    return PyLong_FromLongLong(offset);
1699
#else
1700
0
    return PyLong_FromLong(offset);
1701
0
#endif
1702
0
}
1703
1704
#ifdef HAVE_SIGSET_T
1705
/* Convert an iterable of integers to a sigset.
1706
   Return 1 on success, return 0 and raise an exception on error. */
1707
int
1708
_Py_Sigset_Converter(PyObject *obj, void *addr)
1709
0
{
1710
0
    sigset_t *mask = (sigset_t *)addr;
1711
0
    PyObject *iterator, *item;
1712
0
    long signum;
1713
0
    int overflow;
1714
1715
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1716
0
    if (sigemptyset(mask) < (0)) {
1717
        /* Probably only if mask == NULL. */
1718
0
        PyErr_SetFromErrno(PyExc_OSError);
1719
0
        return 0;
1720
0
    }
1721
1722
0
    iterator = PyObject_GetIter(obj);
1723
0
    if (iterator == NULL) {
1724
0
        return 0;
1725
0
    }
1726
1727
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1728
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1729
0
        Py_DECREF(item);
1730
0
        if (signum <= 0 || signum >= Py_NSIG) {
1731
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1732
0
                PyErr_Format(PyExc_ValueError,
1733
0
                             "signal number %ld out of range [1; %i]",
1734
0
                             signum, Py_NSIG - 1);
1735
0
            }
1736
0
            goto error;
1737
0
        }
1738
0
        if (sigaddset(mask, (int)signum)) {
1739
0
            if (errno != EINVAL) {
1740
                /* Probably impossible */
1741
0
                PyErr_SetFromErrno(PyExc_OSError);
1742
0
                goto error;
1743
0
            }
1744
            /* For backwards compatibility, allow idioms such as
1745
             * `range(1, NSIG)` but warn about invalid signal numbers
1746
             */
1747
0
            const char msg[] =
1748
0
                "invalid signal number %ld, please use valid_signals()";
1749
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1750
0
                goto error;
1751
0
            }
1752
0
        }
1753
0
    }
1754
0
    if (!PyErr_Occurred()) {
1755
0
        Py_DECREF(iterator);
1756
0
        return 1;
1757
0
    }
1758
1759
0
error:
1760
0
    Py_DECREF(iterator);
1761
0
    return 0;
1762
0
}
1763
#endif /* HAVE_SIGSET_T */
1764
1765
/* Return a dictionary corresponding to the POSIX environment table */
1766
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1767
/* On Darwin/MacOSX a shared library or framework has no access to
1768
** environ directly, we must obtain it with _NSGetEnviron(). See also
1769
** man environ(7).
1770
*/
1771
#include <crt_externs.h>
1772
#define USE_DARWIN_NS_GET_ENVIRON 1
1773
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1774
extern char **environ;
1775
#endif /* !_MSC_VER */
1776
1777
static PyObject *
1778
convertenviron(void)
1779
16
{
1780
16
    PyObject *d;
1781
#ifdef MS_WINDOWS
1782
    wchar_t **e;
1783
#else
1784
16
    char **e;
1785
16
#endif
1786
1787
16
    d = PyDict_New();
1788
16
    if (d == NULL)
1789
0
        return NULL;
1790
#ifdef MS_WINDOWS
1791
    /* _wenviron must be initialized in this way if the program is started
1792
       through main() instead of wmain(). */
1793
    (void)_wgetenv(L"");
1794
    e = _wenviron;
1795
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1796
    /* environ is not accessible as an extern in a shared object on OSX; use
1797
       _NSGetEnviron to resolve it. The value changes if you add environment
1798
       variables between calls to Py_Initialize, so don't cache the value. */
1799
    e = *_NSGetEnviron();
1800
#else
1801
16
    e = environ;
1802
16
#endif
1803
16
    if (e == NULL)
1804
0
        return d;
1805
592
    for (; *e != NULL; e++) {
1806
576
        PyObject *k;
1807
576
        PyObject *v;
1808
#ifdef MS_WINDOWS
1809
        const wchar_t *p = wcschr(*e, L'=');
1810
#else
1811
576
        const char *p = strchr(*e, '=');
1812
576
#endif
1813
576
        if (p == NULL)
1814
0
            continue;
1815
#ifdef MS_WINDOWS
1816
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1817
#else
1818
576
        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1819
576
#endif
1820
576
        if (k == NULL) {
1821
0
            Py_DECREF(d);
1822
0
            return NULL;
1823
0
        }
1824
#ifdef MS_WINDOWS
1825
        v = PyUnicode_FromWideChar(p+1, -1);
1826
#else
1827
576
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1828
576
#endif
1829
576
        if (v == NULL) {
1830
0
            Py_DECREF(k);
1831
0
            Py_DECREF(d);
1832
0
            return NULL;
1833
0
        }
1834
576
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1835
0
            Py_DECREF(v);
1836
0
            Py_DECREF(k);
1837
0
            Py_DECREF(d);
1838
0
            return NULL;
1839
0
        }
1840
576
        Py_DECREF(k);
1841
576
        Py_DECREF(v);
1842
576
    }
1843
16
    return d;
1844
16
}
1845
1846
/* Set a POSIX-specific error from errno, and return NULL */
1847
1848
static PyObject *
1849
posix_error(void)
1850
0
{
1851
0
    return PyErr_SetFromErrno(PyExc_OSError);
1852
0
}
1853
1854
#ifdef MS_WINDOWS
1855
static PyObject *
1856
win32_error(const char* function, const char* filename)
1857
{
1858
    /* XXX We should pass the function name along in the future.
1859
       (winreg.c also wants to pass the function name.)
1860
       This would however require an additional param to the
1861
       Windows error object, which is non-trivial.
1862
    */
1863
    errno = GetLastError();
1864
    if (filename)
1865
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1866
    else
1867
        return PyErr_SetFromWindowsErr(errno);
1868
}
1869
1870
static PyObject *
1871
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1872
{
1873
    /* XXX - see win32_error for comments on 'function' */
1874
    if (filename)
1875
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1876
                    PyExc_OSError,
1877
                    err,
1878
                    filename);
1879
    else
1880
        return PyErr_SetFromWindowsErr(err);
1881
}
1882
1883
static PyObject *
1884
win32_error_object(const char* function, PyObject* filename)
1885
{
1886
    errno = GetLastError();
1887
    return win32_error_object_err(function, filename, errno);
1888
}
1889
1890
#endif /* MS_WINDOWS */
1891
1892
static PyObject *
1893
posix_path_object_error(PyObject *path)
1894
314
{
1895
314
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1896
314
}
1897
1898
static PyObject *
1899
path_object_error(PyObject *path)
1900
314
{
1901
#ifdef MS_WINDOWS
1902
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1903
                PyExc_OSError, 0, path);
1904
#else
1905
314
    return posix_path_object_error(path);
1906
314
#endif
1907
314
}
1908
1909
static PyObject *
1910
path_object_error2(PyObject *path, PyObject *path2)
1911
0
{
1912
#ifdef MS_WINDOWS
1913
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1914
                PyExc_OSError, 0, path, path2);
1915
#else
1916
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1917
0
#endif
1918
0
}
1919
1920
static PyObject *
1921
path_error(path_t *path)
1922
314
{
1923
314
    return path_object_error(path->object);
1924
314
}
1925
1926
static PyObject *
1927
posix_path_error(path_t *path)
1928
0
{
1929
0
    return posix_path_object_error(path->object);
1930
0
}
1931
1932
static PyObject *
1933
path_error2(path_t *path, path_t *path2)
1934
0
{
1935
0
    return path_object_error2(path->object, path2->object);
1936
0
}
1937
1938
1939
/* POSIX generic methods */
1940
1941
static PyObject *
1942
posix_fildes_fd(int fd, int (*func)(int))
1943
0
{
1944
0
    int res;
1945
0
    int async_err = 0;
1946
1947
0
    do {
1948
0
        Py_BEGIN_ALLOW_THREADS
1949
0
        _Py_BEGIN_SUPPRESS_IPH
1950
0
        res = (*func)(fd);
1951
0
        _Py_END_SUPPRESS_IPH
1952
0
        Py_END_ALLOW_THREADS
1953
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1954
0
    if (res != 0)
1955
0
        return (!async_err) ? posix_error() : NULL;
1956
0
    Py_RETURN_NONE;
1957
0
}
1958
1959
1960
#ifdef MS_WINDOWS
1961
/* This is a reimplementation of the C library's chdir function,
1962
   but one that produces Win32 errors instead of DOS error codes.
1963
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1964
   it also needs to set "magic" environment variables indicating
1965
   the per-drive current directory, which are of the form =<drive>: */
1966
static BOOL __stdcall
1967
win32_wchdir(LPCWSTR path)
1968
{
1969
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1970
    int result;
1971
    wchar_t env[4] = L"=x:";
1972
1973
    if(!SetCurrentDirectoryW(path))
1974
        return FALSE;
1975
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1976
    if (!result)
1977
        return FALSE;
1978
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1979
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1980
        if (!new_path) {
1981
            SetLastError(ERROR_OUTOFMEMORY);
1982
            return FALSE;
1983
        }
1984
        result = GetCurrentDirectoryW(result, new_path);
1985
        if (!result) {
1986
            PyMem_RawFree(new_path);
1987
            return FALSE;
1988
        }
1989
    }
1990
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1991
                            wcsncmp(new_path, L"//", 2) == 0);
1992
    if (!is_unc_like_path) {
1993
        env[1] = new_path[0];
1994
        result = SetEnvironmentVariableW(env, new_path);
1995
    }
1996
    if (new_path != path_buf)
1997
        PyMem_RawFree(new_path);
1998
    return result ? TRUE : FALSE;
1999
}
2000
#endif
2001
2002
#ifdef MS_WINDOWS
2003
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2004
   - time stamps are restricted to second resolution
2005
   - file modification times suffer from forth-and-back conversions between
2006
     UTC and local time
2007
   Therefore, we implement our own stat, based on the Win32 API directly.
2008
*/
2009
#define HAVE_STAT_NSEC 1
2010
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2011
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2012
2013
static void
2014
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2015
                       BY_HANDLE_FILE_INFORMATION *info,
2016
                       ULONG *reparse_tag)
2017
{
2018
    memset(info, 0, sizeof(*info));
2019
    info->dwFileAttributes = pFileData->dwFileAttributes;
2020
    info->ftCreationTime   = pFileData->ftCreationTime;
2021
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
2022
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
2023
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
2024
    info->nFileSizeLow     = pFileData->nFileSizeLow;
2025
/*  info->nNumberOfLinks   = 1; */
2026
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2027
        *reparse_tag = pFileData->dwReserved0;
2028
    else
2029
        *reparse_tag = 0;
2030
}
2031
2032
static BOOL
2033
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
2034
{
2035
    HANDLE hFindFile;
2036
    WIN32_FIND_DATAW FileData;
2037
    LPCWSTR filename = pszFile;
2038
    size_t n = wcslen(pszFile);
2039
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2040
        // cannot use PyMem_Malloc here because we do not hold the GIL
2041
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2042
        if(!filename) {
2043
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2044
            return FALSE;
2045
        }
2046
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2047
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2048
            ((LPWSTR)filename)[n] = L'\0';
2049
        }
2050
        if (!n || (n == 1 && filename[1] == L':')) {
2051
            // Nothing left to query
2052
            free((void *)filename);
2053
            return FALSE;
2054
        }
2055
    }
2056
    hFindFile = FindFirstFileW(filename, &FileData);
2057
    if (pszFile != filename) {
2058
        free((void *)filename);
2059
    }
2060
    if (hFindFile == INVALID_HANDLE_VALUE) {
2061
        return FALSE;
2062
    }
2063
    FindClose(hFindFile);
2064
    find_data_to_file_info(&FileData, info, reparse_tag);
2065
    return TRUE;
2066
}
2067
2068
2069
static void
2070
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2071
                         struct _Py_stat_struct *result)
2072
{
2073
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2074
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2075
           the filename has an extension that is commonly used by files
2076
           that CreateProcessW can execute. A real implementation calls
2077
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2078
           AccessCheck to check for generic read, write, and execute
2079
           access. */
2080
        const wchar_t *fileExtension = wcsrchr(path, '.');
2081
        if (fileExtension) {
2082
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2083
                _wcsicmp(fileExtension, L".bat") == 0 ||
2084
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2085
                _wcsicmp(fileExtension, L".com") == 0) {
2086
                result->st_mode |= 0111;
2087
            }
2088
        }
2089
    }
2090
}
2091
2092
2093
static int
2094
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2095
                      BOOL traverse)
2096
{
2097
    HANDLE hFile;
2098
    BY_HANDLE_FILE_INFORMATION fileInfo;
2099
    FILE_BASIC_INFO basicInfo;
2100
    FILE_BASIC_INFO *pBasicInfo = NULL;
2101
    FILE_ID_INFO idInfo;
2102
    FILE_ID_INFO *pIdInfo = NULL;
2103
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2104
    DWORD fileType, error;
2105
    BOOL isUnhandledTag = FALSE;
2106
    int retval = 0;
2107
2108
    DWORD access = FILE_READ_ATTRIBUTES;
2109
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2110
    if (!traverse) {
2111
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2112
    }
2113
2114
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2115
    if (hFile == INVALID_HANDLE_VALUE) {
2116
        /* Either the path doesn't exist, or the caller lacks access. */
2117
        error = GetLastError();
2118
        switch (error) {
2119
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2120
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2121
            /* Try reading the parent directory. */
2122
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2123
                /* Cannot read the parent directory. */
2124
                switch (GetLastError()) {
2125
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2126
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2127
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2128
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2129
                    break;
2130
                /* Restore the error from CreateFileW(). */
2131
                default:
2132
                    SetLastError(error);
2133
                }
2134
2135
                return -1;
2136
            }
2137
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2138
                if (traverse ||
2139
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2140
                    /* The stat call has to traverse but cannot, so fail. */
2141
                    SetLastError(error);
2142
                    return -1;
2143
                }
2144
            }
2145
            break;
2146
2147
        case ERROR_INVALID_PARAMETER:
2148
            /* \\.\con requires read or write access. */
2149
            hFile = CreateFileW(path, access | GENERIC_READ,
2150
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2151
                        OPEN_EXISTING, flags, NULL);
2152
            if (hFile == INVALID_HANDLE_VALUE) {
2153
                SetLastError(error);
2154
                return -1;
2155
            }
2156
            break;
2157
2158
        case ERROR_CANT_ACCESS_FILE:
2159
            /* bpo37834: open unhandled reparse points if traverse fails. */
2160
            if (traverse) {
2161
                traverse = FALSE;
2162
                isUnhandledTag = TRUE;
2163
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2164
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2165
            }
2166
            if (hFile == INVALID_HANDLE_VALUE) {
2167
                SetLastError(error);
2168
                return -1;
2169
            }
2170
            break;
2171
2172
        default:
2173
            return -1;
2174
        }
2175
    }
2176
2177
    if (hFile != INVALID_HANDLE_VALUE) {
2178
        /* Handle types other than files on disk. */
2179
        fileType = GetFileType(hFile);
2180
        if (fileType != FILE_TYPE_DISK) {
2181
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2182
                retval = -1;
2183
                goto cleanup;
2184
            }
2185
            DWORD fileAttributes = GetFileAttributesW(path);
2186
            memset(result, 0, sizeof(*result));
2187
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2188
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2189
                /* \\.\pipe\ or \\.\mailslot\ */
2190
                result->st_mode = _S_IFDIR;
2191
            } else if (fileType == FILE_TYPE_CHAR) {
2192
                /* \\.\nul */
2193
                result->st_mode = _S_IFCHR;
2194
            } else if (fileType == FILE_TYPE_PIPE) {
2195
                /* \\.\pipe\spam */
2196
                result->st_mode = _S_IFIFO;
2197
            }
2198
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2199
            goto cleanup;
2200
        }
2201
2202
        /* Query the reparse tag, and traverse a non-link. */
2203
        if (!traverse) {
2204
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2205
                    &tagInfo, sizeof(tagInfo))) {
2206
                /* Allow devices that do not support FileAttributeTagInfo. */
2207
                switch (GetLastError()) {
2208
                case ERROR_INVALID_PARAMETER:
2209
                case ERROR_INVALID_FUNCTION:
2210
                case ERROR_NOT_SUPPORTED:
2211
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2212
                    tagInfo.ReparseTag = 0;
2213
                    break;
2214
                default:
2215
                    retval = -1;
2216
                    goto cleanup;
2217
                }
2218
            } else if (tagInfo.FileAttributes &
2219
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2220
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2221
                    if (isUnhandledTag) {
2222
                        /* Traversing previously failed for either this link
2223
                           or its target. */
2224
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2225
                        retval = -1;
2226
                        goto cleanup;
2227
                    }
2228
                /* Traverse a non-link, but not if traversing already failed
2229
                   for an unhandled tag. */
2230
                } else if (!isUnhandledTag) {
2231
                    CloseHandle(hFile);
2232
                    return win32_xstat_slow_impl(path, result, TRUE);
2233
                }
2234
            }
2235
        }
2236
2237
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2238
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2239
                                          &basicInfo, sizeof(basicInfo))) {
2240
            switch (GetLastError()) {
2241
            case ERROR_INVALID_PARAMETER:
2242
            case ERROR_INVALID_FUNCTION:
2243
            case ERROR_NOT_SUPPORTED:
2244
                /* Volumes and physical disks are block devices, e.g.
2245
                   \\.\C: and \\.\PhysicalDrive0. */
2246
                memset(result, 0, sizeof(*result));
2247
                result->st_mode = 0x6000; /* S_IFBLK */
2248
                goto cleanup;
2249
            }
2250
            retval = -1;
2251
            goto cleanup;
2252
        }
2253
2254
        /* Successfully got FileBasicInfo, so we'll pass it along */
2255
        pBasicInfo = &basicInfo;
2256
2257
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2258
            /* Successfully got FileIdInfo, so pass it along */
2259
            pIdInfo = &idInfo;
2260
        }
2261
    }
2262
2263
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2264
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2265
2266
cleanup:
2267
    if (hFile != INVALID_HANDLE_VALUE) {
2268
        /* Preserve last error if we are failing */
2269
        error = retval ? GetLastError() : 0;
2270
        if (!CloseHandle(hFile)) {
2271
            retval = -1;
2272
        } else if (retval) {
2273
            /* Restore last error */
2274
            SetLastError(error);
2275
        }
2276
    }
2277
2278
    return retval;
2279
}
2280
2281
static int
2282
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2283
                 BOOL traverse)
2284
{
2285
    FILE_STAT_BASIC_INFORMATION statInfo;
2286
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2287
                                     &statInfo, sizeof(statInfo))) {
2288
        if (// Cannot use fast path for reparse points ...
2289
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2290
            // ... unless it's a name surrogate (symlink) and we're not following
2291
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2292
        ) {
2293
            _Py_stat_basic_info_to_stat(&statInfo, result);
2294
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2295
            return 0;
2296
        }
2297
    } else {
2298
        switch(GetLastError()) {
2299
        case ERROR_FILE_NOT_FOUND:
2300
        case ERROR_PATH_NOT_FOUND:
2301
        case ERROR_NOT_READY:
2302
        case ERROR_BAD_NET_NAME:
2303
            /* These errors aren't worth retrying with the slow path */
2304
            return -1;
2305
        case ERROR_NOT_SUPPORTED:
2306
            /* indicates the API couldn't be loaded */
2307
            break;
2308
        }
2309
    }
2310
2311
    return win32_xstat_slow_impl(path, result, traverse);
2312
}
2313
2314
static int
2315
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2316
{
2317
    /* Protocol violation: we explicitly clear errno, instead of
2318
       setting it to a POSIX error. Callers should use GetLastError. */
2319
    int code = win32_xstat_impl(path, result, traverse);
2320
    errno = 0;
2321
2322
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2323
    result->st_ctime = result->st_birthtime;
2324
    result->st_ctime_nsec = result->st_birthtime_nsec;
2325
    return code;
2326
}
2327
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2328
2329
   In Posix, stat automatically traverses symlinks and returns the stat
2330
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2331
   default does not traverse symlinks and instead returns attributes for
2332
   the symlink.
2333
2334
   Instead, we will open the file (which *does* traverse symlinks by default)
2335
   and GetFileInformationByHandle(). */
2336
2337
static int
2338
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2339
{
2340
    return win32_xstat(path, result, FALSE);
2341
}
2342
2343
static int
2344
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2345
{
2346
    return win32_xstat(path, result, TRUE);
2347
}
2348
2349
#endif /* MS_WINDOWS */
2350
2351
PyDoc_STRVAR(stat_result__doc__,
2352
"stat_result: Result from stat, fstat, or lstat.\n\n\
2353
This object may be accessed either as a tuple of\n\
2354
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2355
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2356
\n\
2357
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2358
or st_flags, they are available as attributes only.\n\
2359
\n\
2360
See os.stat for more information.");
2361
2362
static PyStructSequence_Field stat_result_fields[] = {
2363
    {"st_mode",    "protection bits"},
2364
    {"st_ino",     "inode"},
2365
    {"st_dev",     "device"},
2366
    {"st_nlink",   "number of hard links"},
2367
    {"st_uid",     "user ID of owner"},
2368
    {"st_gid",     "group ID of owner"},
2369
    {"st_size",    "total size, in bytes"},
2370
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2371
    {NULL,   "integer time of last access"},
2372
    {NULL,   "integer time of last modification"},
2373
    {NULL,   "integer time of last change"},
2374
    {"st_atime",   "time of last access"},
2375
    {"st_mtime",   "time of last modification"},
2376
    {"st_ctime",   "time of last change"},
2377
    {"st_atime_ns",   "time of last access in nanoseconds"},
2378
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2379
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2380
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2381
    {"st_blksize", "blocksize for filesystem I/O"},
2382
#endif
2383
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2384
    {"st_blocks",  "number of blocks allocated"},
2385
#endif
2386
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2387
    {"st_rdev",    "device type (if inode device)"},
2388
#endif
2389
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2390
    {"st_flags",   "user defined flags for file"},
2391
#endif
2392
#ifdef HAVE_STRUCT_STAT_ST_GEN
2393
    {"st_gen",    "generation number"},
2394
#endif
2395
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2396
    {"st_birthtime",   "time of creation"},
2397
#endif
2398
#ifdef MS_WINDOWS
2399
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2400
#endif
2401
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2402
    {"st_file_attributes", "Windows file attribute bits"},
2403
#endif
2404
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2405
    {"st_fstype",  "Type of filesystem"},
2406
#endif
2407
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2408
    {"st_reparse_tag", "Windows reparse tag"},
2409
#endif
2410
    {0}
2411
};
2412
2413
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2414
#define ST_BLKSIZE_IDX 16
2415
#else
2416
#define ST_BLKSIZE_IDX 15
2417
#endif
2418
2419
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2420
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2421
#else
2422
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2423
#endif
2424
2425
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2426
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2427
#else
2428
#define ST_RDEV_IDX ST_BLOCKS_IDX
2429
#endif
2430
2431
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2432
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2433
#else
2434
#define ST_FLAGS_IDX ST_RDEV_IDX
2435
#endif
2436
2437
#ifdef HAVE_STRUCT_STAT_ST_GEN
2438
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2439
#else
2440
#define ST_GEN_IDX ST_FLAGS_IDX
2441
#endif
2442
2443
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2444
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2445
#else
2446
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2447
#endif
2448
2449
#ifdef MS_WINDOWS
2450
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2451
#else
2452
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2453
#endif
2454
2455
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2456
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2457
#else
2458
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2459
#endif
2460
2461
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2462
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2463
#else
2464
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2465
#endif
2466
2467
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2468
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2469
#else
2470
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2471
#endif
2472
2473
static PyStructSequence_Desc stat_result_desc = {
2474
    "os.stat_result", /* name; see issue gh-63408 */
2475
    stat_result__doc__, /* doc */
2476
    stat_result_fields,
2477
    10
2478
};
2479
2480
PyDoc_STRVAR(statvfs_result__doc__,
2481
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2482
This object may be accessed either as a tuple of\n\
2483
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2484
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2485
\n\
2486
See os.statvfs for more information.");
2487
2488
static PyStructSequence_Field statvfs_result_fields[] = {
2489
    {"f_bsize",  },
2490
    {"f_frsize", },
2491
    {"f_blocks", },
2492
    {"f_bfree",  },
2493
    {"f_bavail", },
2494
    {"f_files",  },
2495
    {"f_ffree",  },
2496
    {"f_favail", },
2497
    {"f_flag",   },
2498
    {"f_namemax",},
2499
    {"f_fsid",   },
2500
    {0}
2501
};
2502
2503
static PyStructSequence_Desc statvfs_result_desc = {
2504
    "os.statvfs_result", /* name; see issue gh-63408 */
2505
    statvfs_result__doc__, /* doc */
2506
    statvfs_result_fields,
2507
    10
2508
};
2509
2510
#if defined(HAVE_WAITID)
2511
PyDoc_STRVAR(waitid_result__doc__,
2512
"waitid_result: Result from waitid.\n\n\
2513
This object may be accessed either as a tuple of\n\
2514
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2515
or via the attributes si_pid, si_uid, and so on.\n\
2516
\n\
2517
See os.waitid for more information.");
2518
2519
static PyStructSequence_Field waitid_result_fields[] = {
2520
    {"si_pid",  },
2521
    {"si_uid", },
2522
    {"si_signo", },
2523
    {"si_status",  },
2524
    {"si_code", },
2525
    {0}
2526
};
2527
2528
static PyStructSequence_Desc waitid_result_desc = {
2529
    MODNAME ".waitid_result", /* name */
2530
    waitid_result__doc__, /* doc */
2531
    waitid_result_fields,
2532
    5
2533
};
2534
#endif
2535
2536
static PyObject *
2537
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2538
0
{
2539
0
    PyStructSequence *result;
2540
0
    int i;
2541
2542
    // ht_module doesn't get set in PyStructSequence_NewType(),
2543
    // so we can't use PyType_GetModule().
2544
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2545
0
    if (mod == NULL) {
2546
0
        return NULL;
2547
0
    }
2548
0
    _posixstate *state = get_posix_state(mod);
2549
0
    Py_DECREF(mod);
2550
0
    if (state == NULL) {
2551
0
        return NULL;
2552
0
    }
2553
0
#define structseq_new state->statresult_new_orig
2554
2555
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2556
0
    if (!result)
2557
0
        return NULL;
2558
    /* If we have been initialized from a tuple,
2559
       st_?time might be set to None. Initialize it
2560
       from the int slots.  */
2561
0
    for (i = 7; i <= 9; i++) {
2562
0
        if (result->ob_item[i+3] == Py_None) {
2563
0
            Py_DECREF(Py_None);
2564
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2565
0
        }
2566
0
    }
2567
0
    return (PyObject*)result;
2568
0
}
2569
2570
static int
2571
_posix_clear(PyObject *module)
2572
0
{
2573
0
    _posixstate *state = get_posix_state(module);
2574
0
    Py_CLEAR(state->billion);
2575
0
    Py_CLEAR(state->DirEntryType);
2576
0
    Py_CLEAR(state->ScandirIteratorType);
2577
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2578
0
    Py_CLEAR(state->SchedParamType);
2579
0
#endif
2580
0
    Py_CLEAR(state->StatResultType);
2581
0
#ifdef HAVE_STATX
2582
0
    Py_CLEAR(state->StatxResultType);
2583
0
#endif
2584
0
    Py_CLEAR(state->StatVFSResultType);
2585
0
    Py_CLEAR(state->TerminalSizeType);
2586
0
    Py_CLEAR(state->TimesResultType);
2587
0
    Py_CLEAR(state->UnameResultType);
2588
0
#if defined(HAVE_WAITID)
2589
0
    Py_CLEAR(state->WaitidResultType);
2590
0
#endif
2591
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2592
0
    Py_CLEAR(state->struct_rusage);
2593
0
#endif
2594
0
    Py_CLEAR(state->st_mode);
2595
0
    return 0;
2596
0
}
2597
2598
static int
2599
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2600
865
{
2601
865
    _posixstate *state = get_posix_state(module);
2602
865
    Py_VISIT(state->billion);
2603
865
    Py_VISIT(state->DirEntryType);
2604
865
    Py_VISIT(state->ScandirIteratorType);
2605
865
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2606
865
    Py_VISIT(state->SchedParamType);
2607
865
#endif
2608
865
    Py_VISIT(state->StatResultType);
2609
865
#ifdef HAVE_STATX
2610
865
    Py_VISIT(state->StatxResultType);
2611
865
#endif
2612
865
    Py_VISIT(state->StatVFSResultType);
2613
865
    Py_VISIT(state->TerminalSizeType);
2614
865
    Py_VISIT(state->TimesResultType);
2615
865
    Py_VISIT(state->UnameResultType);
2616
865
#if defined(HAVE_WAITID)
2617
865
    Py_VISIT(state->WaitidResultType);
2618
865
#endif
2619
865
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2620
865
    Py_VISIT(state->struct_rusage);
2621
865
#endif
2622
865
    Py_VISIT(state->st_mode);
2623
865
    return 0;
2624
865
}
2625
2626
static void
2627
_posix_free(void *module)
2628
0
{
2629
0
   _posix_clear((PyObject *)module);
2630
0
}
2631
2632
2633
45.0k
#define SEC_TO_NS (1000000000LL)
2634
static PyObject *
2635
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2636
15.0k
{
2637
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2638
15.0k
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2639
15.0k
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2640
15.0k
    }
2641
0
    else {
2642
0
        PyObject *ns_total = NULL;
2643
0
        PyObject *s_in_ns = NULL;
2644
0
        PyObject *s = _PyLong_FromTime_t(sec);
2645
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2646
0
        if (s == NULL || ns_fractional == NULL) {
2647
0
            goto exit;
2648
0
        }
2649
2650
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2651
0
        if (s_in_ns == NULL) {
2652
0
            goto exit;
2653
0
        }
2654
2655
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2656
2657
0
    exit:
2658
0
        Py_XDECREF(s);
2659
0
        Py_XDECREF(ns_fractional);
2660
0
        Py_XDECREF(s_in_ns);
2661
0
        return ns_total;
2662
0
    }
2663
15.0k
}
2664
2665
static int
2666
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2667
          int ns_index, time_t sec, unsigned long nsec)
2668
15.0k
{
2669
15.0k
    assert(!PyErr_Occurred());
2670
15.0k
    assert(nsec < SEC_TO_NS);
2671
2672
15.0k
    if (s_index >= 0) {
2673
15.0k
        PyObject *s = _PyLong_FromTime_t(sec);
2674
15.0k
        if (s == NULL) {
2675
0
            return -1;
2676
0
        }
2677
15.0k
        PyStructSequence_SET_ITEM(v, s_index, s);
2678
15.0k
    }
2679
2680
15.0k
    if (f_index >= 0) {
2681
15.0k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2682
15.0k
        if (float_s == NULL) {
2683
0
            return -1;
2684
0
        }
2685
15.0k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2686
15.0k
    }
2687
2688
15.0k
    if (ns_index >= 0) {
2689
15.0k
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2690
15.0k
        if (ns_total == NULL) {
2691
0
            return -1;
2692
0
        }
2693
15.0k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2694
15.0k
    }
2695
2696
15.0k
    assert(!PyErr_Occurred());
2697
15.0k
    return 0;
2698
15.0k
}
2699
#undef SEC_TO_NS
2700
2701
#ifdef MS_WINDOWS
2702
static PyObject*
2703
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2704
{
2705
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2706
    if (!o_low || !high) {
2707
        return o_low;
2708
    }
2709
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2710
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2711
    if (!l64) {
2712
        Py_XDECREF(o_high);
2713
        Py_DECREF(o_low);
2714
        return NULL;
2715
    }
2716
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2717
    Py_DECREF(l64);
2718
    if (!o_high) {
2719
        Py_DECREF(o_low);
2720
        return NULL;
2721
    }
2722
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2723
    Py_DECREF(o_high);
2724
    return o_low;
2725
}
2726
#endif
2727
2728
/* pack a system stat C structure into the Python stat tuple
2729
   (used by posix_stat() and posix_fstat()) */
2730
static PyObject*
2731
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2732
5.00k
{
2733
5.00k
    assert(!PyErr_Occurred());
2734
2735
5.00k
    _posixstate *state = get_posix_state(module);
2736
5.00k
    PyObject *StatResultType = state->StatResultType;
2737
5.00k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2738
5.00k
    if (v == NULL) {
2739
0
        return NULL;
2740
0
    }
2741
2742
5.00k
#define SET_ITEM(pos, expr) \
2743
50.0k
    do { \
2744
50.0k
        PyObject *obj = (expr); \
2745
50.0k
        if (obj == NULL) { \
2746
0
            goto error; \
2747
0
        } \
2748
50.0k
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2749
50.0k
    } while (0)
2750
2751
5.00k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2752
#ifdef MS_WINDOWS
2753
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2754
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2755
#else
2756
5.00k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2757
5.00k
                  "stat.st_ino is larger than unsigned long long");
2758
5.00k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2759
5.00k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2760
5.00k
#endif
2761
5.00k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2762
#if defined(MS_WINDOWS)
2763
    SET_ITEM(4, PyLong_FromLong(0));
2764
    SET_ITEM(5, PyLong_FromLong(0));
2765
#else
2766
5.00k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2767
5.00k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2768
5.00k
#endif
2769
5.00k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2770
5.00k
                  "stat.st_size is larger than long long");
2771
5.00k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2772
2773
    // Set st_atime, st_mtime and st_ctime
2774
5.00k
    unsigned long ansec, mnsec, cnsec;
2775
5.00k
#if defined(HAVE_STAT_TV_NSEC)
2776
5.00k
    ansec = st->st_atim.tv_nsec;
2777
5.00k
    mnsec = st->st_mtim.tv_nsec;
2778
5.00k
    cnsec = st->st_ctim.tv_nsec;
2779
#elif defined(HAVE_STAT_TV_NSEC2)
2780
    ansec = st->st_atimespec.tv_nsec;
2781
    mnsec = st->st_mtimespec.tv_nsec;
2782
    cnsec = st->st_ctimespec.tv_nsec;
2783
#elif defined(HAVE_STAT_NSEC)
2784
    ansec = st->st_atime_nsec;
2785
    mnsec = st->st_mtime_nsec;
2786
    cnsec = st->st_ctime_nsec;
2787
#else
2788
    ansec = mnsec = cnsec = 0;
2789
#endif
2790
5.00k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2791
0
        goto error;
2792
0
    }
2793
5.00k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2794
0
        goto error;
2795
0
    }
2796
5.00k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2797
0
        goto error;
2798
0
    }
2799
2800
5.00k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2801
5.00k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2802
5.00k
#endif
2803
5.00k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2804
5.00k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2805
5.00k
#endif
2806
5.00k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2807
5.00k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2808
5.00k
#endif
2809
#ifdef HAVE_STRUCT_STAT_ST_GEN
2810
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2811
#endif
2812
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2813
    {
2814
      unsigned long bsec, bnsec;
2815
      bsec = (long)st->st_birthtime;
2816
#ifdef HAVE_STAT_TV_NSEC2
2817
      bnsec = st->st_birthtimespec.tv_nsec;
2818
#else
2819
      bnsec = 0;
2820
#endif
2821
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2822
    }
2823
#elif defined(MS_WINDOWS)
2824
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2825
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2826
        goto error;
2827
    }
2828
#endif
2829
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2830
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2831
#endif
2832
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2833
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2834
             PyLong_FromUnsignedLong(st->st_file_attributes));
2835
#endif
2836
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2837
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2838
#endif
2839
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2840
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2841
#endif
2842
2843
5.00k
    assert(!PyErr_Occurred());
2844
5.00k
    return v;
2845
2846
0
error:
2847
0
    Py_DECREF(v);
2848
0
    return NULL;
2849
2850
5.00k
#undef SET_ITEM
2851
5.00k
}
2852
2853
/* POSIX methods */
2854
2855
2856
static PyObject *
2857
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2858
              int dir_fd, int follow_symlinks)
2859
5.31k
{
2860
5.31k
    STRUCT_STAT st;
2861
5.31k
    int result;
2862
2863
5.31k
#ifdef HAVE_FSTATAT
2864
5.31k
    int fstatat_unavailable = 0;
2865
5.31k
#endif
2866
2867
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2868
    if (follow_symlinks_specified(function_name, follow_symlinks))
2869
        return NULL;
2870
#endif
2871
2872
5.31k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2873
5.31k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2874
5.31k
        fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2875
0
        return NULL;
2876
2877
5.31k
    Py_BEGIN_ALLOW_THREADS
2878
5.31k
    if (path->fd != -1)
2879
0
        result = FSTAT(path->fd, &st);
2880
#ifdef MS_WINDOWS
2881
    else if (follow_symlinks)
2882
        result = win32_stat(path->wide, &st);
2883
    else
2884
        result = win32_lstat(path->wide, &st);
2885
#else
2886
5.31k
    else
2887
5.31k
#if defined(HAVE_LSTAT)
2888
5.31k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2889
0
        result = LSTAT(path->narrow, &st);
2890
5.31k
    else
2891
5.31k
#endif /* HAVE_LSTAT */
2892
5.31k
#ifdef HAVE_FSTATAT
2893
5.31k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2894
0
        if (HAVE_FSTATAT_RUNTIME) {
2895
0
            result = fstatat(dir_fd, path->narrow, &st,
2896
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2897
2898
0
        } else {
2899
0
            fstatat_unavailable = 1;
2900
0
        }
2901
0
    } else
2902
5.31k
#endif /* HAVE_FSTATAT */
2903
5.31k
        result = STAT(path->narrow, &st);
2904
5.31k
#endif /* MS_WINDOWS */
2905
5.31k
    Py_END_ALLOW_THREADS
2906
2907
5.31k
#ifdef HAVE_FSTATAT
2908
5.31k
    if (fstatat_unavailable) {
2909
0
        argument_unavailable_error("stat", "dir_fd");
2910
0
        return NULL;
2911
0
    }
2912
5.31k
#endif
2913
2914
5.31k
    if (result != 0) {
2915
314
        return path_error(path);
2916
314
    }
2917
2918
5.00k
    return _pystat_fromstructstat(module, &st);
2919
5.31k
}
2920
2921
/*[python input]
2922
2923
for s in """
2924
2925
FACCESSAT
2926
FCHMODAT
2927
FCHOWNAT
2928
FSTATAT
2929
LINKAT
2930
MKDIRAT
2931
MKFIFOAT
2932
MKNODAT
2933
OPENAT
2934
READLINKAT
2935
SYMLINKAT
2936
UNLINKAT
2937
2938
""".strip().split():
2939
    s = s.strip()
2940
    print("""
2941
#ifdef HAVE_{s}
2942
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2943
#else
2944
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2945
#endif
2946
""".rstrip().format(s=s))
2947
2948
for s in """
2949
2950
FCHDIR
2951
FCHMOD
2952
FCHOWN
2953
FDOPENDIR
2954
FEXECVE
2955
FPATHCONF
2956
FSTATVFS
2957
FTRUNCATE
2958
2959
""".strip().split():
2960
    s = s.strip()
2961
    print("""
2962
#ifdef HAVE_{s}
2963
    #define PATH_HAVE_{s} 1
2964
#else
2965
    #define PATH_HAVE_{s} 0
2966
#endif
2967
2968
""".rstrip().format(s=s))
2969
[python start generated code]*/
2970
2971
#ifdef HAVE_FACCESSAT
2972
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2973
#else
2974
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2975
#endif
2976
2977
#ifdef HAVE_FCHMODAT
2978
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2979
#else
2980
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2981
#endif
2982
2983
#ifdef HAVE_FCHOWNAT
2984
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2985
#else
2986
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2987
#endif
2988
2989
#ifdef HAVE_FSTATAT
2990
0
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2991
#else
2992
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2993
#endif
2994
2995
#ifdef HAVE_LINKAT
2996
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2997
#else
2998
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2999
#endif
3000
3001
#ifdef HAVE_MKDIRAT
3002
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3003
#else
3004
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3005
#endif
3006
3007
#ifdef HAVE_MKFIFOAT
3008
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3009
#else
3010
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3011
#endif
3012
3013
#ifdef HAVE_MKNODAT
3014
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3015
#else
3016
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3017
#endif
3018
3019
#ifdef HAVE_OPENAT
3020
0
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3021
#else
3022
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3023
#endif
3024
3025
#ifdef HAVE_READLINKAT
3026
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3027
#else
3028
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3029
#endif
3030
3031
#ifdef HAVE_SYMLINKAT
3032
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3033
#else
3034
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3035
#endif
3036
3037
#ifdef HAVE_UNLINKAT
3038
0
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3039
#else
3040
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3041
#endif
3042
3043
#ifdef HAVE_FCHDIR
3044
    #define PATH_HAVE_FCHDIR 1
3045
#else
3046
    #define PATH_HAVE_FCHDIR 0
3047
#endif
3048
3049
#ifdef HAVE_FCHMOD
3050
    #define PATH_HAVE_FCHMOD 1
3051
#else
3052
    #define PATH_HAVE_FCHMOD 0
3053
#endif
3054
3055
#ifdef HAVE_FCHOWN
3056
    #define PATH_HAVE_FCHOWN 1
3057
#else
3058
    #define PATH_HAVE_FCHOWN 0
3059
#endif
3060
3061
#ifdef HAVE_FDOPENDIR
3062
    #define PATH_HAVE_FDOPENDIR 1
3063
#else
3064
    #define PATH_HAVE_FDOPENDIR 0
3065
#endif
3066
3067
#ifdef HAVE_FEXECVE
3068
    #define PATH_HAVE_FEXECVE 1
3069
#else
3070
    #define PATH_HAVE_FEXECVE 0
3071
#endif
3072
3073
#ifdef HAVE_FPATHCONF
3074
    #define PATH_HAVE_FPATHCONF 1
3075
#else
3076
    #define PATH_HAVE_FPATHCONF 0
3077
#endif
3078
3079
#ifdef HAVE_FSTATVFS
3080
    #define PATH_HAVE_FSTATVFS 1
3081
#else
3082
    #define PATH_HAVE_FSTATVFS 0
3083
#endif
3084
3085
#ifdef HAVE_FTRUNCATE
3086
    #define PATH_HAVE_FTRUNCATE 1
3087
#else
3088
    #define PATH_HAVE_FTRUNCATE 0
3089
#endif
3090
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3091
3092
#ifdef MS_WINDOWS
3093
    #undef PATH_HAVE_FTRUNCATE
3094
    #define PATH_HAVE_FTRUNCATE 1
3095
    #undef PATH_HAVE_FCHMOD
3096
    #define PATH_HAVE_FCHMOD 1
3097
#endif
3098
3099
/*[python input]
3100
3101
class path_t_converter(CConverter):
3102
3103
    type = "path_t"
3104
    impl_by_reference = True
3105
    parse_by_reference = True
3106
3107
    converter = 'path_converter'
3108
3109
    def converter_init(self, *, allow_fd=False, make_wide=None,
3110
                       nonstrict=False, nullable=False,
3111
                       suppress_value_error=False):
3112
        # right now path_t doesn't support default values.
3113
        # to support a default value, you'll need to override initialize().
3114
        if self.default not in (unspecified, None):
3115
            fail("Can't specify a default to the path_t converter!")
3116
3117
        if self.c_default not in (None, 'Py_None'):
3118
            raise RuntimeError("Can't specify a c_default to the path_t converter!")
3119
3120
        self.nullable = nullable
3121
        self.nonstrict = nonstrict
3122
        self.make_wide = make_wide
3123
        self.suppress_value_error = suppress_value_error
3124
        self.allow_fd = allow_fd
3125
3126
    def pre_render(self):
3127
        def strify(value):
3128
            if isinstance(value, str):
3129
                return value
3130
            return str(int(bool(value)))
3131
3132
        # add self.py_name here when merging with posixmodule conversion
3133
        if self.make_wide is None:
3134
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3135
                self.function.name,
3136
                self.name,
3137
                strify(self.nullable),
3138
                strify(self.nonstrict),
3139
                strify(self.suppress_value_error),
3140
                strify(self.allow_fd),
3141
            )
3142
        else:
3143
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3144
                self.function.name,
3145
                self.name,
3146
                strify(self.nullable),
3147
                strify(self.nonstrict),
3148
                strify(self.make_wide),
3149
                strify(self.suppress_value_error),
3150
                strify(self.allow_fd),
3151
            )
3152
3153
    def cleanup(self):
3154
        return "path_cleanup(&" + self.name + ");\n"
3155
3156
3157
class dir_fd_converter(CConverter):
3158
    type = 'int'
3159
3160
    def converter_init(self, requires=None):
3161
        if self.default in (unspecified, None):
3162
            self.c_default = 'DEFAULT_DIR_FD'
3163
        if isinstance(requires, str):
3164
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3165
        else:
3166
            self.converter = 'dir_fd_converter'
3167
3168
class uid_t_converter(CConverter):
3169
    type = "uid_t"
3170
    converter = '_Py_Uid_Converter'
3171
3172
class gid_t_converter(CConverter):
3173
    type = "gid_t"
3174
    converter = '_Py_Gid_Converter'
3175
3176
class dev_t_converter(CConverter):
3177
    type = 'dev_t'
3178
    converter = '_Py_Dev_Converter'
3179
3180
class dev_t_return_converter(unsigned_long_return_converter):
3181
    type = 'dev_t'
3182
    conversion_fn = '_PyLong_FromDev'
3183
    unsigned_cast = '(dev_t)'
3184
3185
class pid_t_converter(CConverter):
3186
    type = 'pid_t'
3187
    format_unit = '" _Py_PARSE_PID "'
3188
3189
    def parse_arg(self, argname, displayname, *, limited_capi):
3190
        return self.format_code("""
3191
            {paramname} = PyLong_AsPid({argname});
3192
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3193
                goto exit;
3194
            }}}}
3195
            """, argname=argname)
3196
3197
class idtype_t_converter(CConverter):
3198
    type = 'idtype_t'
3199
    converter = 'idtype_t_converter'
3200
3201
class id_t_converter(CConverter):
3202
    type = 'id_t'
3203
    format_unit = '" _Py_PARSE_PID "'
3204
3205
    def parse_arg(self, argname, displayname, *, limited_capi):
3206
        return self.format_code("""
3207
            {paramname} = (id_t)PyLong_AsPid({argname});
3208
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3209
                goto exit;
3210
            }}}}
3211
            """, argname=argname)
3212
3213
class intptr_t_converter(CConverter):
3214
    type = 'intptr_t'
3215
    format_unit = '" _Py_PARSE_INTPTR "'
3216
3217
    def parse_arg(self, argname, displayname, *, limited_capi):
3218
        return self.format_code("""
3219
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3220
            if (!{paramname} && PyErr_Occurred()) {{{{
3221
                goto exit;
3222
            }}}}
3223
            """, argname=argname)
3224
3225
class Py_off_t_converter(CConverter):
3226
    type = 'Py_off_t'
3227
    converter = 'Py_off_t_converter'
3228
3229
class Py_off_t_return_converter(long_return_converter):
3230
    type = 'Py_off_t'
3231
    conversion_fn = 'PyLong_FromPy_off_t'
3232
3233
class confname_converter(CConverter):
3234
    type="int"
3235
    converter="conv_confname"
3236
3237
    def converter_init(self, *, table):
3238
        self.table = table
3239
3240
    def parse_arg(self, argname, displayname, *, limited_capi):
3241
        return self.format_code("""
3242
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3243
                goto exit;
3244
            }}}}
3245
        """, argname=argname, converter=self.converter, table=self.table)
3246
3247
[python start generated code]*/
3248
/*[python end generated code: output=da39a3ee5e6b4b0d input=d2759f2332cd39b3]*/
3249
3250
/*[clinic input]
3251
3252
os.stat
3253
3254
    path : path_t(allow_fd=True)
3255
        Path to be examined; can be string, bytes, a path-like object or
3256
        open-file-descriptor int.
3257
3258
    *
3259
3260
    dir_fd : dir_fd(requires='fstatat') = None
3261
        If not None, it should be a file descriptor open to a directory,
3262
        and path should be a relative string; path will then be relative to
3263
        that directory.
3264
3265
    follow_symlinks: bool = True
3266
        If False, and the last element of the path is a symbolic link,
3267
        stat will examine the symbolic link itself instead of the file
3268
        the link points to.
3269
3270
Perform a stat system call on the given path.
3271
3272
dir_fd and follow_symlinks may not be implemented
3273
  on your platform.  If they are unavailable, using them will raise a
3274
  NotImplementedError.
3275
3276
It's an error to use dir_fd or follow_symlinks when specifying path as
3277
  an open file descriptor.
3278
3279
[clinic start generated code]*/
3280
3281
static PyObject *
3282
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3283
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3284
5.31k
{
3285
5.31k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3286
5.31k
}
3287
3288
3289
/*[clinic input]
3290
@permit_long_summary
3291
os.lstat
3292
3293
    path : path_t
3294
3295
    *
3296
3297
    dir_fd : dir_fd(requires='fstatat') = None
3298
3299
Perform a stat system call on the given path, without following symbolic links.
3300
3301
Like stat(), but do not follow symbolic links.
3302
Equivalent to stat(path, follow_symlinks=False).
3303
[clinic start generated code]*/
3304
3305
static PyObject *
3306
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3307
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3308
0
{
3309
0
    int follow_symlinks = 0;
3310
0
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3311
0
}
3312
3313
3314
#ifdef HAVE_STATX
3315
typedef struct {
3316
    PyObject_HEAD
3317
    dev_t rdev, dev;
3318
    struct statx stx;
3319
} Py_statx_result;
3320
3321
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3322
3323
#define M(attr, type, offset, doc) \
3324
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3325
#define MM(attr, type, member, doc) \
3326
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3327
#define MX(attr, type, member, doc) \
3328
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3329
3330
static PyMemberDef pystatx_result_members[] = {
3331
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3332
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3333
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3334
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3335
        "Mask of supported bits in stx_attributes"),
3336
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3337
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3338
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3339
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3340
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3341
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3342
    {NULL},
3343
};
3344
3345
#undef MX
3346
#undef MM
3347
#undef M
3348
3349
3350
#define STATX_GET_UINT(ATTR, MASK) \
3351
    static PyObject* \
3352
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3353
0
    { \
3354
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3355
0
        if (!(self->stx.stx_mask & MASK)) { \
3356
0
            Py_RETURN_NONE; \
3357
0
        } \
3358
0
        unsigned long value = self->stx.ATTR; \
3359
0
        return PyLong_FromUnsignedLong(value); \
3360
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
3361
3362
STATX_GET_UINT(stx_uid, STATX_UID)
3363
STATX_GET_UINT(stx_gid, STATX_GID)
3364
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3365
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3366
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3367
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3368
#endif
3369
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3370
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3371
#endif
3372
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3373
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3374
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3375
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3376
#endif
3377
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3378
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3379
#endif
3380
3381
3382
static PyObject*
3383
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3384
0
{
3385
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3386
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3387
0
        Py_RETURN_NONE;
3388
0
    }
3389
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3390
0
}
3391
3392
3393
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3394
    static PyObject* \
3395
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3396
0
    { \
3397
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3398
0
        if (!(self->stx.stx_mask & MASK)) { \
3399
0
            Py_RETURN_NONE; \
3400
0
        } \
3401
0
        unsigned long long value = self->stx.ATTR; \
3402
0
        return PyLong_FromUnsignedLongLong(value); \
3403
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
3404
3405
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3406
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3407
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3408
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3409
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3410
#endif
3411
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3412
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3413
#endif
3414
3415
3416
#define STATX_GET_DOUBLE(ATTR, MASK) \
3417
    static PyObject* \
3418
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3419
0
    { \
3420
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3421
0
        if (!(self->stx.stx_mask & MASK)) { \
3422
0
            Py_RETURN_NONE; \
3423
0
        } \
3424
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3425
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3426
0
        return PyFloat_FromDouble(sec); \
3427
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
3428
3429
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3430
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3431
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3432
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3433
3434
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3435
    static PyObject* \
3436
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3437
0
    { \
3438
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3439
0
        if (!(self->stx.stx_mask & MASK)) { \
3440
0
            Py_RETURN_NONE; \
3441
0
        } \
3442
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3443
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3444
0
        assert(state != NULL); \
3445
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3446
0
    }
3447
3448
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3449
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3450
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3451
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3452
3453
#define G(attr, doc) \
3454
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3455
3456
static PyGetSetDef pystatx_result_getset[] = {
3457
    G(stx_mode, "protection bits"),
3458
    G(stx_nlink, "number of hard links"),
3459
    G(stx_uid, "user ID of owner"),
3460
    G(stx_gid, "group ID of owner"),
3461
    G(stx_ino, "inode"),
3462
    G(stx_size, "total size, in bytes"),
3463
    G(stx_blocks, "number of blocks allocated"),
3464
    G(stx_atime, "time of last access"),
3465
    G(stx_atime_ns, "time of last access in nanoseconds"),
3466
    G(stx_btime, "time of creation"),
3467
    G(stx_btime_ns, "time of creation in nanoseconds"),
3468
    G(stx_ctime, "time of last change"),
3469
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3470
    G(stx_mtime, "time of last modification"),
3471
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3472
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3473
    G(stx_mnt_id, "mount ID"),
3474
#endif
3475
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3476
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3477
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3478
#endif
3479
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3480
    G(stx_subvol, "subvolume ID"),
3481
#endif
3482
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3483
    G(stx_atomic_write_unit_min,
3484
      "minimum size for direct I/O with torn-write protection"),
3485
    G(stx_atomic_write_unit_max,
3486
        "maximum size for direct I/O with torn-write protection"),
3487
    G(stx_atomic_write_segments_max,
3488
        "maximum iovecs for direct I/O with torn-write protection"),
3489
#endif
3490
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3491
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3492
#endif
3493
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3494
    G(stx_atomic_write_unit_max_opt,
3495
        "maximum optimized size for direct I/O with torn-write protection"),
3496
#endif
3497
    {NULL},
3498
};
3499
3500
#undef G
3501
3502
static PyObject *
3503
pystatx_result_repr(PyObject *op)
3504
0
{
3505
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3506
0
    if (writer == NULL) {
3507
0
        return NULL;
3508
0
    }
3509
0
#define WRITE_ASCII(s) \
3510
0
    do { \
3511
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3512
0
            goto error; \
3513
0
        } \
3514
0
    } while (0)
3515
3516
0
    WRITE_ASCII("os.statx_result(");
3517
3518
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3519
0
        if (i > 0) {
3520
0
            WRITE_ASCII(", ");
3521
0
        }
3522
3523
0
        PyMemberDef *d = &pystatx_result_members[i];
3524
0
        WRITE_ASCII(d->name);
3525
0
        WRITE_ASCII("=");
3526
3527
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3528
0
        if (o == NULL) {
3529
0
            goto error;
3530
0
        }
3531
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3532
0
            Py_DECREF(o);
3533
0
            goto error;
3534
0
        }
3535
0
        Py_DECREF(o);
3536
0
    }
3537
3538
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3539
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3540
0
        PyObject *o = d->get(op, d->closure);
3541
0
        if (o == NULL) {
3542
0
            goto error;
3543
0
        }
3544
0
        if (o == Py_None) {
3545
0
            continue;
3546
0
        }
3547
3548
0
        WRITE_ASCII(", ");
3549
0
        WRITE_ASCII(d->name);
3550
0
        WRITE_ASCII("=");
3551
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3552
0
            Py_DECREF(o);
3553
0
            goto error;
3554
0
        }
3555
0
        Py_DECREF(o);
3556
0
    }
3557
3558
0
    WRITE_ASCII(")");
3559
0
    return PyUnicodeWriter_Finish(writer);
3560
0
#undef WRITE_ASCII
3561
3562
0
error:
3563
0
    PyUnicodeWriter_Discard(writer);
3564
0
    return NULL;
3565
0
}
3566
3567
static int
3568
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3569
0
{
3570
0
    Py_VISIT(Py_TYPE(self));
3571
0
    return 0;
3572
0
}
3573
3574
static void
3575
pystatx_result_dealloc(PyObject *op)
3576
0
{
3577
0
    Py_statx_result *self = (Py_statx_result *) op;
3578
0
    PyTypeObject *tp = Py_TYPE(self);
3579
0
    PyObject_GC_UnTrack(self);
3580
0
    tp->tp_free(self);
3581
0
    Py_DECREF(tp);
3582
0
}
3583
3584
static PyType_Slot pystatx_result_slots[] = {
3585
    {Py_tp_repr, pystatx_result_repr},
3586
    {Py_tp_traverse, pystatx_result_traverse},
3587
    {Py_tp_dealloc, pystatx_result_dealloc},
3588
    {Py_tp_members, pystatx_result_members},
3589
    {Py_tp_getset, pystatx_result_getset},
3590
    {0, NULL},
3591
};
3592
3593
static PyType_Spec pystatx_result_spec = {
3594
    .name = "os.statx_result",
3595
    .basicsize = sizeof(Py_statx_result),
3596
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3597
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3598
    .slots = pystatx_result_slots,
3599
};
3600
3601
/*[clinic input]
3602
3603
os.statx
3604
3605
    path : path_t(allow_fd=True)
3606
        Path to be examined; can be string, bytes, a path-like object or
3607
        open-file-descriptor int.
3608
3609
    mask: unsigned_int(bitwise=True)
3610
        A bitmask of STATX_* constants defining the requested information.
3611
3612
    *
3613
3614
    flags: int = 0
3615
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3616
3617
    dir_fd : dir_fd = None
3618
        If not None, it should be a file descriptor open to a directory,
3619
        and path should be a relative string; path will then be relative to
3620
        that directory.
3621
3622
    follow_symlinks: bool = True
3623
        If False, and the last element of the path is a symbolic link,
3624
        statx will examine the symbolic link itself instead of the file
3625
        the link points to.
3626
3627
Perform a statx system call on the given path.
3628
3629
It's an error to use dir_fd or follow_symlinks when specifying path as
3630
  an open file descriptor.
3631
3632
[clinic start generated code]*/
3633
3634
static PyObject *
3635
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3636
              int dir_fd, int follow_symlinks)
3637
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3638
0
{
3639
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3640
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3641
0
        fd_and_follow_symlinks_invalid("statx", path->fd, follow_symlinks)) {
3642
0
        return NULL;
3643
0
    }
3644
3645
    /* reject flags covered by kwargs, but allow unknown flags that may be
3646
       future AT_STATX_* extensions */
3647
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3648
0
        PyErr_Format(PyExc_ValueError,
3649
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3650
0
        return NULL;
3651
0
    }
3652
0
    if (flags & AT_EMPTY_PATH) {
3653
0
        PyErr_Format(PyExc_ValueError,
3654
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3655
0
        return NULL;
3656
0
    }
3657
3658
    /* Future bits may refer to members beyond the current size of struct
3659
       statx, so we need to mask them off to prevent memory corruption. */
3660
0
    mask &= _Py_STATX_KNOWN;
3661
3662
0
    _posixstate *state = get_posix_state(module);
3663
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3664
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3665
0
    if (v == NULL) {
3666
0
        return NULL;
3667
0
    }
3668
3669
0
    int result;
3670
0
    Py_BEGIN_ALLOW_THREADS
3671
0
    if (path->fd != -1) {
3672
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3673
0
    }
3674
0
    else {
3675
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3676
0
    }
3677
0
    Py_END_ALLOW_THREADS
3678
3679
0
    if (result != 0) {
3680
0
        Py_DECREF(v);
3681
0
        return path_error(path);
3682
0
    }
3683
3684
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3685
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3686
3687
0
    assert(!PyErr_Occurred());
3688
0
    return (PyObject *)v;
3689
0
}
3690
#endif /* HAVE_STATX */
3691
3692
3693
/*[clinic input]
3694
os.access -> bool
3695
3696
    path: path_t
3697
        Path to be tested; can be string, bytes, or a path-like object.
3698
3699
    mode: int
3700
        Operating-system mode bitfield.  Can be F_OK to test existence,
3701
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3702
3703
    *
3704
3705
    dir_fd : dir_fd(requires='faccessat') = None
3706
        If not None, it should be a file descriptor open to a directory,
3707
        and path should be relative; path will then be relative to that
3708
        directory.
3709
3710
    effective_ids: bool = False
3711
        If True, access will use the effective uid/gid instead of
3712
        the real uid/gid.
3713
3714
    follow_symlinks: bool = True
3715
        If False, and the last element of the path is a symbolic link,
3716
        access will examine the symbolic link itself instead of the file
3717
        the link points to.
3718
3719
Use the real uid/gid to test for access to a path.
3720
3721
{parameters}
3722
dir_fd, effective_ids, and follow_symlinks may not be implemented
3723
  on your platform.  If they are unavailable, using them will raise a
3724
  NotImplementedError.
3725
3726
Note that most operations will use the effective uid/gid, therefore this
3727
  routine can be used in a suid/sgid environment to test if the invoking
3728
  user has the specified access to the path.
3729
3730
[clinic start generated code]*/
3731
3732
static int
3733
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3734
               int effective_ids, int follow_symlinks)
3735
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3736
0
{
3737
0
    int return_value;
3738
3739
#ifdef MS_WINDOWS
3740
    DWORD attr;
3741
#else
3742
0
    int result;
3743
0
#endif
3744
3745
0
#ifdef HAVE_FACCESSAT
3746
0
    int faccessat_unavailable = 0;
3747
0
#endif
3748
3749
#ifndef HAVE_FACCESSAT
3750
    if (follow_symlinks_specified("access", follow_symlinks))
3751
        return -1;
3752
3753
    if (effective_ids) {
3754
        argument_unavailable_error("access", "effective_ids");
3755
        return -1;
3756
    }
3757
#endif
3758
3759
#ifdef MS_WINDOWS
3760
    Py_BEGIN_ALLOW_THREADS
3761
    attr = GetFileAttributesW(path->wide);
3762
    Py_END_ALLOW_THREADS
3763
3764
    /*
3765
     * Access is possible if
3766
     *   * we didn't get a -1, and
3767
     *     * write access wasn't requested,
3768
     *     * or the file isn't read-only,
3769
     *     * or it's a directory.
3770
     * (Directories cannot be read-only on Windows.)
3771
    */
3772
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3773
            (!(mode & 2) ||
3774
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3775
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3776
#else
3777
3778
0
    Py_BEGIN_ALLOW_THREADS
3779
0
#ifdef HAVE_FACCESSAT
3780
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3781
0
        effective_ids ||
3782
0
        !follow_symlinks) {
3783
3784
0
        if (HAVE_FACCESSAT_RUNTIME) {
3785
0
            int flags = 0;
3786
0
            if (!follow_symlinks)
3787
0
                flags |= AT_SYMLINK_NOFOLLOW;
3788
0
            if (effective_ids)
3789
0
                flags |= AT_EACCESS;
3790
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3791
0
        } else {
3792
0
            faccessat_unavailable = 1;
3793
0
        }
3794
0
    }
3795
0
    else
3796
0
#endif
3797
0
        result = access(path->narrow, mode);
3798
0
    Py_END_ALLOW_THREADS
3799
3800
0
#ifdef HAVE_FACCESSAT
3801
0
    if (faccessat_unavailable) {
3802
0
        if (dir_fd != DEFAULT_DIR_FD) {
3803
0
            argument_unavailable_error("access", "dir_fd");
3804
0
            return -1;
3805
0
        }
3806
0
        if (follow_symlinks_specified("access", follow_symlinks))
3807
0
            return -1;
3808
3809
0
        if (effective_ids) {
3810
0
            argument_unavailable_error("access", "effective_ids");
3811
0
            return -1;
3812
0
        }
3813
        /* should be unreachable */
3814
0
        return -1;
3815
0
    }
3816
0
#endif
3817
0
    return_value = !result;
3818
0
#endif
3819
3820
0
    return return_value;
3821
0
}
3822
3823
#ifndef F_OK
3824
#define F_OK 0
3825
#endif
3826
#ifndef R_OK
3827
#define R_OK 4
3828
#endif
3829
#ifndef W_OK
3830
#define W_OK 2
3831
#endif
3832
#ifndef X_OK
3833
#define X_OK 1
3834
#endif
3835
3836
3837
#ifdef HAVE_TTYNAME_R
3838
/*[clinic input]
3839
os.ttyname
3840
3841
    fd: int
3842
        Integer file descriptor handle.
3843
3844
    /
3845
3846
Return the name of the terminal device connected to 'fd'.
3847
[clinic start generated code]*/
3848
3849
static PyObject *
3850
os_ttyname_impl(PyObject *module, int fd)
3851
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3852
0
{
3853
3854
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3855
0
    if (size == -1) {
3856
0
        return posix_error();
3857
0
    }
3858
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3859
0
    if (buffer == NULL) {
3860
0
        return PyErr_NoMemory();
3861
0
    }
3862
0
    int ret = ttyname_r(fd, buffer, size);
3863
0
    if (ret != 0) {
3864
0
        PyMem_RawFree(buffer);
3865
0
        errno = ret;
3866
0
        return posix_error();
3867
0
    }
3868
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3869
0
    PyMem_RawFree(buffer);
3870
0
    return res;
3871
0
}
3872
#endif
3873
3874
#ifdef HAVE_CTERMID
3875
/*[clinic input]
3876
os.ctermid
3877
3878
Return the name of the controlling terminal for this process.
3879
[clinic start generated code]*/
3880
3881
static PyObject *
3882
os_ctermid_impl(PyObject *module)
3883
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3884
0
{
3885
0
    char *ret;
3886
0
    char buffer[L_ctermid];
3887
3888
#ifdef USE_CTERMID_R
3889
    ret = ctermid_r(buffer);
3890
#else
3891
0
    ret = ctermid(buffer);
3892
0
#endif
3893
0
    if (ret == NULL)
3894
0
        return posix_error();
3895
0
    return PyUnicode_DecodeFSDefault(buffer);
3896
0
}
3897
#endif /* HAVE_CTERMID */
3898
3899
3900
/*[clinic input]
3901
os.chdir
3902
3903
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3904
3905
Change the current working directory to the specified path.
3906
3907
path may always be specified as a string.
3908
On some platforms, path may also be specified as an open file descriptor.
3909
If this functionality is unavailable, using it raises an exception.
3910
[clinic start generated code]*/
3911
3912
static PyObject *
3913
os_chdir_impl(PyObject *module, path_t *path)
3914
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3915
0
{
3916
0
    int result;
3917
3918
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3919
0
        return NULL;
3920
0
    }
3921
3922
0
    Py_BEGIN_ALLOW_THREADS
3923
#ifdef MS_WINDOWS
3924
    /* on unix, success = 0, on windows, success = !0 */
3925
    result = !win32_wchdir(path->wide);
3926
#else
3927
0
#ifdef HAVE_FCHDIR
3928
0
    if (path->fd != -1)
3929
0
        result = fchdir(path->fd);
3930
0
    else
3931
0
#endif
3932
0
        result = chdir(path->narrow);
3933
0
#endif
3934
0
    Py_END_ALLOW_THREADS
3935
3936
0
    if (result) {
3937
0
        return path_error(path);
3938
0
    }
3939
3940
0
    Py_RETURN_NONE;
3941
0
}
3942
3943
3944
#ifdef HAVE_FCHDIR
3945
/*[clinic input]
3946
os.fchdir
3947
3948
    fd: fildes
3949
3950
Change to the directory of the given file descriptor.
3951
3952
fd must be opened on a directory, not a file.
3953
Equivalent to os.chdir(fd).
3954
3955
[clinic start generated code]*/
3956
3957
static PyObject *
3958
os_fchdir_impl(PyObject *module, int fd)
3959
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3960
0
{
3961
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3962
0
        return NULL;
3963
0
    }
3964
0
    return posix_fildes_fd(fd, fchdir);
3965
0
}
3966
#endif /* HAVE_FCHDIR */
3967
3968
#ifdef MS_WINDOWS
3969
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3970
#else
3971
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3972
#endif
3973
3974
#ifdef MS_WINDOWS
3975
static int
3976
win32_lchmod(LPCWSTR path, int mode)
3977
{
3978
    DWORD attr = GetFileAttributesW(path);
3979
    if (attr == INVALID_FILE_ATTRIBUTES) {
3980
        return 0;
3981
    }
3982
    if (mode & _S_IWRITE) {
3983
        attr &= ~FILE_ATTRIBUTE_READONLY;
3984
    }
3985
    else {
3986
        attr |= FILE_ATTRIBUTE_READONLY;
3987
    }
3988
    return SetFileAttributesW(path, attr);
3989
}
3990
3991
static int
3992
win32_hchmod(HANDLE hfile, int mode)
3993
{
3994
    FILE_BASIC_INFO info;
3995
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
3996
                                      &info, sizeof(info)))
3997
    {
3998
        return 0;
3999
    }
4000
    if (mode & _S_IWRITE) {
4001
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4002
    }
4003
    else {
4004
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4005
    }
4006
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4007
                                      &info, sizeof(info));
4008
}
4009
4010
static int
4011
win32_fchmod(int fd, int mode)
4012
{
4013
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4014
    if (hfile == INVALID_HANDLE_VALUE) {
4015
        SetLastError(ERROR_INVALID_HANDLE);
4016
        return 0;
4017
    }
4018
    return win32_hchmod(hfile, mode);
4019
}
4020
4021
#endif /* MS_WINDOWS */
4022
4023
/*[clinic input]
4024
os.chmod
4025
4026
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4027
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
4028
        On some platforms, path may also be specified as an open file descriptor.
4029
        If this functionality is unavailable, using it raises an exception.
4030
4031
    mode: int
4032
        Operating-system mode bitfield.
4033
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4034
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4035
        Python.
4036
4037
    *
4038
4039
    dir_fd : dir_fd(requires='fchmodat') = None
4040
        If not None, it should be a file descriptor open to a directory,
4041
        and path should be relative; path will then be relative to that
4042
        directory.
4043
4044
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4045
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4046
        If False, and the last element of the path is a symbolic link,
4047
        chmod will modify the symbolic link itself instead of the file
4048
        the link points to.
4049
4050
Change the access permissions of a file.
4051
4052
It is an error to use dir_fd or follow_symlinks when specifying path as
4053
  an open file descriptor.
4054
dir_fd and follow_symlinks may not be implemented on your platform.
4055
  If they are unavailable, using them will raise a NotImplementedError.
4056
4057
[clinic start generated code]*/
4058
4059
static PyObject *
4060
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4061
              int follow_symlinks)
4062
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
4063
0
{
4064
0
    int result;
4065
4066
0
#ifdef HAVE_FCHMODAT
4067
0
    int fchmodat_nofollow_unsupported = 0;
4068
0
    int fchmodat_unsupported = 0;
4069
0
#endif
4070
4071
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4072
    if (follow_symlinks_specified("chmod", follow_symlinks))
4073
        return NULL;
4074
#endif
4075
4076
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4077
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4078
0
        return NULL;
4079
0
    }
4080
4081
#ifdef MS_WINDOWS
4082
    result = 0;
4083
    Py_BEGIN_ALLOW_THREADS
4084
    if (path->fd != -1) {
4085
        result = win32_fchmod(path->fd, mode);
4086
    }
4087
    else if (follow_symlinks) {
4088
        HANDLE hfile = CreateFileW(path->wide,
4089
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4090
                                   0, NULL,
4091
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4092
        if (hfile != INVALID_HANDLE_VALUE) {
4093
            result = win32_hchmod(hfile, mode);
4094
            (void)CloseHandle(hfile);
4095
        }
4096
    }
4097
    else {
4098
        result = win32_lchmod(path->wide, mode);
4099
    }
4100
    Py_END_ALLOW_THREADS
4101
    if (!result) {
4102
        return path_error(path);
4103
    }
4104
#else /* MS_WINDOWS */
4105
0
    Py_BEGIN_ALLOW_THREADS
4106
0
#ifdef HAVE_FCHMOD
4107
0
    if (path->fd != -1)
4108
0
        result = fchmod(path->fd, mode);
4109
0
    else
4110
0
#endif /* HAVE_CHMOD */
4111
#ifdef HAVE_LCHMOD
4112
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4113
        result = lchmod(path->narrow, mode);
4114
    else
4115
#endif /* HAVE_LCHMOD */
4116
0
#ifdef HAVE_FCHMODAT
4117
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4118
0
        if (HAVE_FCHMODAT_RUNTIME) {
4119
            /*
4120
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4121
             * The documentation specifically shows how to use it,
4122
             * and then says it isn't implemented yet.
4123
             * (true on linux with glibc 2.15, and openindiana 3.x)
4124
             *
4125
             * Once it is supported, os.chmod will automatically
4126
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4127
             * Until then, we need to be careful what exception we raise.
4128
             */
4129
0
            result = fchmodat(dir_fd, path->narrow, mode,
4130
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4131
            /*
4132
             * But wait!  We can't throw the exception without allowing threads,
4133
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4134
             */
4135
0
            fchmodat_nofollow_unsupported =
4136
0
                             result &&
4137
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4138
0
                             !follow_symlinks;
4139
0
        } else {
4140
0
            fchmodat_unsupported = 1;
4141
0
            fchmodat_nofollow_unsupported = 1;
4142
4143
0
            result = -1;
4144
0
        }
4145
0
    }
4146
0
    else
4147
0
#endif /* HAVE_FHCMODAT */
4148
0
    {
4149
0
#ifdef HAVE_CHMOD
4150
0
        result = chmod(path->narrow, mode);
4151
#elif defined(__wasi__)
4152
        // WASI SDK 15.0 does not support chmod.
4153
        // Ignore missing syscall for now.
4154
        result = 0;
4155
#else
4156
        result = -1;
4157
        errno = ENOSYS;
4158
#endif
4159
0
    }
4160
0
    Py_END_ALLOW_THREADS
4161
4162
0
    if (result) {
4163
0
#ifdef HAVE_FCHMODAT
4164
0
        if (fchmodat_unsupported) {
4165
0
            if (dir_fd != DEFAULT_DIR_FD) {
4166
0
                argument_unavailable_error("chmod", "dir_fd");
4167
0
                return NULL;
4168
0
            }
4169
0
        }
4170
4171
0
        if (fchmodat_nofollow_unsupported) {
4172
0
            if (dir_fd != DEFAULT_DIR_FD)
4173
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4174
0
                                                   dir_fd, follow_symlinks);
4175
0
            else
4176
0
                follow_symlinks_specified("chmod", follow_symlinks);
4177
0
            return NULL;
4178
0
        }
4179
0
        else
4180
0
#endif /* HAVE_FCHMODAT */
4181
0
        return path_error(path);
4182
0
    }
4183
0
#endif /* MS_WINDOWS */
4184
4185
0
    Py_RETURN_NONE;
4186
0
}
4187
4188
4189
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4190
/*[clinic input]
4191
os.fchmod
4192
4193
    fd: int
4194
        The file descriptor of the file to be modified.
4195
    mode: int
4196
        Operating-system mode bitfield.
4197
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4198
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4199
        Python.
4200
4201
Change the access permissions of the file given by file descriptor fd.
4202
4203
Equivalent to os.chmod(fd, mode).
4204
[clinic start generated code]*/
4205
4206
static PyObject *
4207
os_fchmod_impl(PyObject *module, int fd, int mode)
4208
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
4209
0
{
4210
0
    int res;
4211
4212
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4213
0
        return NULL;
4214
0
    }
4215
4216
#ifdef MS_WINDOWS
4217
    res = 0;
4218
    Py_BEGIN_ALLOW_THREADS
4219
    res = win32_fchmod(fd, mode);
4220
    Py_END_ALLOW_THREADS
4221
    if (!res) {
4222
        return PyErr_SetFromWindowsErr(0);
4223
    }
4224
#else /* MS_WINDOWS */
4225
0
    int async_err = 0;
4226
0
    do {
4227
0
        Py_BEGIN_ALLOW_THREADS
4228
0
        res = fchmod(fd, mode);
4229
0
        Py_END_ALLOW_THREADS
4230
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4231
0
    if (res != 0)
4232
0
        return (!async_err) ? posix_error() : NULL;
4233
0
#endif /* MS_WINDOWS */
4234
4235
0
    Py_RETURN_NONE;
4236
0
}
4237
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4238
4239
4240
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4241
/*[clinic input]
4242
os.lchmod
4243
4244
    path: path_t
4245
    mode: int
4246
4247
Change the access permissions of a file, without following symbolic links.
4248
4249
If path is a symlink, this affects the link itself rather than the target.
4250
Equivalent to chmod(path, mode, follow_symlinks=False)."
4251
[clinic start generated code]*/
4252
4253
static PyObject *
4254
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4255
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
4256
{
4257
    int res;
4258
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4259
        return NULL;
4260
    }
4261
#ifdef MS_WINDOWS
4262
    Py_BEGIN_ALLOW_THREADS
4263
    res = win32_lchmod(path->wide, mode);
4264
    Py_END_ALLOW_THREADS
4265
    if (!res) {
4266
        path_error(path);
4267
        return NULL;
4268
    }
4269
#else /* MS_WINDOWS */
4270
    Py_BEGIN_ALLOW_THREADS
4271
    res = lchmod(path->narrow, mode);
4272
    Py_END_ALLOW_THREADS
4273
    if (res < 0) {
4274
        path_error(path);
4275
        return NULL;
4276
    }
4277
#endif /* MS_WINDOWS */
4278
    Py_RETURN_NONE;
4279
}
4280
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4281
4282
4283
#ifdef HAVE_CHFLAGS
4284
/*[clinic input]
4285
os.chflags
4286
4287
    path: path_t
4288
    flags: unsigned_long(bitwise=True)
4289
    follow_symlinks: bool=True
4290
4291
Set file flags.
4292
4293
If follow_symlinks is False, and the last element of the path is a symbolic
4294
  link, chflags will change flags on the symbolic link itself instead of the
4295
  file the link points to.
4296
follow_symlinks may not be implemented on your platform.  If it is
4297
unavailable, using it will raise a NotImplementedError.
4298
4299
[clinic start generated code]*/
4300
4301
static PyObject *
4302
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4303
                int follow_symlinks)
4304
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
4305
{
4306
    int result;
4307
4308
#ifndef HAVE_LCHFLAGS
4309
    if (follow_symlinks_specified("chflags", follow_symlinks))
4310
        return NULL;
4311
#endif
4312
4313
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4314
        return NULL;
4315
    }
4316
4317
    Py_BEGIN_ALLOW_THREADS
4318
#ifdef HAVE_LCHFLAGS
4319
    if (!follow_symlinks)
4320
        result = lchflags(path->narrow, flags);
4321
    else
4322
#endif
4323
        result = chflags(path->narrow, flags);
4324
    Py_END_ALLOW_THREADS
4325
4326
    if (result)
4327
        return path_error(path);
4328
4329
    Py_RETURN_NONE;
4330
}
4331
#endif /* HAVE_CHFLAGS */
4332
4333
4334
#ifdef HAVE_LCHFLAGS
4335
/*[clinic input]
4336
os.lchflags
4337
4338
    path: path_t
4339
    flags: unsigned_long(bitwise=True)
4340
4341
Set file flags.
4342
4343
This function will not follow symbolic links.
4344
Equivalent to chflags(path, flags, follow_symlinks=False).
4345
[clinic start generated code]*/
4346
4347
static PyObject *
4348
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4349
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4350
{
4351
    int res;
4352
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4353
        return NULL;
4354
    }
4355
    Py_BEGIN_ALLOW_THREADS
4356
    res = lchflags(path->narrow, flags);
4357
    Py_END_ALLOW_THREADS
4358
    if (res < 0) {
4359
        return path_error(path);
4360
    }
4361
    Py_RETURN_NONE;
4362
}
4363
#endif /* HAVE_LCHFLAGS */
4364
4365
4366
#ifdef HAVE_CHROOT
4367
/*[clinic input]
4368
os.chroot
4369
    path: path_t
4370
4371
Change root directory to path.
4372
4373
[clinic start generated code]*/
4374
4375
static PyObject *
4376
os_chroot_impl(PyObject *module, path_t *path)
4377
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4378
0
{
4379
0
    int res;
4380
0
    Py_BEGIN_ALLOW_THREADS
4381
0
    res = chroot(path->narrow);
4382
0
    Py_END_ALLOW_THREADS
4383
0
    if (res < 0)
4384
0
        return path_error(path);
4385
0
    Py_RETURN_NONE;
4386
0
}
4387
#endif /* HAVE_CHROOT */
4388
4389
4390
#ifdef HAVE_FSYNC
4391
/*[clinic input]
4392
os.fsync
4393
4394
    fd: fildes
4395
4396
Force write of fd to disk.
4397
[clinic start generated code]*/
4398
4399
static PyObject *
4400
os_fsync_impl(PyObject *module, int fd)
4401
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4402
0
{
4403
0
    return posix_fildes_fd(fd, fsync);
4404
0
}
4405
#endif /* HAVE_FSYNC */
4406
4407
4408
#ifdef HAVE_SYNC
4409
/*[clinic input]
4410
os.sync
4411
4412
Force write of everything to disk.
4413
[clinic start generated code]*/
4414
4415
static PyObject *
4416
os_sync_impl(PyObject *module)
4417
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4418
0
{
4419
0
    Py_BEGIN_ALLOW_THREADS
4420
0
    sync();
4421
0
    Py_END_ALLOW_THREADS
4422
0
    Py_RETURN_NONE;
4423
0
}
4424
#endif /* HAVE_SYNC */
4425
4426
4427
#ifdef HAVE_FDATASYNC
4428
#ifdef __hpux
4429
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4430
#endif
4431
4432
/*[clinic input]
4433
os.fdatasync
4434
4435
    fd: fildes
4436
4437
Force write of fd to disk without forcing update of metadata.
4438
[clinic start generated code]*/
4439
4440
static PyObject *
4441
os_fdatasync_impl(PyObject *module, int fd)
4442
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4443
0
{
4444
0
    return posix_fildes_fd(fd, fdatasync);
4445
0
}
4446
#endif /* HAVE_FDATASYNC */
4447
4448
4449
#ifdef HAVE_CHOWN
4450
/*[clinic input]
4451
os.chown
4452
4453
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4454
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4455
4456
    uid: uid_t
4457
4458
    gid: gid_t
4459
4460
    *
4461
4462
    dir_fd : dir_fd(requires='fchownat') = None
4463
        If not None, it should be a file descriptor open to a directory,
4464
        and path should be relative; path will then be relative to that
4465
        directory.
4466
4467
    follow_symlinks: bool = True
4468
        If False, and the last element of the path is a symbolic link,
4469
        stat will examine the symbolic link itself instead of the file
4470
        the link points to.
4471
4472
Change the owner and group id of path to the numeric uid and gid.\
4473
4474
path may always be specified as a string.
4475
On some platforms, path may also be specified as an open file descriptor.
4476
  If this functionality is unavailable, using it raises an exception.
4477
If dir_fd is not None, it should be a file descriptor open to a directory,
4478
  and path should be relative; path will then be relative to that directory.
4479
If follow_symlinks is False, and the last element of the path is a symbolic
4480
  link, chown will modify the symbolic link itself instead of the file the
4481
  link points to.
4482
It is an error to use dir_fd or follow_symlinks when specifying path as
4483
  an open file descriptor.
4484
dir_fd and follow_symlinks may not be implemented on your platform.
4485
  If they are unavailable, using them will raise a NotImplementedError.
4486
4487
[clinic start generated code]*/
4488
4489
static PyObject *
4490
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4491
              int dir_fd, int follow_symlinks)
4492
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4493
0
{
4494
0
    int result;
4495
4496
0
#if defined(HAVE_FCHOWNAT)
4497
0
    int fchownat_unsupported = 0;
4498
0
#endif
4499
4500
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4501
    if (follow_symlinks_specified("chown", follow_symlinks))
4502
        return NULL;
4503
#endif
4504
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4505
0
        fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
4506
0
        return NULL;
4507
4508
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4509
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4510
0
        return NULL;
4511
0
    }
4512
4513
0
    Py_BEGIN_ALLOW_THREADS
4514
0
#ifdef HAVE_FCHOWN
4515
0
    if (path->fd != -1)
4516
0
        result = fchown(path->fd, uid, gid);
4517
0
    else
4518
0
#endif
4519
0
#ifdef HAVE_LCHOWN
4520
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4521
0
        result = lchown(path->narrow, uid, gid);
4522
0
    else
4523
0
#endif
4524
0
#ifdef HAVE_FCHOWNAT
4525
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4526
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4527
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4528
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4529
0
      } else {
4530
0
         fchownat_unsupported = 1;
4531
0
      }
4532
0
    } else
4533
0
#endif
4534
0
        result = chown(path->narrow, uid, gid);
4535
0
    Py_END_ALLOW_THREADS
4536
4537
0
#ifdef HAVE_FCHOWNAT
4538
0
    if (fchownat_unsupported) {
4539
        /* This would be incorrect if the current platform
4540
         * doesn't support lchown.
4541
         */
4542
0
        argument_unavailable_error(NULL, "dir_fd");
4543
0
        return NULL;
4544
0
    }
4545
0
#endif
4546
4547
0
    if (result)
4548
0
        return path_error(path);
4549
4550
0
    Py_RETURN_NONE;
4551
0
}
4552
#endif /* HAVE_CHOWN */
4553
4554
4555
#ifdef HAVE_FCHOWN
4556
/*[clinic input]
4557
os.fchown
4558
4559
    fd: int
4560
    uid: uid_t
4561
    gid: gid_t
4562
4563
Change the owner and group id of the file specified by file descriptor.
4564
4565
Equivalent to os.chown(fd, uid, gid).
4566
4567
[clinic start generated code]*/
4568
4569
static PyObject *
4570
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4571
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4572
0
{
4573
0
    int res;
4574
0
    int async_err = 0;
4575
4576
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4577
0
        return NULL;
4578
0
    }
4579
4580
0
    do {
4581
0
        Py_BEGIN_ALLOW_THREADS
4582
0
        res = fchown(fd, uid, gid);
4583
0
        Py_END_ALLOW_THREADS
4584
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4585
0
    if (res != 0)
4586
0
        return (!async_err) ? posix_error() : NULL;
4587
4588
0
    Py_RETURN_NONE;
4589
0
}
4590
#endif /* HAVE_FCHOWN */
4591
4592
4593
#ifdef HAVE_LCHOWN
4594
/*[clinic input]
4595
os.lchown
4596
4597
    path : path_t
4598
    uid: uid_t
4599
    gid: gid_t
4600
4601
Change the owner and group id of path to the numeric uid and gid.
4602
4603
This function will not follow symbolic links.
4604
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4605
[clinic start generated code]*/
4606
4607
static PyObject *
4608
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4609
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4610
0
{
4611
0
    int res;
4612
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4613
0
        return NULL;
4614
0
    }
4615
0
    Py_BEGIN_ALLOW_THREADS
4616
0
    res = lchown(path->narrow, uid, gid);
4617
0
    Py_END_ALLOW_THREADS
4618
0
    if (res < 0) {
4619
0
        return path_error(path);
4620
0
    }
4621
0
    Py_RETURN_NONE;
4622
0
}
4623
#endif /* HAVE_LCHOWN */
4624
4625
4626
static PyObject *
4627
posix_getcwd(int use_bytes)
4628
0
{
4629
#ifdef MS_WINDOWS
4630
    wchar_t wbuf[MAXPATHLEN];
4631
    wchar_t *wbuf2 = wbuf;
4632
    DWORD len;
4633
4634
    Py_BEGIN_ALLOW_THREADS
4635
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4636
    /* If the buffer is large enough, len does not include the
4637
       terminating \0. If the buffer is too small, len includes
4638
       the space needed for the terminator. */
4639
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4640
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4641
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4642
        }
4643
        else {
4644
            wbuf2 = NULL;
4645
        }
4646
        if (wbuf2) {
4647
            len = GetCurrentDirectoryW(len, wbuf2);
4648
        }
4649
    }
4650
    Py_END_ALLOW_THREADS
4651
4652
    if (!wbuf2) {
4653
        PyErr_NoMemory();
4654
        return NULL;
4655
    }
4656
    if (!len) {
4657
        PyErr_SetFromWindowsErr(0);
4658
        if (wbuf2 != wbuf)
4659
            PyMem_RawFree(wbuf2);
4660
        return NULL;
4661
    }
4662
4663
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4664
    if (wbuf2 != wbuf) {
4665
        PyMem_RawFree(wbuf2);
4666
    }
4667
4668
    if (use_bytes) {
4669
        if (resobj == NULL) {
4670
            return NULL;
4671
        }
4672
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4673
    }
4674
4675
    return resobj;
4676
#else
4677
0
    const size_t chunk = 1024;
4678
4679
0
    char *buf = NULL;
4680
0
    char *cwd = NULL;
4681
0
    size_t buflen = 0;
4682
4683
0
    Py_BEGIN_ALLOW_THREADS
4684
0
    do {
4685
0
        char *newbuf;
4686
0
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4687
0
            buflen += chunk;
4688
0
            newbuf = PyMem_RawRealloc(buf, buflen);
4689
0
        }
4690
0
        else {
4691
0
            newbuf = NULL;
4692
0
        }
4693
0
        if (newbuf == NULL) {
4694
0
            PyMem_RawFree(buf);
4695
0
            buf = NULL;
4696
0
            break;
4697
0
        }
4698
0
        buf = newbuf;
4699
4700
0
        cwd = getcwd(buf, buflen);
4701
0
    } while (cwd == NULL && errno == ERANGE);
4702
0
    Py_END_ALLOW_THREADS
4703
4704
0
    if (buf == NULL) {
4705
0
        return PyErr_NoMemory();
4706
0
    }
4707
0
    if (cwd == NULL) {
4708
0
        posix_error();
4709
0
        PyMem_RawFree(buf);
4710
0
        return NULL;
4711
0
    }
4712
4713
0
    PyObject *obj;
4714
0
    if (use_bytes) {
4715
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4716
0
    }
4717
0
    else {
4718
0
        obj = PyUnicode_DecodeFSDefault(buf);
4719
0
    }
4720
0
#ifdef __linux__
4721
0
    if (buf[0] != '/') {
4722
        /*
4723
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4724
         * relative pathname starting with '(unreachable)'. We detect this
4725
         * and fail with ENOENT, matching newer glibc behaviour.
4726
         */
4727
0
        errno = ENOENT;
4728
0
        path_object_error(obj);
4729
0
        PyMem_RawFree(buf);
4730
0
        return NULL;
4731
0
    }
4732
0
#endif
4733
0
    assert(buf[0] == '/');
4734
0
    PyMem_RawFree(buf);
4735
4736
0
    return obj;
4737
0
#endif   /* !MS_WINDOWS */
4738
0
}
4739
4740
4741
/*[clinic input]
4742
os.getcwd
4743
4744
Return a unicode string representing the current working directory.
4745
[clinic start generated code]*/
4746
4747
static PyObject *
4748
os_getcwd_impl(PyObject *module)
4749
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4750
0
{
4751
0
    return posix_getcwd(0);
4752
0
}
4753
4754
4755
/*[clinic input]
4756
os.getcwdb
4757
4758
Return a bytes string representing the current working directory.
4759
[clinic start generated code]*/
4760
4761
static PyObject *
4762
os_getcwdb_impl(PyObject *module)
4763
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4764
0
{
4765
0
    return posix_getcwd(1);
4766
0
}
4767
4768
4769
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4770
#define HAVE_LINK 1
4771
#endif
4772
4773
#ifdef HAVE_LINK
4774
/*[clinic input]
4775
4776
@permit_long_docstring_body
4777
os.link
4778
4779
    src : path_t
4780
    dst : path_t
4781
    *
4782
    src_dir_fd : dir_fd = None
4783
    dst_dir_fd : dir_fd = None
4784
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4785
4786
Create a hard link to a file.
4787
4788
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4789
  descriptor open to a directory, and the respective path string (src or dst)
4790
  should be relative; the path will then be relative to that directory.
4791
If follow_symlinks is False, and the last element of src is a symbolic
4792
  link, link will create a link to the symbolic link itself instead of the
4793
  file the link points to.
4794
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4795
  platform.  If they are unavailable, using them will raise a
4796
  NotImplementedError.
4797
[clinic start generated code]*/
4798
4799
static PyObject *
4800
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4801
             int dst_dir_fd, int follow_symlinks)
4802
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4803
0
{
4804
#ifdef MS_WINDOWS
4805
    BOOL result = FALSE;
4806
#else
4807
0
    int result;
4808
0
#endif
4809
4810
0
#ifdef HAVE_LINKAT
4811
0
    if (HAVE_LINKAT_RUNTIME) {
4812
0
        if (follow_symlinks < 0) {
4813
0
            follow_symlinks = 1;
4814
0
        }
4815
0
    }
4816
0
    else
4817
0
#endif
4818
0
    {
4819
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4820
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4821
0
            return NULL;
4822
0
        }
4823
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4824
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4825
0
#if defined(MS_WINDOWS) || defined(__linux__)
4826
0
        if (follow_symlinks == 1) {
4827
0
            argument_unavailable_error("link", "follow_symlinks=True");
4828
0
            return NULL;
4829
0
        }
4830
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4831
        if (follow_symlinks == 0) {
4832
            argument_unavailable_error("link", "follow_symlinks=False");
4833
            return NULL;
4834
        }
4835
#else
4836
        if (follow_symlinks >= 0) {
4837
            argument_unavailable_error("link", "follow_symlinks");
4838
            return NULL;
4839
        }
4840
#endif
4841
0
    }
4842
4843
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4844
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4845
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4846
0
        return NULL;
4847
0
    }
4848
4849
#ifdef MS_WINDOWS
4850
    Py_BEGIN_ALLOW_THREADS
4851
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4852
    Py_END_ALLOW_THREADS
4853
4854
    if (!result)
4855
        return path_error2(src, dst);
4856
#else
4857
0
    Py_BEGIN_ALLOW_THREADS
4858
0
#ifdef HAVE_LINKAT
4859
0
    if (HAVE_LINKAT_RUNTIME) {
4860
0
        result = linkat(src_dir_fd, src->narrow,
4861
0
            dst_dir_fd, dst->narrow,
4862
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4863
0
    }
4864
0
    else
4865
0
#endif
4866
0
    {
4867
        /* linkat not available */
4868
0
        result = link(src->narrow, dst->narrow);
4869
0
    }
4870
0
    Py_END_ALLOW_THREADS
4871
4872
0
    if (result)
4873
0
        return path_error2(src, dst);
4874
0
#endif /* MS_WINDOWS */
4875
4876
0
    Py_RETURN_NONE;
4877
0
}
4878
#endif
4879
4880
4881
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4882
static PyObject *
4883
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4884
{
4885
    PyObject *v;
4886
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4887
    BOOL result, return_bytes;
4888
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4889
    /* only claim to have space for MAX_PATH */
4890
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4891
    wchar_t *wnamebuf = NULL;
4892
4893
    WIN32_FIND_DATAW wFileData;
4894
    const wchar_t *po_wchars;
4895
4896
    if (!path->wide) { /* Default arg: "." */
4897
        po_wchars = L".";
4898
        len = 1;
4899
        return_bytes = 0;
4900
    } else {
4901
        po_wchars = path->wide;
4902
        len = wcslen(path->wide);
4903
        return_bytes = PyBytes_Check(path->object);
4904
    }
4905
    /* The +5 is so we can append "\\*.*\0" */
4906
    wnamebuf = PyMem_New(wchar_t, len + 5);
4907
    if (!wnamebuf) {
4908
        PyErr_NoMemory();
4909
        goto exit;
4910
    }
4911
    wcscpy(wnamebuf, po_wchars);
4912
    if (len > 0) {
4913
        wchar_t wch = wnamebuf[len-1];
4914
        if (wch != SEP && wch != ALTSEP && wch != L':')
4915
            wnamebuf[len++] = SEP;
4916
        wcscpy(wnamebuf + len, L"*.*");
4917
    }
4918
    if ((list = PyList_New(0)) == NULL) {
4919
        goto exit;
4920
    }
4921
    Py_BEGIN_ALLOW_THREADS
4922
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4923
    Py_END_ALLOW_THREADS
4924
    if (hFindFile == INVALID_HANDLE_VALUE) {
4925
        int error = GetLastError();
4926
        if (error == ERROR_FILE_NOT_FOUND)
4927
            goto exit;
4928
        path_error(path);
4929
        Py_CLEAR(list);
4930
        goto exit;
4931
    }
4932
    do {
4933
        /* Skip over . and .. */
4934
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4935
            wcscmp(wFileData.cFileName, L"..") != 0) {
4936
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4937
                                       wcslen(wFileData.cFileName));
4938
            if (return_bytes && v) {
4939
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4940
            }
4941
            if (v == NULL) {
4942
                Py_CLEAR(list);
4943
                break;
4944
            }
4945
            if (PyList_Append(list, v) != 0) {
4946
                Py_DECREF(v);
4947
                Py_CLEAR(list);
4948
                break;
4949
            }
4950
            Py_DECREF(v);
4951
        }
4952
        Py_BEGIN_ALLOW_THREADS
4953
        result = FindNextFileW(hFindFile, &wFileData);
4954
        Py_END_ALLOW_THREADS
4955
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4956
           it got to the end of the directory. */
4957
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4958
            path_error(path);
4959
            Py_CLEAR(list);
4960
            goto exit;
4961
        }
4962
    } while (result == TRUE);
4963
4964
exit:
4965
    if (hFindFile != INVALID_HANDLE_VALUE) {
4966
        if (FindClose(hFindFile) == FALSE) {
4967
            if (list != NULL) {
4968
                path_error(path);
4969
                Py_CLEAR(list);
4970
            }
4971
        }
4972
    }
4973
    PyMem_Free(wnamebuf);
4974
4975
    return list;
4976
}  /* end of _listdir_windows_no_opendir */
4977
4978
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4979
4980
static PyObject *
4981
_posix_listdir(path_t *path, PyObject *list)
4982
120
{
4983
120
    PyObject *v;
4984
120
    DIR *dirp = NULL;
4985
120
    struct dirent *ep;
4986
120
    int return_str; /* if false, return bytes */
4987
120
#ifdef HAVE_FDOPENDIR
4988
120
    int fd = -1;
4989
120
#endif
4990
4991
120
    errno = 0;
4992
120
#ifdef HAVE_FDOPENDIR
4993
120
    if (path->fd != -1) {
4994
0
      if (HAVE_FDOPENDIR_RUNTIME) {
4995
        /* closedir() closes the FD, so we duplicate it */
4996
0
        fd = _Py_dup(path->fd);
4997
0
        if (fd == -1)
4998
0
            return NULL;
4999
5000
0
        return_str = 1;
5001
5002
0
        Py_BEGIN_ALLOW_THREADS
5003
0
        dirp = fdopendir(fd);
5004
0
        Py_END_ALLOW_THREADS
5005
0
      } else {
5006
0
        PyErr_SetString(PyExc_TypeError,
5007
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5008
0
        return NULL;
5009
0
      }
5010
0
    }
5011
120
    else
5012
120
#endif
5013
120
    {
5014
120
        const char *name;
5015
120
        if (path->narrow) {
5016
120
            name = path->narrow;
5017
            /* only return bytes if they specified a bytes object */
5018
120
            return_str = !PyBytes_Check(path->object);
5019
120
        }
5020
0
        else {
5021
0
            name = ".";
5022
0
            return_str = 1;
5023
0
        }
5024
5025
120
        Py_BEGIN_ALLOW_THREADS
5026
120
        dirp = opendir(name);
5027
120
        Py_END_ALLOW_THREADS
5028
120
    }
5029
5030
120
    if (dirp == NULL) {
5031
0
        path_error(path);
5032
0
        list = NULL;
5033
0
#ifdef HAVE_FDOPENDIR
5034
0
        if (fd != -1) {
5035
0
            Py_BEGIN_ALLOW_THREADS
5036
0
            close(fd);
5037
0
            Py_END_ALLOW_THREADS
5038
0
        }
5039
0
#endif
5040
0
        goto exit;
5041
0
    }
5042
120
    if ((list = PyList_New(0)) == NULL) {
5043
0
        goto exit;
5044
0
    }
5045
7.08k
    for (;;) {
5046
7.08k
        errno = 0;
5047
7.08k
        Py_BEGIN_ALLOW_THREADS
5048
7.08k
        ep = readdir(dirp);
5049
7.08k
        Py_END_ALLOW_THREADS
5050
7.08k
        if (ep == NULL) {
5051
120
            if (errno == 0) {
5052
120
                break;
5053
120
            } else {
5054
0
                path_error(path);
5055
0
                Py_CLEAR(list);
5056
0
                goto exit;
5057
0
            }
5058
120
        }
5059
6.96k
        if (ep->d_name[0] == '.' &&
5060
240
            (NAMLEN(ep) == 1 ||
5061
120
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5062
240
            continue;
5063
6.72k
        if (return_str)
5064
6.72k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5065
0
        else
5066
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5067
6.72k
        if (v == NULL) {
5068
0
            Py_CLEAR(list);
5069
0
            break;
5070
0
        }
5071
6.72k
        if (PyList_Append(list, v) != 0) {
5072
0
            Py_DECREF(v);
5073
0
            Py_CLEAR(list);
5074
0
            break;
5075
0
        }
5076
6.72k
        Py_DECREF(v);
5077
6.72k
    }
5078
5079
120
exit:
5080
120
    if (dirp != NULL) {
5081
120
        Py_BEGIN_ALLOW_THREADS
5082
120
#ifdef HAVE_FDOPENDIR
5083
120
        if (fd > -1)
5084
0
            rewinddir(dirp);
5085
120
#endif
5086
120
        closedir(dirp);
5087
120
        Py_END_ALLOW_THREADS
5088
120
    }
5089
5090
120
    return list;
5091
120
}  /* end of _posix_listdir */
5092
#endif  /* which OS */
5093
5094
5095
/*[clinic input]
5096
@permit_long_docstring_body
5097
os.listdir
5098
5099
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5100
5101
Return a list containing the names of the files in the directory.
5102
5103
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
5104
  the filenames returned will also be bytes; in all other circumstances
5105
  the filenames returned will be str.
5106
If path is None, uses the path='.'.
5107
On some platforms, path may also be specified as an open file descriptor;\
5108
  the file descriptor must refer to a directory.
5109
  If this functionality is unavailable, using it raises NotImplementedError.
5110
5111
The list is in arbitrary order.  It does not include the special
5112
entries '.' and '..' even if they are present in the directory.
5113
5114
5115
[clinic start generated code]*/
5116
5117
static PyObject *
5118
os_listdir_impl(PyObject *module, path_t *path)
5119
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
5120
120
{
5121
120
    if (PySys_Audit("os.listdir", "O",
5122
120
                    path->object ? path->object : Py_None) < 0) {
5123
0
        return NULL;
5124
0
    }
5125
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5126
    return _listdir_windows_no_opendir(path, NULL);
5127
#else
5128
120
    return _posix_listdir(path, NULL);
5129
120
#endif
5130
120
}
5131
5132
5133
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5134
5135
/*[clinic input]
5136
os.listdrives
5137
5138
Return a list containing the names of drives in the system.
5139
5140
A drive name typically looks like 'C:\\'.
5141
5142
[clinic start generated code]*/
5143
5144
static PyObject *
5145
os_listdrives_impl(PyObject *module)
5146
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5147
{
5148
    /* Number of possible drives is limited, so 256 should always be enough.
5149
       On the day when it is not, listmounts() will have to be used. */
5150
    wchar_t buffer[256];
5151
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5152
    PyObject *result = NULL;
5153
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5154
        return NULL;
5155
    }
5156
5157
    Py_BEGIN_ALLOW_THREADS;
5158
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5159
    Py_END_ALLOW_THREADS;
5160
5161
    if (!buflen) {
5162
        PyErr_SetFromWindowsErr(0);
5163
        return NULL;
5164
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5165
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5166
        return NULL;
5167
    }
5168
5169
    /* buflen includes a null terminator, so remove it */
5170
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5171
    if (str) {
5172
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5173
        if (nullchar) {
5174
            result = PyUnicode_Split(str, nullchar, -1);
5175
            Py_DECREF(nullchar);
5176
        }
5177
        Py_DECREF(str);
5178
    }
5179
    return result;
5180
}
5181
5182
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5183
5184
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5185
5186
/*[clinic input]
5187
os.listvolumes
5188
5189
Return a list containing the volumes in the system.
5190
5191
Volumes are typically represented as a GUID path.
5192
5193
[clinic start generated code]*/
5194
5195
static PyObject *
5196
os_listvolumes_impl(PyObject *module)
5197
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5198
{
5199
    PyObject *result = PyList_New(0);
5200
    HANDLE find = INVALID_HANDLE_VALUE;
5201
    wchar_t buffer[MAX_PATH + 1];
5202
    if (!result) {
5203
        return NULL;
5204
    }
5205
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5206
        Py_DECREF(result);
5207
        return NULL;
5208
    }
5209
5210
    int err = 0;
5211
    Py_BEGIN_ALLOW_THREADS;
5212
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5213
    if (find == INVALID_HANDLE_VALUE) {
5214
        err = GetLastError();
5215
    }
5216
    Py_END_ALLOW_THREADS;
5217
5218
    while (!err) {
5219
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5220
        if (!s || PyList_Append(result, s) < 0) {
5221
            Py_XDECREF(s);
5222
            Py_CLEAR(result);
5223
            break;
5224
        }
5225
        Py_DECREF(s);
5226
5227
        Py_BEGIN_ALLOW_THREADS;
5228
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5229
            err = GetLastError();
5230
        }
5231
        Py_END_ALLOW_THREADS;
5232
    }
5233
5234
    if (find != INVALID_HANDLE_VALUE) {
5235
        Py_BEGIN_ALLOW_THREADS;
5236
        FindVolumeClose(find);
5237
        Py_END_ALLOW_THREADS;
5238
    }
5239
    if (err && err != ERROR_NO_MORE_FILES) {
5240
        PyErr_SetFromWindowsErr(err);
5241
        Py_XDECREF(result);
5242
        result = NULL;
5243
    }
5244
    return result;
5245
}
5246
5247
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5248
5249
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5250
5251
/*[clinic input]
5252
os.listmounts
5253
5254
    volume: path_t
5255
5256
Return a list containing mount points for a particular volume.
5257
5258
'volume' should be a GUID path as returned from os.listvolumes.
5259
5260
[clinic start generated code]*/
5261
5262
static PyObject *
5263
os_listmounts_impl(PyObject *module, path_t *volume)
5264
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5265
{
5266
    wchar_t default_buffer[MAX_PATH + 1];
5267
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5268
    LPWSTR buffer = default_buffer;
5269
    DWORD attributes;
5270
    PyObject *str = NULL;
5271
    PyObject *nullchar = NULL;
5272
    PyObject *result = NULL;
5273
5274
    /* Ensure we have a valid volume path before continuing */
5275
    Py_BEGIN_ALLOW_THREADS
5276
    attributes = GetFileAttributesW(volume->wide);
5277
    Py_END_ALLOW_THREADS
5278
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5279
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5280
    {
5281
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5282
    }
5283
5284
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5285
        return NULL;
5286
    }
5287
5288
    while (1) {
5289
        BOOL success;
5290
        Py_BEGIN_ALLOW_THREADS
5291
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5292
                                                   buflen, &buflen);
5293
        Py_END_ALLOW_THREADS
5294
        if (success) {
5295
            break;
5296
        }
5297
        if (GetLastError() != ERROR_MORE_DATA) {
5298
            PyErr_SetFromWindowsErr(0);
5299
            goto exit;
5300
        }
5301
        if (buffer != default_buffer) {
5302
            PyMem_Free((void *)buffer);
5303
        }
5304
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5305
        if (!buffer) {
5306
            PyErr_NoMemory();
5307
            goto exit;
5308
        }
5309
    }
5310
    if (buflen < 2) {
5311
        result = PyList_New(0);
5312
        goto exit;
5313
    }
5314
    // buflen includes two null terminators, one for the last string
5315
    // and one for the array of strings.
5316
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5317
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5318
    if (str && nullchar) {
5319
        result = PyUnicode_Split(str, nullchar, -1);
5320
    }
5321
exit:
5322
    if (buffer != default_buffer) {
5323
        PyMem_Free(buffer);
5324
    }
5325
    Py_XDECREF(nullchar);
5326
    Py_XDECREF(str);
5327
    return result;
5328
}
5329
5330
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5331
5332
#ifdef MS_WINDOWS
5333
5334
/*[clinic input]
5335
os._path_isdevdrive
5336
5337
    path: path_t
5338
5339
Determines whether the specified path is on a Windows Dev Drive.
5340
5341
[clinic start generated code]*/
5342
5343
static PyObject *
5344
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5345
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5346
{
5347
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5348
    /* This flag will be documented at
5349
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5350
       after release, and will be available in the latest WinSDK.
5351
       We include the flag to avoid a specific version dependency
5352
       on the latest WinSDK. */
5353
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5354
#endif
5355
    int err = 0;
5356
    PyObject *r = NULL;
5357
    wchar_t volume[MAX_PATH];
5358
5359
    Py_BEGIN_ALLOW_THREADS
5360
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5361
        /* invalid path of some kind */
5362
        /* Note that this also includes the case where a volume is mounted
5363
           in a path longer than 260 characters. This is likely to be rare
5364
           and problematic for other reasons, so a (soft) failure in this
5365
           check seems okay. */
5366
        err = GetLastError();
5367
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5368
        /* only care about local dev drives */
5369
        r = Py_False;
5370
    } else {
5371
        HANDLE hVolume = CreateFileW(
5372
            volume,
5373
            FILE_READ_ATTRIBUTES,
5374
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5375
            NULL,
5376
            OPEN_EXISTING,
5377
            FILE_FLAG_BACKUP_SEMANTICS,
5378
            NULL
5379
        );
5380
        if (hVolume == INVALID_HANDLE_VALUE) {
5381
            err = GetLastError();
5382
        } else {
5383
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5384
            volumeState.Version = 1;
5385
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5386
            if (!DeviceIoControl(
5387
                hVolume,
5388
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5389
                &volumeState,
5390
                sizeof(volumeState),
5391
                &volumeState,
5392
                sizeof(volumeState),
5393
                NULL,
5394
                NULL
5395
            )) {
5396
                err = GetLastError();
5397
            }
5398
            CloseHandle(hVolume);
5399
            if (err == ERROR_INVALID_PARAMETER) {
5400
                /* not supported on this platform */
5401
                r = Py_False;
5402
            } else if (!err) {
5403
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5404
                    ? Py_True : Py_False;
5405
            }
5406
        }
5407
    }
5408
    Py_END_ALLOW_THREADS
5409
5410
    if (err) {
5411
        PyErr_SetFromWindowsErr(err);
5412
        return NULL;
5413
    }
5414
5415
    if (r) {
5416
        return Py_NewRef(r);
5417
    }
5418
5419
    return NULL;
5420
}
5421
5422
5423
int
5424
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5425
{
5426
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5427
    DWORD result;
5428
5429
    result = GetFullPathNameW(path,
5430
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5431
                              NULL);
5432
    if (!result) {
5433
        return -1;
5434
    }
5435
5436
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5437
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5438
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5439
        }
5440
        else {
5441
            woutbufp = NULL;
5442
        }
5443
        if (!woutbufp) {
5444
            *abspath_p = NULL;
5445
            return 0;
5446
        }
5447
5448
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5449
        if (!result) {
5450
            PyMem_RawFree(woutbufp);
5451
            return -1;
5452
        }
5453
    }
5454
5455
    if (woutbufp != woutbuf) {
5456
        *abspath_p = woutbufp;
5457
        return 0;
5458
    }
5459
5460
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5461
    return 0;
5462
}
5463
5464
5465
/* A helper function for abspath on win32 */
5466
/*[clinic input]
5467
os._getfullpathname
5468
5469
    path: path_t
5470
    /
5471
5472
[clinic start generated code]*/
5473
5474
static PyObject *
5475
os__getfullpathname_impl(PyObject *module, path_t *path)
5476
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5477
{
5478
    wchar_t *abspath;
5479
5480
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5481
        return win32_error_object("GetFullPathNameW", path->object);
5482
    }
5483
    if (abspath == NULL) {
5484
        return PyErr_NoMemory();
5485
    }
5486
5487
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5488
    PyMem_RawFree(abspath);
5489
    if (str == NULL) {
5490
        return NULL;
5491
    }
5492
    if (PyBytes_Check(path->object)) {
5493
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5494
    }
5495
    return str;
5496
}
5497
5498
5499
/*[clinic input]
5500
os._getfinalpathname
5501
5502
    path: path_t
5503
    /
5504
5505
A helper function for samepath on windows.
5506
[clinic start generated code]*/
5507
5508
static PyObject *
5509
os__getfinalpathname_impl(PyObject *module, path_t *path)
5510
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5511
{
5512
    HANDLE hFile;
5513
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5514
    int buf_size = Py_ARRAY_LENGTH(buf);
5515
    int result_length;
5516
    PyObject *result;
5517
5518
    Py_BEGIN_ALLOW_THREADS
5519
    hFile = CreateFileW(
5520
        path->wide,
5521
        0, /* desired access */
5522
        0, /* share mode */
5523
        NULL, /* security attributes */
5524
        OPEN_EXISTING,
5525
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5526
        FILE_FLAG_BACKUP_SEMANTICS,
5527
        NULL);
5528
    Py_END_ALLOW_THREADS
5529
5530
    if (hFile == INVALID_HANDLE_VALUE) {
5531
        return win32_error_object("CreateFileW", path->object);
5532
    }
5533
5534
    /* We have a good handle to the target, use it to determine the
5535
       target path name. */
5536
    while (1) {
5537
        Py_BEGIN_ALLOW_THREADS
5538
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5539
                                                  buf_size, VOLUME_NAME_DOS);
5540
        Py_END_ALLOW_THREADS
5541
5542
        if (!result_length) {
5543
            result = win32_error_object("GetFinalPathNameByHandleW",
5544
                                         path->object);
5545
            goto cleanup;
5546
        }
5547
5548
        if (result_length < buf_size) {
5549
            break;
5550
        }
5551
5552
        wchar_t *tmp;
5553
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5554
                            result_length * sizeof(*tmp));
5555
        if (!tmp) {
5556
            result = PyErr_NoMemory();
5557
            goto cleanup;
5558
        }
5559
5560
        buf_size = result_length;
5561
        target_path = tmp;
5562
    }
5563
5564
    result = PyUnicode_FromWideChar(target_path, result_length);
5565
    if (result && PyBytes_Check(path->object)) {
5566
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5567
    }
5568
5569
cleanup:
5570
    if (target_path != buf) {
5571
        PyMem_Free(target_path);
5572
    }
5573
    CloseHandle(hFile);
5574
    return result;
5575
}
5576
5577
/*[clinic input]
5578
os._findfirstfile
5579
    path: path_t
5580
    /
5581
A function to get the real file name without accessing the file in Windows.
5582
[clinic start generated code]*/
5583
5584
static PyObject *
5585
os__findfirstfile_impl(PyObject *module, path_t *path)
5586
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5587
{
5588
    PyObject *result;
5589
    HANDLE hFindFile;
5590
    WIN32_FIND_DATAW wFileData;
5591
    WCHAR *wRealFileName;
5592
5593
    Py_BEGIN_ALLOW_THREADS
5594
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5595
    Py_END_ALLOW_THREADS
5596
5597
    if (hFindFile == INVALID_HANDLE_VALUE) {
5598
        path_error(path);
5599
        return NULL;
5600
    }
5601
5602
    wRealFileName = wFileData.cFileName;
5603
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5604
    FindClose(hFindFile);
5605
    return result;
5606
}
5607
5608
5609
/*[clinic input]
5610
os._getvolumepathname
5611
5612
    path: path_t
5613
5614
A helper function for ismount on Win32.
5615
[clinic start generated code]*/
5616
5617
static PyObject *
5618
os__getvolumepathname_impl(PyObject *module, path_t *path)
5619
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5620
{
5621
    PyObject *result;
5622
    wchar_t *mountpath=NULL;
5623
    size_t buflen;
5624
    BOOL ret;
5625
5626
    /* Volume path should be shorter than entire path */
5627
    buflen = Py_MAX(path->length, MAX_PATH);
5628
5629
    if (buflen > PY_DWORD_MAX) {
5630
        PyErr_SetString(PyExc_OverflowError, "path too long");
5631
        return NULL;
5632
    }
5633
5634
    mountpath = PyMem_New(wchar_t, buflen);
5635
    if (mountpath == NULL)
5636
        return PyErr_NoMemory();
5637
5638
    Py_BEGIN_ALLOW_THREADS
5639
    ret = GetVolumePathNameW(path->wide, mountpath,
5640
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5641
    Py_END_ALLOW_THREADS
5642
5643
    if (!ret) {
5644
        result = win32_error_object("_getvolumepathname", path->object);
5645
        goto exit;
5646
    }
5647
    result = PyUnicode_FromWideChar(mountpath, -1);
5648
    if (PyBytes_Check(path->object))
5649
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5650
5651
exit:
5652
    PyMem_Free(mountpath);
5653
    return result;
5654
}
5655
5656
5657
/*[clinic input]
5658
os._path_splitroot
5659
5660
    path: path_t,
5661
    /
5662
5663
Removes everything after the root on Win32.
5664
[clinic start generated code]*/
5665
5666
static PyObject *
5667
os__path_splitroot_impl(PyObject *module, path_t *path)
5668
/*[clinic end generated code: output=ab7f1a88b654581c input=42831e41f8458f6d]*/
5669
{
5670
    wchar_t *buffer;
5671
    wchar_t *end;
5672
    PyObject *result = NULL;
5673
    HRESULT ret;
5674
5675
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5676
    if (!buffer) {
5677
        return NULL;
5678
    }
5679
    wcscpy(buffer, path->wide);
5680
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5681
        *p = L'\\';
5682
    }
5683
5684
    Py_BEGIN_ALLOW_THREADS
5685
    ret = PathCchSkipRoot(buffer, &end);
5686
    Py_END_ALLOW_THREADS
5687
    if (FAILED(ret)) {
5688
        result = Py_BuildValue("sO", "", path->object);
5689
    } else if (end != buffer) {
5690
        size_t rootLen = (size_t)(end - buffer);
5691
        result = Py_BuildValue("NN",
5692
            PyUnicode_FromWideChar(path->wide, rootLen),
5693
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5694
        );
5695
    } else {
5696
        result = Py_BuildValue("Os", path->object, "");
5697
    }
5698
    PyMem_Free(buffer);
5699
5700
    return result;
5701
}
5702
5703
5704
#define PY_IFREG  1 // Regular file
5705
#define PY_IFDIR  2 // Directory
5706
#define PY_IFLNK  4 // Symlink
5707
#define PY_IFMNT  8 // Mount Point (junction)
5708
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5709
#define PY_IFRRP 32 // Regular Reparse Point
5710
5711
static inline BOOL
5712
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5713
{
5714
    switch (testedType) {
5715
    case PY_IFREG:
5716
        return diskDevice && attributes &&
5717
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5718
    case PY_IFDIR:
5719
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5720
    case PY_IFLNK:
5721
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5722
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5723
    case PY_IFMNT:
5724
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5725
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5726
    case PY_IFLRP:
5727
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5728
               IsReparseTagNameSurrogate(reparseTag);
5729
    case PY_IFRRP:
5730
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5731
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5732
    }
5733
5734
    return FALSE;
5735
}
5736
5737
static BOOL
5738
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5739
{
5740
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5741
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5742
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5743
5744
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5745
    if (diskOnly && !diskDevice) {
5746
        return FALSE;
5747
    }
5748
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5749
        FILE_ATTRIBUTE_TAG_INFO info;
5750
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5751
                                            sizeof(info)) &&
5752
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5753
                         testedType);
5754
    }
5755
    FILE_BASIC_INFO info;
5756
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5757
                                        sizeof(info)) &&
5758
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5759
}
5760
5761
static BOOL
5762
_testFileTypeByName(LPCWSTR path, int testedType)
5763
{
5764
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5765
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5766
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5767
5768
    FILE_STAT_BASIC_INFORMATION info;
5769
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5770
                                     sizeof(info)))
5771
    {
5772
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5773
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5774
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5775
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5776
                                diskDevice, testedType);
5777
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5778
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5779
        {
5780
            return result;
5781
        }
5782
    }
5783
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5784
                GetLastError()))
5785
    {
5786
        return FALSE;
5787
    }
5788
5789
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5790
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5791
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5792
    }
5793
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5794
                               OPEN_EXISTING, flags, NULL);
5795
    if (hfile != INVALID_HANDLE_VALUE) {
5796
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5797
        CloseHandle(hfile);
5798
        return result;
5799
    }
5800
5801
    switch (GetLastError()) {
5802
    case ERROR_ACCESS_DENIED:
5803
    case ERROR_SHARING_VIOLATION:
5804
    case ERROR_CANT_ACCESS_FILE:
5805
    case ERROR_INVALID_PARAMETER:
5806
        int rc;
5807
        STRUCT_STAT st;
5808
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5809
            rc = STAT(path, &st);
5810
        }
5811
        else {
5812
            // PY_IFRRP is not generally supported in this case, except for
5813
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5814
            rc = LSTAT(path, &st);
5815
        }
5816
        if (!rc) {
5817
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5818
                             st.st_mode & S_IFREG, testedType);
5819
        }
5820
    }
5821
5822
    return FALSE;
5823
}
5824
5825
5826
static BOOL
5827
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5828
{
5829
    FILE_STAT_BASIC_INFORMATION info;
5830
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5831
                                     sizeof(info)))
5832
    {
5833
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5834
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5835
        {
5836
            return TRUE;
5837
        }
5838
    }
5839
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5840
                    GetLastError()))
5841
    {
5842
        return FALSE;
5843
    }
5844
5845
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5846
    if (!followLinks) {
5847
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5848
    }
5849
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5850
                               OPEN_EXISTING, flags, NULL);
5851
    if (hfile != INVALID_HANDLE_VALUE) {
5852
        if (followLinks) {
5853
            CloseHandle(hfile);
5854
            return TRUE;
5855
        }
5856
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5857
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5858
        CloseHandle(hfile);
5859
        if (!result) {
5860
            return TRUE;
5861
        }
5862
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5863
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5864
        if (hfile != INVALID_HANDLE_VALUE) {
5865
            CloseHandle(hfile);
5866
            return TRUE;
5867
        }
5868
    }
5869
5870
    switch (GetLastError()) {
5871
    case ERROR_ACCESS_DENIED:
5872
    case ERROR_SHARING_VIOLATION:
5873
    case ERROR_CANT_ACCESS_FILE:
5874
    case ERROR_INVALID_PARAMETER:
5875
        STRUCT_STAT _st;
5876
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5877
    }
5878
5879
    return FALSE;
5880
}
5881
5882
5883
static BOOL
5884
_testFileExists(path_t *path, BOOL followLinks)
5885
{
5886
    BOOL result = FALSE;
5887
    if (path->value_error) {
5888
        return FALSE;
5889
    }
5890
5891
    Py_BEGIN_ALLOW_THREADS
5892
    if (path->fd != -1) {
5893
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5894
        if (hfile != INVALID_HANDLE_VALUE) {
5895
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5896
                result = TRUE;
5897
            }
5898
        }
5899
    }
5900
    else if (path->wide) {
5901
        result = _testFileExistsByName(path->wide, followLinks);
5902
    }
5903
    Py_END_ALLOW_THREADS
5904
5905
    return result;
5906
}
5907
5908
5909
static BOOL
5910
_testFileType(path_t *path, int testedType)
5911
{
5912
    BOOL result = FALSE;
5913
    if (path->value_error) {
5914
        return FALSE;
5915
    }
5916
5917
    Py_BEGIN_ALLOW_THREADS
5918
    if (path->fd != -1) {
5919
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5920
        if (hfile != INVALID_HANDLE_VALUE) {
5921
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5922
        }
5923
    }
5924
    else if (path->wide) {
5925
        result = _testFileTypeByName(path->wide, testedType);
5926
    }
5927
    Py_END_ALLOW_THREADS
5928
5929
    return result;
5930
}
5931
5932
5933
/*[clinic input]
5934
os._path_exists -> bool
5935
5936
    path: path_t(allow_fd=True, suppress_value_error=True)
5937
5938
Test whether a path exists.  Returns False for broken symbolic links.
5939
5940
[clinic start generated code]*/
5941
5942
static int
5943
os__path_exists_impl(PyObject *module, path_t *path)
5944
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5945
{
5946
    return _testFileExists(path, TRUE);
5947
}
5948
5949
5950
/*[clinic input]
5951
os._path_lexists -> bool
5952
5953
    path: path_t(allow_fd=True, suppress_value_error=True)
5954
5955
Test whether a path exists.  Returns True for broken symbolic links.
5956
5957
[clinic start generated code]*/
5958
5959
static int
5960
os__path_lexists_impl(PyObject *module, path_t *path)
5961
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5962
{
5963
    return _testFileExists(path, FALSE);
5964
}
5965
5966
5967
/*[clinic input]
5968
os._path_isdir -> bool
5969
5970
    path: path_t(allow_fd=True, suppress_value_error=True),
5971
    /
5972
5973
Return true if the pathname refers to an existing directory.
5974
5975
[clinic start generated code]*/
5976
5977
static int
5978
os__path_isdir_impl(PyObject *module, path_t *path)
5979
/*[clinic end generated code: output=d5786196f9e2fa7a input=0d3fd790564d244b]*/
5980
{
5981
    return _testFileType(path, PY_IFDIR);
5982
}
5983
5984
5985
/*[clinic input]
5986
os._path_isfile -> bool
5987
5988
    path: path_t(allow_fd=True, suppress_value_error=True)
5989
5990
Test whether a path is a regular file
5991
5992
[clinic start generated code]*/
5993
5994
static int
5995
os__path_isfile_impl(PyObject *module, path_t *path)
5996
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
5997
{
5998
    return _testFileType(path, PY_IFREG);
5999
}
6000
6001
6002
/*[clinic input]
6003
os._path_islink -> bool
6004
6005
    path: path_t(allow_fd=True, suppress_value_error=True)
6006
6007
Test whether a path is a symbolic link
6008
6009
[clinic start generated code]*/
6010
6011
static int
6012
os__path_islink_impl(PyObject *module, path_t *path)
6013
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6014
{
6015
    return _testFileType(path, PY_IFLNK);
6016
}
6017
6018
6019
/*[clinic input]
6020
os._path_isjunction -> bool
6021
6022
    path: path_t(allow_fd=True, suppress_value_error=True)
6023
6024
Test whether a path is a junction
6025
6026
[clinic start generated code]*/
6027
6028
static int
6029
os__path_isjunction_impl(PyObject *module, path_t *path)
6030
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6031
{
6032
    return _testFileType(path, PY_IFMNT);
6033
}
6034
6035
#undef PY_IFREG
6036
#undef PY_IFDIR
6037
#undef PY_IFLNK
6038
#undef PY_IFMNT
6039
#undef PY_IFLRP
6040
#undef PY_IFRRP
6041
6042
#endif /* MS_WINDOWS */
6043
6044
6045
/*[clinic input]
6046
os._path_splitroot_ex
6047
6048
    path: path_t(make_wide=True, nonstrict=True),
6049
    /
6050
6051
Split a pathname into drive, root and tail.
6052
6053
The tail contains anything after the root.
6054
[clinic start generated code]*/
6055
6056
static PyObject *
6057
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6058
/*[clinic end generated code: output=4b0072b6cdf4b611 input=4ac47b394d68bd21]*/
6059
0
{
6060
0
    Py_ssize_t drvsize, rootsize;
6061
0
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6062
6063
0
    const wchar_t *buffer = path->wide;
6064
0
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6065
0
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6066
0
    if (drv == NULL) {
6067
0
        goto exit;
6068
0
    }
6069
0
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6070
0
    if (root == NULL) {
6071
0
        goto exit;
6072
0
    }
6073
0
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6074
0
                                  path->length - drvsize - rootsize);
6075
0
    if (tail == NULL) {
6076
0
        goto exit;
6077
0
    }
6078
0
    if (PyBytes_Check(path->object)) {
6079
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6080
0
        if (drv == NULL) {
6081
0
            goto exit;
6082
0
        }
6083
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6084
0
        if (root == NULL) {
6085
0
            goto exit;
6086
0
        }
6087
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6088
0
        if (tail == NULL) {
6089
0
            goto exit;
6090
0
        }
6091
0
    }
6092
0
    result = PyTuple_Pack(3, drv, root, tail);
6093
0
exit:
6094
0
    Py_XDECREF(drv);
6095
0
    Py_XDECREF(root);
6096
0
    Py_XDECREF(tail);
6097
0
    return result;
6098
0
}
6099
6100
6101
/*[clinic input]
6102
os._path_normpath
6103
6104
    path: path_t(make_wide=True, nonstrict=True)
6105
6106
Normalize path, eliminating double slashes, etc.
6107
[clinic start generated code]*/
6108
6109
static PyObject *
6110
os__path_normpath_impl(PyObject *module, path_t *path)
6111
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6112
80
{
6113
80
    PyObject *result;
6114
80
    Py_ssize_t norm_len;
6115
80
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6116
80
                                               path->length, &norm_len);
6117
80
    if (!norm_len) {
6118
0
        result = PyUnicode_FromOrdinal('.');
6119
0
    }
6120
80
    else {
6121
80
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6122
80
    }
6123
80
    if (PyBytes_Check(path->object)) {
6124
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6125
0
    }
6126
80
    return result;
6127
80
}
6128
6129
/*[clinic input]
6130
os.mkdir
6131
6132
    path : path_t
6133
6134
    mode: int = 0o777
6135
6136
    *
6137
6138
    dir_fd : dir_fd(requires='mkdirat') = None
6139
6140
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
6141
6142
Create a directory.
6143
6144
If dir_fd is not None, it should be a file descriptor open to a directory,
6145
  and path should be relative; path will then be relative to that directory.
6146
dir_fd may not be implemented on your platform.
6147
  If it is unavailable, using it will raise a NotImplementedError.
6148
6149
The mode argument is ignored on Windows. Where it is used, the current umask
6150
value is first masked out.
6151
[clinic start generated code]*/
6152
6153
static PyObject *
6154
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6155
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
6156
0
{
6157
0
    int result;
6158
#ifdef MS_WINDOWS
6159
    int error = 0;
6160
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6161
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6162
#endif
6163
0
#ifdef HAVE_MKDIRAT
6164
0
    int mkdirat_unavailable = 0;
6165
0
#endif
6166
6167
0
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6168
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6169
0
        return NULL;
6170
0
    }
6171
6172
#ifdef MS_WINDOWS
6173
    Py_BEGIN_ALLOW_THREADS
6174
    // For API sets that don't support these APIs, we have no choice
6175
    // but to silently create a directory with default ACL.
6176
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6177
    if (mode == 0700 /* 0o700 */) {
6178
        ULONG sdSize;
6179
        pSecAttr = &secAttr;
6180
        // Set a discretionary ACL (D) that is protected (P) and includes
6181
        // inheritable (OICI) entries that allow (A) full control (FA) to
6182
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6183
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6184
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6185
            SDDL_REVISION_1,
6186
            &secAttr.lpSecurityDescriptor,
6187
            &sdSize
6188
        )) {
6189
            error = GetLastError();
6190
        }
6191
    }
6192
#endif
6193
    if (!error) {
6194
        result = CreateDirectoryW(path->wide, pSecAttr);
6195
        if (secAttr.lpSecurityDescriptor &&
6196
            // uncommonly, LocalFree returns non-zero on error, but still uses
6197
            // GetLastError() to see what the error code is
6198
            LocalFree(secAttr.lpSecurityDescriptor)) {
6199
            error = GetLastError();
6200
        }
6201
    }
6202
    Py_END_ALLOW_THREADS
6203
6204
    if (error) {
6205
        return PyErr_SetFromWindowsErr(error);
6206
    }
6207
    if (!result) {
6208
        return path_error(path);
6209
    }
6210
#else
6211
0
    Py_BEGIN_ALLOW_THREADS
6212
0
#if HAVE_MKDIRAT
6213
0
    if (dir_fd != DEFAULT_DIR_FD) {
6214
0
      if (HAVE_MKDIRAT_RUNTIME) {
6215
0
        result = mkdirat(dir_fd, path->narrow, mode);
6216
6217
0
      } else {
6218
0
        mkdirat_unavailable = 1;
6219
0
      }
6220
0
    } else
6221
0
#endif
6222
#if defined(__WATCOMC__) && !defined(__QNX__)
6223
        result = mkdir(path->narrow);
6224
#else
6225
0
        result = mkdir(path->narrow, mode);
6226
0
#endif
6227
0
    Py_END_ALLOW_THREADS
6228
6229
0
#if HAVE_MKDIRAT
6230
0
    if (mkdirat_unavailable) {
6231
0
        argument_unavailable_error(NULL, "dir_fd");
6232
0
        return NULL;
6233
0
    }
6234
0
#endif
6235
6236
0
    if (result < 0)
6237
0
        return path_error(path);
6238
0
#endif /* MS_WINDOWS */
6239
0
    Py_RETURN_NONE;
6240
0
}
6241
6242
6243
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6244
#if defined(HAVE_SYS_RESOURCE_H)
6245
#include <sys/resource.h>
6246
#endif
6247
6248
6249
#ifdef HAVE_NICE
6250
/*[clinic input]
6251
os.nice
6252
6253
    increment: int
6254
    /
6255
6256
Add increment to the priority of process and return the new priority.
6257
[clinic start generated code]*/
6258
6259
static PyObject *
6260
os_nice_impl(PyObject *module, int increment)
6261
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6262
0
{
6263
0
    int value;
6264
6265
    /* There are two flavours of 'nice': one that returns the new
6266
       priority (as required by almost all standards out there) and the
6267
       Linux/FreeBSD one, which returns '0' on success and advices
6268
       the use of getpriority() to get the new priority.
6269
6270
       If we are of the nice family that returns the new priority, we
6271
       need to clear errno before the call, and check if errno is filled
6272
       before calling posix_error() on a returnvalue of -1, because the
6273
       -1 may be the actual new priority! */
6274
6275
0
    errno = 0;
6276
0
    value = nice(increment);
6277
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6278
    if (value == 0)
6279
        value = getpriority(PRIO_PROCESS, 0);
6280
#endif
6281
0
    if (value == -1 && errno != 0)
6282
        /* either nice() or getpriority() returned an error */
6283
0
        return posix_error();
6284
0
    return PyLong_FromLong((long) value);
6285
0
}
6286
#endif /* HAVE_NICE */
6287
6288
6289
#ifdef HAVE_GETPRIORITY
6290
/*[clinic input]
6291
os.getpriority
6292
6293
    which: int
6294
    who: int
6295
6296
Return program scheduling priority.
6297
[clinic start generated code]*/
6298
6299
static PyObject *
6300
os_getpriority_impl(PyObject *module, int which, int who)
6301
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6302
0
{
6303
0
    int retval;
6304
6305
0
    errno = 0;
6306
0
    retval = getpriority(which, who);
6307
0
    if (errno != 0)
6308
0
        return posix_error();
6309
0
    return PyLong_FromLong((long)retval);
6310
0
}
6311
#endif /* HAVE_GETPRIORITY */
6312
6313
6314
#ifdef HAVE_SETPRIORITY
6315
/*[clinic input]
6316
os.setpriority
6317
6318
    which: int
6319
    who: int
6320
    priority: int
6321
6322
Set program scheduling priority.
6323
[clinic start generated code]*/
6324
6325
static PyObject *
6326
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6327
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6328
0
{
6329
0
    int retval;
6330
6331
0
    retval = setpriority(which, who, priority);
6332
0
    if (retval == -1)
6333
0
        return posix_error();
6334
0
    Py_RETURN_NONE;
6335
0
}
6336
#endif /* HAVE_SETPRIORITY */
6337
6338
6339
static PyObject *
6340
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6341
241
{
6342
241
    const char *function_name = is_replace ? "replace" : "rename";
6343
241
    int dir_fd_specified;
6344
6345
241
#ifdef HAVE_RENAMEAT
6346
241
    int renameat_unavailable = 0;
6347
241
#endif
6348
6349
#ifdef MS_WINDOWS
6350
    BOOL result;
6351
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6352
#else
6353
241
    int result;
6354
241
#endif
6355
6356
241
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6357
241
                       (dst_dir_fd != DEFAULT_DIR_FD);
6358
#ifndef HAVE_RENAMEAT
6359
    if (dir_fd_specified) {
6360
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6361
        return NULL;
6362
    }
6363
#endif
6364
6365
241
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6366
241
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6367
241
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6368
0
        return NULL;
6369
0
    }
6370
6371
#ifdef MS_WINDOWS
6372
    Py_BEGIN_ALLOW_THREADS
6373
    result = MoveFileExW(src->wide, dst->wide, flags);
6374
    Py_END_ALLOW_THREADS
6375
6376
    if (!result)
6377
        return path_error2(src, dst);
6378
6379
#else
6380
241
    Py_BEGIN_ALLOW_THREADS
6381
241
#ifdef HAVE_RENAMEAT
6382
241
    if (dir_fd_specified) {
6383
0
        if (HAVE_RENAMEAT_RUNTIME) {
6384
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6385
0
        } else {
6386
0
            renameat_unavailable = 1;
6387
0
        }
6388
0
    } else
6389
241
#endif
6390
241
    result = rename(src->narrow, dst->narrow);
6391
241
    Py_END_ALLOW_THREADS
6392
6393
6394
241
#ifdef HAVE_RENAMEAT
6395
241
    if (renameat_unavailable) {
6396
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6397
0
        return NULL;
6398
0
    }
6399
241
#endif
6400
6401
241
    if (result)
6402
0
        return path_error2(src, dst);
6403
241
#endif
6404
241
    Py_RETURN_NONE;
6405
241
}
6406
6407
6408
/*[clinic input]
6409
@permit_long_docstring_body
6410
os.rename
6411
6412
    src : path_t
6413
    dst : path_t
6414
    *
6415
    src_dir_fd : dir_fd = None
6416
    dst_dir_fd : dir_fd = None
6417
6418
Rename a file or directory.
6419
6420
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6421
  descriptor open to a directory, and the respective path string (src or dst)
6422
  should be relative; the path will then be relative to that directory.
6423
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6424
  If they are unavailable, using them will raise a NotImplementedError.
6425
[clinic start generated code]*/
6426
6427
static PyObject *
6428
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6429
               int dst_dir_fd)
6430
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6431
0
{
6432
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6433
0
}
6434
6435
6436
/*[clinic input]
6437
@permit_long_docstring_body
6438
os.replace = os.rename
6439
6440
Rename a file or directory, overwriting the destination.
6441
6442
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6443
  descriptor open to a directory, and the respective path string (src or dst)
6444
  should be relative; the path will then be relative to that directory.
6445
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6446
  If they are unavailable, using them will raise a NotImplementedError.
6447
[clinic start generated code]*/
6448
6449
static PyObject *
6450
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6451
                int dst_dir_fd)
6452
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6453
241
{
6454
241
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6455
241
}
6456
6457
6458
/*[clinic input]
6459
os.rmdir
6460
6461
    path: path_t
6462
    *
6463
    dir_fd: dir_fd(requires='unlinkat') = None
6464
6465
Remove a directory.
6466
6467
If dir_fd is not None, it should be a file descriptor open to a directory,
6468
  and path should be relative; path will then be relative to that directory.
6469
dir_fd may not be implemented on your platform.
6470
  If it is unavailable, using it will raise a NotImplementedError.
6471
[clinic start generated code]*/
6472
6473
static PyObject *
6474
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6475
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6476
0
{
6477
0
    int result;
6478
0
#ifdef HAVE_UNLINKAT
6479
0
    int unlinkat_unavailable = 0;
6480
0
#endif
6481
6482
0
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6483
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6484
0
        return NULL;
6485
0
    }
6486
6487
0
    Py_BEGIN_ALLOW_THREADS
6488
#ifdef MS_WINDOWS
6489
    /* Windows, success=1, UNIX, success=0 */
6490
    result = !RemoveDirectoryW(path->wide);
6491
#else
6492
0
#ifdef HAVE_UNLINKAT
6493
0
    if (dir_fd != DEFAULT_DIR_FD) {
6494
0
      if (HAVE_UNLINKAT_RUNTIME) {
6495
0
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6496
0
      } else {
6497
0
        unlinkat_unavailable = 1;
6498
0
        result = -1;
6499
0
      }
6500
0
    } else
6501
0
#endif
6502
0
        result = rmdir(path->narrow);
6503
0
#endif
6504
0
    Py_END_ALLOW_THREADS
6505
6506
0
#ifdef HAVE_UNLINKAT
6507
0
    if (unlinkat_unavailable) {
6508
0
        argument_unavailable_error("rmdir", "dir_fd");
6509
0
        return NULL;
6510
0
    }
6511
0
#endif
6512
6513
0
    if (result)
6514
0
        return path_error(path);
6515
6516
0
    Py_RETURN_NONE;
6517
0
}
6518
6519
6520
#ifdef HAVE_SYSTEM
6521
#ifdef MS_WINDOWS
6522
/*[clinic input]
6523
os.system -> long
6524
6525
    command: Py_UNICODE
6526
6527
Execute the command in a subshell.
6528
[clinic start generated code]*/
6529
6530
static long
6531
os_system_impl(PyObject *module, const wchar_t *command)
6532
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6533
{
6534
    long result;
6535
6536
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6537
        return -1;
6538
    }
6539
6540
    Py_BEGIN_ALLOW_THREADS
6541
    _Py_BEGIN_SUPPRESS_IPH
6542
    result = _wsystem(command);
6543
    _Py_END_SUPPRESS_IPH
6544
    Py_END_ALLOW_THREADS
6545
    return result;
6546
}
6547
#else /* MS_WINDOWS */
6548
/*[clinic input]
6549
os.system -> long
6550
6551
    command: unicode_fs_encoded
6552
6553
Execute the command in a subshell.
6554
[clinic start generated code]*/
6555
6556
static long
6557
os_system_impl(PyObject *module, PyObject *command)
6558
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6559
0
{
6560
0
    long result;
6561
0
    const char *bytes = PyBytes_AsString(command);
6562
6563
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6564
0
        return -1;
6565
0
    }
6566
6567
0
    Py_BEGIN_ALLOW_THREADS
6568
0
    result = system(bytes);
6569
0
    Py_END_ALLOW_THREADS
6570
0
    return result;
6571
0
}
6572
#endif
6573
#endif /* HAVE_SYSTEM */
6574
6575
6576
#ifdef HAVE_UMASK
6577
/*[clinic input]
6578
os.umask
6579
6580
    mask: int
6581
    /
6582
6583
Set the current numeric umask and return the previous umask.
6584
[clinic start generated code]*/
6585
6586
static PyObject *
6587
os_umask_impl(PyObject *module, int mask)
6588
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6589
0
{
6590
0
    int i = (int)umask(mask);
6591
0
    if (i < 0)
6592
0
        return posix_error();
6593
0
    return PyLong_FromLong((long)i);
6594
0
}
6595
#endif
6596
6597
#ifdef MS_WINDOWS
6598
6599
/* override the default DeleteFileW behavior so that directory
6600
symlinks can be removed with this function, the same as with
6601
Unix symlinks */
6602
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6603
{
6604
    WIN32_FILE_ATTRIBUTE_DATA info;
6605
    WIN32_FIND_DATAW find_data;
6606
    HANDLE find_data_handle;
6607
    int is_directory = 0;
6608
    int is_link = 0;
6609
6610
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6611
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6612
6613
        /* Get WIN32_FIND_DATA structure for the path to determine if
6614
           it is a symlink */
6615
        if(is_directory &&
6616
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6617
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6618
6619
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6620
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6621
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6622
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6623
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6624
                FindClose(find_data_handle);
6625
            }
6626
        }
6627
    }
6628
6629
    if (is_directory && is_link)
6630
        return RemoveDirectoryW(lpFileName);
6631
6632
    return DeleteFileW(lpFileName);
6633
}
6634
#endif /* MS_WINDOWS */
6635
6636
6637
/*[clinic input]
6638
os.unlink
6639
6640
    path: path_t
6641
    *
6642
    dir_fd: dir_fd(requires='unlinkat')=None
6643
6644
Remove a file (same as remove()).
6645
6646
If dir_fd is not None, it should be a file descriptor open to a directory,
6647
  and path should be relative; path will then be relative to that directory.
6648
dir_fd may not be implemented on your platform.
6649
  If it is unavailable, using it will raise a NotImplementedError.
6650
6651
[clinic start generated code]*/
6652
6653
static PyObject *
6654
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6655
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6656
0
{
6657
0
    int result;
6658
0
#ifdef HAVE_UNLINKAT
6659
0
    int unlinkat_unavailable = 0;
6660
0
#endif
6661
6662
0
    if (PySys_Audit("os.remove", "Oi", path->object,
6663
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6664
0
        return NULL;
6665
0
    }
6666
6667
0
    Py_BEGIN_ALLOW_THREADS
6668
0
    _Py_BEGIN_SUPPRESS_IPH
6669
#ifdef MS_WINDOWS
6670
    /* Windows, success=1, UNIX, success=0 */
6671
    result = !Py_DeleteFileW(path->wide);
6672
#else
6673
0
#ifdef HAVE_UNLINKAT
6674
0
    if (dir_fd != DEFAULT_DIR_FD) {
6675
0
      if (HAVE_UNLINKAT_RUNTIME) {
6676
6677
0
        result = unlinkat(dir_fd, path->narrow, 0);
6678
0
      } else {
6679
0
        unlinkat_unavailable = 1;
6680
0
      }
6681
0
    } else
6682
0
#endif /* HAVE_UNLINKAT */
6683
0
        result = unlink(path->narrow);
6684
0
#endif
6685
0
    _Py_END_SUPPRESS_IPH
6686
0
    Py_END_ALLOW_THREADS
6687
6688
0
#ifdef HAVE_UNLINKAT
6689
0
    if (unlinkat_unavailable) {
6690
0
        argument_unavailable_error(NULL, "dir_fd");
6691
0
        return NULL;
6692
0
    }
6693
0
#endif
6694
6695
0
    if (result)
6696
0
        return path_error(path);
6697
6698
0
    Py_RETURN_NONE;
6699
0
}
6700
6701
6702
/*[clinic input]
6703
os.remove = os.unlink
6704
6705
Remove a file (same as unlink()).
6706
6707
If dir_fd is not None, it should be a file descriptor open to a directory,
6708
  and path should be relative; path will then be relative to that directory.
6709
dir_fd may not be implemented on your platform.
6710
  If it is unavailable, using it will raise a NotImplementedError.
6711
[clinic start generated code]*/
6712
6713
static PyObject *
6714
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6715
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6716
0
{
6717
0
    return os_unlink_impl(module, path, dir_fd);
6718
0
}
6719
6720
6721
static PyStructSequence_Field uname_result_fields[] = {
6722
    {"sysname",    "operating system name"},
6723
    {"nodename",   "name of machine on network (implementation-defined)"},
6724
    {"release",    "operating system release"},
6725
    {"version",    "operating system version"},
6726
    {"machine",    "hardware identifier"},
6727
    {NULL}
6728
};
6729
6730
PyDoc_STRVAR(uname_result__doc__,
6731
"uname_result: Result from os.uname().\n\n\
6732
This object may be accessed either as a tuple of\n\
6733
  (sysname, nodename, release, version, machine),\n\
6734
or via the attributes sysname, nodename, release, version, and machine.\n\
6735
\n\
6736
See os.uname for more information.");
6737
6738
static PyStructSequence_Desc uname_result_desc = {
6739
    MODNAME ".uname_result", /* name */
6740
    uname_result__doc__, /* doc */
6741
    uname_result_fields,
6742
    5
6743
};
6744
6745
#ifdef HAVE_UNAME
6746
/*[clinic input]
6747
os.uname
6748
6749
Return an object identifying the current operating system.
6750
6751
The object behaves like a named tuple with the following fields:
6752
  (sysname, nodename, release, version, machine)
6753
6754
[clinic start generated code]*/
6755
6756
static PyObject *
6757
os_uname_impl(PyObject *module)
6758
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6759
0
{
6760
0
    struct utsname u;
6761
0
    int res;
6762
0
    PyObject *value;
6763
6764
0
    Py_BEGIN_ALLOW_THREADS
6765
0
    res = uname(&u);
6766
0
    Py_END_ALLOW_THREADS
6767
0
    if (res < 0)
6768
0
        return posix_error();
6769
6770
0
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6771
0
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6772
0
    if (value == NULL)
6773
0
        return NULL;
6774
6775
0
#define SET(i, field) \
6776
0
    { \
6777
0
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6778
0
    if (!o) { \
6779
0
        Py_DECREF(value); \
6780
0
        return NULL; \
6781
0
    } \
6782
0
    PyStructSequence_SET_ITEM(value, i, o); \
6783
0
    } \
6784
0
6785
0
    SET(0, u.sysname);
6786
0
    SET(1, u.nodename);
6787
0
    SET(2, u.release);
6788
0
    SET(3, u.version);
6789
0
    SET(4, u.machine);
6790
6791
0
#undef SET
6792
6793
0
    return value;
6794
0
}
6795
#endif /* HAVE_UNAME */
6796
6797
6798
6799
typedef struct {
6800
    int    now;
6801
    time_t atime_s;
6802
    long   atime_ns;
6803
    time_t mtime_s;
6804
    long   mtime_ns;
6805
} utime_t;
6806
6807
/*
6808
 * these macros assume that "ut" is a pointer to a utime_t
6809
 * they also intentionally leak the declaration of a pointer named "time"
6810
 */
6811
#define UTIME_TO_TIMESPEC \
6812
0
    struct timespec ts[2]; \
6813
0
    struct timespec *time; \
6814
0
    if (ut->now) \
6815
0
        time = NULL; \
6816
0
    else { \
6817
0
        ts[0].tv_sec = ut->atime_s; \
6818
0
        ts[0].tv_nsec = ut->atime_ns; \
6819
0
        ts[1].tv_sec = ut->mtime_s; \
6820
0
        ts[1].tv_nsec = ut->mtime_ns; \
6821
0
        time = ts; \
6822
0
    } \
6823
6824
#define UTIME_TO_TIMEVAL \
6825
0
    struct timeval tv[2]; \
6826
0
    struct timeval *time; \
6827
0
    if (ut->now) \
6828
0
        time = NULL; \
6829
0
    else { \
6830
0
        tv[0].tv_sec = ut->atime_s; \
6831
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6832
0
        tv[1].tv_sec = ut->mtime_s; \
6833
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6834
0
        time = tv; \
6835
0
    } \
6836
6837
#define UTIME_TO_UTIMBUF \
6838
    struct utimbuf u; \
6839
    struct utimbuf *time; \
6840
    if (ut->now) \
6841
        time = NULL; \
6842
    else { \
6843
        u.actime = ut->atime_s; \
6844
        u.modtime = ut->mtime_s; \
6845
        time = &u; \
6846
    }
6847
6848
#define UTIME_TO_TIME_T \
6849
    time_t timet[2]; \
6850
    time_t *time; \
6851
    if (ut->now) \
6852
        time = NULL; \
6853
    else { \
6854
        timet[0] = ut->atime_s; \
6855
        timet[1] = ut->mtime_s; \
6856
        time = timet; \
6857
    } \
6858
6859
6860
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6861
6862
static int
6863
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6864
0
{
6865
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6866
    if (HAVE_UTIMENSAT_RUNTIME) {
6867
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6868
        UTIME_TO_TIMESPEC;
6869
        return utimensat(dir_fd, path, time, flags);
6870
    }  else {
6871
        errno = ENOSYS;
6872
        return -1;
6873
    }
6874
#elif defined(HAVE_UTIMENSAT)
6875
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6876
0
    UTIME_TO_TIMESPEC;
6877
0
    return utimensat(dir_fd, path, time, flags);
6878
#elif defined(HAVE_FUTIMESAT)
6879
    UTIME_TO_TIMEVAL;
6880
    /*
6881
     * follow_symlinks will never be false here;
6882
     * we only allow !follow_symlinks and dir_fd together
6883
     * if we have utimensat()
6884
     */
6885
    assert(follow_symlinks);
6886
    return futimesat(dir_fd, path, time);
6887
#endif
6888
0
}
6889
6890
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6891
#else
6892
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6893
#endif
6894
6895
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6896
6897
static int
6898
utime_fd(utime_t *ut, int fd)
6899
0
{
6900
0
#ifdef HAVE_FUTIMENS
6901
6902
0
    if (HAVE_FUTIMENS_RUNTIME) {
6903
6904
0
    UTIME_TO_TIMESPEC;
6905
0
    return futimens(fd, time);
6906
6907
0
    } else
6908
#ifndef HAVE_FUTIMES
6909
    {
6910
        /* Not sure if this can happen */
6911
        PyErr_SetString(
6912
            PyExc_RuntimeError,
6913
            "neither futimens nor futimes are supported"
6914
            " on this system");
6915
        return -1;
6916
    }
6917
#endif
6918
6919
0
#endif
6920
0
#ifdef HAVE_FUTIMES
6921
0
    {
6922
0
    UTIME_TO_TIMEVAL;
6923
0
    return futimes(fd, time);
6924
0
    }
6925
0
#endif
6926
0
}
6927
6928
    #define PATH_UTIME_HAVE_FD 1
6929
#else
6930
    #define PATH_UTIME_HAVE_FD 0
6931
#endif
6932
6933
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6934
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6935
#endif
6936
6937
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6938
6939
static int
6940
utime_nofollow_symlinks(utime_t *ut, const char *path)
6941
0
{
6942
0
#ifdef HAVE_UTIMENSAT
6943
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6944
0
        UTIME_TO_TIMESPEC;
6945
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6946
0
    } else
6947
#ifndef HAVE_LUTIMES
6948
    {
6949
        /* Not sure if this can happen */
6950
        PyErr_SetString(
6951
            PyExc_RuntimeError,
6952
            "neither utimensat nor lutimes are supported"
6953
            " on this system");
6954
        return -1;
6955
    }
6956
#endif
6957
0
#endif
6958
6959
0
#ifdef HAVE_LUTIMES
6960
0
    {
6961
0
    UTIME_TO_TIMEVAL;
6962
0
    return lutimes(path, time);
6963
0
    }
6964
0
#endif
6965
0
}
6966
6967
#endif
6968
6969
#ifndef MS_WINDOWS
6970
6971
static int
6972
utime_default(utime_t *ut, const char *path)
6973
0
{
6974
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6975
    if (HAVE_UTIMENSAT_RUNTIME) {
6976
        UTIME_TO_TIMESPEC;
6977
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6978
    } else {
6979
        UTIME_TO_TIMEVAL;
6980
        return utimes(path, time);
6981
    }
6982
#elif defined(HAVE_UTIMENSAT)
6983
0
    UTIME_TO_TIMESPEC;
6984
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6985
#elif defined(HAVE_UTIMES)
6986
    UTIME_TO_TIMEVAL;
6987
    return utimes(path, time);
6988
#elif defined(HAVE_UTIME_H)
6989
    UTIME_TO_UTIMBUF;
6990
    return utime(path, time);
6991
#else
6992
    UTIME_TO_TIME_T;
6993
    return utime(path, time);
6994
#endif
6995
0
}
6996
6997
#endif
6998
6999
static int
7000
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7001
0
{
7002
0
    int result = 0;
7003
0
    PyObject *divmod;
7004
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7005
0
    if (!divmod)
7006
0
        goto exit;
7007
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7008
0
        PyErr_Format(PyExc_TypeError,
7009
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7010
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7011
0
        goto exit;
7012
0
    }
7013
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7014
0
    if ((*s == -1) && PyErr_Occurred())
7015
0
        goto exit;
7016
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7017
0
    if ((*ns == -1) && PyErr_Occurred())
7018
0
        goto exit;
7019
7020
0
    result = 1;
7021
0
exit:
7022
0
    Py_XDECREF(divmod);
7023
0
    return result;
7024
0
}
7025
7026
7027
/*[clinic input]
7028
os.utime
7029
7030
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7031
    times: object = None
7032
    *
7033
    ns: object = NULL
7034
    dir_fd: dir_fd(requires='futimensat') = None
7035
    follow_symlinks: bool=True
7036
7037
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
7038
7039
Set the access and modified time of path.
7040
7041
path may always be specified as a string.
7042
On some platforms, path may also be specified as an open file descriptor.
7043
  If this functionality is unavailable, using it raises an exception.
7044
7045
If times is not None, it must be a tuple (atime, mtime);
7046
    atime and mtime should be expressed as float seconds since the epoch.
7047
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7048
    atime_ns and mtime_ns should be expressed as integer nanoseconds
7049
    since the epoch.
7050
If times is None and ns is unspecified, utime uses the current time.
7051
Specifying tuples for both times and ns is an error.
7052
7053
If dir_fd is not None, it should be a file descriptor open to a directory,
7054
  and path should be relative; path will then be relative to that directory.
7055
If follow_symlinks is False, and the last element of the path is a symbolic
7056
  link, utime will modify the symbolic link itself instead of the file the
7057
  link points to.
7058
It is an error to use dir_fd or follow_symlinks when specifying path
7059
  as an open file descriptor.
7060
dir_fd and follow_symlinks may not be available on your platform.
7061
  If they are unavailable, using them will raise a NotImplementedError.
7062
7063
[clinic start generated code]*/
7064
7065
static PyObject *
7066
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7067
              int dir_fd, int follow_symlinks)
7068
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
7069
0
{
7070
#ifdef MS_WINDOWS
7071
    HANDLE hFile;
7072
    FILETIME atime, mtime;
7073
#else
7074
0
    int result;
7075
0
#endif
7076
7077
0
    utime_t utime;
7078
7079
0
    memset(&utime, 0, sizeof(utime_t));
7080
7081
0
    if (times != Py_None && ns) {
7082
0
        PyErr_SetString(PyExc_ValueError,
7083
0
                     "utime: you may specify either 'times'"
7084
0
                     " or 'ns' but not both");
7085
0
        return NULL;
7086
0
    }
7087
7088
0
    if (times != Py_None) {
7089
0
        time_t a_sec, m_sec;
7090
0
        long a_nsec, m_nsec;
7091
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7092
0
            PyErr_SetString(PyExc_TypeError,
7093
0
                         "utime: 'times' must be either"
7094
0
                         " a tuple of two numbers or None");
7095
0
            return NULL;
7096
0
        }
7097
0
        utime.now = 0;
7098
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7099
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7100
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7101
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7102
0
            return NULL;
7103
0
        }
7104
0
        utime.atime_s = a_sec;
7105
0
        utime.atime_ns = a_nsec;
7106
0
        utime.mtime_s = m_sec;
7107
0
        utime.mtime_ns = m_nsec;
7108
0
    }
7109
0
    else if (ns) {
7110
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7111
0
            PyErr_SetString(PyExc_TypeError,
7112
0
                         "utime: 'ns' must be a tuple of two ints");
7113
0
            return NULL;
7114
0
        }
7115
0
        utime.now = 0;
7116
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7117
0
                                      &utime.atime_s, &utime.atime_ns) ||
7118
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7119
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7120
0
            return NULL;
7121
0
        }
7122
0
    }
7123
0
    else {
7124
        /* times and ns are both None/unspecified. use "now". */
7125
0
        utime.now = 1;
7126
0
    }
7127
7128
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7129
    if (follow_symlinks_specified("utime", follow_symlinks))
7130
        return NULL;
7131
#endif
7132
7133
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7134
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7135
0
        fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
7136
0
        return NULL;
7137
7138
#if !defined(HAVE_UTIMENSAT)
7139
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7140
        PyErr_SetString(PyExc_ValueError,
7141
                     "utime: cannot use dir_fd and follow_symlinks "
7142
                     "together on this platform");
7143
        return NULL;
7144
    }
7145
#endif
7146
7147
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7148
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7149
0
        return NULL;
7150
0
    }
7151
7152
#ifdef MS_WINDOWS
7153
    Py_BEGIN_ALLOW_THREADS
7154
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7155
                        NULL, OPEN_EXISTING,
7156
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7157
    Py_END_ALLOW_THREADS
7158
    if (hFile == INVALID_HANDLE_VALUE) {
7159
        path_error(path);
7160
        return NULL;
7161
    }
7162
7163
    if (utime.now) {
7164
        GetSystemTimeAsFileTime(&mtime);
7165
        atime = mtime;
7166
    }
7167
    else {
7168
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7169
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7170
    }
7171
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7172
        path_error(path);
7173
        CloseHandle(hFile);
7174
        return NULL;
7175
    }
7176
    CloseHandle(hFile);
7177
#else /* MS_WINDOWS */
7178
0
    Py_BEGIN_ALLOW_THREADS
7179
7180
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7181
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7182
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7183
0
    else
7184
0
#endif
7185
7186
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7187
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7188
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7189
7190
0
    } else
7191
0
#endif
7192
7193
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7194
0
    if (path->fd != -1)
7195
0
        result = utime_fd(&utime, path->fd);
7196
0
    else
7197
0
#endif
7198
7199
0
    result = utime_default(&utime, path->narrow);
7200
7201
0
    Py_END_ALLOW_THREADS
7202
7203
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7204
    /* See utime_dir_fd implementation */
7205
    if (result == -1 && errno == ENOSYS) {
7206
        argument_unavailable_error(NULL, "dir_fd");
7207
        return NULL;
7208
    }
7209
#endif
7210
7211
0
    if (result < 0) {
7212
0
        path_error(path);
7213
0
        return NULL;
7214
0
    }
7215
7216
0
#endif /* MS_WINDOWS */
7217
7218
0
    Py_RETURN_NONE;
7219
0
}
7220
7221
/* Process operations */
7222
7223
7224
/*[clinic input]
7225
os._exit
7226
7227
    status: int
7228
7229
Exit to the system with specified status, without normal exit processing.
7230
[clinic start generated code]*/
7231
7232
static PyObject *
7233
os__exit_impl(PyObject *module, int status)
7234
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
7235
0
{
7236
0
    _exit(status);
7237
0
    return NULL; /* Make gcc -Wall happy */
7238
0
}
7239
7240
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7241
#define EXECV_CHAR wchar_t
7242
#else
7243
0
#define EXECV_CHAR char
7244
#endif
7245
7246
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7247
static void
7248
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7249
0
{
7250
0
    Py_ssize_t i;
7251
0
    for (i = 0; i < count; i++)
7252
0
        PyMem_Free(array[i]);
7253
0
    PyMem_Free(array);
7254
0
}
7255
7256
static int
7257
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7258
0
{
7259
0
    Py_ssize_t size;
7260
0
    PyObject *ub;
7261
0
    int result = 0;
7262
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7263
    if (!PyUnicode_FSDecoder(o, &ub))
7264
        return 0;
7265
    *out = PyUnicode_AsWideCharString(ub, &size);
7266
    if (*out)
7267
        result = 1;
7268
#else
7269
0
    if (!PyUnicode_FSConverter(o, &ub))
7270
0
        return 0;
7271
0
    size = PyBytes_GET_SIZE(ub);
7272
0
    *out = PyMem_Malloc(size + 1);
7273
0
    if (*out) {
7274
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7275
0
        result = 1;
7276
0
    } else
7277
0
        PyErr_NoMemory();
7278
0
#endif
7279
0
    Py_DECREF(ub);
7280
0
    return result;
7281
0
}
7282
#endif
7283
7284
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7285
static EXECV_CHAR**
7286
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7287
0
{
7288
0
    Py_ssize_t i, pos, envc;
7289
0
    PyObject *keys=NULL, *vals=NULL;
7290
0
    PyObject *key2, *val2, *keyval;
7291
0
    EXECV_CHAR **envlist;
7292
7293
0
    i = PyMapping_Size(env);
7294
0
    if (i < 0)
7295
0
        return NULL;
7296
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7297
0
    if (envlist == NULL) {
7298
0
        PyErr_NoMemory();
7299
0
        return NULL;
7300
0
    }
7301
0
    envc = 0;
7302
0
    keys = PyMapping_Keys(env);
7303
0
    if (!keys)
7304
0
        goto error;
7305
0
    vals = PyMapping_Values(env);
7306
0
    if (!vals)
7307
0
        goto error;
7308
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7309
0
        PyErr_Format(PyExc_TypeError,
7310
0
                     "env.keys() or env.values() is not a list");
7311
0
        goto error;
7312
0
    }
7313
7314
0
    for (pos = 0; pos < i; pos++) {
7315
0
        PyObject *key = PyList_GetItem(keys, pos);  // Borrowed ref.
7316
0
        if (key == NULL) {
7317
0
            goto error;
7318
0
        }
7319
0
        PyObject *val = PyList_GetItem(vals, pos);  // Borrowed ref.
7320
0
        if (val == NULL) {
7321
0
            goto error;
7322
0
        }
7323
7324
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7325
        if (!PyUnicode_FSDecoder(key, &key2))
7326
            goto error;
7327
        if (!PyUnicode_FSDecoder(val, &val2)) {
7328
            Py_DECREF(key2);
7329
            goto error;
7330
        }
7331
        /* Search from index 1 because on Windows starting '=' is allowed for
7332
           defining hidden environment variables. */
7333
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7334
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7335
        {
7336
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7337
            Py_DECREF(key2);
7338
            Py_DECREF(val2);
7339
            goto error;
7340
        }
7341
        keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7342
#else
7343
0
        if (!PyUnicode_FSConverter(key, &key2))
7344
0
            goto error;
7345
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7346
0
            Py_DECREF(key2);
7347
0
            goto error;
7348
0
        }
7349
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7350
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7351
0
        {
7352
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7353
0
            Py_DECREF(key2);
7354
0
            Py_DECREF(val2);
7355
0
            goto error;
7356
0
        }
7357
0
        keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7358
0
                                             PyBytes_AS_STRING(val2));
7359
0
#endif
7360
0
        Py_DECREF(key2);
7361
0
        Py_DECREF(val2);
7362
0
        if (!keyval)
7363
0
            goto error;
7364
7365
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7366
0
            Py_DECREF(keyval);
7367
0
            goto error;
7368
0
        }
7369
7370
0
        Py_DECREF(keyval);
7371
0
    }
7372
0
    Py_DECREF(vals);
7373
0
    Py_DECREF(keys);
7374
7375
0
    envlist[envc] = 0;
7376
0
    *envc_ptr = envc;
7377
0
    return envlist;
7378
7379
0
error:
7380
0
    Py_XDECREF(keys);
7381
0
    Py_XDECREF(vals);
7382
0
    free_string_array(envlist, envc);
7383
0
    return NULL;
7384
0
}
7385
7386
static EXECV_CHAR**
7387
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7388
0
{
7389
0
    int i;
7390
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7391
0
    if (argvlist == NULL) {
7392
0
        PyErr_NoMemory();
7393
0
        return NULL;
7394
0
    }
7395
0
    for (i = 0; i < *argc; i++) {
7396
0
        PyObject* item = PySequence_ITEM(argv, i);
7397
0
        if (item == NULL)
7398
0
            goto fail;
7399
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7400
0
            Py_DECREF(item);
7401
0
            goto fail;
7402
0
        }
7403
0
        Py_DECREF(item);
7404
0
    }
7405
0
    argvlist[*argc] = NULL;
7406
0
    return argvlist;
7407
0
fail:
7408
0
    *argc = i;
7409
0
    free_string_array(argvlist, *argc);
7410
0
    return NULL;
7411
0
}
7412
7413
#endif
7414
7415
7416
#ifdef HAVE_EXECV
7417
/*[clinic input]
7418
os.execv
7419
7420
    path: path_t
7421
        Path of executable file.
7422
    argv: object
7423
        Tuple or list of strings.
7424
    /
7425
7426
Execute an executable path with arguments, replacing current process.
7427
[clinic start generated code]*/
7428
7429
static PyObject *
7430
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7431
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7432
0
{
7433
0
    EXECV_CHAR **argvlist;
7434
0
    Py_ssize_t argc;
7435
7436
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7437
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7438
0
        PyErr_SetString(PyExc_RuntimeError,
7439
0
                        "exec not supported for isolated subinterpreters");
7440
0
        return NULL;
7441
0
    }
7442
7443
    /* execv has two arguments: (path, argv), where
7444
       argv is a list or tuple of strings. */
7445
7446
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7447
0
        PyErr_SetString(PyExc_TypeError,
7448
0
                        "execv() arg 2 must be a tuple or list");
7449
0
        return NULL;
7450
0
    }
7451
0
    argc = PySequence_Size(argv);
7452
0
    if (argc < 1) {
7453
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7454
0
        return NULL;
7455
0
    }
7456
7457
0
    argvlist = parse_arglist(argv, &argc);
7458
0
    if (argvlist == NULL) {
7459
0
        return NULL;
7460
0
    }
7461
0
    if (!argvlist[0][0]) {
7462
0
        PyErr_SetString(PyExc_ValueError,
7463
0
            "execv() arg 2 first element cannot be empty");
7464
0
        free_string_array(argvlist, argc);
7465
0
        return NULL;
7466
0
    }
7467
7468
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7469
0
        free_string_array(argvlist, argc);
7470
0
        return NULL;
7471
0
    }
7472
7473
0
    _Py_BEGIN_SUPPRESS_IPH
7474
#ifdef HAVE_WEXECV
7475
    _wexecv(path->wide, argvlist);
7476
#else
7477
0
    execv(path->narrow, argvlist);
7478
0
#endif
7479
0
    _Py_END_SUPPRESS_IPH
7480
7481
    /* If we get here it's definitely an error */
7482
7483
0
    posix_error();
7484
0
    free_string_array(argvlist, argc);
7485
0
    return NULL;
7486
0
}
7487
7488
7489
/*[clinic input]
7490
os.execve
7491
7492
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7493
        Path of executable file.
7494
    argv: object
7495
        Tuple or list of strings.
7496
    env: object
7497
        Dictionary of strings mapping to strings.
7498
7499
Execute an executable path with arguments, replacing current process.
7500
[clinic start generated code]*/
7501
7502
static PyObject *
7503
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7504
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7505
0
{
7506
0
    EXECV_CHAR **argvlist = NULL;
7507
0
    EXECV_CHAR **envlist;
7508
0
    Py_ssize_t argc, envc;
7509
7510
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7511
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7512
0
        PyErr_SetString(PyExc_RuntimeError,
7513
0
                        "exec not supported for isolated subinterpreters");
7514
0
        return NULL;
7515
0
    }
7516
7517
    /* execve has three arguments: (path, argv, env), where
7518
       argv is a list or tuple of strings and env is a dictionary
7519
       like posix.environ. */
7520
7521
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7522
0
        PyErr_SetString(PyExc_TypeError,
7523
0
                        "execve: argv must be a tuple or list");
7524
0
        goto fail_0;
7525
0
    }
7526
0
    argc = PySequence_Size(argv);
7527
0
    if (argc < 1) {
7528
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7529
0
        return NULL;
7530
0
    }
7531
7532
0
    if (!PyMapping_Check(env)) {
7533
0
        PyErr_SetString(PyExc_TypeError,
7534
0
                        "execve: environment must be a mapping object");
7535
0
        goto fail_0;
7536
0
    }
7537
7538
0
    argvlist = parse_arglist(argv, &argc);
7539
0
    if (argvlist == NULL) {
7540
0
        goto fail_0;
7541
0
    }
7542
0
    if (!argvlist[0][0]) {
7543
0
        PyErr_SetString(PyExc_ValueError,
7544
0
            "execve: argv first element cannot be empty");
7545
0
        goto fail_0;
7546
0
    }
7547
7548
0
    envlist = parse_envlist(env, &envc);
7549
0
    if (envlist == NULL)
7550
0
        goto fail_0;
7551
7552
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7553
0
        goto fail_1;
7554
0
    }
7555
7556
0
    _Py_BEGIN_SUPPRESS_IPH
7557
0
#ifdef HAVE_FEXECVE
7558
0
    if (path->fd > -1)
7559
0
        fexecve(path->fd, argvlist, envlist);
7560
0
    else
7561
0
#endif
7562
#ifdef HAVE_WEXECV
7563
        _wexecve(path->wide, argvlist, envlist);
7564
#else
7565
0
        execve(path->narrow, argvlist, envlist);
7566
0
#endif
7567
0
    _Py_END_SUPPRESS_IPH
7568
7569
    /* If we get here it's definitely an error */
7570
7571
0
    posix_path_error(path);
7572
0
  fail_1:
7573
0
    free_string_array(envlist, envc);
7574
0
  fail_0:
7575
0
    if (argvlist)
7576
0
        free_string_array(argvlist, argc);
7577
0
    return NULL;
7578
0
}
7579
7580
#endif /* HAVE_EXECV */
7581
7582
#ifdef HAVE_POSIX_SPAWN
7583
7584
enum posix_spawn_file_actions_identifier {
7585
    POSIX_SPAWN_OPEN,
7586
    POSIX_SPAWN_CLOSE,
7587
    POSIX_SPAWN_DUP2
7588
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7589
    ,POSIX_SPAWN_CLOSEFROM
7590
#endif
7591
};
7592
7593
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7594
static int
7595
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7596
#endif
7597
7598
static int
7599
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7600
                        int resetids, int setsid, PyObject *setsigmask,
7601
                        PyObject *setsigdef, PyObject *scheduler,
7602
                        posix_spawnattr_t *attrp)
7603
0
{
7604
0
    long all_flags = 0;
7605
7606
0
    errno = posix_spawnattr_init(attrp);
7607
0
    if (errno) {
7608
0
        posix_error();
7609
0
        return -1;
7610
0
    }
7611
7612
0
    if (setpgroup) {
7613
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7614
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7615
0
            goto fail;
7616
0
        }
7617
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7618
0
        if (errno) {
7619
0
            posix_error();
7620
0
            goto fail;
7621
0
        }
7622
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7623
0
    }
7624
7625
0
    if (resetids) {
7626
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7627
0
    }
7628
7629
0
    if (setsid) {
7630
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7631
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7632
#endif
7633
0
#ifdef POSIX_SPAWN_SETSID
7634
0
        all_flags |= POSIX_SPAWN_SETSID;
7635
#elif defined(POSIX_SPAWN_SETSID_NP)
7636
        all_flags |= POSIX_SPAWN_SETSID_NP;
7637
#else
7638
        argument_unavailable_error(func_name, "setsid");
7639
        return -1;
7640
#endif
7641
7642
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7643
        } else {
7644
            argument_unavailable_error(func_name, "setsid");
7645
            return -1;
7646
        }
7647
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7648
7649
0
    }
7650
7651
0
#ifdef HAVE_SIGSET_T
7652
0
   if (setsigmask) {
7653
0
        sigset_t set;
7654
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7655
0
            goto fail;
7656
0
        }
7657
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7658
0
        if (errno) {
7659
0
            posix_error();
7660
0
            goto fail;
7661
0
        }
7662
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7663
0
    }
7664
7665
0
    if (setsigdef) {
7666
0
        sigset_t set;
7667
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7668
0
            goto fail;
7669
0
        }
7670
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7671
0
        if (errno) {
7672
0
            posix_error();
7673
0
            goto fail;
7674
0
        }
7675
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7676
0
    }
7677
#else
7678
    if (setsigmask || setsigdef) {
7679
        PyErr_SetString(PyExc_NotImplementedError,
7680
                        "sigset is not supported on this platform");
7681
        goto fail;
7682
    }
7683
#endif
7684
7685
0
    if (scheduler) {
7686
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7687
0
        PyObject *py_schedpolicy;
7688
0
        PyObject *schedparam_obj;
7689
0
        struct sched_param schedparam;
7690
7691
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7692
0
                        ";A scheduler tuple must have two elements",
7693
0
                        &py_schedpolicy, &schedparam_obj)) {
7694
0
            goto fail;
7695
0
        }
7696
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7697
0
            goto fail;
7698
0
        }
7699
0
        if (py_schedpolicy != Py_None) {
7700
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7701
7702
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7703
0
                goto fail;
7704
0
            }
7705
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7706
0
            if (errno) {
7707
0
                posix_error();
7708
0
                goto fail;
7709
0
            }
7710
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7711
0
        }
7712
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7713
0
        if (errno) {
7714
0
            posix_error();
7715
0
            goto fail;
7716
0
        }
7717
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7718
#else
7719
        PyErr_SetString(PyExc_NotImplementedError,
7720
                "The scheduler option is not supported in this system.");
7721
        goto fail;
7722
#endif
7723
0
    }
7724
7725
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7726
0
    if (errno) {
7727
0
        posix_error();
7728
0
        goto fail;
7729
0
    }
7730
7731
0
    return 0;
7732
7733
0
fail:
7734
0
    (void)posix_spawnattr_destroy(attrp);
7735
0
    return -1;
7736
0
}
7737
7738
static int
7739
parse_file_actions(PyObject *file_actions,
7740
                   posix_spawn_file_actions_t *file_actionsp,
7741
                   PyObject *temp_buffer)
7742
0
{
7743
0
    PyObject *seq;
7744
0
    PyObject *file_action = NULL;
7745
0
    PyObject *tag_obj;
7746
7747
0
    seq = PySequence_Fast(file_actions,
7748
0
                          "file_actions must be a sequence or None");
7749
0
    if (seq == NULL) {
7750
0
        return -1;
7751
0
    }
7752
7753
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7754
0
    if (errno) {
7755
0
        posix_error();
7756
0
        Py_DECREF(seq);
7757
0
        return -1;
7758
0
    }
7759
7760
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7761
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7762
0
        Py_INCREF(file_action);
7763
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7764
0
            PyErr_SetString(PyExc_TypeError,
7765
0
                "Each file_actions element must be a non-empty tuple");
7766
0
            goto fail;
7767
0
        }
7768
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7769
0
        if (tag == -1 && PyErr_Occurred()) {
7770
0
            goto fail;
7771
0
        }
7772
7773
        /* Populate the file_actions object */
7774
0
        switch (tag) {
7775
0
            case POSIX_SPAWN_OPEN: {
7776
0
                int fd, oflag;
7777
0
                PyObject *path;
7778
0
                unsigned long mode;
7779
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7780
0
                        ";A open file_action tuple must have 5 elements",
7781
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7782
0
                        &oflag, &mode))
7783
0
                {
7784
0
                    goto fail;
7785
0
                }
7786
0
                if (PyList_Append(temp_buffer, path)) {
7787
0
                    Py_DECREF(path);
7788
0
                    goto fail;
7789
0
                }
7790
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7791
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7792
0
                if (errno) {
7793
0
                    posix_error();
7794
0
                    Py_DECREF(path);
7795
0
                    goto fail;
7796
0
                }
7797
0
                Py_DECREF(path);
7798
0
                break;
7799
0
            }
7800
0
            case POSIX_SPAWN_CLOSE: {
7801
0
                int fd;
7802
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7803
0
                        ";A close file_action tuple must have 2 elements",
7804
0
                        &tag_obj, &fd))
7805
0
                {
7806
0
                    goto fail;
7807
0
                }
7808
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7809
0
                if (errno) {
7810
0
                    posix_error();
7811
0
                    goto fail;
7812
0
                }
7813
0
                break;
7814
0
            }
7815
0
            case POSIX_SPAWN_DUP2: {
7816
0
                int fd1, fd2;
7817
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7818
0
                        ";A dup2 file_action tuple must have 3 elements",
7819
0
                        &tag_obj, &fd1, &fd2))
7820
0
                {
7821
0
                    goto fail;
7822
0
                }
7823
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7824
0
                                                         fd1, fd2);
7825
0
                if (errno) {
7826
0
                    posix_error();
7827
0
                    goto fail;
7828
0
                }
7829
0
                break;
7830
0
            }
7831
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7832
            case POSIX_SPAWN_CLOSEFROM: {
7833
                int fd;
7834
                if (!PyArg_ParseTuple(file_action, "Oi"
7835
                        ";A closefrom file_action tuple must have 2 elements",
7836
                        &tag_obj, &fd))
7837
                {
7838
                    goto fail;
7839
                }
7840
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7841
                                                                 fd);
7842
                if (errno) {
7843
                    posix_error();
7844
                    goto fail;
7845
                }
7846
                break;
7847
            }
7848
#endif
7849
0
            default: {
7850
0
                PyErr_SetString(PyExc_TypeError,
7851
0
                                "Unknown file_actions identifier");
7852
0
                goto fail;
7853
0
            }
7854
0
        }
7855
0
        Py_DECREF(file_action);
7856
0
    }
7857
7858
0
    Py_DECREF(seq);
7859
0
    return 0;
7860
7861
0
fail:
7862
0
    Py_DECREF(seq);
7863
0
    Py_DECREF(file_action);
7864
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7865
0
    return -1;
7866
0
}
7867
7868
7869
static PyObject *
7870
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7871
               PyObject *env, PyObject *file_actions,
7872
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7873
               PyObject *setsigdef, PyObject *scheduler)
7874
0
{
7875
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7876
0
    EXECV_CHAR **argvlist = NULL;
7877
0
    EXECV_CHAR **envlist = NULL;
7878
0
    posix_spawn_file_actions_t file_actions_buf;
7879
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7880
0
    posix_spawnattr_t attr;
7881
0
    posix_spawnattr_t *attrp = NULL;
7882
0
    Py_ssize_t argc, envc;
7883
0
    PyObject *result = NULL;
7884
0
    PyObject *temp_buffer = NULL;
7885
0
    pid_t pid;
7886
0
    int err_code;
7887
7888
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7889
       argv is a list or tuple of strings and env is a dictionary
7890
       like posix.environ. */
7891
7892
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7893
0
        PyErr_Format(PyExc_TypeError,
7894
0
                     "%s: argv must be a tuple or list", func_name);
7895
0
        goto exit;
7896
0
    }
7897
0
    argc = PySequence_Size(argv);
7898
0
    if (argc < 1) {
7899
0
        PyErr_Format(PyExc_ValueError,
7900
0
                     "%s: argv must not be empty", func_name);
7901
0
        return NULL;
7902
0
    }
7903
7904
0
    if (!PyMapping_Check(env) && env != Py_None) {
7905
0
        PyErr_Format(PyExc_TypeError,
7906
0
                     "%s: environment must be a mapping object or None", func_name);
7907
0
        goto exit;
7908
0
    }
7909
7910
0
    argvlist = parse_arglist(argv, &argc);
7911
0
    if (argvlist == NULL) {
7912
0
        goto exit;
7913
0
    }
7914
0
    if (!argvlist[0][0]) {
7915
0
        PyErr_Format(PyExc_ValueError,
7916
0
                     "%s: argv first element cannot be empty", func_name);
7917
0
        goto exit;
7918
0
    }
7919
7920
#ifdef USE_DARWIN_NS_GET_ENVIRON
7921
    // There is no environ global in this situation.
7922
    char **environ = NULL;
7923
#endif
7924
7925
0
    if (env == Py_None) {
7926
#ifdef USE_DARWIN_NS_GET_ENVIRON
7927
        environ = *_NSGetEnviron();
7928
#endif
7929
0
        envlist = environ;
7930
0
    } else {
7931
0
        envlist = parse_envlist(env, &envc);
7932
0
        if (envlist == NULL) {
7933
0
            goto exit;
7934
0
        }
7935
0
    }
7936
7937
0
    if (file_actions != NULL && file_actions != Py_None) {
7938
        /* There is a bug in old versions of glibc that makes some of the
7939
         * helper functions for manipulating file actions not copy the provided
7940
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7941
         * copy the value of path for some old versions of glibc (<2.20).
7942
         * The use of temp_buffer here is a workaround that keeps the
7943
         * python objects that own the buffers alive until posix_spawn gets called.
7944
         * Check https://bugs.python.org/issue33630 and
7945
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7946
0
        temp_buffer = PyList_New(0);
7947
0
        if (!temp_buffer) {
7948
0
            goto exit;
7949
0
        }
7950
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7951
0
            goto exit;
7952
0
        }
7953
0
        file_actionsp = &file_actions_buf;
7954
0
    }
7955
7956
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7957
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7958
0
        goto exit;
7959
0
    }
7960
0
    attrp = &attr;
7961
7962
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7963
0
        goto exit;
7964
0
    }
7965
7966
0
    _Py_BEGIN_SUPPRESS_IPH
7967
0
#ifdef HAVE_POSIX_SPAWNP
7968
0
    if (use_posix_spawnp) {
7969
0
        err_code = posix_spawnp(&pid, path->narrow,
7970
0
                                file_actionsp, attrp, argvlist, envlist);
7971
0
    }
7972
0
    else
7973
0
#endif /* HAVE_POSIX_SPAWNP */
7974
0
    {
7975
0
        err_code = posix_spawn(&pid, path->narrow,
7976
0
                               file_actionsp, attrp, argvlist, envlist);
7977
0
    }
7978
0
    _Py_END_SUPPRESS_IPH
7979
7980
0
    if (err_code) {
7981
0
        errno = err_code;
7982
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
7983
0
        goto exit;
7984
0
    }
7985
#ifdef _Py_MEMORY_SANITIZER
7986
    __msan_unpoison(&pid, sizeof(pid));
7987
#endif
7988
0
    result = PyLong_FromPid(pid);
7989
7990
0
exit:
7991
0
    if (file_actionsp) {
7992
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
7993
0
    }
7994
0
    if (attrp) {
7995
0
        (void)posix_spawnattr_destroy(attrp);
7996
0
    }
7997
0
    if (envlist && envlist != environ) {
7998
0
        free_string_array(envlist, envc);
7999
0
    }
8000
0
    if (argvlist) {
8001
0
        free_string_array(argvlist, argc);
8002
0
    }
8003
0
    Py_XDECREF(temp_buffer);
8004
0
    return result;
8005
0
}
8006
8007
8008
/*[clinic input]
8009
8010
os.posix_spawn
8011
    path: path_t
8012
        Path of executable file.
8013
    argv: object
8014
        Tuple or list of strings.
8015
    env: object
8016
        Dictionary of strings mapping to strings.
8017
    /
8018
    *
8019
    file_actions: object(c_default='NULL') = ()
8020
        A sequence of file action tuples.
8021
    setpgroup: object = NULL
8022
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8023
    resetids: bool = False
8024
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8025
    setsid: bool = False
8026
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8027
    setsigmask: object(c_default='NULL') = ()
8028
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8029
    setsigdef: object(c_default='NULL') = ()
8030
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8031
    scheduler: object = NULL
8032
        A tuple with the scheduler policy (optional) and parameters.
8033
8034
Execute the program specified by path in a new process.
8035
[clinic start generated code]*/
8036
8037
static PyObject *
8038
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8039
                    PyObject *env, PyObject *file_actions,
8040
                    PyObject *setpgroup, int resetids, int setsid,
8041
                    PyObject *setsigmask, PyObject *setsigdef,
8042
                    PyObject *scheduler)
8043
/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
8044
0
{
8045
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8046
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8047
0
                          scheduler);
8048
0
}
8049
 #endif /* HAVE_POSIX_SPAWN */
8050
8051
8052
8053
#ifdef HAVE_POSIX_SPAWNP
8054
/*[clinic input]
8055
8056
os.posix_spawnp
8057
    path: path_t
8058
        Path of executable file.
8059
    argv: object
8060
        Tuple or list of strings.
8061
    env: object
8062
        Dictionary of strings mapping to strings.
8063
    /
8064
    *
8065
    file_actions: object(c_default='NULL') = ()
8066
        A sequence of file action tuples.
8067
    setpgroup: object = NULL
8068
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8069
    resetids: bool = False
8070
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8071
    setsid: bool = False
8072
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8073
    setsigmask: object(c_default='NULL') = ()
8074
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8075
    setsigdef: object(c_default='NULL') = ()
8076
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8077
    scheduler: object = NULL
8078
        A tuple with the scheduler policy (optional) and parameters.
8079
8080
Execute the program specified by path in a new process.
8081
[clinic start generated code]*/
8082
8083
static PyObject *
8084
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8085
                     PyObject *env, PyObject *file_actions,
8086
                     PyObject *setpgroup, int resetids, int setsid,
8087
                     PyObject *setsigmask, PyObject *setsigdef,
8088
                     PyObject *scheduler)
8089
/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
8090
0
{
8091
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8092
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8093
0
                          scheduler);
8094
0
}
8095
#endif /* HAVE_POSIX_SPAWNP */
8096
8097
#ifdef HAVE_RTPSPAWN
8098
static intptr_t
8099
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8100
               const char  *envp[])
8101
{
8102
     RTP_ID rtpid;
8103
     int status;
8104
     pid_t res;
8105
     int async_err = 0;
8106
8107
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8108
        uStackSize=0 cannot be used, the default stack size is too small for
8109
        Python. */
8110
     if (envp) {
8111
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8112
                          100, 0x1000000, 0, VX_FP_TASK);
8113
     }
8114
     else {
8115
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8116
                          100, 0x1000000, 0, VX_FP_TASK);
8117
     }
8118
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8119
         do {
8120
             res = waitpid((pid_t)rtpid, &status, 0);
8121
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8122
8123
         if (res < 0)
8124
             return RTP_ID_ERROR;
8125
         return ((intptr_t)status);
8126
     }
8127
     return ((intptr_t)rtpid);
8128
}
8129
#endif
8130
8131
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8132
/*[clinic input]
8133
os.spawnv
8134
8135
    mode: int
8136
        Mode of process creation.
8137
    path: path_t
8138
        Path of executable file.
8139
    argv: object
8140
        Tuple or list of strings.
8141
    /
8142
8143
Execute the program specified by path in a new process.
8144
[clinic start generated code]*/
8145
8146
static PyObject *
8147
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8148
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8149
{
8150
    EXECV_CHAR **argvlist;
8151
    int i;
8152
    Py_ssize_t argc;
8153
    intptr_t spawnval;
8154
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8155
8156
    /* spawnv has three arguments: (mode, path, argv), where
8157
       argv is a list or tuple of strings. */
8158
8159
    if (PyList_Check(argv)) {
8160
        argc = PyList_Size(argv);
8161
        getitem = PyList_GetItem;
8162
    }
8163
    else if (PyTuple_Check(argv)) {
8164
        argc = PyTuple_Size(argv);
8165
        getitem = PyTuple_GetItem;
8166
    }
8167
    else {
8168
        PyErr_SetString(PyExc_TypeError,
8169
                        "spawnv() arg 2 must be a tuple or list");
8170
        return NULL;
8171
    }
8172
    if (argc == 0) {
8173
        PyErr_SetString(PyExc_ValueError,
8174
            "spawnv() arg 2 cannot be empty");
8175
        return NULL;
8176
    }
8177
8178
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8179
    if (argvlist == NULL) {
8180
        return PyErr_NoMemory();
8181
    }
8182
    for (i = 0; i < argc; i++) {
8183
        if (!fsconvert_strdup((*getitem)(argv, i),
8184
                              &argvlist[i])) {
8185
            free_string_array(argvlist, i);
8186
            PyErr_SetString(
8187
                PyExc_TypeError,
8188
                "spawnv() arg 2 must contain only strings");
8189
            return NULL;
8190
        }
8191
        if (i == 0 && !argvlist[0][0]) {
8192
            free_string_array(argvlist, i + 1);
8193
            PyErr_SetString(
8194
                PyExc_ValueError,
8195
                "spawnv() arg 2 first element cannot be empty");
8196
            return NULL;
8197
        }
8198
    }
8199
    argvlist[argc] = NULL;
8200
8201
#if !defined(HAVE_RTPSPAWN)
8202
    if (mode == _OLD_P_OVERLAY)
8203
        mode = _P_OVERLAY;
8204
#endif
8205
8206
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8207
                    Py_None) < 0) {
8208
        free_string_array(argvlist, argc);
8209
        return NULL;
8210
    }
8211
8212
    Py_BEGIN_ALLOW_THREADS
8213
    _Py_BEGIN_SUPPRESS_IPH
8214
#ifdef HAVE_WSPAWNV
8215
    spawnval = _wspawnv(mode, path->wide, argvlist);
8216
#elif defined(HAVE_RTPSPAWN)
8217
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8218
#else
8219
    spawnval = _spawnv(mode, path->narrow, argvlist);
8220
#endif
8221
    _Py_END_SUPPRESS_IPH
8222
    Py_END_ALLOW_THREADS
8223
8224
    int saved_errno = errno;
8225
    free_string_array(argvlist, argc);
8226
8227
    if (spawnval == -1) {
8228
        errno = saved_errno;
8229
        posix_error();
8230
        return NULL;
8231
    }
8232
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8233
}
8234
8235
/*[clinic input]
8236
os.spawnve
8237
8238
    mode: int
8239
        Mode of process creation.
8240
    path: path_t
8241
        Path of executable file.
8242
    argv: object
8243
        Tuple or list of strings.
8244
    env: object
8245
        Dictionary of strings mapping to strings.
8246
    /
8247
8248
Execute the program specified by path in a new process.
8249
[clinic start generated code]*/
8250
8251
static PyObject *
8252
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8253
                PyObject *env)
8254
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8255
{
8256
    EXECV_CHAR **argvlist;
8257
    EXECV_CHAR **envlist;
8258
    PyObject *res = NULL;
8259
    Py_ssize_t argc, i, envc;
8260
    intptr_t spawnval;
8261
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8262
    Py_ssize_t lastarg = 0;
8263
8264
    /* spawnve has four arguments: (mode, path, argv, env), where
8265
       argv is a list or tuple of strings and env is a dictionary
8266
       like posix.environ. */
8267
8268
    if (PyList_Check(argv)) {
8269
        argc = PyList_Size(argv);
8270
        getitem = PyList_GetItem;
8271
    }
8272
    else if (PyTuple_Check(argv)) {
8273
        argc = PyTuple_Size(argv);
8274
        getitem = PyTuple_GetItem;
8275
    }
8276
    else {
8277
        PyErr_SetString(PyExc_TypeError,
8278
                        "spawnve() arg 2 must be a tuple or list");
8279
        goto fail_0;
8280
    }
8281
    if (argc == 0) {
8282
        PyErr_SetString(PyExc_ValueError,
8283
            "spawnve() arg 2 cannot be empty");
8284
        goto fail_0;
8285
    }
8286
    if (!PyMapping_Check(env)) {
8287
        PyErr_SetString(PyExc_TypeError,
8288
                        "spawnve() arg 3 must be a mapping object");
8289
        goto fail_0;
8290
    }
8291
8292
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8293
    if (argvlist == NULL) {
8294
        PyErr_NoMemory();
8295
        goto fail_0;
8296
    }
8297
    for (i = 0; i < argc; i++) {
8298
        if (!fsconvert_strdup((*getitem)(argv, i),
8299
                              &argvlist[i]))
8300
        {
8301
            lastarg = i;
8302
            goto fail_1;
8303
        }
8304
        if (i == 0 && !argvlist[0][0]) {
8305
            lastarg = i + 1;
8306
            PyErr_SetString(
8307
                PyExc_ValueError,
8308
                "spawnv() arg 2 first element cannot be empty");
8309
            goto fail_1;
8310
        }
8311
    }
8312
    lastarg = argc;
8313
    argvlist[argc] = NULL;
8314
8315
    envlist = parse_envlist(env, &envc);
8316
    if (envlist == NULL)
8317
        goto fail_1;
8318
8319
#if !defined(HAVE_RTPSPAWN)
8320
    if (mode == _OLD_P_OVERLAY)
8321
        mode = _P_OVERLAY;
8322
#endif
8323
8324
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8325
        goto fail_2;
8326
    }
8327
8328
    Py_BEGIN_ALLOW_THREADS
8329
    _Py_BEGIN_SUPPRESS_IPH
8330
#ifdef HAVE_WSPAWNV
8331
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8332
#elif defined(HAVE_RTPSPAWN)
8333
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8334
                           (const char **)envlist);
8335
#else
8336
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8337
#endif
8338
    _Py_END_SUPPRESS_IPH
8339
    Py_END_ALLOW_THREADS
8340
8341
    if (spawnval == -1)
8342
        (void) posix_error();
8343
    else
8344
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8345
8346
  fail_2:
8347
    while (--envc >= 0) {
8348
        PyMem_Free(envlist[envc]);
8349
    }
8350
    PyMem_Free(envlist);
8351
  fail_1:
8352
    free_string_array(argvlist, lastarg);
8353
  fail_0:
8354
    return res;
8355
}
8356
8357
#endif /* HAVE_SPAWNV */
8358
8359
#ifdef HAVE_FORK
8360
8361
/* Helper function to validate arguments.
8362
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8363
   If obj is non-NULL it must be callable.  */
8364
static int
8365
check_null_or_callable(PyObject *obj, const char* obj_name)
8366
6
{
8367
6
    if (obj && !PyCallable_Check(obj)) {
8368
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8369
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8370
0
        return -1;
8371
0
    }
8372
6
    return 0;
8373
6
}
8374
8375
/*[clinic input]
8376
os.register_at_fork
8377
8378
    *
8379
    before: object=NULL
8380
        A callable to be called in the parent before the fork() syscall.
8381
    after_in_child: object=NULL
8382
        A callable to be called in the child after fork().
8383
    after_in_parent: object=NULL
8384
        A callable to be called in the parent after fork().
8385
8386
Register callables to be called when forking a new process.
8387
8388
'before' callbacks are called in reverse order.
8389
'after_in_child' and 'after_in_parent' callbacks are called in order.
8390
8391
[clinic start generated code]*/
8392
8393
static PyObject *
8394
os_register_at_fork_impl(PyObject *module, PyObject *before,
8395
                         PyObject *after_in_child, PyObject *after_in_parent)
8396
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8397
2
{
8398
2
    PyInterpreterState *interp;
8399
8400
2
    if (!before && !after_in_child && !after_in_parent) {
8401
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8402
0
        return NULL;
8403
0
    }
8404
2
    if (check_null_or_callable(before, "before") ||
8405
2
        check_null_or_callable(after_in_child, "after_in_child") ||
8406
2
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8407
0
        return NULL;
8408
0
    }
8409
2
    interp = _PyInterpreterState_GET();
8410
8411
2
    if (register_at_forker(&interp->before_forkers, before)) {
8412
0
        return NULL;
8413
0
    }
8414
2
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8415
0
        return NULL;
8416
0
    }
8417
2
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8418
0
        return NULL;
8419
0
    }
8420
2
    Py_RETURN_NONE;
8421
2
}
8422
#endif /* HAVE_FORK */
8423
8424
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8425
// Common code to raise a warning if we detect there is more than one thread
8426
// running in the process. Best effort, silent if unable to count threads.
8427
// Constraint: Quick. Never overcounts. Never leaves an error set.
8428
//
8429
// This should only be called from the parent process after
8430
// PyOS_AfterFork_Parent().
8431
static int
8432
warn_about_fork_with_threads(const char* name)
8433
0
{
8434
    // It's not safe to issue the warning while the world is stopped, because
8435
    // other threads might be holding locks that we need, which would deadlock.
8436
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8437
8438
    // TODO: Consider making an `os` module API to return the current number
8439
    // of threads in the process. That'd presumably use this platform code but
8440
    // raise an error rather than using the inaccurate fallback.
8441
0
    Py_ssize_t num_python_threads = 0;
8442
#if defined(__APPLE__) && defined(HAVE_GETPID)
8443
    mach_port_t macos_self = mach_task_self();
8444
    mach_port_t macos_task;
8445
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8446
        thread_array_t macos_threads;
8447
        mach_msg_type_number_t macos_n_threads;
8448
        if (task_threads(macos_task, &macos_threads,
8449
                         &macos_n_threads) == KERN_SUCCESS) {
8450
            num_python_threads = macos_n_threads;
8451
        }
8452
    }
8453
#elif defined(__linux__)
8454
    // Linux /proc/self/stat 20th field is the number of threads.
8455
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8456
0
    if (proc_stat) {
8457
0
        size_t n;
8458
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8459
        // observed on the author's workstation.
8460
0
        char stat_line[160];
8461
0
        n = fread(&stat_line, 1, 159, proc_stat);
8462
0
        stat_line[n] = '\0';
8463
0
        fclose(proc_stat);
8464
8465
0
        char *saveptr = NULL;
8466
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8467
0
        unsigned int idx;
8468
0
        for (idx = 19; idx && field; --idx) {
8469
0
            field = strtok_r(NULL, " ", &saveptr);
8470
0
        }
8471
0
        if (idx == 0 && field) {  // found the 20th field
8472
0
            num_python_threads = atoi(field);  // 0 on error
8473
0
        }
8474
0
    }
8475
0
#endif
8476
0
    if (num_python_threads <= 0) {
8477
        // Fall back to just the number our threading module knows about.
8478
        // An incomplete view of the world, but better than nothing.
8479
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8480
0
        if (!threading) {
8481
0
            PyErr_Clear();
8482
0
            return 0;
8483
0
        }
8484
0
        PyObject *threading_active =
8485
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8486
0
        if (!threading_active) {
8487
0
            PyErr_Clear();
8488
0
            Py_DECREF(threading);
8489
0
            return 0;
8490
0
        }
8491
0
        PyObject *threading_limbo =
8492
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8493
0
        if (!threading_limbo) {
8494
0
            PyErr_Clear();
8495
0
            Py_DECREF(threading);
8496
0
            Py_DECREF(threading_active);
8497
0
            return 0;
8498
0
        }
8499
0
        Py_DECREF(threading);
8500
        // Duplicating what threading.active_count() does but without holding
8501
        // threading._active_limbo_lock so our count could be inaccurate if
8502
        // these dicts are mid-update from another thread.  Not a big deal.
8503
        // Worst case if someone replaced threading._active or threading._limbo
8504
        // with non-dicts, we get -1 from *Length() below and undercount.
8505
        // Nobody should, but we're best effort so we clear errors and move on.
8506
0
        num_python_threads = (PyMapping_Length(threading_active)
8507
0
                              + PyMapping_Length(threading_limbo));
8508
0
        PyErr_Clear();
8509
0
        Py_DECREF(threading_active);
8510
0
        Py_DECREF(threading_limbo);
8511
0
    }
8512
0
    if (num_python_threads > 1) {
8513
0
        return PyErr_WarnFormat(
8514
0
                PyExc_DeprecationWarning, 1,
8515
0
#ifdef HAVE_GETPID
8516
0
                "This process (pid=%d) is multi-threaded, "
8517
#else
8518
                "This process is multi-threaded, "
8519
#endif
8520
0
                "use of %s() may lead to deadlocks in the child.",
8521
0
#ifdef HAVE_GETPID
8522
0
                getpid(),
8523
0
#endif
8524
0
                name);
8525
0
    }
8526
0
    return 0;
8527
0
}
8528
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8529
8530
#ifdef HAVE_FORK1
8531
/*[clinic input]
8532
os.fork1
8533
8534
Fork a child process with a single multiplexed (i.e., not bound) thread.
8535
8536
Return 0 to child process and PID of child to parent process.
8537
[clinic start generated code]*/
8538
8539
static PyObject *
8540
os_fork1_impl(PyObject *module)
8541
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8542
{
8543
    pid_t pid;
8544
8545
    PyInterpreterState *interp = _PyInterpreterState_GET();
8546
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8547
        PyErr_SetString(PyExc_PythonFinalizationError,
8548
                        "can't fork at interpreter shutdown");
8549
        return NULL;
8550
    }
8551
    if (!_Py_IsMainInterpreter(interp)) {
8552
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8553
        return NULL;
8554
    }
8555
    PyOS_BeforeFork();
8556
    pid = fork1();
8557
    int saved_errno = errno;
8558
    if (pid == 0) {
8559
        /* child: this clobbers and resets the import lock. */
8560
        PyOS_AfterFork_Child();
8561
    } else {
8562
        /* parent: release the import lock. */
8563
        PyOS_AfterFork_Parent();
8564
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8565
        if (warn_about_fork_with_threads("fork1") < 0) {
8566
            return NULL;
8567
        }
8568
    }
8569
    if (pid == -1) {
8570
        errno = saved_errno;
8571
        return posix_error();
8572
    }
8573
    return PyLong_FromPid(pid);
8574
}
8575
#endif /* HAVE_FORK1 */
8576
8577
8578
#ifdef HAVE_FORK
8579
/*[clinic input]
8580
os.fork
8581
8582
Fork a child process.
8583
8584
Return 0 to child process and PID of child to parent process.
8585
[clinic start generated code]*/
8586
8587
static PyObject *
8588
os_fork_impl(PyObject *module)
8589
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8590
0
{
8591
0
    pid_t pid;
8592
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8593
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8594
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8595
0
                        "can't fork at interpreter shutdown");
8596
0
        return NULL;
8597
0
    }
8598
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8599
0
        PyErr_SetString(PyExc_RuntimeError,
8600
0
                        "fork not supported for isolated subinterpreters");
8601
0
        return NULL;
8602
0
    }
8603
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8604
0
        return NULL;
8605
0
    }
8606
0
    PyOS_BeforeFork();
8607
0
    pid = fork();
8608
0
    int saved_errno = errno;
8609
0
    if (pid == 0) {
8610
        /* child: this clobbers and resets the import lock. */
8611
0
        PyOS_AfterFork_Child();
8612
0
    } else {
8613
        /* parent: release the import lock. */
8614
0
        PyOS_AfterFork_Parent();
8615
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8616
0
        if (warn_about_fork_with_threads("fork") < 0)
8617
0
            return NULL;
8618
0
    }
8619
0
    if (pid == -1) {
8620
0
        errno = saved_errno;
8621
0
        return posix_error();
8622
0
    }
8623
0
    return PyLong_FromPid(pid);
8624
0
}
8625
#endif /* HAVE_FORK */
8626
8627
8628
#ifdef HAVE_SCHED_H
8629
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8630
/*[clinic input]
8631
os.sched_get_priority_max
8632
8633
    policy: int
8634
8635
Get the maximum scheduling priority for policy.
8636
[clinic start generated code]*/
8637
8638
static PyObject *
8639
os_sched_get_priority_max_impl(PyObject *module, int policy)
8640
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8641
0
{
8642
    /* make sure that errno is cleared before the call */
8643
0
    errno = 0;
8644
0
    int max = sched_get_priority_max(policy);
8645
0
    if (max == -1 && errno)
8646
0
        return posix_error();
8647
0
    return PyLong_FromLong(max);
8648
0
}
8649
8650
8651
/*[clinic input]
8652
os.sched_get_priority_min
8653
8654
    policy: int
8655
8656
Get the minimum scheduling priority for policy.
8657
[clinic start generated code]*/
8658
8659
static PyObject *
8660
os_sched_get_priority_min_impl(PyObject *module, int policy)
8661
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8662
0
{
8663
    /* make sure that errno is cleared before the call */
8664
0
    errno = 0;
8665
0
    int min = sched_get_priority_min(policy);
8666
0
    if (min == -1 && errno)
8667
0
        return posix_error();
8668
0
    return PyLong_FromLong(min);
8669
0
}
8670
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8671
8672
8673
#ifdef HAVE_SCHED_SETSCHEDULER
8674
/*[clinic input]
8675
os.sched_getscheduler
8676
    pid: pid_t
8677
    /
8678
8679
Get the scheduling policy for the process identified by pid.
8680
8681
Passing 0 for pid returns the scheduling policy for the calling process.
8682
[clinic start generated code]*/
8683
8684
static PyObject *
8685
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8686
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8687
0
{
8688
0
    int policy;
8689
8690
0
    policy = sched_getscheduler(pid);
8691
0
    if (policy < 0)
8692
0
        return posix_error();
8693
0
    return PyLong_FromLong(policy);
8694
0
}
8695
#endif /* HAVE_SCHED_SETSCHEDULER */
8696
8697
8698
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8699
/*[clinic input]
8700
class os.sched_param "PyObject *" "SchedParamType"
8701
8702
@classmethod
8703
os.sched_param.__new__
8704
8705
    sched_priority: object
8706
        A scheduling parameter.
8707
8708
Currently has only one field: sched_priority
8709
[clinic start generated code]*/
8710
8711
static PyObject *
8712
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8713
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8714
0
{
8715
0
    PyObject *res;
8716
8717
0
    res = PyStructSequence_New(type);
8718
0
    if (!res)
8719
0
        return NULL;
8720
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8721
0
    return res;
8722
0
}
8723
8724
static PyObject *
8725
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8726
0
{
8727
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8728
0
}
8729
8730
static PyMethodDef os_sched_param_reduce_method = {
8731
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8732
};
8733
8734
PyDoc_VAR(os_sched_param__doc__);
8735
8736
static PyStructSequence_Field sched_param_fields[] = {
8737
    {"sched_priority", "the scheduling priority"},
8738
    {0}
8739
};
8740
8741
static PyStructSequence_Desc sched_param_desc = {
8742
    MODNAME ".sched_param", /* name */
8743
    os_sched_param__doc__, /* doc */
8744
    sched_param_fields,
8745
    1
8746
};
8747
8748
static int
8749
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8750
0
{
8751
0
    long priority;
8752
8753
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8754
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8755
0
        return 0;
8756
0
    }
8757
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8758
0
    if (priority == -1 && PyErr_Occurred())
8759
0
        return 0;
8760
0
    if (priority > INT_MAX || priority < INT_MIN) {
8761
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8762
0
        return 0;
8763
0
    }
8764
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8765
0
    return 1;
8766
0
}
8767
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8768
8769
8770
#ifdef HAVE_SCHED_SETSCHEDULER
8771
/*[clinic input]
8772
os.sched_setscheduler
8773
8774
    pid: pid_t
8775
    policy: int
8776
    param as param_obj: object
8777
    /
8778
8779
Set the scheduling policy for the process identified by pid.
8780
8781
If pid is 0, the calling process is changed.
8782
param is an instance of sched_param.
8783
[clinic start generated code]*/
8784
8785
static PyObject *
8786
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8787
                           PyObject *param_obj)
8788
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8789
0
{
8790
0
    struct sched_param param;
8791
0
    if (!convert_sched_param(module, param_obj, &param)) {
8792
0
        return NULL;
8793
0
    }
8794
8795
    /*
8796
    ** sched_setscheduler() returns 0 in Linux, but the previous
8797
    ** scheduling policy under Solaris/Illumos, and others.
8798
    ** On error, -1 is returned in all Operating Systems.
8799
    */
8800
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8801
0
        return posix_error();
8802
0
    Py_RETURN_NONE;
8803
0
}
8804
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8805
8806
8807
#ifdef HAVE_SCHED_SETPARAM
8808
/*[clinic input]
8809
os.sched_getparam
8810
    pid: pid_t
8811
    /
8812
8813
Returns scheduling parameters for the process identified by pid.
8814
8815
If pid is 0, returns parameters for the calling process.
8816
Return value is an instance of sched_param.
8817
[clinic start generated code]*/
8818
8819
static PyObject *
8820
os_sched_getparam_impl(PyObject *module, pid_t pid)
8821
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8822
0
{
8823
0
    struct sched_param param;
8824
0
    PyObject *result;
8825
0
    PyObject *priority;
8826
8827
0
    if (sched_getparam(pid, &param))
8828
0
        return posix_error();
8829
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8830
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8831
0
    if (!result)
8832
0
        return NULL;
8833
0
    priority = PyLong_FromLong(param.sched_priority);
8834
0
    if (!priority) {
8835
0
        Py_DECREF(result);
8836
0
        return NULL;
8837
0
    }
8838
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8839
0
    return result;
8840
0
}
8841
8842
8843
/*[clinic input]
8844
os.sched_setparam
8845
    pid: pid_t
8846
    param as param_obj: object
8847
    /
8848
8849
Set scheduling parameters for the process identified by pid.
8850
8851
If pid is 0, sets parameters for the calling process.
8852
param should be an instance of sched_param.
8853
[clinic start generated code]*/
8854
8855
static PyObject *
8856
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8857
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8858
0
{
8859
0
    struct sched_param param;
8860
0
    if (!convert_sched_param(module, param_obj, &param)) {
8861
0
        return NULL;
8862
0
    }
8863
8864
0
    if (sched_setparam(pid, &param))
8865
0
        return posix_error();
8866
0
    Py_RETURN_NONE;
8867
0
}
8868
#endif /* HAVE_SCHED_SETPARAM */
8869
8870
8871
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8872
/*[clinic input]
8873
@permit_long_summary
8874
os.sched_rr_get_interval -> double
8875
    pid: pid_t
8876
    /
8877
8878
Return the round-robin quantum for the process identified by pid, in seconds.
8879
8880
Value returned is a float.
8881
[clinic start generated code]*/
8882
8883
static double
8884
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8885
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8886
0
{
8887
0
    struct timespec interval;
8888
0
    if (sched_rr_get_interval(pid, &interval)) {
8889
0
        posix_error();
8890
0
        return -1.0;
8891
0
    }
8892
#ifdef _Py_MEMORY_SANITIZER
8893
    __msan_unpoison(&interval, sizeof(interval));
8894
#endif
8895
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8896
0
}
8897
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8898
8899
8900
/*[clinic input]
8901
os.sched_yield
8902
8903
Voluntarily relinquish the CPU.
8904
[clinic start generated code]*/
8905
8906
static PyObject *
8907
os_sched_yield_impl(PyObject *module)
8908
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8909
0
{
8910
0
    int result;
8911
0
    Py_BEGIN_ALLOW_THREADS
8912
0
    result = sched_yield();
8913
0
    Py_END_ALLOW_THREADS
8914
0
    if (result < 0) {
8915
0
        return posix_error();
8916
0
    }
8917
0
    Py_RETURN_NONE;
8918
0
}
8919
8920
#ifdef HAVE_SCHED_SETAFFINITY
8921
/* The minimum number of CPUs allocated in a cpu_set_t */
8922
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8923
8924
/*[clinic input]
8925
os.sched_setaffinity
8926
    pid: pid_t
8927
    mask : object
8928
    /
8929
8930
Set the CPU affinity of the process identified by pid to mask.
8931
8932
mask should be an iterable of integers identifying CPUs.
8933
[clinic start generated code]*/
8934
8935
static PyObject *
8936
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8937
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8938
0
{
8939
0
    int ncpus;
8940
0
    size_t setsize;
8941
0
    cpu_set_t *cpu_set = NULL;
8942
0
    PyObject *iterator = NULL, *item;
8943
8944
0
    iterator = PyObject_GetIter(mask);
8945
0
    if (iterator == NULL)
8946
0
        return NULL;
8947
8948
0
    ncpus = NCPUS_START;
8949
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8950
0
    cpu_set = CPU_ALLOC(ncpus);
8951
0
    if (cpu_set == NULL) {
8952
0
        PyErr_NoMemory();
8953
0
        goto error;
8954
0
    }
8955
0
    CPU_ZERO_S(setsize, cpu_set);
8956
8957
0
    while ((item = PyIter_Next(iterator))) {
8958
0
        long cpu;
8959
0
        if (!PyIndex_Check(item)) {
8960
0
            PyErr_Format(PyExc_TypeError,
8961
0
                        "expected an iterator of ints, "
8962
0
                        "but iterator yielded %R",
8963
0
                        Py_TYPE(item));
8964
0
            Py_DECREF(item);
8965
0
            goto error;
8966
0
        }
8967
0
        cpu = PyLong_AsLong(item);
8968
0
        Py_DECREF(item);
8969
0
        if (cpu < 0) {
8970
0
            if (!PyErr_Occurred())
8971
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
8972
0
            goto error;
8973
0
        }
8974
0
        if (cpu > INT_MAX - 1) {
8975
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
8976
0
            goto error;
8977
0
        }
8978
0
        if (cpu >= ncpus) {
8979
            /* Grow CPU mask to fit the CPU number */
8980
0
            int newncpus = ncpus;
8981
0
            cpu_set_t *newmask;
8982
0
            size_t newsetsize;
8983
0
            while (newncpus <= cpu) {
8984
0
                if (newncpus > INT_MAX / 2)
8985
0
                    newncpus = cpu + 1;
8986
0
                else
8987
0
                    newncpus = newncpus * 2;
8988
0
            }
8989
0
            newmask = CPU_ALLOC(newncpus);
8990
0
            if (newmask == NULL) {
8991
0
                PyErr_NoMemory();
8992
0
                goto error;
8993
0
            }
8994
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
8995
0
            CPU_ZERO_S(newsetsize, newmask);
8996
0
            memcpy(newmask, cpu_set, setsize);
8997
0
            CPU_FREE(cpu_set);
8998
0
            setsize = newsetsize;
8999
0
            cpu_set = newmask;
9000
0
            ncpus = newncpus;
9001
0
        }
9002
0
        CPU_SET_S(cpu, setsize, cpu_set);
9003
0
    }
9004
0
    if (PyErr_Occurred()) {
9005
0
        goto error;
9006
0
    }
9007
0
    Py_CLEAR(iterator);
9008
9009
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9010
0
        posix_error();
9011
0
        goto error;
9012
0
    }
9013
0
    CPU_FREE(cpu_set);
9014
0
    Py_RETURN_NONE;
9015
9016
0
error:
9017
0
    if (cpu_set)
9018
0
        CPU_FREE(cpu_set);
9019
0
    Py_XDECREF(iterator);
9020
0
    return NULL;
9021
0
}
9022
9023
9024
/*[clinic input]
9025
@permit_long_summary
9026
os.sched_getaffinity
9027
    pid: pid_t
9028
    /
9029
9030
Return the affinity of the process identified by pid (or the current process if zero).
9031
9032
The affinity is returned as a set of CPU identifiers.
9033
[clinic start generated code]*/
9034
9035
static PyObject *
9036
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9037
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9038
0
{
9039
0
    int ncpus = NCPUS_START;
9040
0
    size_t setsize;
9041
0
    cpu_set_t *mask;
9042
9043
0
    while (1) {
9044
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9045
0
        mask = CPU_ALLOC(ncpus);
9046
0
        if (mask == NULL) {
9047
0
            return PyErr_NoMemory();
9048
0
        }
9049
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9050
0
            break;
9051
0
        }
9052
0
        CPU_FREE(mask);
9053
0
        if (errno != EINVAL) {
9054
0
            return posix_error();
9055
0
        }
9056
0
        if (ncpus > INT_MAX / 2) {
9057
0
            PyErr_SetString(PyExc_OverflowError,
9058
0
                            "could not allocate a large enough CPU set");
9059
0
            return NULL;
9060
0
        }
9061
0
        ncpus *= 2;
9062
0
    }
9063
9064
0
    PyObject *res = PySet_New(NULL);
9065
0
    if (res == NULL) {
9066
0
        goto error;
9067
0
    }
9068
9069
0
    int cpu = 0;
9070
0
    int count = CPU_COUNT_S(setsize, mask);
9071
0
    for (; count; cpu++) {
9072
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9073
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9074
0
            --count;
9075
0
            if (cpu_num == NULL) {
9076
0
                goto error;
9077
0
            }
9078
0
            if (PySet_Add(res, cpu_num)) {
9079
0
                Py_DECREF(cpu_num);
9080
0
                goto error;
9081
0
            }
9082
0
            Py_DECREF(cpu_num);
9083
0
        }
9084
0
    }
9085
0
    CPU_FREE(mask);
9086
0
    return res;
9087
9088
0
error:
9089
0
    if (mask) {
9090
0
        CPU_FREE(mask);
9091
0
    }
9092
0
    Py_XDECREF(res);
9093
0
    return NULL;
9094
0
}
9095
#endif /* HAVE_SCHED_SETAFFINITY */
9096
9097
#endif /* HAVE_SCHED_H */
9098
9099
9100
#ifdef HAVE_POSIX_OPENPT
9101
/*[clinic input]
9102
os.posix_openpt -> int
9103
9104
    oflag: int
9105
    /
9106
9107
Open and return a file descriptor for a master pseudo-terminal device.
9108
9109
Performs a posix_openpt() C function call. The oflag argument is used to
9110
set file status flags and file access modes as specified in the manual page
9111
of posix_openpt() of your system.
9112
[clinic start generated code]*/
9113
9114
static int
9115
os_posix_openpt_impl(PyObject *module, int oflag)
9116
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
9117
0
{
9118
0
    int fd;
9119
9120
0
#if defined(O_CLOEXEC)
9121
0
    oflag |= O_CLOEXEC;
9122
0
#endif
9123
9124
0
    fd = posix_openpt(oflag);
9125
0
    if (fd == -1) {
9126
0
        posix_error();
9127
0
        return -1;
9128
0
    }
9129
9130
    // Just in case, likely a no-op given O_CLOEXEC above.
9131
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9132
0
        close(fd);
9133
0
        return -1;
9134
0
    }
9135
9136
0
    return fd;
9137
0
}
9138
#endif /* HAVE_POSIX_OPENPT */
9139
9140
#ifdef HAVE_GRANTPT
9141
/*[clinic input]
9142
os.grantpt
9143
9144
    fd: fildes
9145
        File descriptor of a master pseudo-terminal device.
9146
    /
9147
9148
Grant access to the slave pseudo-terminal device.
9149
9150
Performs a grantpt() C function call.
9151
[clinic start generated code]*/
9152
9153
static PyObject *
9154
os_grantpt_impl(PyObject *module, int fd)
9155
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9156
0
{
9157
0
    int ret;
9158
0
    int saved_errno;
9159
0
    PyOS_sighandler_t sig_saved;
9160
9161
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9162
9163
0
    ret = grantpt(fd);
9164
0
    if (ret == -1)
9165
0
        saved_errno = errno;
9166
9167
0
    PyOS_setsig(SIGCHLD, sig_saved);
9168
9169
0
    if (ret == -1) {
9170
0
        errno = saved_errno;
9171
0
        return posix_error();
9172
0
    }
9173
9174
0
    Py_RETURN_NONE;
9175
0
}
9176
#endif /* HAVE_GRANTPT */
9177
9178
#ifdef HAVE_UNLOCKPT
9179
/*[clinic input]
9180
os.unlockpt
9181
9182
    fd: fildes
9183
        File descriptor of a master pseudo-terminal device.
9184
    /
9185
9186
Unlock a pseudo-terminal master/slave pair.
9187
9188
Performs an unlockpt() C function call.
9189
[clinic start generated code]*/
9190
9191
static PyObject *
9192
os_unlockpt_impl(PyObject *module, int fd)
9193
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9194
0
{
9195
0
    if (unlockpt(fd) == -1)
9196
0
        return posix_error();
9197
9198
0
    Py_RETURN_NONE;
9199
0
}
9200
#endif /* HAVE_UNLOCKPT */
9201
9202
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9203
static PyObject *
9204
py_ptsname(int fd)
9205
0
{
9206
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9207
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9208
0
    errno = 0;
9209
0
    char *name = ptsname(fd);
9210
0
    if (name == NULL) {
9211
0
        return posix_error();
9212
0
    }
9213
0
    return PyUnicode_DecodeFSDefault(name);
9214
0
}
9215
9216
/*[clinic input]
9217
os.ptsname
9218
9219
    fd: fildes
9220
        File descriptor of a master pseudo-terminal device.
9221
    /
9222
9223
Return the name of the slave pseudo-terminal device.
9224
9225
If the ptsname_r() C function is available, it is called;
9226
otherwise, performs a ptsname() C function call.
9227
[clinic start generated code]*/
9228
9229
static PyObject *
9230
os_ptsname_impl(PyObject *module, int fd)
9231
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9232
0
{
9233
0
#ifdef HAVE_PTSNAME_R
9234
0
    int ret;
9235
0
    char name[MAXPATHLEN+1];
9236
9237
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9238
0
        ret = ptsname_r(fd, name, sizeof(name));
9239
0
    }
9240
0
    else {
9241
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9242
0
        return py_ptsname(fd);
9243
0
    }
9244
0
    if (ret != 0) {
9245
0
        errno = ret;
9246
0
        return posix_error();
9247
0
    }
9248
9249
0
    return PyUnicode_DecodeFSDefault(name);
9250
#else
9251
    return py_ptsname(fd);
9252
#endif /* HAVE_PTSNAME_R */
9253
0
}
9254
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9255
9256
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9257
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9258
#  define DEV_PTY_FILE "/dev/ptc"
9259
#  define HAVE_DEV_PTMX
9260
#else
9261
#  define DEV_PTY_FILE "/dev/ptmx"
9262
#endif
9263
9264
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9265
#ifdef HAVE_PTY_H
9266
#include <pty.h>
9267
#elif defined(HAVE_LIBUTIL_H)
9268
#include <libutil.h>
9269
#elif defined(HAVE_UTIL_H)
9270
#include <util.h>
9271
#endif /* HAVE_PTY_H */
9272
#ifdef HAVE_UTMP_H
9273
#include <utmp.h>
9274
#endif /* HAVE_UTMP_H */
9275
#ifdef HAVE_STROPTS_H
9276
#include <stropts.h>
9277
#endif
9278
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9279
9280
9281
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9282
/*[clinic input]
9283
os.openpty
9284
9285
Open a pseudo-terminal.
9286
9287
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9288
for both the master and slave ends.
9289
[clinic start generated code]*/
9290
9291
static PyObject *
9292
os_openpty_impl(PyObject *module)
9293
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9294
0
{
9295
0
    int master_fd = -1, slave_fd = -1;
9296
#ifndef HAVE_OPENPTY
9297
    char * slave_name;
9298
#endif
9299
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9300
    PyOS_sighandler_t sig_saved;
9301
#if defined(__sun) && defined(__SVR4)
9302
    extern char *ptsname(int fildes);
9303
#endif
9304
#endif
9305
9306
0
#ifdef HAVE_OPENPTY
9307
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9308
0
        goto posix_error;
9309
9310
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9311
0
        goto error;
9312
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9313
0
        goto error;
9314
9315
#elif defined(HAVE__GETPTY)
9316
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9317
    if (slave_name == NULL)
9318
        goto posix_error;
9319
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9320
        goto error;
9321
9322
    slave_fd = _Py_open(slave_name, O_RDWR);
9323
    if (slave_fd < 0)
9324
        goto error;
9325
9326
#else
9327
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9328
    if (master_fd < 0)
9329
        goto posix_error;
9330
9331
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9332
9333
    /* change permission of slave */
9334
    if (grantpt(master_fd) < 0) {
9335
        int saved_errno = errno;
9336
        PyOS_setsig(SIGCHLD, sig_saved);
9337
        errno = saved_errno;
9338
        goto posix_error;
9339
    }
9340
9341
    /* unlock slave */
9342
    if (unlockpt(master_fd) < 0) {
9343
        int saved_errno = errno;
9344
        PyOS_setsig(SIGCHLD, sig_saved);
9345
        errno = saved_errno;
9346
        goto posix_error;
9347
    }
9348
9349
    PyOS_setsig(SIGCHLD, sig_saved);
9350
9351
    slave_name = ptsname(master_fd); /* get name of slave */
9352
    if (slave_name == NULL)
9353
        goto posix_error;
9354
9355
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9356
    if (slave_fd == -1)
9357
        goto error;
9358
9359
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9360
        goto posix_error;
9361
9362
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
9363
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9364
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9365
#ifndef __hpux
9366
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9367
#endif /* __hpux */
9368
#endif /* HAVE_CYGWIN */
9369
#endif /* HAVE_OPENPTY */
9370
9371
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9372
9373
0
posix_error:
9374
0
    posix_error();
9375
0
error:
9376
0
    if (master_fd != -1)
9377
0
        close(master_fd);
9378
0
    if (slave_fd != -1)
9379
0
        close(slave_fd);
9380
0
    return NULL;
9381
0
}
9382
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9383
9384
9385
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9386
#define HAVE_FALLBACK_LOGIN_TTY 1
9387
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9388
9389
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9390
/*[clinic input]
9391
os.login_tty
9392
9393
    fd: fildes
9394
    /
9395
9396
Prepare the tty of which fd is a file descriptor for a new login session.
9397
9398
Make the calling process a session leader; make the tty the
9399
controlling tty, the stdin, the stdout, and the stderr of the
9400
calling process; close fd.
9401
[clinic start generated code]*/
9402
9403
static PyObject *
9404
os_login_tty_impl(PyObject *module, int fd)
9405
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
9406
0
{
9407
0
#ifdef HAVE_LOGIN_TTY
9408
0
    if (login_tty(fd) == -1) {
9409
0
        return posix_error();
9410
0
    }
9411
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9412
    /* Establish a new session. */
9413
    if (setsid() == -1) {
9414
        return posix_error();
9415
    }
9416
9417
    /* The tty becomes the controlling terminal. */
9418
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9419
        return posix_error();
9420
    }
9421
9422
    /* The tty becomes stdin/stdout/stderr */
9423
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9424
        return posix_error();
9425
    }
9426
    if (fd > 2) {
9427
        close(fd);
9428
    }
9429
#endif /* HAVE_LOGIN_TTY */
9430
0
    Py_RETURN_NONE;
9431
0
}
9432
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9433
9434
9435
#ifdef HAVE_FORKPTY
9436
/*[clinic input]
9437
os.forkpty
9438
9439
Fork a new process with a new pseudo-terminal as controlling tty.
9440
9441
Returns a tuple of (pid, master_fd).
9442
Like fork(), return pid of 0 to the child process,
9443
and pid of child to the parent process.
9444
To both, return fd of newly opened pseudo-terminal.
9445
The master_fd is non-inheritable.
9446
[clinic start generated code]*/
9447
9448
static PyObject *
9449
os_forkpty_impl(PyObject *module)
9450
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9451
0
{
9452
0
    int master_fd = -1;
9453
0
    pid_t pid;
9454
9455
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9456
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9457
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9458
0
                        "can't fork at interpreter shutdown");
9459
0
        return NULL;
9460
0
    }
9461
0
    if (!_Py_IsMainInterpreter(interp)) {
9462
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9463
0
        return NULL;
9464
0
    }
9465
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9466
0
        return NULL;
9467
0
    }
9468
0
    PyOS_BeforeFork();
9469
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9470
0
    if (pid == 0) {
9471
        /* child: this clobbers and resets the import lock. */
9472
0
        PyOS_AfterFork_Child();
9473
0
    } else {
9474
        /* parent: release the import lock. */
9475
0
        PyOS_AfterFork_Parent();
9476
        /* set O_CLOEXEC on master_fd */
9477
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9478
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9479
0
                                   "non-inheritable in forkpty()");
9480
0
        }
9481
9482
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9483
0
        if (warn_about_fork_with_threads("forkpty") < 0)
9484
0
            return NULL;
9485
0
    }
9486
0
    if (pid == -1) {
9487
0
        return posix_error();
9488
0
    }
9489
9490
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9491
0
}
9492
#endif /* HAVE_FORKPTY */
9493
9494
9495
#ifdef HAVE_GETEGID
9496
/*[clinic input]
9497
os.getegid
9498
9499
Return the current process's effective group id.
9500
[clinic start generated code]*/
9501
9502
static PyObject *
9503
os_getegid_impl(PyObject *module)
9504
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9505
16
{
9506
16
    return _PyLong_FromGid(getegid());
9507
16
}
9508
#endif /* HAVE_GETEGID */
9509
9510
9511
#ifdef HAVE_GETEUID
9512
/*[clinic input]
9513
os.geteuid
9514
9515
Return the current process's effective user id.
9516
[clinic start generated code]*/
9517
9518
static PyObject *
9519
os_geteuid_impl(PyObject *module)
9520
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9521
16
{
9522
16
    return _PyLong_FromUid(geteuid());
9523
16
}
9524
#endif /* HAVE_GETEUID */
9525
9526
9527
#ifdef HAVE_GETGID
9528
/*[clinic input]
9529
os.getgid
9530
9531
Return the current process's group id.
9532
[clinic start generated code]*/
9533
9534
static PyObject *
9535
os_getgid_impl(PyObject *module)
9536
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9537
16
{
9538
16
    return _PyLong_FromGid(getgid());
9539
16
}
9540
#endif /* HAVE_GETGID */
9541
9542
9543
#if defined(HAVE_GETPID)
9544
/*[clinic input]
9545
os.getpid
9546
9547
Return the current process id.
9548
[clinic start generated code]*/
9549
9550
static PyObject *
9551
os_getpid_impl(PyObject *module)
9552
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9553
0
{
9554
0
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9555
0
    return PyLong_FromPid(getpid());
9556
#else
9557
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9558
#endif
9559
0
}
9560
#endif /* defined(HAVE_GETPID) */
9561
9562
#ifdef NGROUPS_MAX
9563
0
#define MAX_GROUPS NGROUPS_MAX
9564
#else
9565
    /* defined to be 16 on Solaris7, so this should be a small number */
9566
#define MAX_GROUPS 64
9567
#endif
9568
9569
#ifdef HAVE_GETGROUPLIST
9570
9571
#ifdef __APPLE__
9572
/*[clinic input]
9573
os.getgrouplist
9574
9575
    user: str
9576
        username to lookup
9577
    group as basegid: int
9578
        base group id of the user
9579
    /
9580
9581
Returns a list of groups to which a user belongs.
9582
[clinic start generated code]*/
9583
9584
static PyObject *
9585
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9586
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9587
#else
9588
/*[clinic input]
9589
os.getgrouplist
9590
9591
    user: str
9592
        username to lookup
9593
    group as basegid: gid_t
9594
        base group id of the user
9595
    /
9596
9597
Returns a list of groups to which a user belongs.
9598
[clinic start generated code]*/
9599
9600
static PyObject *
9601
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9602
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9603
#endif
9604
0
{
9605
0
    int i, ngroups;
9606
0
    PyObject *list;
9607
#ifdef __APPLE__
9608
    int *groups;
9609
#else
9610
0
    gid_t *groups;
9611
0
#endif
9612
9613
    /*
9614
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9615
     * number of supplemental groups a users can belong to.
9616
     * We have to increment it by one because
9617
     * getgrouplist() returns both the supplemental groups
9618
     * and the primary group, i.e. all of the groups the
9619
     * user belongs to.
9620
     */
9621
0
    ngroups = 1 + MAX_GROUPS;
9622
9623
0
    while (1) {
9624
#ifdef __APPLE__
9625
        groups = PyMem_New(int, ngroups);
9626
#else
9627
0
        groups = PyMem_New(gid_t, ngroups);
9628
0
#endif
9629
0
        if (groups == NULL) {
9630
0
            return PyErr_NoMemory();
9631
0
        }
9632
9633
0
        int old_ngroups = ngroups;
9634
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9635
            /* Success */
9636
0
            break;
9637
0
        }
9638
9639
        /* getgrouplist() fails if the group list is too small */
9640
0
        PyMem_Free(groups);
9641
9642
0
        if (ngroups > old_ngroups) {
9643
            /* If the group list is too small, the glibc implementation of
9644
               getgrouplist() sets ngroups to the total number of groups and
9645
               returns -1. */
9646
0
        }
9647
0
        else {
9648
            /* Double the group list size */
9649
0
            if (ngroups > INT_MAX / 2) {
9650
0
                return PyErr_NoMemory();
9651
0
            }
9652
0
            ngroups *= 2;
9653
0
        }
9654
9655
        /* Retry getgrouplist() with a larger group list */
9656
0
    }
9657
9658
#ifdef _Py_MEMORY_SANITIZER
9659
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9660
    __msan_unpoison(&ngroups, sizeof(ngroups));
9661
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9662
#endif
9663
9664
0
    list = PyList_New(ngroups);
9665
0
    if (list == NULL) {
9666
0
        PyMem_Free(groups);
9667
0
        return NULL;
9668
0
    }
9669
9670
0
    for (i = 0; i < ngroups; i++) {
9671
#ifdef __APPLE__
9672
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9673
#else
9674
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9675
0
#endif
9676
0
        if (o == NULL) {
9677
0
            Py_DECREF(list);
9678
0
            PyMem_Free(groups);
9679
0
            return NULL;
9680
0
        }
9681
0
        PyList_SET_ITEM(list, i, o);
9682
0
    }
9683
9684
0
    PyMem_Free(groups);
9685
9686
0
    return list;
9687
0
}
9688
#endif /* HAVE_GETGROUPLIST */
9689
9690
9691
#ifdef HAVE_GETGROUPS
9692
/*[clinic input]
9693
os.getgroups
9694
9695
Return list of supplemental group IDs for the process.
9696
[clinic start generated code]*/
9697
9698
static PyObject *
9699
os_getgroups_impl(PyObject *module)
9700
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9701
0
{
9702
    // Call getgroups with length 0 to get the actual number of groups
9703
0
    int n = getgroups(0, NULL);
9704
0
    if (n < 0) {
9705
0
        return posix_error();
9706
0
    }
9707
9708
0
    if (n == 0) {
9709
0
        return PyList_New(0);
9710
0
    }
9711
9712
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9713
0
    if (grouplist == NULL) {
9714
0
        return PyErr_NoMemory();
9715
0
    }
9716
9717
0
    n = getgroups(n, grouplist);
9718
0
    if (n == -1) {
9719
0
        posix_error();
9720
0
        PyMem_Free(grouplist);
9721
0
        return NULL;
9722
0
    }
9723
9724
0
    PyObject *result = PyList_New(n);
9725
0
    if (result == NULL) {
9726
0
        goto error;
9727
0
    }
9728
9729
0
    for (int i = 0; i < n; ++i) {
9730
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9731
0
        if (group == NULL) {
9732
0
            goto error;
9733
0
        }
9734
0
        PyList_SET_ITEM(result, i, group);
9735
0
    }
9736
0
    PyMem_Free(grouplist);
9737
9738
0
    return result;
9739
9740
0
error:
9741
0
    PyMem_Free(grouplist);
9742
0
    Py_XDECREF(result);
9743
0
    return NULL;
9744
0
}
9745
#endif /* HAVE_GETGROUPS */
9746
9747
#ifdef HAVE_INITGROUPS
9748
#ifdef __APPLE__
9749
/*[clinic input]
9750
os.initgroups
9751
9752
    username as oname: unicode_fs_encoded
9753
    gid: int
9754
    /
9755
9756
Initialize the group access list.
9757
9758
Call the system initgroups() to initialize the group access list with all of
9759
the groups of which the specified username is a member, plus the specified
9760
group id.
9761
[clinic start generated code]*/
9762
9763
static PyObject *
9764
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9765
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9766
#else
9767
/*[clinic input]
9768
os.initgroups
9769
9770
    username as oname: unicode_fs_encoded
9771
    gid: gid_t
9772
    /
9773
9774
Initialize the group access list.
9775
9776
Call the system initgroups() to initialize the group access list with all of
9777
the groups of which the specified username is a member, plus the specified
9778
group id.
9779
[clinic start generated code]*/
9780
9781
static PyObject *
9782
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9783
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9784
#endif
9785
0
{
9786
0
    const char *username = PyBytes_AS_STRING(oname);
9787
9788
0
    if (initgroups(username, gid) == -1)
9789
0
        return PyErr_SetFromErrno(PyExc_OSError);
9790
9791
0
    Py_RETURN_NONE;
9792
0
}
9793
#endif /* HAVE_INITGROUPS */
9794
9795
9796
#ifdef HAVE_GETPGID
9797
/*[clinic input]
9798
os.getpgid
9799
9800
    pid: pid_t
9801
9802
Call the system call getpgid(), and return the result.
9803
[clinic start generated code]*/
9804
9805
static PyObject *
9806
os_getpgid_impl(PyObject *module, pid_t pid)
9807
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9808
0
{
9809
0
    pid_t pgid = getpgid(pid);
9810
0
    if (pgid < 0)
9811
0
        return posix_error();
9812
0
    return PyLong_FromPid(pgid);
9813
0
}
9814
#endif /* HAVE_GETPGID */
9815
9816
9817
#ifdef HAVE_GETPGRP
9818
/*[clinic input]
9819
os.getpgrp
9820
9821
Return the current process group id.
9822
[clinic start generated code]*/
9823
9824
static PyObject *
9825
os_getpgrp_impl(PyObject *module)
9826
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9827
0
{
9828
#ifdef GETPGRP_HAVE_ARG
9829
    return PyLong_FromPid(getpgrp(0));
9830
#else /* GETPGRP_HAVE_ARG */
9831
0
    return PyLong_FromPid(getpgrp());
9832
0
#endif /* GETPGRP_HAVE_ARG */
9833
0
}
9834
#endif /* HAVE_GETPGRP */
9835
9836
9837
#ifdef HAVE_SETPGRP
9838
/*[clinic input]
9839
os.setpgrp
9840
9841
Make the current process the leader of its process group.
9842
[clinic start generated code]*/
9843
9844
static PyObject *
9845
os_setpgrp_impl(PyObject *module)
9846
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9847
0
{
9848
#ifdef SETPGRP_HAVE_ARG
9849
    if (setpgrp(0, 0) < 0)
9850
#else /* SETPGRP_HAVE_ARG */
9851
0
    if (setpgrp() < 0)
9852
0
#endif /* SETPGRP_HAVE_ARG */
9853
0
        return posix_error();
9854
0
    Py_RETURN_NONE;
9855
0
}
9856
#endif /* HAVE_SETPGRP */
9857
9858
#ifdef HAVE_GETPPID
9859
9860
#ifdef MS_WINDOWS
9861
#include <winternl.h>
9862
#include <ProcessSnapshot.h>
9863
9864
// The structure definition in winternl.h may be incomplete.
9865
// This structure is the full version from the MSDN documentation.
9866
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9867
    NTSTATUS ExitStatus;
9868
    PVOID PebBaseAddress;
9869
    ULONG_PTR AffinityMask;
9870
    LONG BasePriority;
9871
    ULONG_PTR UniqueProcessId;
9872
    ULONG_PTR InheritedFromUniqueProcessId;
9873
} PROCESS_BASIC_INFORMATION_FULL;
9874
9875
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9876
    IN    HANDLE           ProcessHandle,
9877
    IN    PROCESSINFOCLASS ProcessInformationClass,
9878
    OUT   PVOID            ProcessInformation,
9879
    IN    ULONG            ProcessInformationLength,
9880
    OUT   PULONG           ReturnLength OPTIONAL);
9881
9882
// This function returns the process ID of the parent process.
9883
// Returns 0 on failure.
9884
static ULONG
9885
win32_getppid_fast(void)
9886
{
9887
    NTSTATUS status;
9888
    HMODULE ntdll;
9889
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9890
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9891
    static ULONG cached_ppid = 0;
9892
9893
    if (cached_ppid) {
9894
        // No need to query the kernel again.
9895
        return cached_ppid;
9896
    }
9897
9898
    ntdll = GetModuleHandleW(L"ntdll.dll");
9899
    if (!ntdll) {
9900
        return 0;
9901
    }
9902
9903
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9904
    if (!pNtQueryInformationProcess) {
9905
        return 0;
9906
    }
9907
9908
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9909
                                        ProcessBasicInformation,
9910
                                        &basic_information,
9911
                                        sizeof(basic_information),
9912
                                        NULL);
9913
9914
    if (!NT_SUCCESS(status)) {
9915
        return 0;
9916
    }
9917
9918
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9919
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9920
    // zero and (ULONG) -1.
9921
9922
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9923
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9924
    {
9925
        return 0;
9926
    }
9927
9928
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9929
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9930
    // process. This process ID will be correctly returned even if the parent process has
9931
    // exited or been terminated.
9932
9933
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9934
    return cached_ppid;
9935
}
9936
9937
static PyObject*
9938
win32_getppid(void)
9939
{
9940
    DWORD error;
9941
    PyObject* result = NULL;
9942
    HANDLE process = GetCurrentProcess();
9943
    HPSS snapshot = NULL;
9944
    ULONG pid;
9945
9946
    pid = win32_getppid_fast();
9947
    if (pid != 0) {
9948
        return PyLong_FromUnsignedLong(pid);
9949
    }
9950
9951
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9952
9953
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9954
    if (error != ERROR_SUCCESS) {
9955
        return PyErr_SetFromWindowsErr(error);
9956
    }
9957
9958
    PSS_PROCESS_INFORMATION info;
9959
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
9960
                             sizeof(info));
9961
    if (error == ERROR_SUCCESS) {
9962
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
9963
    }
9964
    else {
9965
        result = PyErr_SetFromWindowsErr(error);
9966
    }
9967
9968
    PssFreeSnapshot(process, snapshot);
9969
    return result;
9970
}
9971
#endif /*MS_WINDOWS*/
9972
9973
9974
/*[clinic input]
9975
os.getppid
9976
9977
Return the parent's process id.
9978
9979
If the parent process has already exited, Windows machines will still
9980
return its id; others systems will return the id of the 'init' process (1).
9981
[clinic start generated code]*/
9982
9983
static PyObject *
9984
os_getppid_impl(PyObject *module)
9985
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
9986
0
{
9987
#ifdef MS_WINDOWS
9988
    return win32_getppid();
9989
#else
9990
0
    return PyLong_FromPid(getppid());
9991
0
#endif
9992
0
}
9993
#endif /* HAVE_GETPPID */
9994
9995
9996
#ifdef HAVE_GETLOGIN
9997
/*[clinic input]
9998
os.getlogin
9999
10000
Return the actual login name.
10001
[clinic start generated code]*/
10002
10003
static PyObject *
10004
os_getlogin_impl(PyObject *module)
10005
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10006
0
{
10007
0
    PyObject *result = NULL;
10008
#ifdef MS_WINDOWS
10009
    wchar_t user_name[UNLEN + 1];
10010
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10011
10012
    if (GetUserNameW(user_name, &num_chars)) {
10013
        /* num_chars is the number of unicode chars plus null terminator */
10014
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10015
    }
10016
    else
10017
        result = PyErr_SetFromWindowsErr(GetLastError());
10018
#elif defined (HAVE_GETLOGIN_R)
10019
# if defined (HAVE_MAXLOGNAME)
10020
    char name[MAXLOGNAME + 1];
10021
# elif defined (HAVE_UT_NAMESIZE)
10022
    char name[UT_NAMESIZE + 1];
10023
# else
10024
    char name[256];
10025
# endif
10026
0
    int err = getlogin_r(name, sizeof(name));
10027
0
    if (err) {
10028
0
        int old_errno = errno;
10029
0
        errno = err;
10030
0
        posix_error();
10031
0
        errno = old_errno;
10032
0
    }
10033
0
    else {
10034
0
        result = PyUnicode_DecodeFSDefault(name);
10035
0
    }
10036
#else
10037
    char *name;
10038
    int old_errno = errno;
10039
10040
    errno = 0;
10041
    name = getlogin();
10042
    if (name == NULL) {
10043
        if (errno)
10044
            posix_error();
10045
        else
10046
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10047
    }
10048
    else
10049
        result = PyUnicode_DecodeFSDefault(name);
10050
    errno = old_errno;
10051
#endif
10052
0
    return result;
10053
0
}
10054
#endif /* HAVE_GETLOGIN */
10055
10056
10057
#ifdef HAVE_GETUID
10058
/*[clinic input]
10059
os.getuid
10060
10061
Return the current process's user id.
10062
[clinic start generated code]*/
10063
10064
static PyObject *
10065
os_getuid_impl(PyObject *module)
10066
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10067
16
{
10068
16
    return _PyLong_FromUid(getuid());
10069
16
}
10070
#endif /* HAVE_GETUID */
10071
10072
10073
#ifdef MS_WINDOWS
10074
#define HAVE_KILL
10075
#endif /* MS_WINDOWS */
10076
10077
#ifdef HAVE_KILL
10078
/*[clinic input]
10079
os.kill
10080
10081
    pid: pid_t
10082
    signal: Py_ssize_t
10083
    /
10084
10085
Kill a process with a signal.
10086
[clinic start generated code]*/
10087
10088
static PyObject *
10089
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10090
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10091
0
{
10092
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10093
0
        return NULL;
10094
0
    }
10095
0
#ifndef MS_WINDOWS
10096
0
    if (kill(pid, (int)signal) == -1) {
10097
0
        return posix_error();
10098
0
    }
10099
10100
    // Check immediately if the signal was sent to the current process.
10101
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10102
    // is cheap.
10103
0
    if (PyErr_CheckSignals()) {
10104
0
        return NULL;
10105
0
    }
10106
10107
0
    Py_RETURN_NONE;
10108
#else /* !MS_WINDOWS */
10109
    DWORD sig = (DWORD)signal;
10110
10111
#ifdef HAVE_WINDOWS_CONSOLE_IO
10112
    /* Console processes which share a common console can be sent CTRL+C or
10113
       CTRL+BREAK events, provided they handle said events. */
10114
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10115
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10116
            return PyErr_SetFromWindowsErr(0);
10117
        }
10118
        Py_RETURN_NONE;
10119
    }
10120
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10121
10122
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10123
       attempt to open and terminate the process. */
10124
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10125
    if (handle == NULL) {
10126
        return PyErr_SetFromWindowsErr(0);
10127
    }
10128
10129
    BOOL res = TerminateProcess(handle, sig);
10130
    CloseHandle(handle);
10131
    if (res == 0) {
10132
        return PyErr_SetFromWindowsErr(0);
10133
    }
10134
10135
    Py_RETURN_NONE;
10136
#endif /* !MS_WINDOWS */
10137
0
}
10138
#endif /* HAVE_KILL */
10139
10140
10141
#ifdef HAVE_KILLPG
10142
/*[clinic input]
10143
os.killpg
10144
10145
    pgid: pid_t
10146
    signal: int
10147
    /
10148
10149
Kill a process group with a signal.
10150
[clinic start generated code]*/
10151
10152
static PyObject *
10153
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10154
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10155
0
{
10156
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10157
0
        return NULL;
10158
0
    }
10159
    /* XXX some man pages make the `pgid` parameter an int, others
10160
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10161
       take the same type. Moreover, pid_t is always at least as wide as
10162
       int (else compilation of this module fails), which is safe. */
10163
0
    if (killpg(pgid, signal) == -1)
10164
0
        return posix_error();
10165
0
    Py_RETURN_NONE;
10166
0
}
10167
#endif /* HAVE_KILLPG */
10168
10169
10170
#ifdef HAVE_PLOCK
10171
#ifdef HAVE_SYS_LOCK_H
10172
#include <sys/lock.h>
10173
#endif
10174
10175
/*[clinic input]
10176
os.plock
10177
    op: int
10178
    /
10179
10180
Lock program segments into memory.");
10181
[clinic start generated code]*/
10182
10183
static PyObject *
10184
os_plock_impl(PyObject *module, int op)
10185
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10186
{
10187
    if (plock(op) == -1)
10188
        return posix_error();
10189
    Py_RETURN_NONE;
10190
}
10191
#endif /* HAVE_PLOCK */
10192
10193
10194
#ifdef HAVE_SETUID
10195
/*[clinic input]
10196
os.setuid
10197
10198
    uid: uid_t
10199
    /
10200
10201
Set the current process's user id.
10202
[clinic start generated code]*/
10203
10204
static PyObject *
10205
os_setuid_impl(PyObject *module, uid_t uid)
10206
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10207
0
{
10208
0
    if (setuid(uid) < 0)
10209
0
        return posix_error();
10210
0
    Py_RETURN_NONE;
10211
0
}
10212
#endif /* HAVE_SETUID */
10213
10214
10215
#ifdef HAVE_SETEUID
10216
/*[clinic input]
10217
os.seteuid
10218
10219
    euid: uid_t
10220
    /
10221
10222
Set the current process's effective user id.
10223
[clinic start generated code]*/
10224
10225
static PyObject *
10226
os_seteuid_impl(PyObject *module, uid_t euid)
10227
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10228
0
{
10229
0
    if (seteuid(euid) < 0)
10230
0
        return posix_error();
10231
0
    Py_RETURN_NONE;
10232
0
}
10233
#endif /* HAVE_SETEUID */
10234
10235
10236
#ifdef HAVE_SETEGID
10237
/*[clinic input]
10238
os.setegid
10239
10240
    egid: gid_t
10241
    /
10242
10243
Set the current process's effective group id.
10244
[clinic start generated code]*/
10245
10246
static PyObject *
10247
os_setegid_impl(PyObject *module, gid_t egid)
10248
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10249
0
{
10250
0
    if (setegid(egid) < 0)
10251
0
        return posix_error();
10252
0
    Py_RETURN_NONE;
10253
0
}
10254
#endif /* HAVE_SETEGID */
10255
10256
10257
#ifdef HAVE_SETREUID
10258
/*[clinic input]
10259
os.setreuid
10260
10261
    ruid: uid_t
10262
    euid: uid_t
10263
    /
10264
10265
Set the current process's real and effective user ids.
10266
[clinic start generated code]*/
10267
10268
static PyObject *
10269
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10270
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10271
0
{
10272
0
    if (setreuid(ruid, euid) < 0) {
10273
0
        return posix_error();
10274
0
    } else {
10275
0
        Py_RETURN_NONE;
10276
0
    }
10277
0
}
10278
#endif /* HAVE_SETREUID */
10279
10280
10281
#ifdef HAVE_SETREGID
10282
/*[clinic input]
10283
os.setregid
10284
10285
    rgid: gid_t
10286
    egid: gid_t
10287
    /
10288
10289
Set the current process's real and effective group ids.
10290
[clinic start generated code]*/
10291
10292
static PyObject *
10293
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10294
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10295
0
{
10296
0
    if (setregid(rgid, egid) < 0)
10297
0
        return posix_error();
10298
0
    Py_RETURN_NONE;
10299
0
}
10300
#endif /* HAVE_SETREGID */
10301
10302
10303
#ifdef HAVE_SETGID
10304
/*[clinic input]
10305
os.setgid
10306
    gid: gid_t
10307
    /
10308
10309
Set the current process's group id.
10310
[clinic start generated code]*/
10311
10312
static PyObject *
10313
os_setgid_impl(PyObject *module, gid_t gid)
10314
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10315
0
{
10316
0
    if (setgid(gid) < 0)
10317
0
        return posix_error();
10318
0
    Py_RETURN_NONE;
10319
0
}
10320
#endif /* HAVE_SETGID */
10321
10322
10323
#ifdef HAVE_SETGROUPS
10324
/*[clinic input]
10325
os.setgroups
10326
10327
    groups: object
10328
    /
10329
10330
Set the groups of the current process to list.
10331
[clinic start generated code]*/
10332
10333
static PyObject *
10334
os_setgroups(PyObject *module, PyObject *groups)
10335
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10336
0
{
10337
0
    if (!PySequence_Check(groups)) {
10338
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10339
0
        return NULL;
10340
0
    }
10341
0
    Py_ssize_t len = PySequence_Size(groups);
10342
0
    if (len < 0) {
10343
0
        return NULL;
10344
0
    }
10345
0
    if (len > MAX_GROUPS) {
10346
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10347
0
        return NULL;
10348
0
    }
10349
10350
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10351
0
    if (grouplist == NULL) {
10352
0
        PyErr_NoMemory();
10353
0
        return NULL;
10354
0
    }
10355
0
    for (Py_ssize_t i = 0; i < len; i++) {
10356
0
        PyObject *elem;
10357
0
        elem = PySequence_GetItem(groups, i);
10358
0
        if (!elem) {
10359
0
            PyMem_Free(grouplist);
10360
0
            return NULL;
10361
0
        }
10362
0
        if (!PyIndex_Check(elem)) {
10363
0
            PyErr_SetString(PyExc_TypeError,
10364
0
                            "groups must be integers");
10365
0
            Py_DECREF(elem);
10366
0
            PyMem_Free(grouplist);
10367
0
            return NULL;
10368
0
        } else {
10369
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10370
0
                Py_DECREF(elem);
10371
0
                PyMem_Free(grouplist);
10372
0
                return NULL;
10373
0
            }
10374
0
        }
10375
0
        Py_DECREF(elem);
10376
0
    }
10377
10378
0
    if (setgroups(len, grouplist) < 0) {
10379
0
        posix_error();
10380
0
        PyMem_Free(grouplist);
10381
0
        return NULL;
10382
0
    }
10383
0
    PyMem_Free(grouplist);
10384
0
    Py_RETURN_NONE;
10385
0
}
10386
#endif /* HAVE_SETGROUPS */
10387
10388
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10389
static PyObject *
10390
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10391
0
{
10392
0
    PyObject *result;
10393
0
    PyObject *struct_rusage;
10394
10395
0
    if (pid == -1)
10396
0
        return posix_error();
10397
10398
    // If wait succeeded but no child was ready to report status, ru will not
10399
    // have been populated.
10400
0
    if (pid == 0) {
10401
0
        memset(ru, 0, sizeof(*ru));
10402
0
    }
10403
10404
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10405
0
    if (struct_rusage == NULL)
10406
0
        return NULL;
10407
10408
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10409
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10410
0
    Py_DECREF(struct_rusage);
10411
0
    if (!result)
10412
0
        return NULL;
10413
10414
0
    int pos = 0;
10415
10416
0
#ifndef doubletime
10417
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10418
0
#endif
10419
10420
0
#define SET_RESULT(CALL)                                     \
10421
0
    do {                                                     \
10422
0
        PyObject *item = (CALL);                             \
10423
0
        if (item == NULL) {                                  \
10424
0
            Py_DECREF(result);                               \
10425
0
            return NULL;                                     \
10426
0
        }                                                    \
10427
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10428
0
    } while(0)
10429
10430
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10431
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10432
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10433
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10434
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10435
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10436
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10437
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10438
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10439
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10440
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10441
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10442
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10443
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10444
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10445
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10446
0
#undef SET_RESULT
10447
10448
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10449
0
}
10450
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10451
10452
10453
#ifdef HAVE_WAIT3
10454
/*[clinic input]
10455
os.wait3
10456
10457
    options: int
10458
Wait for completion of a child process.
10459
10460
Returns a tuple of information about the child process:
10461
  (pid, status, rusage)
10462
[clinic start generated code]*/
10463
10464
static PyObject *
10465
os_wait3_impl(PyObject *module, int options)
10466
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10467
0
{
10468
0
    pid_t pid;
10469
0
    struct rusage ru;
10470
0
    int async_err = 0;
10471
0
    WAIT_TYPE status;
10472
0
    WAIT_STATUS_INT(status) = 0;
10473
10474
0
    do {
10475
0
        Py_BEGIN_ALLOW_THREADS
10476
0
        pid = wait3(&status, options, &ru);
10477
0
        Py_END_ALLOW_THREADS
10478
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10479
0
    if (pid < 0)
10480
0
        return (!async_err) ? posix_error() : NULL;
10481
10482
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10483
0
}
10484
#endif /* HAVE_WAIT3 */
10485
10486
10487
#ifdef HAVE_WAIT4
10488
/*[clinic input]
10489
10490
os.wait4
10491
10492
    pid: pid_t
10493
    options: int
10494
10495
Wait for completion of a specific child process.
10496
10497
Returns a tuple of information about the child process:
10498
  (pid, status, rusage)
10499
[clinic start generated code]*/
10500
10501
static PyObject *
10502
os_wait4_impl(PyObject *module, pid_t pid, int options)
10503
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10504
0
{
10505
0
    pid_t res;
10506
0
    struct rusage ru;
10507
0
    int async_err = 0;
10508
0
    WAIT_TYPE status;
10509
0
    WAIT_STATUS_INT(status) = 0;
10510
10511
0
    do {
10512
0
        Py_BEGIN_ALLOW_THREADS
10513
0
        res = wait4(pid, &status, options, &ru);
10514
0
        Py_END_ALLOW_THREADS
10515
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10516
0
    if (res < 0)
10517
0
        return (!async_err) ? posix_error() : NULL;
10518
10519
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10520
0
}
10521
#endif /* HAVE_WAIT4 */
10522
10523
10524
#if defined(HAVE_WAITID)
10525
/*[clinic input]
10526
os.waitid
10527
10528
    idtype: idtype_t
10529
        Must be one of be P_PID, P_PGID or P_ALL.
10530
    id: id_t
10531
        The id to wait on.
10532
    options: int
10533
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10534
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10535
    /
10536
10537
Returns the result of waiting for a process or processes.
10538
10539
Returns either waitid_result or None if WNOHANG is specified and there are
10540
no children in a waitable state.
10541
[clinic start generated code]*/
10542
10543
static PyObject *
10544
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10545
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10546
0
{
10547
0
    PyObject *result;
10548
0
    int res;
10549
0
    int async_err = 0;
10550
0
    siginfo_t si;
10551
0
    si.si_pid = 0;
10552
10553
0
    do {
10554
0
        Py_BEGIN_ALLOW_THREADS
10555
0
        res = waitid(idtype, id, &si, options);
10556
0
        Py_END_ALLOW_THREADS
10557
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10558
0
    if (res < 0)
10559
0
        return (!async_err) ? posix_error() : NULL;
10560
10561
0
    if (si.si_pid == 0)
10562
0
        Py_RETURN_NONE;
10563
10564
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10565
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10566
0
    if (!result)
10567
0
        return NULL;
10568
10569
0
    int pos = 0;
10570
10571
0
#define SET_RESULT(CALL)                                     \
10572
0
    do {                                                     \
10573
0
        PyObject *item = (CALL);                             \
10574
0
        if (item == NULL) {                                  \
10575
0
            Py_DECREF(result);                               \
10576
0
            return NULL;                                     \
10577
0
        }                                                    \
10578
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10579
0
    } while(0)
10580
10581
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10582
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10583
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10584
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10585
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10586
10587
0
#undef SET_RESULT
10588
10589
0
    return result;
10590
0
}
10591
#endif /* defined(HAVE_WAITID) */
10592
10593
10594
#if defined(HAVE_WAITPID)
10595
/*[clinic input]
10596
os.waitpid
10597
    pid: pid_t
10598
    options: int
10599
    /
10600
10601
Wait for completion of a given child process.
10602
10603
Returns a tuple of information regarding the child process:
10604
    (pid, status)
10605
10606
The options argument is ignored on Windows.
10607
[clinic start generated code]*/
10608
10609
static PyObject *
10610
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10611
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10612
0
{
10613
0
    pid_t res;
10614
0
    int async_err = 0;
10615
0
    WAIT_TYPE status;
10616
0
    WAIT_STATUS_INT(status) = 0;
10617
10618
0
    do {
10619
0
        Py_BEGIN_ALLOW_THREADS
10620
0
        res = waitpid(pid, &status, options);
10621
0
        Py_END_ALLOW_THREADS
10622
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10623
0
    if (res < 0)
10624
0
        return (!async_err) ? posix_error() : NULL;
10625
10626
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10627
0
}
10628
#elif defined(HAVE_CWAIT)
10629
/* MS C has a variant of waitpid() that's usable for most purposes. */
10630
/*[clinic input]
10631
os.waitpid
10632
    pid: intptr_t
10633
    options: int
10634
    /
10635
10636
Wait for completion of a given process.
10637
10638
Returns a tuple of information regarding the process:
10639
    (pid, status << 8)
10640
10641
The options argument is ignored on Windows.
10642
[clinic start generated code]*/
10643
10644
static PyObject *
10645
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10646
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10647
{
10648
    int status;
10649
    intptr_t res;
10650
    int async_err = 0;
10651
10652
    do {
10653
        Py_BEGIN_ALLOW_THREADS
10654
        _Py_BEGIN_SUPPRESS_IPH
10655
        res = _cwait(&status, pid, options);
10656
        _Py_END_SUPPRESS_IPH
10657
        Py_END_ALLOW_THREADS
10658
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10659
    if (res < 0)
10660
        return (!async_err) ? posix_error() : NULL;
10661
10662
    unsigned long long ustatus = (unsigned int)status;
10663
10664
    /* shift the status left a byte so this is more like the POSIX waitpid */
10665
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10666
}
10667
#endif
10668
10669
10670
#ifdef HAVE_WAIT
10671
/*[clinic input]
10672
os.wait
10673
10674
Wait for completion of a child process.
10675
10676
Returns a tuple of information about the child process:
10677
    (pid, status)
10678
[clinic start generated code]*/
10679
10680
static PyObject *
10681
os_wait_impl(PyObject *module)
10682
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10683
0
{
10684
0
    pid_t pid;
10685
0
    int async_err = 0;
10686
0
    WAIT_TYPE status;
10687
0
    WAIT_STATUS_INT(status) = 0;
10688
10689
0
    do {
10690
0
        Py_BEGIN_ALLOW_THREADS
10691
0
        pid = wait(&status);
10692
0
        Py_END_ALLOW_THREADS
10693
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10694
0
    if (pid < 0)
10695
0
        return (!async_err) ? posix_error() : NULL;
10696
10697
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10698
0
}
10699
#endif /* HAVE_WAIT */
10700
10701
10702
// This system call always crashes on older Android versions.
10703
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10704
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10705
/*[clinic input]
10706
os.pidfd_open
10707
  pid: pid_t
10708
  flags: unsigned_int = 0
10709
10710
Return a file descriptor referring to the process *pid*.
10711
10712
The descriptor can be used to perform process management without races and
10713
signals.
10714
[clinic start generated code]*/
10715
10716
static PyObject *
10717
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10718
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10719
0
{
10720
0
    int fd = syscall(__NR_pidfd_open, pid, flags);
10721
0
    if (fd < 0) {
10722
0
        return posix_error();
10723
0
    }
10724
0
    return PyLong_FromLong(fd);
10725
0
}
10726
#endif
10727
10728
10729
#ifdef HAVE_SETNS
10730
/*[clinic input]
10731
os.setns
10732
  fd: fildes
10733
    A file descriptor to a namespace.
10734
  nstype: int = 0
10735
    Type of namespace.
10736
10737
Move the calling thread into different namespaces.
10738
[clinic start generated code]*/
10739
10740
static PyObject *
10741
os_setns_impl(PyObject *module, int fd, int nstype)
10742
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10743
0
{
10744
0
    int res;
10745
10746
0
    Py_BEGIN_ALLOW_THREADS
10747
0
    res = setns(fd, nstype);
10748
0
    Py_END_ALLOW_THREADS
10749
10750
0
    if (res != 0) {
10751
0
        return posix_error();
10752
0
    }
10753
10754
0
    Py_RETURN_NONE;
10755
0
}
10756
#endif
10757
10758
10759
#ifdef HAVE_UNSHARE
10760
/*[clinic input]
10761
os.unshare
10762
  flags: int
10763
    Namespaces to be unshared.
10764
10765
Disassociate parts of a process (or thread) execution context.
10766
[clinic start generated code]*/
10767
10768
static PyObject *
10769
os_unshare_impl(PyObject *module, int flags)
10770
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10771
0
{
10772
0
    int res;
10773
10774
0
    Py_BEGIN_ALLOW_THREADS
10775
0
    res = unshare(flags);
10776
0
    Py_END_ALLOW_THREADS
10777
10778
0
    if (res != 0) {
10779
0
        return posix_error();
10780
0
    }
10781
10782
0
    Py_RETURN_NONE;
10783
0
}
10784
#endif
10785
10786
10787
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10788
/*[clinic input]
10789
os.readlink
10790
10791
    path: path_t
10792
    *
10793
    dir_fd: dir_fd(requires='readlinkat') = None
10794
10795
Return a string representing the path to which the symbolic link points.
10796
10797
If dir_fd is not None, it should be a file descriptor open to a directory,
10798
and path should be relative; path will then be relative to that directory.
10799
10800
dir_fd may not be implemented on your platform.  If it is unavailable,
10801
using it will raise a NotImplementedError.
10802
[clinic start generated code]*/
10803
10804
static PyObject *
10805
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10806
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10807
0
{
10808
0
#if defined(HAVE_READLINK)
10809
0
    char buffer[MAXPATHLEN+1];
10810
0
    ssize_t length;
10811
0
#ifdef HAVE_READLINKAT
10812
0
    int readlinkat_unavailable = 0;
10813
0
#endif
10814
10815
0
    Py_BEGIN_ALLOW_THREADS
10816
0
#ifdef HAVE_READLINKAT
10817
0
    if (dir_fd != DEFAULT_DIR_FD) {
10818
0
        if (HAVE_READLINKAT_RUNTIME) {
10819
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10820
0
        } else {
10821
0
            readlinkat_unavailable = 1;
10822
0
        }
10823
0
    } else
10824
0
#endif
10825
0
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10826
0
    Py_END_ALLOW_THREADS
10827
10828
0
#ifdef HAVE_READLINKAT
10829
0
    if (readlinkat_unavailable) {
10830
0
        argument_unavailable_error(NULL, "dir_fd");
10831
0
        return NULL;
10832
0
    }
10833
0
#endif
10834
10835
0
    if (length < 0) {
10836
0
        return path_error(path);
10837
0
    }
10838
0
    buffer[length] = '\0';
10839
10840
0
    if (PyUnicode_Check(path->object))
10841
0
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10842
0
    else
10843
0
        return PyBytes_FromStringAndSize(buffer, length);
10844
#elif defined(MS_WINDOWS)
10845
    DWORD n_bytes_returned;
10846
    DWORD io_result = 0;
10847
    HANDLE reparse_point_handle;
10848
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10849
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10850
    PyObject *result = NULL;
10851
10852
    /* First get a handle to the reparse point */
10853
    Py_BEGIN_ALLOW_THREADS
10854
    reparse_point_handle = CreateFileW(
10855
        path->wide,
10856
        0,
10857
        0,
10858
        0,
10859
        OPEN_EXISTING,
10860
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10861
        0);
10862
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10863
        /* New call DeviceIoControl to read the reparse point */
10864
        io_result = DeviceIoControl(
10865
            reparse_point_handle,
10866
            FSCTL_GET_REPARSE_POINT,
10867
            0, 0, /* in buffer */
10868
            target_buffer, sizeof(target_buffer),
10869
            &n_bytes_returned,
10870
            0 /* we're not using OVERLAPPED_IO */
10871
            );
10872
        CloseHandle(reparse_point_handle);
10873
    }
10874
    Py_END_ALLOW_THREADS
10875
10876
    if (io_result == 0) {
10877
        return path_error(path);
10878
    }
10879
10880
    wchar_t *name = NULL;
10881
    Py_ssize_t nameLen = 0;
10882
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10883
    {
10884
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10885
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10886
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10887
    }
10888
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10889
    {
10890
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10891
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10892
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10893
    }
10894
    else
10895
    {
10896
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10897
    }
10898
    if (name) {
10899
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10900
            /* Our buffer is mutable, so this is okay */
10901
            name[1] = L'\\';
10902
        }
10903
        result = PyUnicode_FromWideChar(name, nameLen);
10904
        if (result && PyBytes_Check(path->object)) {
10905
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10906
        }
10907
    }
10908
    return result;
10909
#endif
10910
0
}
10911
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10912
10913
#if defined(MS_WINDOWS)
10914
10915
/* Remove the last portion of the path - return 0 on success */
10916
static int
10917
_dirnameW(WCHAR *path)
10918
{
10919
    WCHAR *ptr;
10920
    size_t length = wcsnlen_s(path, MAX_PATH);
10921
    if (length == MAX_PATH) {
10922
        return -1;
10923
    }
10924
10925
    /* walk the path from the end until a backslash is encountered */
10926
    for(ptr = path + length; ptr != path; ptr--) {
10927
        if (*ptr == L'\\' || *ptr == L'/') {
10928
            break;
10929
        }
10930
    }
10931
    *ptr = 0;
10932
    return 0;
10933
}
10934
10935
#endif
10936
10937
#ifdef HAVE_SYMLINK
10938
10939
#if defined(MS_WINDOWS)
10940
10941
/* Is this path absolute? */
10942
static int
10943
_is_absW(const WCHAR *path)
10944
{
10945
    return path[0] == L'\\' || path[0] == L'/' ||
10946
        (path[0] && path[1] == L':');
10947
}
10948
10949
/* join root and rest with a backslash - return 0 on success */
10950
static int
10951
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10952
{
10953
    if (_is_absW(rest)) {
10954
        return wcscpy_s(dest_path, MAX_PATH, rest);
10955
    }
10956
10957
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
10958
        return -1;
10959
    }
10960
10961
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
10962
        return -1;
10963
    }
10964
10965
    return wcscat_s(dest_path, MAX_PATH, rest);
10966
}
10967
10968
/* Return True if the path at src relative to dest is a directory */
10969
static int
10970
_check_dirW(LPCWSTR src, LPCWSTR dest)
10971
{
10972
    WIN32_FILE_ATTRIBUTE_DATA src_info;
10973
    WCHAR dest_parent[MAX_PATH];
10974
    WCHAR src_resolved[MAX_PATH] = L"";
10975
10976
    /* dest_parent = os.path.dirname(dest) */
10977
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
10978
        _dirnameW(dest_parent)) {
10979
        return 0;
10980
    }
10981
    /* src_resolved = os.path.join(dest_parent, src) */
10982
    if (_joinW(src_resolved, dest_parent, src)) {
10983
        return 0;
10984
    }
10985
    return (
10986
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
10987
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
10988
    );
10989
}
10990
#endif
10991
10992
10993
/*[clinic input]
10994
os.symlink
10995
    src: path_t
10996
    dst: path_t
10997
    target_is_directory: bool = False
10998
    *
10999
    dir_fd: dir_fd(requires='symlinkat')=None
11000
11001
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
11002
11003
Create a symbolic link pointing to src named dst.
11004
11005
target_is_directory is required on Windows if the target is to be
11006
  interpreted as a directory.  (On Windows, symlink requires
11007
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
11008
  target_is_directory is ignored on non-Windows platforms.
11009
11010
If dir_fd is not None, it should be a file descriptor open to a directory,
11011
  and path should be relative; path will then be relative to that directory.
11012
dir_fd may not be implemented on your platform.
11013
  If it is unavailable, using it will raise a NotImplementedError.
11014
11015
[clinic start generated code]*/
11016
11017
static PyObject *
11018
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11019
                int target_is_directory, int dir_fd)
11020
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
11021
0
{
11022
#ifdef MS_WINDOWS
11023
    DWORD result;
11024
    DWORD flags = 0;
11025
11026
    /* Assumed true, set to false if detected to not be available. */
11027
    static int windows_has_symlink_unprivileged_flag = TRUE;
11028
#else
11029
0
    int result;
11030
0
#ifdef HAVE_SYMLINKAT
11031
0
    int symlinkat_unavailable = 0;
11032
0
#endif
11033
0
#endif
11034
11035
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11036
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11037
0
        return NULL;
11038
0
    }
11039
11040
#ifdef MS_WINDOWS
11041
11042
    if (windows_has_symlink_unprivileged_flag) {
11043
        /* Allow non-admin symlinks if system allows it. */
11044
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11045
    }
11046
11047
    Py_BEGIN_ALLOW_THREADS
11048
    _Py_BEGIN_SUPPRESS_IPH
11049
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11050
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11051
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11052
    }
11053
11054
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11055
    _Py_END_SUPPRESS_IPH
11056
    Py_END_ALLOW_THREADS
11057
11058
    if (windows_has_symlink_unprivileged_flag && !result &&
11059
        ERROR_INVALID_PARAMETER == GetLastError()) {
11060
11061
        Py_BEGIN_ALLOW_THREADS
11062
        _Py_BEGIN_SUPPRESS_IPH
11063
        /* This error might be caused by
11064
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11065
        Try again, and update windows_has_symlink_unprivileged_flag if we
11066
        are successful this time.
11067
11068
        NOTE: There is a risk of a race condition here if there are other
11069
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11070
        another process (or thread) changes that condition in between our
11071
        calls to CreateSymbolicLink.
11072
        */
11073
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11074
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11075
        _Py_END_SUPPRESS_IPH
11076
        Py_END_ALLOW_THREADS
11077
11078
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11079
            windows_has_symlink_unprivileged_flag = FALSE;
11080
        }
11081
    }
11082
11083
    if (!result)
11084
        return path_error2(src, dst);
11085
11086
#else
11087
11088
0
    Py_BEGIN_ALLOW_THREADS
11089
0
#ifdef HAVE_SYMLINKAT
11090
0
    if (dir_fd != DEFAULT_DIR_FD) {
11091
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11092
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11093
0
        } else {
11094
0
            symlinkat_unavailable = 1;
11095
0
        }
11096
0
    } else
11097
0
#endif
11098
0
        result = symlink(src->narrow, dst->narrow);
11099
0
    Py_END_ALLOW_THREADS
11100
11101
0
#ifdef HAVE_SYMLINKAT
11102
0
    if (symlinkat_unavailable) {
11103
0
          argument_unavailable_error(NULL, "dir_fd");
11104
0
          return NULL;
11105
0
    }
11106
0
#endif
11107
11108
0
    if (result)
11109
0
        return path_error2(src, dst);
11110
0
#endif
11111
11112
0
    Py_RETURN_NONE;
11113
0
}
11114
#endif /* HAVE_SYMLINK */
11115
11116
11117
static PyStructSequence_Field times_result_fields[] = {
11118
    {"user",    "user time"},
11119
    {"system",   "system time"},
11120
    {"children_user",    "user time of children"},
11121
    {"children_system",    "system time of children"},
11122
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11123
    {NULL}
11124
};
11125
11126
PyDoc_STRVAR(times_result__doc__,
11127
"times_result: Result from os.times().\n\n\
11128
This object may be accessed either as a tuple of\n\
11129
  (user, system, children_user, children_system, elapsed),\n\
11130
or via the attributes user, system, children_user, children_system,\n\
11131
and elapsed.\n\
11132
\n\
11133
See os.times for more information.");
11134
11135
static PyStructSequence_Desc times_result_desc = {
11136
    MODNAME ".times_result", /* name */
11137
    times_result__doc__, /* doc */
11138
    times_result_fields,
11139
    5
11140
};
11141
11142
static PyObject *
11143
build_times_result(PyObject *module, double user, double system,
11144
    double children_user, double children_system,
11145
    double elapsed)
11146
0
{
11147
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11148
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11149
0
    if (value == NULL)
11150
0
        return NULL;
11151
11152
0
#define SET(i, field) \
11153
0
    { \
11154
0
    PyObject *o = PyFloat_FromDouble(field); \
11155
0
    if (!o) { \
11156
0
        Py_DECREF(value); \
11157
0
        return NULL; \
11158
0
    } \
11159
0
    PyStructSequence_SET_ITEM(value, i, o); \
11160
0
    } \
11161
0
11162
0
    SET(0, user);
11163
0
    SET(1, system);
11164
0
    SET(2, children_user);
11165
0
    SET(3, children_system);
11166
0
    SET(4, elapsed);
11167
11168
0
#undef SET
11169
11170
0
    return value;
11171
0
}
11172
11173
11174
/*[clinic input]
11175
os.times
11176
11177
Return a collection containing process timing information.
11178
11179
The object returned behaves like a named tuple with these fields:
11180
  (utime, stime, cutime, cstime, elapsed_time)
11181
All fields are floating-point numbers.
11182
[clinic start generated code]*/
11183
11184
static PyObject *
11185
os_times_impl(PyObject *module)
11186
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11187
0
{
11188
#ifdef MS_WINDOWS
11189
    FILETIME create, exit, kernel, user;
11190
    HANDLE hProc;
11191
    hProc = GetCurrentProcess();
11192
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11193
    /* The fields of a FILETIME structure are the hi and lo part
11194
       of a 64-bit value expressed in 100 nanosecond units.
11195
       1e7 is one second in such units; 1e-7 the inverse.
11196
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11197
    */
11198
    return build_times_result(module,
11199
        (double)(user.dwHighDateTime*429.4967296 +
11200
                 user.dwLowDateTime*1e-7),
11201
        (double)(kernel.dwHighDateTime*429.4967296 +
11202
                 kernel.dwLowDateTime*1e-7),
11203
        (double)0,
11204
        (double)0,
11205
        (double)0);
11206
#else /* MS_WINDOWS */
11207
0
    _posixstate *state = get_posix_state(module);
11208
0
    long ticks_per_second = state->ticks_per_second;
11209
11210
0
    struct tms process;
11211
0
    clock_t elapsed;
11212
0
    errno = 0;
11213
0
    elapsed = times(&process);
11214
0
    if (elapsed == (clock_t) -1) {
11215
0
        return posix_error();
11216
0
    }
11217
11218
0
    return build_times_result(module,
11219
0
        (double)process.tms_utime / ticks_per_second,
11220
0
        (double)process.tms_stime / ticks_per_second,
11221
0
        (double)process.tms_cutime / ticks_per_second,
11222
0
        (double)process.tms_cstime / ticks_per_second,
11223
0
        (double)elapsed / ticks_per_second);
11224
0
#endif /* MS_WINDOWS */
11225
0
}
11226
11227
11228
#if defined(HAVE_TIMERFD_CREATE)
11229
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11230
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11231
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11232
11233
static PyObject *
11234
build_itimerspec(const struct itimerspec* curr_value)
11235
0
{
11236
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11237
0
                                                          curr_value->it_value.tv_nsec);
11238
0
    PyObject *value = PyFloat_FromDouble(_value);
11239
0
    if (value == NULL) {
11240
0
        return NULL;
11241
0
    }
11242
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11243
0
                                                   curr_value->it_interval.tv_nsec);
11244
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11245
0
    if (interval == NULL) {
11246
0
        Py_DECREF(value);
11247
0
        return NULL;
11248
0
    }
11249
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
11250
0
    Py_DECREF(interval);
11251
0
    Py_DECREF(value);
11252
0
    return tuple;
11253
0
}
11254
11255
static PyObject *
11256
build_itimerspec_ns(const struct itimerspec* curr_value)
11257
0
{
11258
0
    PyTime_t value, interval;
11259
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11260
0
        return NULL;
11261
0
    }
11262
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11263
0
        return NULL;
11264
0
    }
11265
0
    return Py_BuildValue("LL", value, interval);
11266
0
}
11267
11268
/*[clinic input]
11269
os.timerfd_create
11270
11271
    clockid: int
11272
        A valid clock ID constant as timer file descriptor.
11273
11274
        time.CLOCK_REALTIME
11275
        time.CLOCK_MONOTONIC
11276
        time.CLOCK_BOOTTIME
11277
    /
11278
    *
11279
    flags: int = 0
11280
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11281
11282
        os.TFD_NONBLOCK
11283
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11284
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11285
11286
        os.TFD_CLOEXEC
11287
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11288
11289
Create and return a timer file descriptor.
11290
[clinic start generated code]*/
11291
11292
static PyObject *
11293
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11294
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11295
11296
0
{
11297
0
    int fd;
11298
0
    Py_BEGIN_ALLOW_THREADS
11299
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11300
0
    fd = timerfd_create(clockid, flags);
11301
0
    Py_END_ALLOW_THREADS
11302
0
    if (fd == -1) {
11303
0
        return PyErr_SetFromErrno(PyExc_OSError);
11304
0
    }
11305
0
    return PyLong_FromLong(fd);
11306
0
}
11307
11308
/*[clinic input]
11309
os.timerfd_settime
11310
11311
    fd: fildes
11312
        A timer file descriptor.
11313
    /
11314
    *
11315
    flags: int = 0
11316
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11317
    initial as initial_double: double = 0.0
11318
        The initial expiration time, in seconds.
11319
    interval as interval_double: double = 0.0
11320
        The timer's interval, in seconds.
11321
11322
Alter a timer file descriptor's internal timer in seconds.
11323
[clinic start generated code]*/
11324
11325
static PyObject *
11326
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11327
                        double initial_double, double interval_double)
11328
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11329
0
{
11330
0
    PyTime_t initial, interval;
11331
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11332
0
                                  &initial) < 0) {
11333
0
        return NULL;
11334
0
    }
11335
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11336
0
                                  &interval) < 0) {
11337
0
        return NULL;
11338
0
    }
11339
11340
0
    struct itimerspec new_value, old_value;
11341
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11342
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11343
0
        return NULL;
11344
0
    }
11345
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11346
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11347
0
        return NULL;
11348
0
    }
11349
11350
0
    int result;
11351
0
    Py_BEGIN_ALLOW_THREADS
11352
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11353
0
    Py_END_ALLOW_THREADS
11354
0
    if (result == -1) {
11355
0
        return PyErr_SetFromErrno(PyExc_OSError);
11356
0
    }
11357
0
    return build_itimerspec(&old_value);
11358
0
}
11359
11360
11361
/*[clinic input]
11362
os.timerfd_settime_ns
11363
11364
    fd: fildes
11365
        A timer file descriptor.
11366
    /
11367
    *
11368
    flags: int = 0
11369
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11370
    initial: long_long = 0
11371
        initial expiration timing in seconds.
11372
    interval: long_long = 0
11373
        interval for the timer in seconds.
11374
11375
Alter a timer file descriptor's internal timer in nanoseconds.
11376
[clinic start generated code]*/
11377
11378
static PyObject *
11379
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11380
                           long long initial, long long interval)
11381
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11382
0
{
11383
0
    struct itimerspec new_value;
11384
0
    struct itimerspec old_value;
11385
0
    int result;
11386
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11387
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11388
0
        return NULL;
11389
0
    }
11390
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11391
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11392
0
        return NULL;
11393
0
    }
11394
0
    Py_BEGIN_ALLOW_THREADS
11395
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11396
0
    Py_END_ALLOW_THREADS
11397
0
    if (result == -1) {
11398
0
        return PyErr_SetFromErrno(PyExc_OSError);
11399
0
    }
11400
0
    return build_itimerspec_ns(&old_value);
11401
0
}
11402
11403
/*[clinic input]
11404
@permit_long_summary
11405
os.timerfd_gettime
11406
11407
    fd: fildes
11408
        A timer file descriptor.
11409
    /
11410
11411
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11412
[clinic start generated code]*/
11413
11414
static PyObject *
11415
os_timerfd_gettime_impl(PyObject *module, int fd)
11416
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11417
0
{
11418
0
    struct itimerspec curr_value;
11419
0
    int result;
11420
0
    Py_BEGIN_ALLOW_THREADS
11421
0
    result = timerfd_gettime(fd, &curr_value);
11422
0
    Py_END_ALLOW_THREADS
11423
0
    if (result == -1) {
11424
0
        return PyErr_SetFromErrno(PyExc_OSError);
11425
0
    }
11426
0
    return build_itimerspec(&curr_value);
11427
0
}
11428
11429
11430
/*[clinic input]
11431
@permit_long_summary
11432
os.timerfd_gettime_ns
11433
11434
    fd: fildes
11435
        A timer file descriptor.
11436
    /
11437
11438
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11439
[clinic start generated code]*/
11440
11441
static PyObject *
11442
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11443
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11444
0
{
11445
0
    struct itimerspec curr_value;
11446
0
    int result;
11447
0
    Py_BEGIN_ALLOW_THREADS
11448
0
    result = timerfd_gettime(fd, &curr_value);
11449
0
    Py_END_ALLOW_THREADS
11450
0
    if (result == -1) {
11451
0
        return PyErr_SetFromErrno(PyExc_OSError);
11452
0
    }
11453
0
    return build_itimerspec_ns(&curr_value);
11454
0
}
11455
11456
#undef ONE_SECOND_IN_NS
11457
#undef EXTRACT_NSEC
11458
11459
#endif  /* HAVE_TIMERFD_CREATE */
11460
11461
#ifdef HAVE_GETSID
11462
/*[clinic input]
11463
os.getsid
11464
11465
    pid: pid_t
11466
    /
11467
11468
Call the system call getsid(pid) and return the result.
11469
[clinic start generated code]*/
11470
11471
static PyObject *
11472
os_getsid_impl(PyObject *module, pid_t pid)
11473
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11474
0
{
11475
0
    int sid;
11476
0
    sid = getsid(pid);
11477
0
    if (sid < 0)
11478
0
        return posix_error();
11479
0
    return PyLong_FromLong((long)sid);
11480
0
}
11481
#endif /* HAVE_GETSID */
11482
11483
11484
#ifdef HAVE_SETSID
11485
/*[clinic input]
11486
os.setsid
11487
11488
Call the system call setsid().
11489
[clinic start generated code]*/
11490
11491
static PyObject *
11492
os_setsid_impl(PyObject *module)
11493
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11494
0
{
11495
0
    if (setsid() < 0)
11496
0
        return posix_error();
11497
0
    Py_RETURN_NONE;
11498
0
}
11499
#endif /* HAVE_SETSID */
11500
11501
11502
#ifdef HAVE_SETPGID
11503
/*[clinic input]
11504
os.setpgid
11505
11506
    pid: pid_t
11507
    pgrp: pid_t
11508
    /
11509
11510
Call the system call setpgid(pid, pgrp).
11511
[clinic start generated code]*/
11512
11513
static PyObject *
11514
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11515
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11516
0
{
11517
0
    if (setpgid(pid, pgrp) < 0)
11518
0
        return posix_error();
11519
0
    Py_RETURN_NONE;
11520
0
}
11521
#endif /* HAVE_SETPGID */
11522
11523
11524
#ifdef HAVE_TCGETPGRP
11525
/*[clinic input]
11526
os.tcgetpgrp
11527
11528
    fd: int
11529
    /
11530
11531
Return the process group associated with the terminal specified by fd.
11532
[clinic start generated code]*/
11533
11534
static PyObject *
11535
os_tcgetpgrp_impl(PyObject *module, int fd)
11536
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11537
0
{
11538
0
    pid_t pgid = tcgetpgrp(fd);
11539
0
    if (pgid < 0)
11540
0
        return posix_error();
11541
0
    return PyLong_FromPid(pgid);
11542
0
}
11543
#endif /* HAVE_TCGETPGRP */
11544
11545
11546
#ifdef HAVE_TCSETPGRP
11547
/*[clinic input]
11548
os.tcsetpgrp
11549
11550
    fd: int
11551
    pgid: pid_t
11552
    /
11553
11554
Set the process group associated with the terminal specified by fd.
11555
[clinic start generated code]*/
11556
11557
static PyObject *
11558
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11559
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11560
0
{
11561
0
    if (tcsetpgrp(fd, pgid) < 0)
11562
0
        return posix_error();
11563
0
    Py_RETURN_NONE;
11564
0
}
11565
#endif /* HAVE_TCSETPGRP */
11566
11567
/* Functions acting on file descriptors */
11568
11569
#ifdef O_CLOEXEC
11570
extern int _Py_open_cloexec_works;
11571
#endif
11572
11573
11574
/*[clinic input]
11575
os.open -> int
11576
    path: path_t
11577
    flags: int
11578
    mode: int = 0o777
11579
    *
11580
    dir_fd: dir_fd(requires='openat') = None
11581
11582
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11583
11584
Open a file for low level IO.  Returns a file descriptor (integer).
11585
11586
If dir_fd is not None, it should be a file descriptor open to a directory,
11587
  and path should be relative; path will then be relative to that directory.
11588
dir_fd may not be implemented on your platform.
11589
  If it is unavailable, using it will raise a NotImplementedError.
11590
[clinic start generated code]*/
11591
11592
static int
11593
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11594
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11595
241
{
11596
241
    int fd;
11597
241
    int async_err = 0;
11598
241
#ifdef HAVE_OPENAT
11599
241
    int openat_unavailable = 0;
11600
241
#endif
11601
11602
241
#ifdef O_CLOEXEC
11603
241
    int *atomic_flag_works = &_Py_open_cloexec_works;
11604
#elif !defined(MS_WINDOWS)
11605
    int *atomic_flag_works = NULL;
11606
#endif
11607
11608
#ifdef MS_WINDOWS
11609
    flags |= O_NOINHERIT;
11610
#elif defined(O_CLOEXEC)
11611
241
    flags |= O_CLOEXEC;
11612
241
#endif
11613
11614
241
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11615
0
        return -1;
11616
0
    }
11617
11618
241
    _Py_BEGIN_SUPPRESS_IPH
11619
241
    do {
11620
241
        Py_BEGIN_ALLOW_THREADS
11621
#ifdef MS_WINDOWS
11622
        fd = _wopen(path->wide, flags, mode);
11623
#else
11624
241
#ifdef HAVE_OPENAT
11625
241
        if (dir_fd != DEFAULT_DIR_FD) {
11626
0
            if (HAVE_OPENAT_RUNTIME) {
11627
0
                fd = openat(dir_fd, path->narrow, flags, mode);
11628
11629
0
            } else {
11630
0
                openat_unavailable = 1;
11631
0
                fd = -1;
11632
0
            }
11633
0
        } else
11634
241
#endif /* HAVE_OPENAT */
11635
241
            fd = open(path->narrow, flags, mode);
11636
241
#endif /* !MS_WINDOWS */
11637
241
        Py_END_ALLOW_THREADS
11638
241
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11639
241
    _Py_END_SUPPRESS_IPH
11640
11641
241
#ifdef HAVE_OPENAT
11642
241
    if (openat_unavailable) {
11643
0
        argument_unavailable_error(NULL, "dir_fd");
11644
0
        return -1;
11645
0
    }
11646
241
#endif
11647
11648
241
    if (fd < 0) {
11649
0
        if (!async_err)
11650
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11651
0
        return -1;
11652
0
    }
11653
11654
241
#ifndef MS_WINDOWS
11655
241
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11656
0
        close(fd);
11657
0
        return -1;
11658
0
    }
11659
241
#endif
11660
11661
241
    return fd;
11662
241
}
11663
11664
11665
/*[clinic input]
11666
os.close
11667
11668
    fd: int
11669
11670
Close a file descriptor.
11671
[clinic start generated code]*/
11672
11673
static PyObject *
11674
os_close_impl(PyObject *module, int fd)
11675
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11676
0
{
11677
0
    int res;
11678
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11679
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11680
     * for more details.
11681
     */
11682
0
    Py_BEGIN_ALLOW_THREADS
11683
0
    _Py_BEGIN_SUPPRESS_IPH
11684
0
    res = close(fd);
11685
0
    _Py_END_SUPPRESS_IPH
11686
0
    Py_END_ALLOW_THREADS
11687
0
    if (res < 0)
11688
0
        return posix_error();
11689
0
    Py_RETURN_NONE;
11690
0
}
11691
11692
/*[clinic input]
11693
os.closerange
11694
11695
    fd_low: int
11696
    fd_high: int
11697
    /
11698
11699
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11700
[clinic start generated code]*/
11701
11702
static PyObject *
11703
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11704
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11705
0
{
11706
0
    Py_BEGIN_ALLOW_THREADS
11707
0
    _Py_closerange(fd_low, fd_high - 1);
11708
0
    Py_END_ALLOW_THREADS
11709
0
    Py_RETURN_NONE;
11710
0
}
11711
11712
11713
/*[clinic input]
11714
os.dup -> int
11715
11716
    fd: int
11717
    /
11718
11719
Return a duplicate of a file descriptor.
11720
[clinic start generated code]*/
11721
11722
static int
11723
os_dup_impl(PyObject *module, int fd)
11724
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11725
0
{
11726
0
    return _Py_dup(fd);
11727
0
}
11728
11729
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11730
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11731
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11732
/*[clinic input]
11733
os.dup2 -> int
11734
    fd: int
11735
    fd2: int
11736
    inheritable: bool=True
11737
11738
Duplicate file descriptor.
11739
[clinic start generated code]*/
11740
11741
static int
11742
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11743
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11744
0
{
11745
0
    int res = 0;
11746
0
#if defined(HAVE_DUP3) && \
11747
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11748
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11749
0
    static int dup3_works = -1;
11750
0
#endif
11751
11752
    /* dup2() can fail with EINTR if the target FD is already open, because it
11753
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11754
     * upon close(), and therefore below.
11755
     */
11756
#ifdef MS_WINDOWS
11757
    Py_BEGIN_ALLOW_THREADS
11758
    _Py_BEGIN_SUPPRESS_IPH
11759
    res = dup2(fd, fd2);
11760
    _Py_END_SUPPRESS_IPH
11761
    Py_END_ALLOW_THREADS
11762
    if (res < 0) {
11763
        posix_error();
11764
        return -1;
11765
    }
11766
    res = fd2; // msvcrt dup2 returns 0 on success.
11767
11768
    /* Character files like console cannot be make non-inheritable */
11769
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11770
        close(fd2);
11771
        return -1;
11772
    }
11773
11774
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11775
    Py_BEGIN_ALLOW_THREADS
11776
    if (!inheritable)
11777
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11778
    else
11779
        res = dup2(fd, fd2);
11780
    Py_END_ALLOW_THREADS
11781
    if (res < 0) {
11782
        posix_error();
11783
        return -1;
11784
    }
11785
11786
#else
11787
11788
0
#ifdef HAVE_DUP3
11789
0
    if (!inheritable && dup3_works != 0) {
11790
0
        Py_BEGIN_ALLOW_THREADS
11791
0
        res = dup3(fd, fd2, O_CLOEXEC);
11792
0
        Py_END_ALLOW_THREADS
11793
0
        if (res < 0) {
11794
0
            if (dup3_works == -1)
11795
0
                dup3_works = (errno != ENOSYS);
11796
0
            if (dup3_works) {
11797
0
                posix_error();
11798
0
                return -1;
11799
0
            }
11800
0
        }
11801
0
    }
11802
11803
0
    if (inheritable || dup3_works == 0)
11804
0
    {
11805
0
#endif
11806
0
        Py_BEGIN_ALLOW_THREADS
11807
0
        res = dup2(fd, fd2);
11808
0
        Py_END_ALLOW_THREADS
11809
0
        if (res < 0) {
11810
0
            posix_error();
11811
0
            return -1;
11812
0
        }
11813
11814
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11815
0
            close(fd2);
11816
0
            return -1;
11817
0
        }
11818
0
#ifdef HAVE_DUP3
11819
0
    }
11820
0
#endif
11821
11822
0
#endif
11823
11824
0
    return res;
11825
0
}
11826
#endif
11827
11828
11829
#ifdef HAVE_LOCKF
11830
/*[clinic input]
11831
os.lockf
11832
11833
    fd: int
11834
        An open file descriptor.
11835
    command: int
11836
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11837
    length: Py_off_t
11838
        The number of bytes to lock, starting at the current position.
11839
    /
11840
11841
Apply, test or remove a POSIX lock on an open file descriptor.
11842
11843
[clinic start generated code]*/
11844
11845
static PyObject *
11846
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11847
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11848
0
{
11849
0
    int res;
11850
11851
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11852
0
        return NULL;
11853
0
    }
11854
11855
0
    Py_BEGIN_ALLOW_THREADS
11856
0
    res = lockf(fd, command, length);
11857
0
    Py_END_ALLOW_THREADS
11858
11859
0
    if (res < 0)
11860
0
        return posix_error();
11861
11862
0
    Py_RETURN_NONE;
11863
0
}
11864
#endif /* HAVE_LOCKF */
11865
11866
11867
/*[clinic input]
11868
@permit_long_docstring_body
11869
os.lseek -> Py_off_t
11870
11871
    fd: int
11872
        An open file descriptor, as returned by os.open().
11873
    position: Py_off_t
11874
        Position, interpreted relative to 'whence'.
11875
    whence as how: int
11876
        The relative position to seek from. Valid values are:
11877
        - SEEK_SET: seek from the start of the file.
11878
        - SEEK_CUR: seek from the current file position.
11879
        - SEEK_END: seek from the end of the file.
11880
    /
11881
11882
Set the position of a file descriptor.  Return the new position.
11883
11884
The return value is the number of bytes relative to the beginning of the file.
11885
[clinic start generated code]*/
11886
11887
static Py_off_t
11888
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11889
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11890
0
{
11891
0
    Py_off_t result;
11892
11893
0
#ifdef SEEK_SET
11894
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11895
0
    switch (how) {
11896
0
        case 0: how = SEEK_SET; break;
11897
0
        case 1: how = SEEK_CUR; break;
11898
0
        case 2: how = SEEK_END; break;
11899
0
    }
11900
0
#endif /* SEEK_END */
11901
11902
0
    Py_BEGIN_ALLOW_THREADS
11903
0
    _Py_BEGIN_SUPPRESS_IPH
11904
#ifdef MS_WINDOWS
11905
    result = _lseeki64(fd, position, how);
11906
#else
11907
0
    result = lseek(fd, position, how);
11908
0
#endif
11909
0
    _Py_END_SUPPRESS_IPH
11910
0
    Py_END_ALLOW_THREADS
11911
0
    if (result < 0)
11912
0
        posix_error();
11913
11914
0
    return result;
11915
0
}
11916
11917
11918
/*[clinic input]
11919
os.read
11920
    fd: int
11921
    length: Py_ssize_t
11922
    /
11923
11924
Read from a file descriptor.  Returns a bytes object.
11925
[clinic start generated code]*/
11926
11927
static PyObject *
11928
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11929
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11930
0
{
11931
0
    if (length < 0) {
11932
0
        errno = EINVAL;
11933
0
        return posix_error();
11934
0
    }
11935
11936
0
    length = Py_MIN(length, _PY_READ_MAX);
11937
11938
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11939
0
    if (writer == NULL) {
11940
0
        return NULL;
11941
0
    }
11942
11943
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11944
0
    if (n == -1) {
11945
0
        PyBytesWriter_Discard(writer);
11946
0
        return NULL;
11947
0
    }
11948
11949
0
    return PyBytesWriter_FinishWithSize(writer, n);
11950
0
}
11951
11952
/*[clinic input]
11953
@permit_long_docstring_body
11954
os.readinto -> Py_ssize_t
11955
    fd: int
11956
    buffer: Py_buffer(accept={rwbuffer})
11957
    /
11958
11959
Read into a buffer object from a file descriptor.
11960
11961
The buffer should be mutable and bytes-like. On success, returns the number of
11962
bytes read. Less bytes may be read than the size of the buffer. The underlying
11963
system call will be retried when interrupted by a signal, unless the signal
11964
handler raises an exception. Other errors will not be retried and an error will
11965
be raised.
11966
11967
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
11968
(which can be used to check for errors without reading data). Never returns
11969
negative.
11970
[clinic start generated code]*/
11971
11972
static Py_ssize_t
11973
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
11974
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
11975
0
{
11976
0
    assert(buffer->len >= 0);
11977
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
11978
    /* Ensure negative is never returned without an error. Simplifies calling
11979
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
11980
        error. */
11981
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
11982
0
    return result;
11983
0
}
11984
11985
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
11986
                                || defined(__APPLE__))) \
11987
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
11988
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
11989
static int
11990
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
11991
0
{
11992
0
    Py_ssize_t i, j;
11993
11994
0
    *iov = PyMem_New(struct iovec, cnt);
11995
0
    if (*iov == NULL) {
11996
0
        PyErr_NoMemory();
11997
0
        return -1;
11998
0
    }
11999
12000
0
    *buf = PyMem_New(Py_buffer, cnt);
12001
0
    if (*buf == NULL) {
12002
0
        PyMem_Free(*iov);
12003
0
        PyErr_NoMemory();
12004
0
        return -1;
12005
0
    }
12006
12007
0
    for (i = 0; i < cnt; i++) {
12008
0
        PyObject *item = PySequence_GetItem(seq, i);
12009
0
        if (item == NULL)
12010
0
            goto fail;
12011
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12012
0
            Py_DECREF(item);
12013
0
            goto fail;
12014
0
        }
12015
0
        Py_DECREF(item);
12016
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12017
0
        (*iov)[i].iov_len = (*buf)[i].len;
12018
0
    }
12019
0
    return 0;
12020
12021
0
fail:
12022
0
    PyMem_Free(*iov);
12023
0
    for (j = 0; j < i; j++) {
12024
0
        PyBuffer_Release(&(*buf)[j]);
12025
0
    }
12026
0
    PyMem_Free(*buf);
12027
0
    return -1;
12028
0
}
12029
12030
static void
12031
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12032
0
{
12033
0
    int i;
12034
0
    PyMem_Free(iov);
12035
0
    for (i = 0; i < cnt; i++) {
12036
0
        PyBuffer_Release(&buf[i]);
12037
0
    }
12038
0
    PyMem_Free(buf);
12039
0
}
12040
#endif
12041
12042
12043
#ifdef HAVE_READV
12044
/*[clinic input]
12045
os.readv -> Py_ssize_t
12046
12047
    fd: int
12048
    buffers: object
12049
    /
12050
12051
Read from a file descriptor fd into an iterable of buffers.
12052
12053
The buffers should be mutable buffers accepting bytes.
12054
readv will transfer data into each buffer until it is full
12055
and then move on to the next buffer in the sequence to hold
12056
the rest of the data.
12057
12058
readv returns the total number of bytes read,
12059
which may be less than the total capacity of all the buffers.
12060
[clinic start generated code]*/
12061
12062
static Py_ssize_t
12063
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12064
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12065
0
{
12066
0
    Py_ssize_t cnt, n;
12067
0
    int async_err = 0;
12068
0
    struct iovec *iov;
12069
0
    Py_buffer *buf;
12070
12071
0
    if (!PySequence_Check(buffers)) {
12072
0
        PyErr_SetString(PyExc_TypeError,
12073
0
            "readv() arg 2 must be a sequence");
12074
0
        return -1;
12075
0
    }
12076
12077
0
    cnt = PySequence_Size(buffers);
12078
0
    if (cnt < 0)
12079
0
        return -1;
12080
12081
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12082
0
        return -1;
12083
12084
0
    do {
12085
0
        Py_BEGIN_ALLOW_THREADS
12086
0
        n = readv(fd, iov, cnt);
12087
0
        Py_END_ALLOW_THREADS
12088
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12089
12090
0
    int saved_errno = errno;
12091
0
    iov_cleanup(iov, buf, cnt);
12092
0
    if (n < 0) {
12093
0
        if (!async_err) {
12094
0
            errno = saved_errno;
12095
0
            posix_error();
12096
0
        }
12097
0
        return -1;
12098
0
    }
12099
12100
0
    return n;
12101
0
}
12102
#endif /* HAVE_READV */
12103
12104
12105
#ifdef HAVE_PREAD
12106
/*[clinic input]
12107
@permit_long_summary
12108
os.pread
12109
12110
    fd: int
12111
    length: Py_ssize_t
12112
    offset: Py_off_t
12113
    /
12114
12115
Read a number of bytes from a file descriptor starting at a particular offset.
12116
12117
Read length bytes from file descriptor fd, starting at offset bytes from
12118
the beginning of the file.  The file offset remains unchanged.
12119
[clinic start generated code]*/
12120
12121
static PyObject *
12122
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12123
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12124
0
{
12125
0
    Py_ssize_t n;
12126
0
    int async_err = 0;
12127
12128
0
    if (length < 0) {
12129
0
        errno = EINVAL;
12130
0
        return posix_error();
12131
0
    }
12132
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12133
0
    if (writer == NULL) {
12134
0
        return NULL;
12135
0
    }
12136
12137
0
    do {
12138
0
        Py_BEGIN_ALLOW_THREADS
12139
0
        _Py_BEGIN_SUPPRESS_IPH
12140
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12141
0
        _Py_END_SUPPRESS_IPH
12142
0
        Py_END_ALLOW_THREADS
12143
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12144
12145
0
    if (n < 0) {
12146
0
        if (!async_err) {
12147
0
            posix_error();
12148
0
        }
12149
0
        PyBytesWriter_Discard(writer);
12150
0
        return NULL;
12151
0
    }
12152
0
    return PyBytesWriter_FinishWithSize(writer, n);
12153
0
}
12154
#endif /* HAVE_PREAD */
12155
12156
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12157
/*[clinic input]
12158
@permit_long_docstring_body
12159
os.preadv -> Py_ssize_t
12160
12161
    fd: int
12162
    buffers: object
12163
    offset: Py_off_t
12164
    flags: int = 0
12165
    /
12166
12167
Reads from a file descriptor into a number of mutable bytes-like objects.
12168
12169
Combines the functionality of readv() and pread(). As readv(), it will
12170
transfer data into each buffer until it is full and then move on to the next
12171
buffer in the sequence to hold the rest of the data. Its fourth argument,
12172
specifies the file offset at which the input operation is to be performed. It
12173
will return the total number of bytes read (which can be less than the total
12174
capacity of all the objects).
12175
12176
The flags argument contains a bitwise OR of zero or more of the following flags:
12177
12178
- RWF_HIPRI
12179
- RWF_NOWAIT
12180
- RWF_DONTCACHE
12181
12182
Using non-zero flags requires Linux 4.6 or newer.
12183
[clinic start generated code]*/
12184
12185
static Py_ssize_t
12186
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12187
               int flags)
12188
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
12189
0
{
12190
0
    Py_ssize_t cnt, n;
12191
0
    int async_err = 0;
12192
0
    struct iovec *iov;
12193
0
    Py_buffer *buf;
12194
12195
0
    if (!PySequence_Check(buffers)) {
12196
0
        PyErr_SetString(PyExc_TypeError,
12197
0
            "preadv2() arg 2 must be a sequence");
12198
0
        return -1;
12199
0
    }
12200
12201
0
    cnt = PySequence_Size(buffers);
12202
0
    if (cnt < 0) {
12203
0
        return -1;
12204
0
    }
12205
12206
#ifndef HAVE_PREADV2
12207
    if(flags != 0) {
12208
        argument_unavailable_error("preadv2", "flags");
12209
        return -1;
12210
    }
12211
#endif
12212
12213
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12214
0
        return -1;
12215
0
    }
12216
0
#ifdef HAVE_PREADV2
12217
0
    do {
12218
0
        Py_BEGIN_ALLOW_THREADS
12219
0
        _Py_BEGIN_SUPPRESS_IPH
12220
0
        n = preadv2(fd, iov, cnt, offset, flags);
12221
0
        _Py_END_SUPPRESS_IPH
12222
0
        Py_END_ALLOW_THREADS
12223
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12224
#else
12225
    do {
12226
#if defined(__APPLE__) && defined(__clang__)
12227
/* This entire function will be removed from the module dict when the API
12228
 * is not available.
12229
 */
12230
#pragma clang diagnostic push
12231
#pragma clang diagnostic ignored "-Wunguarded-availability"
12232
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12233
#endif
12234
        Py_BEGIN_ALLOW_THREADS
12235
        _Py_BEGIN_SUPPRESS_IPH
12236
        n = preadv(fd, iov, cnt, offset);
12237
        _Py_END_SUPPRESS_IPH
12238
        Py_END_ALLOW_THREADS
12239
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12240
12241
#if defined(__APPLE__) && defined(__clang__)
12242
#pragma clang diagnostic pop
12243
#endif
12244
12245
#endif
12246
12247
0
    int saved_errno = errno;
12248
0
    iov_cleanup(iov, buf, cnt);
12249
0
    if (n < 0) {
12250
0
        if (!async_err) {
12251
0
            errno = saved_errno;
12252
0
            posix_error();
12253
0
        }
12254
0
        return -1;
12255
0
    }
12256
12257
0
    return n;
12258
0
}
12259
#endif /* HAVE_PREADV */
12260
12261
12262
/*[clinic input]
12263
os.write -> Py_ssize_t
12264
12265
    fd: int
12266
    data: Py_buffer
12267
    /
12268
12269
Write a bytes object to a file descriptor.
12270
[clinic start generated code]*/
12271
12272
static Py_ssize_t
12273
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12274
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12275
0
{
12276
0
    return _Py_write(fd, data->buf, data->len);
12277
0
}
12278
12279
#ifdef HAVE_SENDFILE
12280
#ifdef __APPLE__
12281
/*[clinic input]
12282
os.sendfile
12283
12284
    out_fd: int
12285
    in_fd: int
12286
    offset: Py_off_t
12287
    count as sbytes: Py_off_t
12288
    headers: object(c_default="NULL") = ()
12289
    trailers: object(c_default="NULL") = ()
12290
    flags: int = 0
12291
12292
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12293
[clinic start generated code]*/
12294
12295
static PyObject *
12296
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12297
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12298
                 int flags)
12299
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12300
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12301
/*[clinic input]
12302
os.sendfile
12303
12304
    out_fd: int
12305
    in_fd: int
12306
    offset: Py_off_t
12307
    count: Py_ssize_t(allow_negative=False)
12308
    headers: object(c_default="NULL") = ()
12309
    trailers: object(c_default="NULL") = ()
12310
    flags: int = 0
12311
12312
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12313
[clinic start generated code]*/
12314
12315
static PyObject *
12316
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12317
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12318
                 int flags)
12319
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12320
#else
12321
/*[clinic input]
12322
os.sendfile
12323
12324
    out_fd: int
12325
    in_fd: int
12326
    offset as offobj: object
12327
    count: Py_ssize_t(allow_negative=False)
12328
12329
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12330
[clinic start generated code]*/
12331
12332
static PyObject *
12333
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12334
                 Py_ssize_t count)
12335
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12336
#endif
12337
0
{
12338
0
    Py_ssize_t ret;
12339
0
    int async_err = 0;
12340
12341
#ifdef __APPLE__
12342
    if(sbytes < 0) {
12343
        PyErr_SetString(PyExc_ValueError,
12344
                        "count cannot be negative");
12345
        return NULL;
12346
    }
12347
#else
12348
0
    assert(count >= 0);
12349
0
#endif
12350
12351
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12352
#ifndef __APPLE__
12353
    off_t sbytes;
12354
#endif
12355
    Py_buffer *hbuf, *tbuf;
12356
    struct sf_hdtr sf;
12357
12358
    sf.headers = NULL;
12359
    sf.trailers = NULL;
12360
12361
    if (headers != NULL) {
12362
        if (!PySequence_Check(headers)) {
12363
            PyErr_SetString(PyExc_TypeError,
12364
                "sendfile() headers must be a sequence");
12365
            return NULL;
12366
        } else {
12367
            Py_ssize_t i = PySequence_Size(headers);
12368
            if (i < 0)
12369
                return NULL;
12370
            if (i > INT_MAX) {
12371
                PyErr_SetString(PyExc_OverflowError,
12372
                    "sendfile() header is too large");
12373
                return NULL;
12374
            }
12375
            if (i > 0) {
12376
                sf.hdr_cnt = (int)i;
12377
                if (iov_setup(&(sf.headers), &hbuf,
12378
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12379
                    return NULL;
12380
#ifdef __APPLE__
12381
                for (i = 0; i < sf.hdr_cnt; i++) {
12382
                    Py_ssize_t blen = sf.headers[i].iov_len;
12383
# define OFF_T_MAX 0x7fffffffffffffff
12384
                    if (sbytes >= OFF_T_MAX - blen) {
12385
                        PyErr_SetString(PyExc_OverflowError,
12386
                            "sendfile() header is too large");
12387
                        return NULL;
12388
                    }
12389
                    sbytes += blen;
12390
                }
12391
#endif
12392
            }
12393
        }
12394
    }
12395
    if (trailers != NULL) {
12396
        if (!PySequence_Check(trailers)) {
12397
            PyErr_SetString(PyExc_TypeError,
12398
                "sendfile() trailers must be a sequence");
12399
            return NULL;
12400
        } else {
12401
            Py_ssize_t i = PySequence_Size(trailers);
12402
            if (i < 0)
12403
                return NULL;
12404
            if (i > INT_MAX) {
12405
                PyErr_SetString(PyExc_OverflowError,
12406
                    "sendfile() trailer is too large");
12407
                return NULL;
12408
            }
12409
            if (i > 0) {
12410
                sf.trl_cnt = (int)i;
12411
                if (iov_setup(&(sf.trailers), &tbuf,
12412
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12413
                    return NULL;
12414
            }
12415
        }
12416
    }
12417
12418
    _Py_BEGIN_SUPPRESS_IPH
12419
    do {
12420
        Py_BEGIN_ALLOW_THREADS
12421
#ifdef __APPLE__
12422
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12423
#else
12424
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12425
#endif
12426
        Py_END_ALLOW_THREADS
12427
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12428
    _Py_END_SUPPRESS_IPH
12429
12430
    int saved_errno = errno;
12431
    if (sf.headers != NULL)
12432
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12433
    if (sf.trailers != NULL)
12434
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12435
12436
    if (ret < 0) {
12437
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12438
            if (sbytes != 0) {
12439
                // some data has been sent
12440
                goto done;
12441
            }
12442
            // no data has been sent; upper application is supposed
12443
            // to retry on EAGAIN or EBUSY
12444
        }
12445
        if (!async_err) {
12446
            errno = saved_errno;
12447
            posix_error();
12448
        }
12449
        return NULL;
12450
    }
12451
    goto done;
12452
12453
done:
12454
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12455
        return PyLong_FromLong(sbytes);
12456
    #else
12457
        return PyLong_FromLongLong(sbytes);
12458
    #endif
12459
12460
#else
12461
0
#ifdef __linux__
12462
0
    if (offobj == Py_None) {
12463
0
        do {
12464
0
            Py_BEGIN_ALLOW_THREADS
12465
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12466
0
            Py_END_ALLOW_THREADS
12467
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12468
0
        if (ret < 0)
12469
0
            return (!async_err) ? posix_error() : NULL;
12470
0
        return PyLong_FromSsize_t(ret);
12471
0
    }
12472
0
#endif
12473
0
    off_t offset;
12474
0
    if (!Py_off_t_converter(offobj, &offset))
12475
0
        return NULL;
12476
12477
#if defined(__sun) && defined(__SVR4)
12478
    // On Solaris, sendfile raises EINVAL rather than returning 0
12479
    // when the offset is equal or bigger than the in_fd size.
12480
    struct stat st;
12481
12482
    do {
12483
        Py_BEGIN_ALLOW_THREADS
12484
        ret = fstat(in_fd, &st);
12485
        Py_END_ALLOW_THREADS
12486
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12487
    if (ret < 0)
12488
        return (!async_err) ? posix_error() : NULL;
12489
12490
    if (offset >= st.st_size) {
12491
        return PyLong_FromLong(0);
12492
    }
12493
12494
    // On illumos specifically sendfile() may perform a partial write but
12495
    // return -1/an error (in one confirmed case the destination socket
12496
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12497
    // code to check if the offset parameter was modified by sendfile().
12498
    //
12499
    // We need this variable to track said change.
12500
    off_t original_offset = offset;
12501
#endif
12502
12503
0
    do {
12504
0
        Py_BEGIN_ALLOW_THREADS
12505
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12506
#if defined(__sun) && defined(__SVR4)
12507
        // This handles illumos-specific sendfile() partial write behavior,
12508
        // see a comment above for more details.
12509
        if (ret < 0 && offset != original_offset) {
12510
            ret = offset - original_offset;
12511
        }
12512
#endif
12513
0
        Py_END_ALLOW_THREADS
12514
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12515
0
    if (ret < 0)
12516
0
        return (!async_err) ? posix_error() : NULL;
12517
0
    return PyLong_FromSsize_t(ret);
12518
0
#endif
12519
0
}
12520
#endif /* HAVE_SENDFILE */
12521
12522
12523
#if defined(__APPLE__)
12524
/*[clinic input]
12525
os._fcopyfile
12526
12527
    in_fd: int
12528
    out_fd: int
12529
    flags: int
12530
    /
12531
12532
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12533
[clinic start generated code]*/
12534
12535
static PyObject *
12536
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12537
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12538
{
12539
    int ret;
12540
12541
    Py_BEGIN_ALLOW_THREADS
12542
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12543
    Py_END_ALLOW_THREADS
12544
    if (ret < 0)
12545
        return posix_error();
12546
    Py_RETURN_NONE;
12547
}
12548
#endif
12549
12550
12551
/*[clinic input]
12552
os.fstat
12553
12554
    fd : int
12555
12556
Perform a stat system call on the given file descriptor.
12557
12558
Like stat(), but for an open file descriptor.
12559
Equivalent to os.stat(fd).
12560
[clinic start generated code]*/
12561
12562
static PyObject *
12563
os_fstat_impl(PyObject *module, int fd)
12564
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12565
0
{
12566
0
    STRUCT_STAT st;
12567
0
    int res;
12568
0
    int async_err = 0;
12569
12570
0
    do {
12571
0
        Py_BEGIN_ALLOW_THREADS
12572
0
        res = FSTAT(fd, &st);
12573
0
        Py_END_ALLOW_THREADS
12574
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12575
0
    if (res != 0) {
12576
#ifdef MS_WINDOWS
12577
        return PyErr_SetFromWindowsErr(0);
12578
#else
12579
0
        return (!async_err) ? posix_error() : NULL;
12580
0
#endif
12581
0
    }
12582
12583
0
    return _pystat_fromstructstat(module, &st);
12584
0
}
12585
12586
12587
/*[clinic input]
12588
os.isatty -> bool
12589
    fd: int
12590
    /
12591
12592
Return True if the fd is connected to a terminal.
12593
12594
Return True if the file descriptor is an open file descriptor
12595
connected to the slave end of a terminal.
12596
[clinic start generated code]*/
12597
12598
static int
12599
os_isatty_impl(PyObject *module, int fd)
12600
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12601
0
{
12602
0
    int return_value;
12603
0
    Py_BEGIN_ALLOW_THREADS
12604
0
    _Py_BEGIN_SUPPRESS_IPH
12605
0
    return_value = isatty(fd);
12606
0
    _Py_END_SUPPRESS_IPH
12607
0
    Py_END_ALLOW_THREADS
12608
0
    return return_value;
12609
0
}
12610
12611
12612
#ifdef HAVE_PIPE
12613
/*[clinic input]
12614
os.pipe
12615
12616
Create a pipe.
12617
12618
Returns a tuple of two file descriptors:
12619
  (read_fd, write_fd)
12620
[clinic start generated code]*/
12621
12622
static PyObject *
12623
os_pipe_impl(PyObject *module)
12624
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12625
0
{
12626
0
    int fds[2];
12627
#ifdef MS_WINDOWS
12628
    HANDLE read, write;
12629
    SECURITY_ATTRIBUTES attr;
12630
    BOOL ok;
12631
#else
12632
0
    int res;
12633
0
#endif
12634
12635
#ifdef MS_WINDOWS
12636
    attr.nLength = sizeof(attr);
12637
    attr.lpSecurityDescriptor = NULL;
12638
    attr.bInheritHandle = FALSE;
12639
12640
    Py_BEGIN_ALLOW_THREADS
12641
    ok = CreatePipe(&read, &write, &attr, 0);
12642
    if (ok) {
12643
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12644
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12645
        if (fds[0] == -1 || fds[1] == -1) {
12646
            CloseHandle(read);
12647
            CloseHandle(write);
12648
            ok = 0;
12649
        }
12650
    }
12651
    Py_END_ALLOW_THREADS
12652
12653
    if (!ok)
12654
        return PyErr_SetFromWindowsErr(0);
12655
#else
12656
12657
0
#ifdef HAVE_PIPE2
12658
0
    Py_BEGIN_ALLOW_THREADS
12659
0
    res = pipe2(fds, O_CLOEXEC);
12660
0
    Py_END_ALLOW_THREADS
12661
12662
0
    if (res != 0 && errno == ENOSYS)
12663
0
    {
12664
0
#endif
12665
0
        Py_BEGIN_ALLOW_THREADS
12666
0
        res = pipe(fds);
12667
0
        Py_END_ALLOW_THREADS
12668
12669
0
        if (res == 0) {
12670
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12671
0
                close(fds[0]);
12672
0
                close(fds[1]);
12673
0
                return NULL;
12674
0
            }
12675
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12676
0
                close(fds[0]);
12677
0
                close(fds[1]);
12678
0
                return NULL;
12679
0
            }
12680
0
        }
12681
0
#ifdef HAVE_PIPE2
12682
0
    }
12683
0
#endif
12684
12685
0
    if (res != 0)
12686
0
        return PyErr_SetFromErrno(PyExc_OSError);
12687
0
#endif /* !MS_WINDOWS */
12688
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12689
0
}
12690
#endif  /* HAVE_PIPE */
12691
12692
12693
#ifdef HAVE_PIPE2
12694
/*[clinic input]
12695
os.pipe2
12696
12697
    flags: int
12698
    /
12699
12700
Create a pipe with flags set atomically.
12701
12702
Returns a tuple of two file descriptors:
12703
  (read_fd, write_fd)
12704
12705
flags can be constructed by ORing together one or more of these values:
12706
O_NONBLOCK, O_CLOEXEC.
12707
[clinic start generated code]*/
12708
12709
static PyObject *
12710
os_pipe2_impl(PyObject *module, int flags)
12711
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12712
0
{
12713
0
    int fds[2];
12714
0
    int res;
12715
12716
0
    res = pipe2(fds, flags);
12717
0
    if (res != 0)
12718
0
        return posix_error();
12719
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12720
0
}
12721
#endif /* HAVE_PIPE2 */
12722
12723
12724
#ifdef HAVE_WRITEV
12725
/*[clinic input]
12726
os.writev -> Py_ssize_t
12727
    fd: int
12728
    buffers: object
12729
    /
12730
12731
Iterate over buffers, and write the contents of each to a file descriptor.
12732
12733
Returns the total number of bytes written.
12734
buffers must be a sequence of bytes-like objects.
12735
[clinic start generated code]*/
12736
12737
static Py_ssize_t
12738
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12739
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12740
0
{
12741
0
    Py_ssize_t cnt;
12742
0
    Py_ssize_t result;
12743
0
    int async_err = 0;
12744
0
    struct iovec *iov;
12745
0
    Py_buffer *buf;
12746
12747
0
    if (!PySequence_Check(buffers)) {
12748
0
        PyErr_SetString(PyExc_TypeError,
12749
0
            "writev() arg 2 must be a sequence");
12750
0
        return -1;
12751
0
    }
12752
0
    cnt = PySequence_Size(buffers);
12753
0
    if (cnt < 0)
12754
0
        return -1;
12755
12756
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12757
0
        return -1;
12758
0
    }
12759
12760
0
    do {
12761
0
        Py_BEGIN_ALLOW_THREADS
12762
0
        result = writev(fd, iov, cnt);
12763
0
        Py_END_ALLOW_THREADS
12764
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12765
12766
0
    if (result < 0 && !async_err)
12767
0
        posix_error();
12768
12769
0
    iov_cleanup(iov, buf, cnt);
12770
0
    return result;
12771
0
}
12772
#endif /* HAVE_WRITEV */
12773
12774
12775
#ifdef HAVE_PWRITE
12776
/*[clinic input]
12777
os.pwrite -> Py_ssize_t
12778
12779
    fd: int
12780
    buffer: Py_buffer
12781
    offset: Py_off_t
12782
    /
12783
12784
Write bytes to a file descriptor starting at a particular offset.
12785
12786
Write buffer to fd, starting at offset bytes from the beginning of
12787
the file.  Returns the number of bytes written.  Does not change the
12788
current file offset.
12789
[clinic start generated code]*/
12790
12791
static Py_ssize_t
12792
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12793
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12794
0
{
12795
0
    Py_ssize_t size;
12796
0
    int async_err = 0;
12797
12798
0
    do {
12799
0
        Py_BEGIN_ALLOW_THREADS
12800
0
        _Py_BEGIN_SUPPRESS_IPH
12801
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12802
0
        _Py_END_SUPPRESS_IPH
12803
0
        Py_END_ALLOW_THREADS
12804
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12805
12806
0
    if (size < 0 && !async_err)
12807
0
        posix_error();
12808
0
    return size;
12809
0
}
12810
#endif /* HAVE_PWRITE */
12811
12812
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12813
/*[clinic input]
12814
@permit_long_summary
12815
@permit_long_docstring_body
12816
os.pwritev -> Py_ssize_t
12817
12818
    fd: int
12819
    buffers: object
12820
    offset: Py_off_t
12821
    flags: int = 0
12822
    /
12823
12824
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12825
12826
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12827
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12828
buffer is written before proceeding to second, and so on. The operating system may
12829
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12830
This function writes the contents of each object to the file descriptor and returns
12831
the total number of bytes written.
12832
12833
The flags argument contains a bitwise OR of zero or more of the following flags:
12834
12835
- RWF_DSYNC
12836
- RWF_SYNC
12837
- RWF_APPEND
12838
- RWF_DONTCACHE
12839
12840
Using non-zero flags requires Linux 4.7 or newer.
12841
[clinic start generated code]*/
12842
12843
static Py_ssize_t
12844
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12845
                int flags)
12846
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=664a67626d485665]*/
12847
0
{
12848
0
    Py_ssize_t cnt;
12849
0
    Py_ssize_t result;
12850
0
    int async_err = 0;
12851
0
    struct iovec *iov;
12852
0
    Py_buffer *buf;
12853
12854
0
    if (!PySequence_Check(buffers)) {
12855
0
        PyErr_SetString(PyExc_TypeError,
12856
0
            "pwritev() arg 2 must be a sequence");
12857
0
        return -1;
12858
0
    }
12859
12860
0
    cnt = PySequence_Size(buffers);
12861
0
    if (cnt < 0) {
12862
0
        return -1;
12863
0
    }
12864
12865
#ifndef HAVE_PWRITEV2
12866
    if(flags != 0) {
12867
        argument_unavailable_error("pwritev2", "flags");
12868
        return -1;
12869
    }
12870
#endif
12871
12872
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12873
0
        return -1;
12874
0
    }
12875
0
#ifdef HAVE_PWRITEV2
12876
0
    do {
12877
0
        Py_BEGIN_ALLOW_THREADS
12878
0
        _Py_BEGIN_SUPPRESS_IPH
12879
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12880
0
        _Py_END_SUPPRESS_IPH
12881
0
        Py_END_ALLOW_THREADS
12882
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12883
#else
12884
12885
#if defined(__APPLE__) && defined(__clang__)
12886
/* This entire function will be removed from the module dict when the API
12887
 * is not available.
12888
 */
12889
#pragma clang diagnostic push
12890
#pragma clang diagnostic ignored "-Wunguarded-availability"
12891
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12892
#endif
12893
    do {
12894
        Py_BEGIN_ALLOW_THREADS
12895
        _Py_BEGIN_SUPPRESS_IPH
12896
        result = pwritev(fd, iov, cnt, offset);
12897
        _Py_END_SUPPRESS_IPH
12898
        Py_END_ALLOW_THREADS
12899
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12900
12901
#if defined(__APPLE__) && defined(__clang__)
12902
#pragma clang diagnostic pop
12903
#endif
12904
12905
#endif
12906
12907
0
    if (result < 0) {
12908
0
        if (!async_err) {
12909
0
            posix_error();
12910
0
        }
12911
0
        result = -1;
12912
0
    }
12913
0
    iov_cleanup(iov, buf, cnt);
12914
12915
0
    return result;
12916
0
}
12917
#endif /* HAVE_PWRITEV */
12918
12919
#ifdef HAVE_COPY_FILE_RANGE
12920
/*[clinic input]
12921
12922
os.copy_file_range
12923
    src: int
12924
        Source file descriptor.
12925
    dst: int
12926
        Destination file descriptor.
12927
    count: Py_ssize_t(allow_negative=False)
12928
        Number of bytes to copy.
12929
    offset_src: object = None
12930
        Starting offset in src.
12931
    offset_dst: object = None
12932
        Starting offset in dst.
12933
12934
Copy count bytes from one file descriptor to another.
12935
12936
If offset_src is None, then src is read from the current position;
12937
respectively for offset_dst.
12938
[clinic start generated code]*/
12939
12940
static PyObject *
12941
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12942
                        PyObject *offset_src, PyObject *offset_dst)
12943
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12944
0
{
12945
0
    off_t offset_src_val, offset_dst_val;
12946
0
    off_t *p_offset_src = NULL;
12947
0
    off_t *p_offset_dst = NULL;
12948
0
    Py_ssize_t ret;
12949
0
    int async_err = 0;
12950
    /* The flags argument is provided to allow
12951
     * for future extensions and currently must be to 0. */
12952
0
    int flags = 0;
12953
12954
12955
0
    if (offset_src != Py_None) {
12956
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12957
0
            return NULL;
12958
0
        }
12959
0
        p_offset_src = &offset_src_val;
12960
0
    }
12961
12962
0
    if (offset_dst != Py_None) {
12963
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12964
0
            return NULL;
12965
0
        }
12966
0
        p_offset_dst = &offset_dst_val;
12967
0
    }
12968
12969
0
    do {
12970
0
        Py_BEGIN_ALLOW_THREADS
12971
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
12972
0
        Py_END_ALLOW_THREADS
12973
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12974
12975
0
    if (ret < 0) {
12976
0
        return (!async_err) ? posix_error() : NULL;
12977
0
    }
12978
12979
0
    return PyLong_FromSsize_t(ret);
12980
0
}
12981
#endif /* HAVE_COPY_FILE_RANGE*/
12982
12983
#if (defined(HAVE_SPLICE) && !defined(_AIX))
12984
/*[clinic input]
12985
12986
os.splice
12987
    src: int
12988
        Source file descriptor.
12989
    dst: int
12990
        Destination file descriptor.
12991
    count: Py_ssize_t(allow_negative=False)
12992
        Number of bytes to copy.
12993
    offset_src: object = None
12994
        Starting offset in src.
12995
    offset_dst: object = None
12996
        Starting offset in dst.
12997
    flags: unsigned_int = 0
12998
        Flags to modify the semantics of the call.
12999
13000
Transfer count bytes from one pipe to a descriptor or vice versa.
13001
13002
If offset_src is None, then src is read from the current position;
13003
respectively for offset_dst. The offset associated to the file
13004
descriptor that refers to a pipe must be None.
13005
[clinic start generated code]*/
13006
13007
static PyObject *
13008
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13009
               PyObject *offset_src, PyObject *offset_dst,
13010
               unsigned int flags)
13011
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13012
0
{
13013
0
    off_t offset_src_val, offset_dst_val;
13014
0
    off_t *p_offset_src = NULL;
13015
0
    off_t *p_offset_dst = NULL;
13016
0
    Py_ssize_t ret;
13017
0
    int async_err = 0;
13018
13019
13020
0
    if (offset_src != Py_None) {
13021
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13022
0
            return NULL;
13023
0
        }
13024
0
        p_offset_src = &offset_src_val;
13025
0
    }
13026
13027
0
    if (offset_dst != Py_None) {
13028
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13029
0
            return NULL;
13030
0
        }
13031
0
        p_offset_dst = &offset_dst_val;
13032
0
    }
13033
13034
0
    do {
13035
0
        Py_BEGIN_ALLOW_THREADS
13036
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13037
0
        Py_END_ALLOW_THREADS
13038
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13039
13040
0
    if (ret < 0) {
13041
0
        return (!async_err) ? posix_error() : NULL;
13042
0
    }
13043
13044
0
    return PyLong_FromSsize_t(ret);
13045
0
}
13046
#endif /* HAVE_SPLICE*/
13047
13048
#ifdef HAVE_MKFIFO
13049
/*[clinic input]
13050
os.mkfifo
13051
13052
    path: path_t
13053
    mode: int=0o666
13054
    *
13055
    dir_fd: dir_fd(requires='mkfifoat')=None
13056
13057
Create a "fifo" (a POSIX named pipe).
13058
13059
If dir_fd is not None, it should be a file descriptor open to a directory,
13060
  and path should be relative; path will then be relative to that directory.
13061
dir_fd may not be implemented on your platform.
13062
  If it is unavailable, using it will raise a NotImplementedError.
13063
[clinic start generated code]*/
13064
13065
static PyObject *
13066
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13067
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
13068
0
{
13069
0
    int result;
13070
0
    int async_err = 0;
13071
0
#ifdef HAVE_MKFIFOAT
13072
0
    int mkfifoat_unavailable = 0;
13073
0
#endif
13074
13075
0
    do {
13076
0
        Py_BEGIN_ALLOW_THREADS
13077
0
#ifdef HAVE_MKFIFOAT
13078
0
        if (dir_fd != DEFAULT_DIR_FD) {
13079
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13080
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13081
13082
0
            } else {
13083
0
                mkfifoat_unavailable = 1;
13084
0
                result = 0;
13085
0
            }
13086
0
        } else
13087
0
#endif
13088
0
            result = mkfifo(path->narrow, mode);
13089
0
        Py_END_ALLOW_THREADS
13090
0
    } while (result != 0 && errno == EINTR &&
13091
0
             !(async_err = PyErr_CheckSignals()));
13092
13093
0
#ifdef HAVE_MKFIFOAT
13094
0
    if (mkfifoat_unavailable) {
13095
0
        argument_unavailable_error(NULL, "dir_fd");
13096
0
        return NULL;
13097
0
    }
13098
0
#endif
13099
13100
0
    if (result != 0)
13101
0
        return (!async_err) ? posix_error() : NULL;
13102
13103
0
    Py_RETURN_NONE;
13104
0
}
13105
#endif /* HAVE_MKFIFO */
13106
13107
13108
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13109
/*[clinic input]
13110
@permit_long_docstring_body
13111
os.mknod
13112
13113
    path: path_t
13114
    mode: int=0o600
13115
    device: dev_t=0
13116
    *
13117
    dir_fd: dir_fd(requires='mknodat')=None
13118
13119
Create a node in the file system.
13120
13121
Create a node in the file system (file, device special file or named pipe)
13122
at path.  mode specifies both the permissions to use and the
13123
type of node to be created, being combined (bitwise OR) with one of
13124
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
13125
device defines the newly created device special file (probably using
13126
os.makedev()).  Otherwise device is ignored.
13127
13128
If dir_fd is not None, it should be a file descriptor open to a directory,
13129
  and path should be relative; path will then be relative to that directory.
13130
dir_fd may not be implemented on your platform.
13131
  If it is unavailable, using it will raise a NotImplementedError.
13132
[clinic start generated code]*/
13133
13134
static PyObject *
13135
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13136
              int dir_fd)
13137
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
13138
0
{
13139
0
    int result;
13140
0
    int async_err = 0;
13141
0
#ifdef HAVE_MKNODAT
13142
0
    int mknodat_unavailable = 0;
13143
0
#endif
13144
13145
0
    do {
13146
0
        Py_BEGIN_ALLOW_THREADS
13147
0
#ifdef HAVE_MKNODAT
13148
0
        if (dir_fd != DEFAULT_DIR_FD) {
13149
0
            if (HAVE_MKNODAT_RUNTIME) {
13150
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13151
13152
0
            } else {
13153
0
                mknodat_unavailable = 1;
13154
0
                result = 0;
13155
0
            }
13156
0
        } else
13157
0
#endif
13158
0
            result = mknod(path->narrow, mode, device);
13159
0
        Py_END_ALLOW_THREADS
13160
0
    } while (result != 0 && errno == EINTR &&
13161
0
             !(async_err = PyErr_CheckSignals()));
13162
0
#ifdef HAVE_MKNODAT
13163
0
    if (mknodat_unavailable) {
13164
0
        argument_unavailable_error(NULL, "dir_fd");
13165
0
        return NULL;
13166
0
    }
13167
0
#endif
13168
0
    if (result != 0)
13169
0
        return (!async_err) ? posix_error() : NULL;
13170
13171
0
    Py_RETURN_NONE;
13172
0
}
13173
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13174
13175
13176
#ifdef HAVE_DEVICE_MACROS
13177
static PyObject *
13178
major_minor_conv(unsigned int value)
13179
0
{
13180
0
#ifdef NODEV
13181
0
    if (value == (unsigned int)NODEV) {
13182
0
        return PyLong_FromLong((int)NODEV);
13183
0
    }
13184
0
#endif
13185
0
    return PyLong_FromUnsignedLong(value);
13186
0
}
13187
13188
static int
13189
major_minor_check(dev_t value)
13190
0
{
13191
0
#ifdef NODEV
13192
0
    if (value == NODEV) {
13193
0
        return 1;
13194
0
    }
13195
0
#endif
13196
0
    return (dev_t)(unsigned int)value == value;
13197
0
}
13198
13199
/*[clinic input]
13200
os.major
13201
13202
    device: dev_t
13203
    /
13204
13205
Extracts a device major number from a raw device number.
13206
[clinic start generated code]*/
13207
13208
static PyObject *
13209
os_major_impl(PyObject *module, dev_t device)
13210
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13211
0
{
13212
0
    return major_minor_conv(major(device));
13213
0
}
13214
13215
13216
/*[clinic input]
13217
os.minor
13218
13219
    device: dev_t
13220
    /
13221
13222
Extracts a device minor number from a raw device number.
13223
[clinic start generated code]*/
13224
13225
static PyObject *
13226
os_minor_impl(PyObject *module, dev_t device)
13227
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13228
0
{
13229
0
    return major_minor_conv(minor(device));
13230
0
}
13231
13232
13233
/*[clinic input]
13234
os.makedev -> dev_t
13235
13236
    major: dev_t
13237
    minor: dev_t
13238
    /
13239
13240
Composes a raw device number from the major and minor device numbers.
13241
[clinic start generated code]*/
13242
13243
static dev_t
13244
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13245
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13246
0
{
13247
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13248
0
        PyErr_SetString(PyExc_OverflowError,
13249
0
                        "Python int too large to convert to C unsigned int");
13250
0
        return (dev_t)-1;
13251
0
    }
13252
0
    return makedev(major, minor);
13253
0
}
13254
#endif /* HAVE_DEVICE_MACROS */
13255
13256
13257
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13258
/*[clinic input]
13259
os.ftruncate
13260
13261
    fd: int
13262
    length: Py_off_t
13263
    /
13264
13265
Truncate a file, specified by file descriptor, to a specific length.
13266
[clinic start generated code]*/
13267
13268
static PyObject *
13269
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13270
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13271
0
{
13272
0
    int result;
13273
0
    int async_err = 0;
13274
13275
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13276
0
        return NULL;
13277
0
    }
13278
13279
0
    do {
13280
0
        Py_BEGIN_ALLOW_THREADS
13281
0
        _Py_BEGIN_SUPPRESS_IPH
13282
#ifdef MS_WINDOWS
13283
        result = _chsize_s(fd, length);
13284
#else
13285
0
        result = ftruncate(fd, length);
13286
0
#endif
13287
0
        _Py_END_SUPPRESS_IPH
13288
0
        Py_END_ALLOW_THREADS
13289
0
    } while (result != 0 && errno == EINTR &&
13290
0
             !(async_err = PyErr_CheckSignals()));
13291
0
    if (result != 0)
13292
0
        return (!async_err) ? posix_error() : NULL;
13293
0
    Py_RETURN_NONE;
13294
0
}
13295
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13296
13297
13298
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13299
/*[clinic input]
13300
os.truncate
13301
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13302
    length: Py_off_t
13303
13304
Truncate a file, specified by path, to a specific length.
13305
13306
On some platforms, path may also be specified as an open file descriptor.
13307
  If this functionality is unavailable, using it raises an exception.
13308
[clinic start generated code]*/
13309
13310
static PyObject *
13311
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13312
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
13313
0
{
13314
0
    int result;
13315
#ifdef MS_WINDOWS
13316
    int fd;
13317
#endif
13318
13319
0
    if (path->fd != -1)
13320
0
        return os_ftruncate_impl(module, path->fd, length);
13321
13322
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13323
0
        return NULL;
13324
0
    }
13325
13326
0
    Py_BEGIN_ALLOW_THREADS
13327
0
    _Py_BEGIN_SUPPRESS_IPH
13328
#ifdef MS_WINDOWS
13329
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13330
    if (fd < 0)
13331
        result = -1;
13332
    else {
13333
        result = _chsize_s(fd, length);
13334
        close(fd);
13335
        if (result < 0)
13336
            errno = result;
13337
    }
13338
#else
13339
0
    result = truncate(path->narrow, length);
13340
0
#endif
13341
0
    _Py_END_SUPPRESS_IPH
13342
0
    Py_END_ALLOW_THREADS
13343
0
    if (result < 0)
13344
0
        return posix_path_error(path);
13345
13346
0
    Py_RETURN_NONE;
13347
0
}
13348
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13349
13350
13351
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
13352
   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
13353
   defined, which is the case in Python on AIX. AIX bug report:
13354
   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
13355
#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
13356
#  define POSIX_FADVISE_AIX_BUG
13357
#endif
13358
13359
13360
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13361
   OSs, support was dropped in WASI preview2. */
13362
#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \
13363
    !defined(__wasi__)
13364
/*[clinic input]
13365
os.posix_fallocate
13366
13367
    fd: int
13368
    offset: Py_off_t
13369
    length: Py_off_t
13370
    /
13371
13372
Ensure a file has allocated at least a particular number of bytes on disk.
13373
13374
Ensure that the file specified by fd encompasses a range of bytes
13375
starting at offset bytes from the beginning and continuing for length bytes.
13376
[clinic start generated code]*/
13377
13378
static PyObject *
13379
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13380
                        Py_off_t length)
13381
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
13382
0
{
13383
0
    int result;
13384
0
    int async_err = 0;
13385
13386
0
    do {
13387
0
        Py_BEGIN_ALLOW_THREADS
13388
0
        result = posix_fallocate(fd, offset, length);
13389
0
        Py_END_ALLOW_THREADS
13390
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13391
13392
0
    if (result == 0)
13393
0
        Py_RETURN_NONE;
13394
13395
0
    if (async_err)
13396
0
        return NULL;
13397
13398
0
    errno = result;
13399
0
    return posix_error();
13400
0
}
13401
#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */
13402
13403
13404
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
13405
/*[clinic input]
13406
os.posix_fadvise
13407
13408
    fd: int
13409
    offset: Py_off_t
13410
    length: Py_off_t
13411
    advice: int
13412
    /
13413
13414
Announce an intention to access data in a specific pattern.
13415
13416
Announce an intention to access data in a specific pattern, thus allowing
13417
the kernel to make optimizations.
13418
The advice applies to the region of the file specified by fd starting at
13419
offset and continuing for length bytes.
13420
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13421
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13422
POSIX_FADV_DONTNEED.
13423
[clinic start generated code]*/
13424
13425
static PyObject *
13426
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13427
                      Py_off_t length, int advice)
13428
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13429
0
{
13430
0
    int result;
13431
0
    int async_err = 0;
13432
13433
0
    do {
13434
0
        Py_BEGIN_ALLOW_THREADS
13435
0
        result = posix_fadvise(fd, offset, length, advice);
13436
0
        Py_END_ALLOW_THREADS
13437
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13438
13439
0
    if (result == 0)
13440
0
        Py_RETURN_NONE;
13441
13442
0
    if (async_err)
13443
0
        return NULL;
13444
13445
0
    errno = result;
13446
0
    return posix_error();
13447
0
}
13448
#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
13449
13450
13451
#ifdef MS_WINDOWS
13452
static PyObject*
13453
win32_putenv(PyObject *name, PyObject *value)
13454
{
13455
    /* Search from index 1 because on Windows starting '=' is allowed for
13456
       defining hidden environment variables. */
13457
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13458
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13459
    {
13460
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13461
        return NULL;
13462
    }
13463
    PyObject *unicode;
13464
    if (value != NULL) {
13465
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13466
    }
13467
    else {
13468
        unicode = PyUnicode_FromFormat("%U=", name);
13469
    }
13470
    if (unicode == NULL) {
13471
        return NULL;
13472
    }
13473
13474
    Py_ssize_t size;
13475
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13476
    Py_DECREF(unicode);
13477
13478
    if (env == NULL) {
13479
        return NULL;
13480
    }
13481
    if (size > _MAX_ENV) {
13482
        PyErr_Format(PyExc_ValueError,
13483
                     "the environment variable is longer than %u characters",
13484
                     _MAX_ENV);
13485
        PyMem_Free(env);
13486
        return NULL;
13487
    }
13488
    if (wcslen(env) != (size_t)size) {
13489
        PyErr_SetString(PyExc_ValueError,
13490
                        "embedded null character");
13491
        PyMem_Free(env);
13492
        return NULL;
13493
    }
13494
13495
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13496
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13497
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13498
13499
       Prefer _wputenv() to be compatible with C libraries using CRT
13500
       variables and CRT functions using these variables (ex: getenv()). */
13501
    int err = _wputenv(env);
13502
13503
    if (err) {
13504
        posix_error();
13505
        PyMem_Free(env);
13506
        return NULL;
13507
    }
13508
    PyMem_Free(env);
13509
13510
    Py_RETURN_NONE;
13511
}
13512
#endif
13513
13514
13515
#ifdef MS_WINDOWS
13516
/*[clinic input]
13517
os.putenv
13518
13519
    name: unicode
13520
    value: unicode
13521
    /
13522
13523
Change or add an environment variable.
13524
[clinic start generated code]*/
13525
13526
static PyObject *
13527
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13528
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13529
{
13530
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13531
        return NULL;
13532
    }
13533
    return win32_putenv(name, value);
13534
}
13535
#else
13536
/*[clinic input]
13537
os.putenv
13538
13539
    name: unicode_fs_encoded
13540
    value: unicode_fs_encoded
13541
    /
13542
13543
Change or add an environment variable.
13544
[clinic start generated code]*/
13545
13546
static PyObject *
13547
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13548
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13549
0
{
13550
0
    const char *name_string = PyBytes_AS_STRING(name);
13551
0
    const char *value_string = PyBytes_AS_STRING(value);
13552
13553
0
    if (strchr(name_string, '=') != NULL) {
13554
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13555
0
        return NULL;
13556
0
    }
13557
13558
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13559
0
        return NULL;
13560
0
    }
13561
13562
0
    if (setenv(name_string, value_string, 1)) {
13563
0
        return posix_error();
13564
0
    }
13565
0
    Py_RETURN_NONE;
13566
0
}
13567
#endif  /* !defined(MS_WINDOWS) */
13568
13569
13570
#ifdef MS_WINDOWS
13571
/*[clinic input]
13572
os.unsetenv
13573
    name: unicode
13574
    /
13575
13576
Delete an environment variable.
13577
[clinic start generated code]*/
13578
13579
static PyObject *
13580
os_unsetenv_impl(PyObject *module, PyObject *name)
13581
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13582
{
13583
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13584
        return NULL;
13585
    }
13586
    return win32_putenv(name, NULL);
13587
}
13588
#else
13589
/*[clinic input]
13590
os.unsetenv
13591
    name: unicode_fs_encoded
13592
    /
13593
13594
Delete an environment variable.
13595
[clinic start generated code]*/
13596
13597
static PyObject *
13598
os_unsetenv_impl(PyObject *module, PyObject *name)
13599
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13600
0
{
13601
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13602
0
        return NULL;
13603
0
    }
13604
#ifdef HAVE_BROKEN_UNSETENV
13605
    unsetenv(PyBytes_AS_STRING(name));
13606
#else
13607
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13608
0
    if (err) {
13609
0
        return posix_error();
13610
0
    }
13611
0
#endif
13612
13613
0
    Py_RETURN_NONE;
13614
0
}
13615
#endif /* !MS_WINDOWS */
13616
13617
13618
#ifdef HAVE_CLEARENV
13619
/*[clinic input]
13620
os._clearenv
13621
[clinic start generated code]*/
13622
13623
static PyObject *
13624
os__clearenv_impl(PyObject *module)
13625
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13626
0
{
13627
0
    errno = 0;
13628
0
    int err = clearenv();
13629
0
    if (err) {
13630
0
        return posix_error();
13631
0
    }
13632
0
    Py_RETURN_NONE;
13633
0
}
13634
#endif
13635
13636
13637
/*[clinic input]
13638
os.strerror
13639
13640
    code: int
13641
    /
13642
13643
Translate an error code to a message string.
13644
[clinic start generated code]*/
13645
13646
static PyObject *
13647
os_strerror_impl(PyObject *module, int code)
13648
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13649
0
{
13650
0
    char *message = strerror(code);
13651
0
    if (message == NULL) {
13652
0
        PyErr_SetString(PyExc_ValueError,
13653
0
                        "strerror() argument out of range");
13654
0
        return NULL;
13655
0
    }
13656
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13657
0
}
13658
13659
13660
#ifdef HAVE_SYS_WAIT_H
13661
#ifdef WCOREDUMP
13662
/*[clinic input]
13663
os.WCOREDUMP -> bool
13664
13665
    status: int
13666
    /
13667
13668
Return True if the process returning status was dumped to a core file.
13669
[clinic start generated code]*/
13670
13671
static int
13672
os_WCOREDUMP_impl(PyObject *module, int status)
13673
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13674
0
{
13675
0
    WAIT_TYPE wait_status;
13676
0
    WAIT_STATUS_INT(wait_status) = status;
13677
0
    return WCOREDUMP(wait_status);
13678
0
}
13679
#endif /* WCOREDUMP */
13680
13681
13682
#ifdef WIFCONTINUED
13683
/*[clinic input]
13684
os.WIFCONTINUED -> bool
13685
13686
    status: int
13687
13688
Return True if a particular process was continued from a job control stop.
13689
13690
Return True if the process returning status was continued from a
13691
job control stop.
13692
[clinic start generated code]*/
13693
13694
static int
13695
os_WIFCONTINUED_impl(PyObject *module, int status)
13696
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13697
0
{
13698
0
    WAIT_TYPE wait_status;
13699
0
    WAIT_STATUS_INT(wait_status) = status;
13700
0
    return WIFCONTINUED(wait_status);
13701
0
}
13702
#endif /* WIFCONTINUED */
13703
13704
13705
#ifdef WIFSTOPPED
13706
/*[clinic input]
13707
os.WIFSTOPPED -> bool
13708
13709
    status: int
13710
13711
Return True if the process returning status was stopped.
13712
[clinic start generated code]*/
13713
13714
static int
13715
os_WIFSTOPPED_impl(PyObject *module, int status)
13716
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13717
0
{
13718
0
    WAIT_TYPE wait_status;
13719
0
    WAIT_STATUS_INT(wait_status) = status;
13720
0
    return WIFSTOPPED(wait_status);
13721
0
}
13722
#endif /* WIFSTOPPED */
13723
13724
13725
#ifdef WIFSIGNALED
13726
/*[clinic input]
13727
os.WIFSIGNALED -> bool
13728
13729
    status: int
13730
13731
Return True if the process returning status was terminated by a signal.
13732
[clinic start generated code]*/
13733
13734
static int
13735
os_WIFSIGNALED_impl(PyObject *module, int status)
13736
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13737
0
{
13738
0
    WAIT_TYPE wait_status;
13739
0
    WAIT_STATUS_INT(wait_status) = status;
13740
0
    return WIFSIGNALED(wait_status);
13741
0
}
13742
#endif /* WIFSIGNALED */
13743
13744
13745
#ifdef WIFEXITED
13746
/*[clinic input]
13747
@permit_long_summary
13748
os.WIFEXITED -> bool
13749
13750
    status: int
13751
13752
Return True if the process returning status exited via the exit() system call.
13753
[clinic start generated code]*/
13754
13755
static int
13756
os_WIFEXITED_impl(PyObject *module, int status)
13757
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13758
0
{
13759
0
    WAIT_TYPE wait_status;
13760
0
    WAIT_STATUS_INT(wait_status) = status;
13761
0
    return WIFEXITED(wait_status);
13762
0
}
13763
#endif /* WIFEXITED */
13764
13765
13766
#ifdef WEXITSTATUS
13767
/*[clinic input]
13768
os.WEXITSTATUS -> int
13769
13770
    status: int
13771
13772
Return the process return code from status.
13773
[clinic start generated code]*/
13774
13775
static int
13776
os_WEXITSTATUS_impl(PyObject *module, int status)
13777
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13778
0
{
13779
0
    WAIT_TYPE wait_status;
13780
0
    WAIT_STATUS_INT(wait_status) = status;
13781
0
    return WEXITSTATUS(wait_status);
13782
0
}
13783
#endif /* WEXITSTATUS */
13784
13785
13786
#ifdef WTERMSIG
13787
/*[clinic input]
13788
@permit_long_summary
13789
os.WTERMSIG -> int
13790
13791
    status: int
13792
13793
Return the signal that terminated the process that provided the status value.
13794
[clinic start generated code]*/
13795
13796
static int
13797
os_WTERMSIG_impl(PyObject *module, int status)
13798
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13799
0
{
13800
0
    WAIT_TYPE wait_status;
13801
0
    WAIT_STATUS_INT(wait_status) = status;
13802
0
    return WTERMSIG(wait_status);
13803
0
}
13804
#endif /* WTERMSIG */
13805
13806
13807
#ifdef WSTOPSIG
13808
/*[clinic input]
13809
os.WSTOPSIG -> int
13810
13811
    status: int
13812
13813
Return the signal that stopped the process that provided the status value.
13814
[clinic start generated code]*/
13815
13816
static int
13817
os_WSTOPSIG_impl(PyObject *module, int status)
13818
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13819
0
{
13820
0
    WAIT_TYPE wait_status;
13821
0
    WAIT_STATUS_INT(wait_status) = status;
13822
0
    return WSTOPSIG(wait_status);
13823
0
}
13824
#endif /* WSTOPSIG */
13825
#endif /* HAVE_SYS_WAIT_H */
13826
13827
13828
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13829
#ifdef _SCO_DS
13830
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13831
   needed definitions in sys/statvfs.h */
13832
#define _SVID3
13833
#endif
13834
#include <sys/statvfs.h>
13835
13836
#ifdef __APPLE__
13837
/* On macOS struct statvfs uses 32-bit integers for block counts,
13838
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13839
 * os.statvfs is implemented in terms of statfs(2).
13840
 */
13841
13842
static PyObject*
13843
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13844
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13845
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13846
    if (v == NULL) {
13847
        return NULL;
13848
    }
13849
13850
    long flags = 0;
13851
    if (st.f_flags & MNT_RDONLY) {
13852
        flags |= ST_RDONLY;
13853
    }
13854
    if (st.f_flags & MNT_NOSUID) {
13855
        flags |= ST_NOSUID;
13856
    }
13857
13858
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13859
13860
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13861
    do {                                                 \
13862
        PyObject *obj = (EXPR);                          \
13863
        if (obj == NULL) {                               \
13864
            Py_DECREF((SEQ));                            \
13865
            return NULL;                                 \
13866
        }                                                \
13867
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13868
    } while (0)
13869
13870
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13871
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13872
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13873
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13874
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13875
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13876
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13877
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13878
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13879
13880
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13881
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13882
13883
#undef SET_ITEM
13884
13885
    return v;
13886
}
13887
13888
#else
13889
13890
13891
13892
static PyObject*
13893
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13894
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13895
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13896
0
    if (v == NULL)
13897
0
        return NULL;
13898
13899
0
    int pos = 0;
13900
13901
0
#define SET_RESULT(CALL)                                     \
13902
0
    do {                                                     \
13903
0
        PyObject *item = (CALL);                             \
13904
0
        if (item == NULL) {                                  \
13905
0
            Py_DECREF(v);                                    \
13906
0
            return NULL;                                     \
13907
0
        }                                                    \
13908
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13909
0
    } while(0)
13910
13911
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13912
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13913
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13914
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13915
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13916
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13917
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13918
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13919
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13920
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13921
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13922
#else
13923
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13924
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13925
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13926
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13927
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13928
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13929
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13930
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13931
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13932
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13933
#endif
13934
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13935
 * (issue #32390). */
13936
#if defined(_AIX) && defined(_ALL_SOURCE)
13937
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13938
#else
13939
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13940
0
#endif
13941
13942
0
#undef SET_RESULT
13943
13944
0
    return v;
13945
0
}
13946
13947
#endif
13948
13949
13950
/*[clinic input]
13951
os.fstatvfs
13952
    fd: int
13953
    /
13954
13955
Perform an fstatvfs system call on the given fd.
13956
13957
Equivalent to statvfs(fd).
13958
[clinic start generated code]*/
13959
13960
static PyObject *
13961
os_fstatvfs_impl(PyObject *module, int fd)
13962
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13963
0
{
13964
0
    int result;
13965
0
    int async_err = 0;
13966
#ifdef __APPLE__
13967
    struct statfs st;
13968
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13969
     * the former uses 32-bit values for block counts.
13970
     */
13971
    do {
13972
        Py_BEGIN_ALLOW_THREADS
13973
        result = fstatfs(fd, &st);
13974
        Py_END_ALLOW_THREADS
13975
    } while (result != 0 && errno == EINTR &&
13976
             !(async_err = PyErr_CheckSignals()));
13977
    if (result != 0)
13978
        return (!async_err) ? posix_error() : NULL;
13979
13980
    return _pystatvfs_fromstructstatfs(module, st);
13981
#else
13982
0
    struct statvfs st;
13983
13984
0
    do {
13985
0
        Py_BEGIN_ALLOW_THREADS
13986
0
        result = fstatvfs(fd, &st);
13987
0
        Py_END_ALLOW_THREADS
13988
0
    } while (result != 0 && errno == EINTR &&
13989
0
             !(async_err = PyErr_CheckSignals()));
13990
0
    if (result != 0)
13991
0
        return (!async_err) ? posix_error() : NULL;
13992
13993
0
    return _pystatvfs_fromstructstatvfs(module, st);
13994
0
#endif
13995
0
}
13996
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
13997
13998
13999
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14000
#include <sys/statvfs.h>
14001
/*[clinic input]
14002
os.statvfs
14003
14004
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14005
14006
Perform a statvfs system call on the given path.
14007
14008
path may always be specified as a string.
14009
On some platforms, path may also be specified as an open file descriptor.
14010
  If this functionality is unavailable, using it raises an exception.
14011
[clinic start generated code]*/
14012
14013
static PyObject *
14014
os_statvfs_impl(PyObject *module, path_t *path)
14015
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
14016
0
{
14017
0
    int result;
14018
14019
#ifdef __APPLE__
14020
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14021
     * the former uses 32-bit values for block counts.
14022
     */
14023
    struct statfs st;
14024
14025
    Py_BEGIN_ALLOW_THREADS
14026
    if (path->fd != -1) {
14027
        result = fstatfs(path->fd, &st);
14028
    }
14029
    else
14030
        result = statfs(path->narrow, &st);
14031
    Py_END_ALLOW_THREADS
14032
14033
    if (result) {
14034
        return path_error(path);
14035
    }
14036
14037
    return _pystatvfs_fromstructstatfs(module, st);
14038
14039
#else
14040
0
    struct statvfs st;
14041
14042
0
    Py_BEGIN_ALLOW_THREADS
14043
0
#ifdef HAVE_FSTATVFS
14044
0
    if (path->fd != -1) {
14045
0
        result = fstatvfs(path->fd, &st);
14046
0
    }
14047
0
    else
14048
0
#endif
14049
0
        result = statvfs(path->narrow, &st);
14050
0
    Py_END_ALLOW_THREADS
14051
14052
0
    if (result) {
14053
0
        return path_error(path);
14054
0
    }
14055
14056
0
    return _pystatvfs_fromstructstatvfs(module, st);
14057
0
#endif
14058
0
}
14059
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14060
14061
14062
#ifdef MS_WINDOWS
14063
/*[clinic input]
14064
os._getdiskusage
14065
14066
    path: path_t
14067
14068
Return disk usage statistics about the given path as a (total, free) tuple.
14069
[clinic start generated code]*/
14070
14071
static PyObject *
14072
os__getdiskusage_impl(PyObject *module, path_t *path)
14073
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
14074
{
14075
    BOOL retval;
14076
    ULARGE_INTEGER _, total, free;
14077
    DWORD err = 0;
14078
14079
    Py_BEGIN_ALLOW_THREADS
14080
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14081
    Py_END_ALLOW_THREADS
14082
    if (retval == 0) {
14083
        if (GetLastError() == ERROR_DIRECTORY) {
14084
            wchar_t *dir_path = NULL;
14085
14086
            dir_path = PyMem_New(wchar_t, path->length + 1);
14087
            if (dir_path == NULL) {
14088
                return PyErr_NoMemory();
14089
            }
14090
14091
            wcscpy_s(dir_path, path->length + 1, path->wide);
14092
14093
            if (_dirnameW(dir_path) != -1) {
14094
                Py_BEGIN_ALLOW_THREADS
14095
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14096
                Py_END_ALLOW_THREADS
14097
            }
14098
            /* Record the last error in case it's modified by PyMem_Free. */
14099
            err = GetLastError();
14100
            PyMem_Free(dir_path);
14101
            if (retval) {
14102
                goto success;
14103
            }
14104
        }
14105
        return PyErr_SetFromWindowsErr(err);
14106
    }
14107
14108
success:
14109
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14110
}
14111
#endif /* MS_WINDOWS */
14112
14113
14114
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14115
 * It maps strings representing configuration variable names to
14116
 * integer values, allowing those functions to be called with the
14117
 * magic names instead of polluting the module's namespace with tons of
14118
 * rarely-used constants.  There are three separate tables that use
14119
 * these definitions.
14120
 *
14121
 * This code is always included, even if none of the interfaces that
14122
 * need it are included.  The #if hackery needed to avoid it would be
14123
 * sufficiently pervasive that it's not worth the loss of readability.
14124
 */
14125
struct constdef {
14126
    const char *name;
14127
    int value;
14128
};
14129
14130
static int
14131
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14132
0
{
14133
0
    if (PyUnicode_Check(arg)) {
14134
0
        PyObject *table = PyObject_GetAttrString(module, tablename);
14135
0
        if (table == NULL) {
14136
0
            return 0;
14137
0
        }
14138
14139
0
        arg = PyObject_GetItem(table, arg);
14140
0
        Py_DECREF(table);
14141
0
        if (arg == NULL) {
14142
0
            PyErr_SetString(
14143
0
                PyExc_ValueError, "unrecognized configuration name");
14144
0
            return 0;
14145
0
        }
14146
0
    } else {
14147
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14148
0
    }
14149
14150
0
    int success = 0;
14151
0
    if (!PyIndex_Check(arg)) {
14152
0
        PyErr_SetString(PyExc_TypeError,
14153
0
            "configuration names must be strings or integers");
14154
0
    } else {
14155
0
        int value = PyLong_AsInt(arg);
14156
0
        if (!(value == -1 && PyErr_Occurred())) {
14157
0
            *valuep = value;
14158
0
            success = 1;
14159
0
        }
14160
0
    }
14161
0
    Py_DECREF(arg);
14162
0
    return success;
14163
0
}
14164
14165
14166
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14167
static struct constdef  posix_constants_pathconf[] = {
14168
#ifdef _PC_ABI_AIO_XFER_MAX
14169
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14170
#endif
14171
#ifdef _PC_ABI_ASYNC_IO
14172
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14173
#endif
14174
#ifdef _PC_ASYNC_IO
14175
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14176
#endif
14177
#ifdef _PC_CHOWN_RESTRICTED
14178
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14179
#endif
14180
#ifdef _PC_FILESIZEBITS
14181
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14182
#endif
14183
#ifdef _PC_LAST
14184
    {"PC_LAST", _PC_LAST},
14185
#endif
14186
#ifdef _PC_LINK_MAX
14187
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14188
#endif
14189
#ifdef _PC_MAX_CANON
14190
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14191
#endif
14192
#ifdef _PC_MAX_INPUT
14193
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14194
#endif
14195
#ifdef _PC_NAME_MAX
14196
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14197
#endif
14198
#ifdef _PC_NO_TRUNC
14199
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14200
#endif
14201
#ifdef _PC_PATH_MAX
14202
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14203
#endif
14204
#ifdef _PC_PIPE_BUF
14205
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14206
#endif
14207
#ifdef _PC_PRIO_IO
14208
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14209
#endif
14210
#ifdef _PC_SOCK_MAXBUF
14211
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14212
#endif
14213
#ifdef _PC_SYNC_IO
14214
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14215
#endif
14216
#ifdef _PC_VDISABLE
14217
    {"PC_VDISABLE",     _PC_VDISABLE},
14218
#endif
14219
#ifdef _PC_ACL_ENABLED
14220
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14221
#endif
14222
#ifdef _PC_MIN_HOLE_SIZE
14223
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14224
#endif
14225
#ifdef _PC_ALLOC_SIZE_MIN
14226
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14227
#endif
14228
#ifdef _PC_REC_INCR_XFER_SIZE
14229
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14230
#endif
14231
#ifdef _PC_REC_MAX_XFER_SIZE
14232
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14233
#endif
14234
#ifdef _PC_REC_MIN_XFER_SIZE
14235
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14236
#endif
14237
#ifdef _PC_REC_XFER_ALIGN
14238
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14239
#endif
14240
#ifdef _PC_SYMLINK_MAX
14241
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14242
#endif
14243
#ifdef _PC_XATTR_ENABLED
14244
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14245
#endif
14246
#ifdef _PC_XATTR_EXISTS
14247
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14248
#endif
14249
#ifdef _PC_TIMESTAMP_RESOLUTION
14250
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14251
#endif
14252
};
14253
#endif
14254
14255
14256
#ifdef HAVE_FPATHCONF
14257
/*[clinic input]
14258
os.fpathconf -> long
14259
14260
    fd: fildes
14261
    name: confname(table="pathconf_names")
14262
    /
14263
14264
Return the configuration limit name for the file descriptor fd.
14265
14266
If there is no limit, return -1.
14267
[clinic start generated code]*/
14268
14269
static long
14270
os_fpathconf_impl(PyObject *module, int fd, int name)
14271
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14272
0
{
14273
0
    long limit;
14274
14275
0
    errno = 0;
14276
0
    limit = fpathconf(fd, name);
14277
0
    if (limit == -1 && errno != 0)
14278
0
        posix_error();
14279
14280
0
    return limit;
14281
0
}
14282
#endif /* HAVE_FPATHCONF */
14283
14284
14285
#ifdef HAVE_PATHCONF
14286
/*[clinic input]
14287
os.pathconf -> long
14288
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14289
    name: confname(table="pathconf_names")
14290
14291
Return the configuration limit name for the file or directory path.
14292
14293
If there is no limit, return -1.
14294
On some platforms, path may also be specified as an open file descriptor.
14295
  If this functionality is unavailable, using it raises an exception.
14296
[clinic start generated code]*/
14297
14298
static long
14299
os_pathconf_impl(PyObject *module, path_t *path, int name)
14300
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
14301
0
{
14302
0
    long limit;
14303
14304
0
    errno = 0;
14305
0
#ifdef HAVE_FPATHCONF
14306
0
    if (path->fd != -1)
14307
0
        limit = fpathconf(path->fd, name);
14308
0
    else
14309
0
#endif
14310
0
        limit = pathconf(path->narrow, name);
14311
0
    if (limit == -1 && errno != 0) {
14312
0
        if (errno == EINVAL)
14313
            /* could be a path or name problem */
14314
0
            posix_error();
14315
0
        else
14316
0
            path_error(path);
14317
0
    }
14318
14319
0
    return limit;
14320
0
}
14321
#endif /* HAVE_PATHCONF */
14322
14323
#ifdef HAVE_CONFSTR
14324
static struct constdef posix_constants_confstr[] = {
14325
#ifdef _CS_ARCHITECTURE
14326
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14327
#endif
14328
#ifdef _CS_GNU_LIBC_VERSION
14329
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14330
#endif
14331
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14332
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14333
#endif
14334
#ifdef _CS_HOSTNAME
14335
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14336
#endif
14337
#ifdef _CS_HW_PROVIDER
14338
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14339
#endif
14340
#ifdef _CS_HW_SERIAL
14341
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14342
#endif
14343
#ifdef _CS_INITTAB_NAME
14344
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14345
#endif
14346
#ifdef _CS_LFS64_CFLAGS
14347
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14348
#endif
14349
#ifdef _CS_LFS64_LDFLAGS
14350
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14351
#endif
14352
#ifdef _CS_LFS64_LIBS
14353
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14354
#endif
14355
#ifdef _CS_LFS64_LINTFLAGS
14356
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14357
#endif
14358
#ifdef _CS_LFS_CFLAGS
14359
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14360
#endif
14361
#ifdef _CS_LFS_LDFLAGS
14362
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14363
#endif
14364
#ifdef _CS_LFS_LIBS
14365
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14366
#endif
14367
#ifdef _CS_LFS_LINTFLAGS
14368
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14369
#endif
14370
#ifdef _CS_MACHINE
14371
    {"CS_MACHINE",      _CS_MACHINE},
14372
#endif
14373
#ifdef _CS_PATH
14374
    {"CS_PATH", _CS_PATH},
14375
#endif
14376
#ifdef _CS_RELEASE
14377
    {"CS_RELEASE",      _CS_RELEASE},
14378
#endif
14379
#ifdef _CS_SRPC_DOMAIN
14380
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14381
#endif
14382
#ifdef _CS_SYSNAME
14383
    {"CS_SYSNAME",      _CS_SYSNAME},
14384
#endif
14385
#ifdef _CS_VERSION
14386
    {"CS_VERSION",      _CS_VERSION},
14387
#endif
14388
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14389
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14390
#endif
14391
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14392
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14393
#endif
14394
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14395
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14396
#endif
14397
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14398
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14399
#endif
14400
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14401
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14402
#endif
14403
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14404
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14405
#endif
14406
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14407
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14408
#endif
14409
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14410
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14411
#endif
14412
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14413
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14414
#endif
14415
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14416
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14417
#endif
14418
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14419
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14420
#endif
14421
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14422
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14423
#endif
14424
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14425
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14426
#endif
14427
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14428
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14429
#endif
14430
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14431
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14432
#endif
14433
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14434
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14435
#endif
14436
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14437
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14438
#endif
14439
#ifdef _MIPS_CS_BASE
14440
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14441
#endif
14442
#ifdef _MIPS_CS_HOSTID
14443
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14444
#endif
14445
#ifdef _MIPS_CS_HW_NAME
14446
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14447
#endif
14448
#ifdef _MIPS_CS_NUM_PROCESSORS
14449
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14450
#endif
14451
#ifdef _MIPS_CS_OSREL_MAJ
14452
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14453
#endif
14454
#ifdef _MIPS_CS_OSREL_MIN
14455
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14456
#endif
14457
#ifdef _MIPS_CS_OSREL_PATCH
14458
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14459
#endif
14460
#ifdef _MIPS_CS_OS_NAME
14461
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14462
#endif
14463
#ifdef _MIPS_CS_OS_PROVIDER
14464
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14465
#endif
14466
#ifdef _MIPS_CS_PROCESSORS
14467
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14468
#endif
14469
#ifdef _MIPS_CS_SERIAL
14470
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14471
#endif
14472
#ifdef _MIPS_CS_VENDOR
14473
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14474
#endif
14475
};
14476
14477
14478
/*[clinic input]
14479
os.confstr
14480
14481
    name: confname(table="confstr_names")
14482
    /
14483
14484
Return a string-valued system configuration variable.
14485
[clinic start generated code]*/
14486
14487
static PyObject *
14488
os_confstr_impl(PyObject *module, int name)
14489
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14490
0
{
14491
0
    PyObject *result = NULL;
14492
0
    char buffer[255];
14493
0
    size_t len;
14494
14495
0
    errno = 0;
14496
0
    len = confstr(name, buffer, sizeof(buffer));
14497
0
    if (len == 0) {
14498
0
        if (errno) {
14499
0
            posix_error();
14500
0
            return NULL;
14501
0
        }
14502
0
        else {
14503
0
            Py_RETURN_NONE;
14504
0
        }
14505
0
    }
14506
14507
0
    if (len >= sizeof(buffer)) {
14508
0
        size_t len2;
14509
0
        char *buf = PyMem_Malloc(len);
14510
0
        if (buf == NULL)
14511
0
            return PyErr_NoMemory();
14512
0
        len2 = confstr(name, buf, len);
14513
0
        assert(len == len2);
14514
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14515
0
        PyMem_Free(buf);
14516
0
    }
14517
0
    else
14518
0
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14519
0
    return result;
14520
0
}
14521
#endif /* HAVE_CONFSTR */
14522
14523
14524
#ifdef HAVE_SYSCONF
14525
static struct constdef posix_constants_sysconf[] = {
14526
#ifdef _SC_2_CHAR_TERM
14527
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14528
#endif
14529
#ifdef _SC_2_C_BIND
14530
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14531
#endif
14532
#ifdef _SC_2_C_DEV
14533
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14534
#endif
14535
#ifdef _SC_2_C_VERSION
14536
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14537
#endif
14538
#ifdef _SC_2_FORT_DEV
14539
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14540
#endif
14541
#ifdef _SC_2_FORT_RUN
14542
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14543
#endif
14544
#ifdef _SC_2_LOCALEDEF
14545
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14546
#endif
14547
#ifdef _SC_2_SW_DEV
14548
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14549
#endif
14550
#ifdef _SC_2_UPE
14551
    {"SC_2_UPE",        _SC_2_UPE},
14552
#endif
14553
#ifdef _SC_2_VERSION
14554
    {"SC_2_VERSION",    _SC_2_VERSION},
14555
#endif
14556
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14557
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14558
#endif
14559
#ifdef _SC_ACL
14560
    {"SC_ACL",  _SC_ACL},
14561
#endif
14562
#ifdef _SC_AIO_LISTIO_MAX
14563
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14564
#endif
14565
#ifdef _SC_AIO_MAX
14566
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14567
#endif
14568
#ifdef _SC_AIO_PRIO_DELTA_MAX
14569
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14570
#endif
14571
#ifdef _SC_ARG_MAX
14572
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14573
#endif
14574
#ifdef _SC_ASYNCHRONOUS_IO
14575
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14576
#endif
14577
#ifdef _SC_ATEXIT_MAX
14578
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14579
#endif
14580
#ifdef _SC_AUDIT
14581
    {"SC_AUDIT",        _SC_AUDIT},
14582
#endif
14583
#ifdef _SC_AVPHYS_PAGES
14584
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14585
#endif
14586
#ifdef _SC_BC_BASE_MAX
14587
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14588
#endif
14589
#ifdef _SC_BC_DIM_MAX
14590
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14591
#endif
14592
#ifdef _SC_BC_SCALE_MAX
14593
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14594
#endif
14595
#ifdef _SC_BC_STRING_MAX
14596
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14597
#endif
14598
#ifdef _SC_CAP
14599
    {"SC_CAP",  _SC_CAP},
14600
#endif
14601
#ifdef _SC_CHARCLASS_NAME_MAX
14602
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14603
#endif
14604
#ifdef _SC_CHAR_BIT
14605
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14606
#endif
14607
#ifdef _SC_CHAR_MAX
14608
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14609
#endif
14610
#ifdef _SC_CHAR_MIN
14611
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14612
#endif
14613
#ifdef _SC_CHILD_MAX
14614
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14615
#endif
14616
#ifdef _SC_CLK_TCK
14617
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14618
#endif
14619
#ifdef _SC_COHER_BLKSZ
14620
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14621
#endif
14622
#ifdef _SC_COLL_WEIGHTS_MAX
14623
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14624
#endif
14625
#ifdef _SC_DCACHE_ASSOC
14626
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14627
#endif
14628
#ifdef _SC_DCACHE_BLKSZ
14629
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14630
#endif
14631
#ifdef _SC_DCACHE_LINESZ
14632
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14633
#endif
14634
#ifdef _SC_DCACHE_SZ
14635
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14636
#endif
14637
#ifdef _SC_DCACHE_TBLKSZ
14638
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14639
#endif
14640
#ifdef _SC_DELAYTIMER_MAX
14641
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14642
#endif
14643
#ifdef _SC_EQUIV_CLASS_MAX
14644
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14645
#endif
14646
#ifdef _SC_EXPR_NEST_MAX
14647
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14648
#endif
14649
#ifdef _SC_FSYNC
14650
    {"SC_FSYNC",        _SC_FSYNC},
14651
#endif
14652
#ifdef _SC_GETGR_R_SIZE_MAX
14653
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14654
#endif
14655
#ifdef _SC_GETPW_R_SIZE_MAX
14656
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14657
#endif
14658
#ifdef _SC_ICACHE_ASSOC
14659
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14660
#endif
14661
#ifdef _SC_ICACHE_BLKSZ
14662
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14663
#endif
14664
#ifdef _SC_ICACHE_LINESZ
14665
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14666
#endif
14667
#ifdef _SC_ICACHE_SZ
14668
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14669
#endif
14670
#ifdef _SC_INF
14671
    {"SC_INF",  _SC_INF},
14672
#endif
14673
#ifdef _SC_INT_MAX
14674
    {"SC_INT_MAX",      _SC_INT_MAX},
14675
#endif
14676
#ifdef _SC_INT_MIN
14677
    {"SC_INT_MIN",      _SC_INT_MIN},
14678
#endif
14679
#ifdef _SC_IOV_MAX
14680
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14681
#endif
14682
#ifdef _SC_IP_SECOPTS
14683
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14684
#endif
14685
#ifdef _SC_JOB_CONTROL
14686
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14687
#endif
14688
#ifdef _SC_KERN_POINTERS
14689
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14690
#endif
14691
#ifdef _SC_KERN_SIM
14692
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14693
#endif
14694
#ifdef _SC_LINE_MAX
14695
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14696
#endif
14697
#ifdef _SC_LOGIN_NAME_MAX
14698
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14699
#endif
14700
#ifdef _SC_LOGNAME_MAX
14701
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14702
#endif
14703
#ifdef _SC_LONG_BIT
14704
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14705
#endif
14706
#ifdef _SC_MAC
14707
    {"SC_MAC",  _SC_MAC},
14708
#endif
14709
#ifdef _SC_MAPPED_FILES
14710
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14711
#endif
14712
#ifdef _SC_MAXPID
14713
    {"SC_MAXPID",       _SC_MAXPID},
14714
#endif
14715
#ifdef _SC_MB_LEN_MAX
14716
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14717
#endif
14718
#ifdef _SC_MEMLOCK
14719
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14720
#endif
14721
#ifdef _SC_MEMLOCK_RANGE
14722
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14723
#endif
14724
#ifdef _SC_MEMORY_PROTECTION
14725
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14726
#endif
14727
#ifdef _SC_MESSAGE_PASSING
14728
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14729
#endif
14730
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14731
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14732
#endif
14733
#ifdef _SC_MQ_OPEN_MAX
14734
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14735
#endif
14736
#ifdef _SC_MQ_PRIO_MAX
14737
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14738
#endif
14739
#ifdef _SC_NACLS_MAX
14740
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14741
#endif
14742
#ifdef _SC_NGROUPS_MAX
14743
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14744
#endif
14745
#ifdef _SC_NL_ARGMAX
14746
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14747
#endif
14748
#ifdef _SC_NL_LANGMAX
14749
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14750
#endif
14751
#ifdef _SC_NL_MSGMAX
14752
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14753
#endif
14754
#ifdef _SC_NL_NMAX
14755
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14756
#endif
14757
#ifdef _SC_NL_SETMAX
14758
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14759
#endif
14760
#ifdef _SC_NL_TEXTMAX
14761
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14762
#endif
14763
#ifdef _SC_NPROCESSORS_CONF
14764
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14765
#endif
14766
#ifdef _SC_NPROCESSORS_ONLN
14767
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14768
#endif
14769
#ifdef _SC_NPROC_CONF
14770
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14771
#endif
14772
#ifdef _SC_NPROC_ONLN
14773
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14774
#endif
14775
#ifdef _SC_NZERO
14776
    {"SC_NZERO",        _SC_NZERO},
14777
#endif
14778
#ifdef _SC_OPEN_MAX
14779
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14780
#endif
14781
#ifdef _SC_PAGESIZE
14782
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14783
#endif
14784
#ifdef _SC_PAGE_SIZE
14785
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14786
#endif
14787
#ifdef _SC_AIX_REALMEM
14788
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14789
#endif
14790
#ifdef _SC_PASS_MAX
14791
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14792
#endif
14793
#ifdef _SC_PHYS_PAGES
14794
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14795
#endif
14796
#ifdef _SC_PII
14797
    {"SC_PII",  _SC_PII},
14798
#endif
14799
#ifdef _SC_PII_INTERNET
14800
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14801
#endif
14802
#ifdef _SC_PII_INTERNET_DGRAM
14803
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14804
#endif
14805
#ifdef _SC_PII_INTERNET_STREAM
14806
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14807
#endif
14808
#ifdef _SC_PII_OSI
14809
    {"SC_PII_OSI",      _SC_PII_OSI},
14810
#endif
14811
#ifdef _SC_PII_OSI_CLTS
14812
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14813
#endif
14814
#ifdef _SC_PII_OSI_COTS
14815
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14816
#endif
14817
#ifdef _SC_PII_OSI_M
14818
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14819
#endif
14820
#ifdef _SC_PII_SOCKET
14821
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14822
#endif
14823
#ifdef _SC_PII_XTI
14824
    {"SC_PII_XTI",      _SC_PII_XTI},
14825
#endif
14826
#ifdef _SC_POLL
14827
    {"SC_POLL", _SC_POLL},
14828
#endif
14829
#ifdef _SC_PRIORITIZED_IO
14830
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14831
#endif
14832
#ifdef _SC_PRIORITY_SCHEDULING
14833
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14834
#endif
14835
#ifdef _SC_REALTIME_SIGNALS
14836
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14837
#endif
14838
#ifdef _SC_RE_DUP_MAX
14839
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14840
#endif
14841
#ifdef _SC_RTSIG_MAX
14842
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14843
#endif
14844
#ifdef _SC_SAVED_IDS
14845
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14846
#endif
14847
#ifdef _SC_SCHAR_MAX
14848
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14849
#endif
14850
#ifdef _SC_SCHAR_MIN
14851
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14852
#endif
14853
#ifdef _SC_SELECT
14854
    {"SC_SELECT",       _SC_SELECT},
14855
#endif
14856
#ifdef _SC_SEMAPHORES
14857
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14858
#endif
14859
#ifdef _SC_SEM_NSEMS_MAX
14860
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14861
#endif
14862
#ifdef _SC_SEM_VALUE_MAX
14863
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14864
#endif
14865
#ifdef _SC_SHARED_MEMORY_OBJECTS
14866
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14867
#endif
14868
#ifdef _SC_SHRT_MAX
14869
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14870
#endif
14871
#ifdef _SC_SHRT_MIN
14872
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14873
#endif
14874
#ifdef _SC_SIGQUEUE_MAX
14875
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14876
#endif
14877
#ifdef _SC_SIGRT_MAX
14878
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14879
#endif
14880
#ifdef _SC_SIGRT_MIN
14881
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14882
#endif
14883
#ifdef _SC_SOFTPOWER
14884
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14885
#endif
14886
#ifdef _SC_SPLIT_CACHE
14887
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14888
#endif
14889
#ifdef _SC_SSIZE_MAX
14890
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14891
#endif
14892
#ifdef _SC_STACK_PROT
14893
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14894
#endif
14895
#ifdef _SC_STREAM_MAX
14896
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14897
#endif
14898
#ifdef _SC_SYNCHRONIZED_IO
14899
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14900
#endif
14901
#ifdef _SC_THREADS
14902
    {"SC_THREADS",      _SC_THREADS},
14903
#endif
14904
#ifdef _SC_THREAD_ATTR_STACKADDR
14905
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14906
#endif
14907
#ifdef _SC_THREAD_ATTR_STACKSIZE
14908
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14909
#endif
14910
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14911
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14912
#endif
14913
#ifdef _SC_THREAD_KEYS_MAX
14914
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14915
#endif
14916
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14917
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14918
#endif
14919
#ifdef _SC_THREAD_PRIO_INHERIT
14920
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14921
#endif
14922
#ifdef _SC_THREAD_PRIO_PROTECT
14923
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14924
#endif
14925
#ifdef _SC_THREAD_PROCESS_SHARED
14926
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14927
#endif
14928
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14929
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14930
#endif
14931
#ifdef _SC_THREAD_STACK_MIN
14932
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14933
#endif
14934
#ifdef _SC_THREAD_THREADS_MAX
14935
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14936
#endif
14937
#ifdef _SC_TIMERS
14938
    {"SC_TIMERS",       _SC_TIMERS},
14939
#endif
14940
#ifdef _SC_TIMER_MAX
14941
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14942
#endif
14943
#ifdef _SC_TTY_NAME_MAX
14944
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14945
#endif
14946
#ifdef _SC_TZNAME_MAX
14947
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14948
#endif
14949
#ifdef _SC_T_IOV_MAX
14950
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14951
#endif
14952
#ifdef _SC_UCHAR_MAX
14953
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14954
#endif
14955
#ifdef _SC_UINT_MAX
14956
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14957
#endif
14958
#ifdef _SC_UIO_MAXIOV
14959
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14960
#endif
14961
#ifdef _SC_ULONG_MAX
14962
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14963
#endif
14964
#ifdef _SC_USHRT_MAX
14965
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14966
#endif
14967
#ifdef _SC_VERSION
14968
    {"SC_VERSION",      _SC_VERSION},
14969
#endif
14970
#ifdef _SC_WORD_BIT
14971
    {"SC_WORD_BIT",     _SC_WORD_BIT},
14972
#endif
14973
#ifdef _SC_XBS5_ILP32_OFF32
14974
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
14975
#endif
14976
#ifdef _SC_XBS5_ILP32_OFFBIG
14977
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
14978
#endif
14979
#ifdef _SC_XBS5_LP64_OFF64
14980
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
14981
#endif
14982
#ifdef _SC_XBS5_LPBIG_OFFBIG
14983
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
14984
#endif
14985
#ifdef _SC_XOPEN_CRYPT
14986
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
14987
#endif
14988
#ifdef _SC_XOPEN_ENH_I18N
14989
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
14990
#endif
14991
#ifdef _SC_XOPEN_LEGACY
14992
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
14993
#endif
14994
#ifdef _SC_XOPEN_REALTIME
14995
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
14996
#endif
14997
#ifdef _SC_XOPEN_REALTIME_THREADS
14998
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
14999
#endif
15000
#ifdef _SC_XOPEN_SHM
15001
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15002
#endif
15003
#ifdef _SC_XOPEN_UNIX
15004
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15005
#endif
15006
#ifdef _SC_XOPEN_VERSION
15007
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15008
#endif
15009
#ifdef _SC_XOPEN_XCU_VERSION
15010
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15011
#endif
15012
#ifdef _SC_XOPEN_XPG2
15013
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15014
#endif
15015
#ifdef _SC_XOPEN_XPG3
15016
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15017
#endif
15018
#ifdef _SC_XOPEN_XPG4
15019
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15020
#endif
15021
#ifdef _SC_MINSIGSTKSZ
15022
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15023
#endif
15024
};
15025
15026
15027
/*[clinic input]
15028
os.sysconf -> long
15029
    name: confname(table="sysconf_names")
15030
    /
15031
15032
Return an integer-valued system configuration variable.
15033
[clinic start generated code]*/
15034
15035
static long
15036
os_sysconf_impl(PyObject *module, int name)
15037
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15038
0
{
15039
0
    long value;
15040
15041
0
    errno = 0;
15042
0
    value = sysconf(name);
15043
0
    if (value == -1 && errno != 0)
15044
0
        posix_error();
15045
0
    return value;
15046
0
}
15047
#endif /* HAVE_SYSCONF */
15048
15049
15050
static int
15051
setup_confname_table(struct constdef *table, size_t tablesize,
15052
                     const char *tablename, PyObject *module)
15053
48
{
15054
48
    PyObject *d = PyDict_New();
15055
48
    if (d == NULL)
15056
0
        return -1;
15057
15058
2.94k
    for (size_t i=0; i < tablesize; ++i) {
15059
2.89k
        PyObject *o = PyLong_FromLong(table[i].value);
15060
2.89k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15061
0
            Py_XDECREF(o);
15062
0
            Py_DECREF(d);
15063
0
            return -1;
15064
0
        }
15065
2.89k
        Py_DECREF(o);
15066
2.89k
    }
15067
48
    return PyModule_Add(module, tablename, d);
15068
48
}
15069
15070
/* Return -1 on failure, 0 on success. */
15071
static int
15072
setup_confname_tables(PyObject *module)
15073
16
{
15074
16
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15075
16
    if (setup_confname_table(posix_constants_pathconf,
15076
16
                             sizeof(posix_constants_pathconf)
15077
16
                               / sizeof(struct constdef),
15078
16
                             "pathconf_names", module))
15079
0
        return -1;
15080
16
#endif
15081
16
#ifdef HAVE_CONFSTR
15082
16
    if (setup_confname_table(posix_constants_confstr,
15083
16
                             sizeof(posix_constants_confstr)
15084
16
                               / sizeof(struct constdef),
15085
16
                             "confstr_names", module))
15086
0
        return -1;
15087
16
#endif
15088
16
#ifdef HAVE_SYSCONF
15089
16
    if (setup_confname_table(posix_constants_sysconf,
15090
16
                             sizeof(posix_constants_sysconf)
15091
16
                               / sizeof(struct constdef),
15092
16
                             "sysconf_names", module))
15093
0
        return -1;
15094
16
#endif
15095
16
    return 0;
15096
16
}
15097
15098
15099
/*[clinic input]
15100
os.abort
15101
15102
Abort the interpreter immediately.
15103
15104
This function 'dumps core' or otherwise fails in the hardest way possible
15105
on the hosting operating system.  This function never returns.
15106
[clinic start generated code]*/
15107
15108
static PyObject *
15109
os_abort_impl(PyObject *module)
15110
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
15111
0
{
15112
0
    abort();
15113
    /*NOTREACHED*/
15114
#ifndef __clang__
15115
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15116
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15117
       is smarter and emits a warning on the return. */
15118
    Py_FatalError("abort() called from Python code didn't abort!");
15119
    return NULL;
15120
#endif
15121
0
}
15122
15123
#ifdef MS_WINDOWS
15124
/* Grab ShellExecute dynamically from shell32 */
15125
static int has_ShellExecute = -1;
15126
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15127
                                              LPCWSTR, INT);
15128
static int
15129
check_ShellExecute(void)
15130
{
15131
    HINSTANCE hShell32;
15132
15133
    /* only recheck */
15134
    if (-1 == has_ShellExecute) {
15135
        Py_BEGIN_ALLOW_THREADS
15136
        /* Security note: this call is not vulnerable to "DLL hijacking".
15137
           SHELL32 is part of "KnownDLLs" and so Windows always load
15138
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15139
           in the DLL search path. */
15140
        hShell32 = LoadLibraryW(L"SHELL32");
15141
        if (hShell32) {
15142
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15143
                                            "ShellExecuteW");
15144
            has_ShellExecute = Py_ShellExecuteW != NULL;
15145
        } else {
15146
            has_ShellExecute = 0;
15147
        }
15148
        Py_END_ALLOW_THREADS
15149
    }
15150
    return has_ShellExecute;
15151
}
15152
15153
15154
/*[clinic input]
15155
os.startfile
15156
    filepath: path_t
15157
    operation: Py_UNICODE = NULL
15158
    arguments: Py_UNICODE = NULL
15159
    cwd: path_t(nullable=True) = None
15160
    show_cmd: int = 1
15161
15162
Start a file with its associated application.
15163
15164
When "operation" is not specified or "open", this acts like
15165
double-clicking the file in Explorer, or giving the file name as an
15166
argument to the DOS "start" command: the file is opened with whatever
15167
application (if any) its extension is associated.
15168
When another "operation" is given, it specifies what should be done with
15169
the file.  A typical operation is "print".
15170
15171
"arguments" is passed to the application, but should be omitted if the
15172
file is a document.
15173
15174
"cwd" is the working directory for the operation. If "filepath" is
15175
relative, it will be resolved against this directory. This argument
15176
should usually be an absolute path.
15177
15178
"show_cmd" can be used to override the recommended visibility option.
15179
See the Windows ShellExecute documentation for values.
15180
15181
startfile returns as soon as the associated application is launched.
15182
There is no option to wait for the application to close, and no way
15183
to retrieve the application's exit status.
15184
15185
The filepath is relative to the current directory.  If you want to use
15186
an absolute path, make sure the first character is not a slash ("/");
15187
the underlying Win32 ShellExecute function doesn't work if it is.
15188
[clinic start generated code]*/
15189
15190
static PyObject *
15191
os_startfile_impl(PyObject *module, path_t *filepath,
15192
                  const wchar_t *operation, const wchar_t *arguments,
15193
                  path_t *cwd, int show_cmd)
15194
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15195
{
15196
    HINSTANCE rc;
15197
15198
    if(!check_ShellExecute()) {
15199
        /* If the OS doesn't have ShellExecute, return a
15200
           NotImplementedError. */
15201
        return PyErr_Format(PyExc_NotImplementedError,
15202
            "startfile not available on this platform");
15203
    }
15204
15205
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15206
        return NULL;
15207
    }
15208
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15209
                    arguments, cwd->object ? cwd->object : Py_None,
15210
                    show_cmd) < 0) {
15211
        return NULL;
15212
    }
15213
15214
    Py_BEGIN_ALLOW_THREADS
15215
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15216
                          arguments, cwd->wide, show_cmd);
15217
    Py_END_ALLOW_THREADS
15218
15219
    if (rc <= (HINSTANCE)32) {
15220
        win32_error_object("startfile", filepath->object);
15221
        return NULL;
15222
    }
15223
    Py_RETURN_NONE;
15224
}
15225
#endif /* MS_WINDOWS */
15226
15227
15228
#ifdef HAVE_GETLOADAVG
15229
/*[clinic input]
15230
os.getloadavg
15231
15232
Return average recent system load information.
15233
15234
Return the number of processes in the system run queue averaged over
15235
the last 1, 5, and 15 minutes as a tuple of three floats.
15236
Raises OSError if the load average was unobtainable.
15237
[clinic start generated code]*/
15238
15239
static PyObject *
15240
os_getloadavg_impl(PyObject *module)
15241
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15242
0
{
15243
0
    double loadavg[3];
15244
0
    if (getloadavg(loadavg, 3)!=3) {
15245
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15246
0
        return NULL;
15247
0
    } else
15248
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15249
0
}
15250
#endif /* HAVE_GETLOADAVG */
15251
15252
15253
/*[clinic input]
15254
os.device_encoding
15255
    fd: int
15256
15257
Return a string describing the encoding of a terminal's file descriptor.
15258
15259
The file descriptor must be attached to a terminal.
15260
If the device is not a terminal, return None.
15261
[clinic start generated code]*/
15262
15263
static PyObject *
15264
os_device_encoding_impl(PyObject *module, int fd)
15265
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15266
0
{
15267
0
    return _Py_device_encoding(fd);
15268
0
}
15269
15270
15271
#ifdef HAVE_SETRESUID
15272
/*[clinic input]
15273
os.setresuid
15274
15275
    ruid: uid_t
15276
    euid: uid_t
15277
    suid: uid_t
15278
    /
15279
15280
Set the current process's real, effective, and saved user ids.
15281
[clinic start generated code]*/
15282
15283
static PyObject *
15284
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15285
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15286
0
{
15287
0
    if (setresuid(ruid, euid, suid) < 0)
15288
0
        return posix_error();
15289
0
    Py_RETURN_NONE;
15290
0
}
15291
#endif /* HAVE_SETRESUID */
15292
15293
15294
#ifdef HAVE_SETRESGID
15295
/*[clinic input]
15296
os.setresgid
15297
15298
    rgid: gid_t
15299
    egid: gid_t
15300
    sgid: gid_t
15301
    /
15302
15303
Set the current process's real, effective, and saved group ids.
15304
[clinic start generated code]*/
15305
15306
static PyObject *
15307
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15308
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15309
0
{
15310
0
    if (setresgid(rgid, egid, sgid) < 0)
15311
0
        return posix_error();
15312
0
    Py_RETURN_NONE;
15313
0
}
15314
#endif /* HAVE_SETRESGID */
15315
15316
15317
#ifdef HAVE_GETRESUID
15318
/*[clinic input]
15319
os.getresuid
15320
15321
Return a tuple of the current process's real, effective, and saved user ids.
15322
[clinic start generated code]*/
15323
15324
static PyObject *
15325
os_getresuid_impl(PyObject *module)
15326
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
15327
0
{
15328
0
    uid_t ruid, euid, suid;
15329
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15330
0
        return posix_error();
15331
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15332
0
                                  _PyLong_FromUid(euid),
15333
0
                                  _PyLong_FromUid(suid));
15334
0
}
15335
#endif /* HAVE_GETRESUID */
15336
15337
15338
#ifdef HAVE_GETRESGID
15339
/*[clinic input]
15340
@permit_long_summary
15341
os.getresgid
15342
15343
Return a tuple of the current process's real, effective, and saved group ids.
15344
[clinic start generated code]*/
15345
15346
static PyObject *
15347
os_getresgid_impl(PyObject *module)
15348
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15349
0
{
15350
0
    gid_t rgid, egid, sgid;
15351
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15352
0
        return posix_error();
15353
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15354
0
                                  _PyLong_FromGid(egid),
15355
0
                                  _PyLong_FromGid(sgid));
15356
0
}
15357
#endif /* HAVE_GETRESGID */
15358
15359
15360
#ifdef USE_XATTRS
15361
/*[clinic input]
15362
os.getxattr
15363
15364
    path: path_t(allow_fd=True)
15365
    attribute: path_t
15366
    *
15367
    follow_symlinks: bool = True
15368
15369
Return the value of extended attribute attribute on path.
15370
15371
path may be either a string, a path-like object, or an open file descriptor.
15372
If follow_symlinks is False, and the last element of the path is a symbolic
15373
  link, getxattr will examine the symbolic link itself instead of the file
15374
  the link points to.
15375
15376
[clinic start generated code]*/
15377
15378
static PyObject *
15379
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15380
                 int follow_symlinks)
15381
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
15382
0
{
15383
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
15384
0
        return NULL;
15385
15386
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15387
0
        return NULL;
15388
0
    }
15389
15390
0
    for (Py_ssize_t i = 0; ; i++) {
15391
0
        ssize_t result;
15392
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15393
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15394
0
        if (!buffer_size) {
15395
0
            path_error(path);
15396
0
            return NULL;
15397
0
        }
15398
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15399
0
        if (writer == NULL) {
15400
0
            return NULL;
15401
0
        }
15402
0
        void *ptr = PyBytesWriter_GetData(writer);
15403
15404
0
        Py_BEGIN_ALLOW_THREADS;
15405
0
        if (path->fd >= 0)
15406
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15407
0
        else if (follow_symlinks)
15408
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15409
0
        else
15410
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15411
0
        Py_END_ALLOW_THREADS;
15412
15413
0
        if (result < 0) {
15414
0
            PyBytesWriter_Discard(writer);
15415
0
            if (errno == ERANGE) {
15416
0
                continue;
15417
0
            }
15418
0
            path_error(path);
15419
0
            return NULL;
15420
0
        }
15421
15422
0
        return PyBytesWriter_FinishWithSize(writer, result);
15423
0
    }
15424
0
}
15425
15426
15427
/*[clinic input]
15428
@permit_long_docstring_body
15429
os.setxattr
15430
15431
    path: path_t(allow_fd=True)
15432
    attribute: path_t
15433
    value: Py_buffer
15434
    flags: int = 0
15435
    *
15436
    follow_symlinks: bool = True
15437
15438
Set extended attribute attribute on path to value.
15439
15440
path may be either a string, a path-like object,  or an open file descriptor.
15441
If follow_symlinks is False, and the last element of the path is a symbolic
15442
  link, setxattr will modify the symbolic link itself instead of the file
15443
  the link points to.
15444
15445
[clinic start generated code]*/
15446
15447
static PyObject *
15448
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15449
                 Py_buffer *value, int flags, int follow_symlinks)
15450
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15451
0
{
15452
0
    ssize_t result;
15453
15454
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
15455
0
        return NULL;
15456
15457
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15458
0
                    value->buf, value->len, flags) < 0) {
15459
0
        return NULL;
15460
0
    }
15461
15462
0
    Py_BEGIN_ALLOW_THREADS;
15463
0
    if (path->fd > -1)
15464
0
        result = fsetxattr(path->fd, attribute->narrow,
15465
0
                           value->buf, value->len, flags);
15466
0
    else if (follow_symlinks)
15467
0
        result = setxattr(path->narrow, attribute->narrow,
15468
0
                           value->buf, value->len, flags);
15469
0
    else
15470
0
        result = lsetxattr(path->narrow, attribute->narrow,
15471
0
                           value->buf, value->len, flags);
15472
0
    Py_END_ALLOW_THREADS;
15473
15474
0
    if (result) {
15475
0
        path_error(path);
15476
0
        return NULL;
15477
0
    }
15478
15479
0
    Py_RETURN_NONE;
15480
0
}
15481
15482
15483
/*[clinic input]
15484
os.removexattr
15485
15486
    path: path_t(allow_fd=True)
15487
    attribute: path_t
15488
    *
15489
    follow_symlinks: bool = True
15490
15491
Remove extended attribute attribute on path.
15492
15493
path may be either a string, a path-like object, or an open file descriptor.
15494
If follow_symlinks is False, and the last element of the path is a symbolic
15495
  link, removexattr will modify the symbolic link itself instead of the file
15496
  the link points to.
15497
15498
[clinic start generated code]*/
15499
15500
static PyObject *
15501
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15502
                    int follow_symlinks)
15503
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15504
0
{
15505
0
    ssize_t result;
15506
15507
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
15508
0
        return NULL;
15509
15510
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15511
0
        return NULL;
15512
0
    }
15513
15514
0
    Py_BEGIN_ALLOW_THREADS;
15515
0
    if (path->fd > -1)
15516
0
        result = fremovexattr(path->fd, attribute->narrow);
15517
0
    else if (follow_symlinks)
15518
0
        result = removexattr(path->narrow, attribute->narrow);
15519
0
    else
15520
0
        result = lremovexattr(path->narrow, attribute->narrow);
15521
0
    Py_END_ALLOW_THREADS;
15522
15523
0
    if (result) {
15524
0
        return path_error(path);
15525
0
    }
15526
15527
0
    Py_RETURN_NONE;
15528
0
}
15529
15530
15531
/*[clinic input]
15532
@permit_long_docstring_body
15533
os.listxattr
15534
15535
    path: path_t(allow_fd=True, nullable=True) = None
15536
    *
15537
    follow_symlinks: bool = True
15538
15539
Return a list of extended attributes on path.
15540
15541
path may be either None, a string, a path-like object, or an open file descriptor.
15542
if path is None, listxattr will examine the current directory.
15543
If follow_symlinks is False, and the last element of the path is a symbolic
15544
  link, listxattr will examine the symbolic link itself instead of the file
15545
  the link points to.
15546
[clinic start generated code]*/
15547
15548
static PyObject *
15549
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15550
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15551
0
{
15552
0
    Py_ssize_t i;
15553
0
    PyObject *result = NULL;
15554
0
    const char *name;
15555
0
    char *buffer = NULL;
15556
15557
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
15558
0
        goto exit;
15559
15560
0
    if (PySys_Audit("os.listxattr", "(O)",
15561
0
                    path->object ? path->object : Py_None) < 0) {
15562
0
        return NULL;
15563
0
    }
15564
15565
0
    name = path->narrow ? path->narrow : ".";
15566
15567
0
    for (i = 0; ; i++) {
15568
0
        const char *start, *trace, *end;
15569
0
        ssize_t length;
15570
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15571
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15572
0
        if (!buffer_size) {
15573
            /* ERANGE */
15574
0
            path_error(path);
15575
0
            break;
15576
0
        }
15577
0
        buffer = PyMem_Malloc(buffer_size);
15578
0
        if (!buffer) {
15579
0
            PyErr_NoMemory();
15580
0
            break;
15581
0
        }
15582
15583
0
        Py_BEGIN_ALLOW_THREADS;
15584
0
        if (path->fd > -1)
15585
0
            length = flistxattr(path->fd, buffer, buffer_size);
15586
0
        else if (follow_symlinks)
15587
0
            length = listxattr(name, buffer, buffer_size);
15588
0
        else
15589
0
            length = llistxattr(name, buffer, buffer_size);
15590
0
        Py_END_ALLOW_THREADS;
15591
15592
0
        if (length < 0) {
15593
0
            if (errno == ERANGE) {
15594
0
                PyMem_Free(buffer);
15595
0
                buffer = NULL;
15596
0
                continue;
15597
0
            }
15598
0
            path_error(path);
15599
0
            break;
15600
0
        }
15601
15602
0
        result = PyList_New(0);
15603
0
        if (!result) {
15604
0
            goto exit;
15605
0
        }
15606
15607
0
        end = buffer + length;
15608
0
        for (trace = start = buffer; trace != end; trace++) {
15609
0
            if (!*trace) {
15610
0
                int error;
15611
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15612
0
                                                                 trace - start);
15613
0
                if (!attribute) {
15614
0
                    Py_SETREF(result, NULL);
15615
0
                    goto exit;
15616
0
                }
15617
0
                error = PyList_Append(result, attribute);
15618
0
                Py_DECREF(attribute);
15619
0
                if (error) {
15620
0
                    Py_SETREF(result, NULL);
15621
0
                    goto exit;
15622
0
                }
15623
0
                start = trace + 1;
15624
0
            }
15625
0
        }
15626
0
    break;
15627
0
    }
15628
0
exit:
15629
0
    if (buffer)
15630
0
        PyMem_Free(buffer);
15631
0
    return result;
15632
0
}
15633
#endif /* USE_XATTRS */
15634
15635
15636
/*[clinic input]
15637
@permit_long_summary
15638
os.urandom
15639
15640
    size: Py_ssize_t(allow_negative=False)
15641
    /
15642
15643
Return a bytes object containing random bytes suitable for cryptographic use.
15644
[clinic start generated code]*/
15645
15646
static PyObject *
15647
os_urandom_impl(PyObject *module, Py_ssize_t size)
15648
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15649
0
{
15650
0
    if (size < 0) {
15651
0
        return PyErr_Format(PyExc_ValueError,
15652
0
                            "negative argument not allowed");
15653
0
    }
15654
15655
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15656
0
    if (writer == NULL) {
15657
0
        return NULL;
15658
0
    }
15659
15660
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15661
0
    if (result == -1) {
15662
0
        PyBytesWriter_Discard(writer);
15663
0
        return NULL;
15664
0
    }
15665
0
    return PyBytesWriter_Finish(writer);
15666
0
}
15667
15668
#ifdef HAVE_MEMFD_CREATE
15669
/*[clinic input]
15670
os.memfd_create
15671
15672
    name: unicode_fs_encoded
15673
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15674
15675
[clinic start generated code]*/
15676
15677
static PyObject *
15678
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15679
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15680
0
{
15681
0
    int fd;
15682
0
    const char *bytes = PyBytes_AS_STRING(name);
15683
0
    Py_BEGIN_ALLOW_THREADS
15684
0
    fd = memfd_create(bytes, flags);
15685
0
    Py_END_ALLOW_THREADS
15686
0
    if (fd == -1) {
15687
0
        return PyErr_SetFromErrno(PyExc_OSError);
15688
0
    }
15689
0
    return PyLong_FromLong(fd);
15690
0
}
15691
#endif
15692
15693
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15694
/*[clinic input]
15695
os.eventfd
15696
15697
    initval: unsigned_int
15698
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15699
15700
Creates and returns an event notification file descriptor.
15701
[clinic start generated code]*/
15702
15703
static PyObject *
15704
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15705
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15706
15707
0
{
15708
    /* initval is limited to uint32_t, internal counter is uint64_t */
15709
0
    int fd;
15710
0
    Py_BEGIN_ALLOW_THREADS
15711
0
    fd = eventfd(initval, flags);
15712
0
    Py_END_ALLOW_THREADS
15713
0
    if (fd == -1) {
15714
0
        return PyErr_SetFromErrno(PyExc_OSError);
15715
0
    }
15716
0
    return PyLong_FromLong(fd);
15717
0
}
15718
15719
/*[clinic input]
15720
os.eventfd_read
15721
15722
    fd: fildes
15723
15724
Read eventfd value
15725
[clinic start generated code]*/
15726
15727
static PyObject *
15728
os_eventfd_read_impl(PyObject *module, int fd)
15729
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15730
0
{
15731
0
    eventfd_t value;
15732
0
    int result;
15733
0
    Py_BEGIN_ALLOW_THREADS
15734
0
    result = eventfd_read(fd, &value);
15735
0
    Py_END_ALLOW_THREADS
15736
0
    if (result == -1) {
15737
0
        return PyErr_SetFromErrno(PyExc_OSError);
15738
0
    }
15739
0
    return PyLong_FromUnsignedLongLong(value);
15740
0
}
15741
15742
/*[clinic input]
15743
os.eventfd_write
15744
15745
    fd: fildes
15746
    value: unsigned_long_long
15747
15748
Write eventfd value.
15749
[clinic start generated code]*/
15750
15751
static PyObject *
15752
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15753
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15754
0
{
15755
0
    int result;
15756
0
    Py_BEGIN_ALLOW_THREADS
15757
0
    result = eventfd_write(fd, value);
15758
0
    Py_END_ALLOW_THREADS
15759
0
    if (result == -1) {
15760
0
        return PyErr_SetFromErrno(PyExc_OSError);
15761
0
    }
15762
0
    Py_RETURN_NONE;
15763
0
}
15764
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15765
15766
/* Terminal size querying */
15767
15768
PyDoc_STRVAR(TerminalSize_docstring,
15769
    "A tuple of (columns, lines) for holding terminal window size");
15770
15771
static PyStructSequence_Field TerminalSize_fields[] = {
15772
    {"columns", "width of the terminal window in characters"},
15773
    {"lines", "height of the terminal window in characters"},
15774
    {NULL, NULL}
15775
};
15776
15777
static PyStructSequence_Desc TerminalSize_desc = {
15778
    "os.terminal_size",
15779
    TerminalSize_docstring,
15780
    TerminalSize_fields,
15781
    2,
15782
};
15783
15784
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15785
/*[clinic input]
15786
os.get_terminal_size
15787
15788
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15789
    /
15790
15791
Return the size of the terminal window as (columns, lines).
15792
15793
The optional argument fd (default standard output) specifies
15794
which file descriptor should be queried.
15795
15796
If the file descriptor is not connected to a terminal, an OSError
15797
is thrown.
15798
15799
This function will only be defined if an implementation is
15800
available for this system.
15801
15802
shutil.get_terminal_size is the high-level function which should
15803
normally be used, os.get_terminal_size is the low-level implementation.
15804
[clinic start generated code]*/
15805
15806
static PyObject *
15807
os_get_terminal_size_impl(PyObject *module, int fd)
15808
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15809
0
{
15810
0
    int columns, lines;
15811
0
    PyObject *termsize;
15812
15813
    /* Under some conditions stdout may not be connected and
15814
     * fileno(stdout) may point to an invalid file descriptor. For example
15815
     * GUI apps don't have valid standard streams by default.
15816
     *
15817
     * If this happens, and the optional fd argument is not present,
15818
     * the ioctl below will fail returning EBADF. This is what we want.
15819
     */
15820
15821
0
#ifdef TERMSIZE_USE_IOCTL
15822
0
    {
15823
0
        struct winsize w;
15824
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15825
0
            return PyErr_SetFromErrno(PyExc_OSError);
15826
0
        columns = w.ws_col;
15827
0
        lines = w.ws_row;
15828
0
    }
15829
0
#endif /* TERMSIZE_USE_IOCTL */
15830
15831
#ifdef TERMSIZE_USE_CONIO
15832
    {
15833
        HANDLE handle;
15834
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15835
        handle = _Py_get_osfhandle(fd);
15836
        if (handle == INVALID_HANDLE_VALUE)
15837
            return NULL;
15838
15839
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15840
            return PyErr_SetFromWindowsErr(0);
15841
15842
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15843
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15844
    }
15845
#endif /* TERMSIZE_USE_CONIO */
15846
15847
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15848
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15849
0
    if (termsize == NULL)
15850
0
        return NULL;
15851
15852
0
    int pos = 0;
15853
15854
0
#define SET_TERMSIZE(CALL)                                   \
15855
0
    do {                                                     \
15856
0
        PyObject *item = (CALL);                             \
15857
0
        if (item == NULL) {                                  \
15858
0
            Py_DECREF(termsize);                             \
15859
0
            return NULL;                                     \
15860
0
        }                                                    \
15861
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15862
0
    } while(0)
15863
15864
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15865
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15866
0
#undef SET_TERMSIZE
15867
15868
0
    return termsize;
15869
0
}
15870
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15871
15872
/*[clinic input]
15873
os.cpu_count
15874
15875
Return the number of logical CPUs in the system.
15876
15877
Return None if indeterminable.
15878
[clinic start generated code]*/
15879
15880
static PyObject *
15881
os_cpu_count_impl(PyObject *module)
15882
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15883
0
{
15884
0
    const PyConfig *config = _Py_GetConfig();
15885
0
    if (config->cpu_count > 0) {
15886
0
        return PyLong_FromLong(config->cpu_count);
15887
0
    }
15888
15889
0
    int ncpu = 0;
15890
#ifdef MS_WINDOWS
15891
# ifdef MS_WINDOWS_DESKTOP
15892
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15893
# else
15894
    ncpu = 0;
15895
# endif
15896
15897
#elif defined(__hpux)
15898
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15899
15900
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15901
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15902
15903
#elif defined(__VXWORKS__)
15904
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15905
15906
#elif defined(__DragonFly__) || \
15907
      defined(__OpenBSD__)   || \
15908
      defined(__FreeBSD__)   || \
15909
      defined(__NetBSD__)    || \
15910
      defined(__APPLE__)
15911
    ncpu = 0;
15912
    size_t len = sizeof(ncpu);
15913
    int mib[2] = {CTL_HW, HW_NCPU};
15914
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15915
        ncpu = 0;
15916
    }
15917
#endif
15918
15919
0
    if (ncpu < 1) {
15920
0
        Py_RETURN_NONE;
15921
0
    }
15922
0
    return PyLong_FromLong(ncpu);
15923
0
}
15924
15925
15926
/*[clinic input]
15927
os.get_inheritable -> bool
15928
15929
    fd: int
15930
    /
15931
15932
Get the close-on-exe flag of the specified file descriptor.
15933
[clinic start generated code]*/
15934
15935
static int
15936
os_get_inheritable_impl(PyObject *module, int fd)
15937
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15938
0
{
15939
0
    int return_value;
15940
0
    _Py_BEGIN_SUPPRESS_IPH
15941
0
    return_value = _Py_get_inheritable(fd);
15942
0
    _Py_END_SUPPRESS_IPH
15943
0
    return return_value;
15944
0
}
15945
15946
15947
/*[clinic input]
15948
os.set_inheritable
15949
    fd: int
15950
    inheritable: int
15951
    /
15952
15953
Set the inheritable flag of the specified file descriptor.
15954
[clinic start generated code]*/
15955
15956
static PyObject *
15957
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15958
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15959
0
{
15960
0
    int result;
15961
15962
0
    _Py_BEGIN_SUPPRESS_IPH
15963
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15964
0
    _Py_END_SUPPRESS_IPH
15965
0
    if (result < 0)
15966
0
        return NULL;
15967
0
    Py_RETURN_NONE;
15968
0
}
15969
15970
15971
#ifdef MS_WINDOWS
15972
#ifndef HANDLE_FLAG_INHERIT
15973
#define HANDLE_FLAG_INHERIT 0x00000001
15974
#endif
15975
15976
/*[clinic input]
15977
os.get_handle_inheritable -> bool
15978
    handle: intptr_t
15979
    /
15980
15981
Get the close-on-exe flag of the specified file descriptor.
15982
[clinic start generated code]*/
15983
15984
static int
15985
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
15986
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
15987
{
15988
    DWORD flags;
15989
15990
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
15991
        PyErr_SetFromWindowsErr(0);
15992
        return -1;
15993
    }
15994
15995
    return flags & HANDLE_FLAG_INHERIT;
15996
}
15997
15998
15999
/*[clinic input]
16000
os.set_handle_inheritable
16001
    handle: intptr_t
16002
    inheritable: bool
16003
    /
16004
16005
Set the inheritable flag of the specified handle.
16006
[clinic start generated code]*/
16007
16008
static PyObject *
16009
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16010
                               int inheritable)
16011
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16012
{
16013
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16014
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16015
        PyErr_SetFromWindowsErr(0);
16016
        return NULL;
16017
    }
16018
    Py_RETURN_NONE;
16019
}
16020
#endif /* MS_WINDOWS */
16021
16022
/*[clinic input]
16023
os.get_blocking -> bool
16024
    fd: int
16025
    /
16026
16027
Get the blocking mode of the file descriptor.
16028
16029
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16030
[clinic start generated code]*/
16031
16032
static int
16033
os_get_blocking_impl(PyObject *module, int fd)
16034
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16035
0
{
16036
0
    int blocking;
16037
16038
0
    _Py_BEGIN_SUPPRESS_IPH
16039
0
    blocking = _Py_get_blocking(fd);
16040
0
    _Py_END_SUPPRESS_IPH
16041
0
    return blocking;
16042
0
}
16043
16044
/*[clinic input]
16045
os.set_blocking
16046
    fd: int
16047
    blocking: bool
16048
    /
16049
16050
Set the blocking mode of the specified file descriptor.
16051
16052
Set the O_NONBLOCK flag if blocking is False,
16053
clear the O_NONBLOCK flag otherwise.
16054
[clinic start generated code]*/
16055
16056
static PyObject *
16057
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16058
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16059
0
{
16060
0
    int result;
16061
16062
0
    _Py_BEGIN_SUPPRESS_IPH
16063
0
    result = _Py_set_blocking(fd, blocking);
16064
0
    _Py_END_SUPPRESS_IPH
16065
0
    if (result < 0)
16066
0
        return NULL;
16067
0
    Py_RETURN_NONE;
16068
0
}
16069
16070
16071
/*[clinic input]
16072
class os.DirEntry "DirEntry *" "DirEntryType"
16073
[clinic start generated code]*/
16074
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16075
16076
typedef struct {
16077
    PyObject_HEAD
16078
    PyObject *name;
16079
    PyObject *path;
16080
    PyObject *stat;
16081
    PyObject *lstat;
16082
#ifdef MS_WINDOWS
16083
    struct _Py_stat_struct win32_lstat;
16084
    uint64_t win32_file_index;
16085
    uint64_t win32_file_index_high;
16086
    int got_file_index;
16087
#else /* POSIX */
16088
#ifdef HAVE_DIRENT_D_TYPE
16089
    unsigned char d_type;
16090
#endif
16091
    ino_t d_ino;
16092
    int dir_fd;
16093
#endif
16094
} DirEntry;
16095
16096
0
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16097
16098
static void
16099
DirEntry_dealloc(PyObject *op)
16100
0
{
16101
0
    DirEntry *entry = DirEntry_CAST(op);
16102
0
    PyTypeObject *tp = Py_TYPE(entry);
16103
0
    Py_XDECREF(entry->name);
16104
0
    Py_XDECREF(entry->path);
16105
0
    Py_XDECREF(entry->stat);
16106
0
    Py_XDECREF(entry->lstat);
16107
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16108
0
    free_func(entry);
16109
0
    Py_DECREF(tp);
16110
0
}
16111
16112
/* Forward reference */
16113
static int
16114
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16115
                   int follow_symlinks, unsigned short mode_bits);
16116
16117
/*[clinic input]
16118
os.DirEntry.is_symlink -> bool
16119
    defining_class: defining_class
16120
    /
16121
16122
Return True if the entry is a symbolic link; cached per entry.
16123
[clinic start generated code]*/
16124
16125
static int
16126
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16127
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16128
0
{
16129
#ifdef MS_WINDOWS
16130
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16131
#elif defined(HAVE_DIRENT_D_TYPE)
16132
    /* POSIX */
16133
0
    if (self->d_type != DT_UNKNOWN)
16134
0
        return self->d_type == DT_LNK;
16135
0
    else
16136
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16137
#else
16138
    /* POSIX without d_type */
16139
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16140
#endif
16141
0
}
16142
16143
/*[clinic input]
16144
os.DirEntry.is_junction -> bool
16145
16146
Return True if the entry is a junction; cached per entry.
16147
[clinic start generated code]*/
16148
16149
static int
16150
os_DirEntry_is_junction_impl(DirEntry *self)
16151
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16152
0
{
16153
#ifdef MS_WINDOWS
16154
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16155
#else
16156
0
    return 0;
16157
0
#endif
16158
0
}
16159
16160
static PyObject *
16161
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16162
0
{
16163
0
    int result;
16164
0
    STRUCT_STAT st;
16165
0
    PyObject *ub;
16166
16167
#ifdef MS_WINDOWS
16168
    if (!PyUnicode_FSDecoder(self->path, &ub))
16169
        return NULL;
16170
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16171
    Py_DECREF(ub);
16172
#else /* POSIX */
16173
0
    if (!PyUnicode_FSConverter(self->path, &ub))
16174
0
        return NULL;
16175
0
    const char *path = PyBytes_AS_STRING(ub);
16176
0
    if (self->dir_fd != DEFAULT_DIR_FD) {
16177
0
#ifdef HAVE_FSTATAT
16178
0
      if (HAVE_FSTATAT_RUNTIME) {
16179
0
        Py_BEGIN_ALLOW_THREADS
16180
0
        result = fstatat(self->dir_fd, path, &st,
16181
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16182
0
        Py_END_ALLOW_THREADS
16183
0
      } else
16184
16185
0
#endif /* HAVE_FSTATAT */
16186
0
      {
16187
0
        Py_DECREF(ub);
16188
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16189
0
        return NULL;
16190
0
      }
16191
0
    }
16192
0
    else
16193
0
#endif
16194
0
    {
16195
0
        Py_BEGIN_ALLOW_THREADS
16196
0
        if (follow_symlinks) {
16197
0
            result = STAT(path, &st);
16198
0
        }
16199
0
        else {
16200
0
            result = LSTAT(path, &st);
16201
0
        }
16202
0
        Py_END_ALLOW_THREADS
16203
0
    }
16204
16205
0
    int saved_errno = errno;
16206
#if defined(MS_WINDOWS)
16207
    PyMem_Free(path);
16208
#else
16209
0
    Py_DECREF(ub);
16210
0
#endif
16211
16212
0
    if (result != 0) {
16213
0
        errno = saved_errno;
16214
0
        path_object_error(self->path);
16215
0
        return NULL;
16216
0
    }
16217
16218
0
    return _pystat_fromstructstat(module, &st);
16219
0
}
16220
16221
static PyObject *
16222
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16223
0
{
16224
0
    if (!self->lstat) {
16225
0
        PyObject *module = PyType_GetModule(defining_class);
16226
#ifdef MS_WINDOWS
16227
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16228
#else /* POSIX */
16229
0
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16230
0
#endif
16231
0
    }
16232
0
    return Py_XNewRef(self->lstat);
16233
0
}
16234
16235
/*[clinic input]
16236
os.DirEntry.stat
16237
    defining_class: defining_class
16238
    /
16239
    *
16240
    follow_symlinks: bool = True
16241
16242
Return stat_result object for the entry; cached per entry.
16243
[clinic start generated code]*/
16244
16245
static PyObject *
16246
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16247
                      int follow_symlinks)
16248
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16249
0
{
16250
0
    if (!follow_symlinks) {
16251
0
        return DirEntry_get_lstat(defining_class, self);
16252
0
    }
16253
16254
0
    if (!self->stat) {
16255
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16256
0
        if (result == -1) {
16257
0
            return NULL;
16258
0
        }
16259
0
        if (result) {
16260
0
            PyObject *module = PyType_GetModule(defining_class);
16261
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16262
0
        }
16263
0
        else {
16264
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16265
0
        }
16266
0
    }
16267
16268
0
    return Py_XNewRef(self->stat);
16269
0
}
16270
16271
/* Set exception and return -1 on error, 0 for False, 1 for True */
16272
static int
16273
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16274
                   int follow_symlinks, unsigned short mode_bits)
16275
0
{
16276
0
    PyObject *stat = NULL;
16277
0
    PyObject *st_mode = NULL;
16278
0
    long mode;
16279
0
    int result;
16280
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16281
0
    int is_symlink;
16282
0
    int need_stat;
16283
0
#endif
16284
#ifdef MS_WINDOWS
16285
    unsigned long dir_bits;
16286
#endif
16287
16288
#ifdef MS_WINDOWS
16289
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16290
    need_stat = follow_symlinks && is_symlink;
16291
#elif defined(HAVE_DIRENT_D_TYPE)
16292
0
    is_symlink = self->d_type == DT_LNK;
16293
0
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16294
0
#endif
16295
16296
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16297
0
    if (need_stat) {
16298
0
#endif
16299
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16300
0
        if (!stat) {
16301
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16302
                /* If file doesn't exist (anymore), then return False
16303
                   (i.e., say it's not a file/directory) */
16304
0
                PyErr_Clear();
16305
0
                return 0;
16306
0
            }
16307
0
            goto error;
16308
0
        }
16309
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16310
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16311
0
        if (!st_mode)
16312
0
            goto error;
16313
16314
0
        mode = PyLong_AsLong(st_mode);
16315
0
        if (mode == -1 && PyErr_Occurred())
16316
0
            goto error;
16317
0
        Py_CLEAR(st_mode);
16318
0
        Py_CLEAR(stat);
16319
0
        result = (mode & S_IFMT) == mode_bits;
16320
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16321
0
    }
16322
0
    else if (is_symlink) {
16323
0
        assert(mode_bits != S_IFLNK);
16324
0
        result = 0;
16325
0
    }
16326
0
    else {
16327
0
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16328
#ifdef MS_WINDOWS
16329
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16330
        if (mode_bits == S_IFDIR)
16331
            result = dir_bits != 0;
16332
        else
16333
            result = dir_bits == 0;
16334
#else /* POSIX */
16335
0
        if (mode_bits == S_IFDIR)
16336
0
            result = self->d_type == DT_DIR;
16337
0
        else
16338
0
            result = self->d_type == DT_REG;
16339
0
#endif
16340
0
    }
16341
0
#endif
16342
16343
0
    return result;
16344
16345
0
error:
16346
0
    Py_XDECREF(st_mode);
16347
0
    Py_XDECREF(stat);
16348
0
    return -1;
16349
0
}
16350
16351
/*[clinic input]
16352
os.DirEntry.is_dir -> bool
16353
    defining_class: defining_class
16354
    /
16355
    *
16356
    follow_symlinks: bool = True
16357
16358
Return True if the entry is a directory; cached per entry.
16359
[clinic start generated code]*/
16360
16361
static int
16362
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16363
                        int follow_symlinks)
16364
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16365
0
{
16366
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16367
0
}
16368
16369
/*[clinic input]
16370
os.DirEntry.is_file -> bool
16371
    defining_class: defining_class
16372
    /
16373
    *
16374
    follow_symlinks: bool = True
16375
16376
Return True if the entry is a file; cached per entry.
16377
[clinic start generated code]*/
16378
16379
static int
16380
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16381
                         int follow_symlinks)
16382
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16383
0
{
16384
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16385
0
}
16386
16387
/*[clinic input]
16388
os.DirEntry.inode
16389
16390
Return inode of the entry; cached per entry.
16391
[clinic start generated code]*/
16392
16393
static PyObject *
16394
os_DirEntry_inode_impl(DirEntry *self)
16395
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16396
0
{
16397
#ifdef MS_WINDOWS
16398
    if (!self->got_file_index) {
16399
        PyObject *unicode;
16400
        STRUCT_STAT stat;
16401
        int result;
16402
16403
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16404
            return NULL;
16405
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16406
        Py_DECREF(unicode);
16407
        result = LSTAT(path, &stat);
16408
16409
        int saved_errno = errno;
16410
        PyMem_Free(path);
16411
16412
        if (result != 0) {
16413
            errno = saved_errno;
16414
            return path_object_error(self->path);
16415
        }
16416
16417
        self->win32_file_index = stat.st_ino;
16418
        self->win32_file_index_high = stat.st_ino_high;
16419
        self->got_file_index = 1;
16420
    }
16421
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16422
#else /* POSIX */
16423
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16424
0
                  "DirEntry.d_ino is larger than unsigned long long");
16425
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16426
0
#endif
16427
0
}
16428
16429
static PyObject *
16430
DirEntry_repr(PyObject *op)
16431
0
{
16432
0
    DirEntry *self = DirEntry_CAST(op);
16433
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16434
0
}
16435
16436
/*[clinic input]
16437
os.DirEntry.__fspath__
16438
16439
Returns the path for the entry.
16440
[clinic start generated code]*/
16441
16442
static PyObject *
16443
os_DirEntry___fspath___impl(DirEntry *self)
16444
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16445
0
{
16446
0
    return Py_NewRef(self->path);
16447
0
}
16448
16449
static PyMemberDef DirEntry_members[] = {
16450
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16451
     "the entry's base filename, relative to scandir() \"path\" argument"},
16452
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16453
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16454
    {NULL}
16455
};
16456
16457
#include "clinic/posixmodule.c.h"
16458
16459
static PyMethodDef DirEntry_methods[] = {
16460
    OS_DIRENTRY_IS_DIR_METHODDEF
16461
    OS_DIRENTRY_IS_FILE_METHODDEF
16462
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16463
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16464
    OS_DIRENTRY_STAT_METHODDEF
16465
    OS_DIRENTRY_INODE_METHODDEF
16466
    OS_DIRENTRY___FSPATH___METHODDEF
16467
    {"__class_getitem__",       Py_GenericAlias,
16468
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16469
    {NULL}
16470
};
16471
16472
static PyType_Slot DirEntryType_slots[] = {
16473
    {Py_tp_dealloc, DirEntry_dealloc},
16474
    {Py_tp_repr, DirEntry_repr},
16475
    {Py_tp_methods, DirEntry_methods},
16476
    {Py_tp_members, DirEntry_members},
16477
    {0, 0},
16478
};
16479
16480
static PyType_Spec DirEntryType_spec = {
16481
    .name = MODNAME ".DirEntry",
16482
    .basicsize = sizeof(DirEntry),
16483
    .flags = (
16484
        Py_TPFLAGS_DEFAULT
16485
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16486
        | Py_TPFLAGS_IMMUTABLETYPE
16487
    ),
16488
    .slots = DirEntryType_slots
16489
};
16490
16491
16492
#ifdef MS_WINDOWS
16493
16494
static wchar_t *
16495
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16496
{
16497
    Py_ssize_t path_len;
16498
    Py_ssize_t size;
16499
    wchar_t *result;
16500
    wchar_t ch;
16501
16502
    if (!path_wide) { /* Default arg: "." */
16503
        path_wide = L".";
16504
        path_len = 1;
16505
    }
16506
    else {
16507
        path_len = wcslen(path_wide);
16508
    }
16509
16510
    /* The +1's are for the path separator and the NUL */
16511
    size = path_len + 1 + wcslen(filename) + 1;
16512
    result = PyMem_New(wchar_t, size);
16513
    if (!result) {
16514
        PyErr_NoMemory();
16515
        return NULL;
16516
    }
16517
    wcscpy(result, path_wide);
16518
    if (path_len > 0) {
16519
        ch = result[path_len - 1];
16520
        if (ch != SEP && ch != ALTSEP && ch != L':')
16521
            result[path_len++] = SEP;
16522
        wcscpy(result + path_len, filename);
16523
    }
16524
    return result;
16525
}
16526
16527
static PyObject *
16528
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16529
{
16530
    DirEntry *entry;
16531
    BY_HANDLE_FILE_INFORMATION file_info;
16532
    ULONG reparse_tag;
16533
    wchar_t *joined_path;
16534
16535
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16536
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16537
    if (!entry)
16538
        return NULL;
16539
    entry->name = NULL;
16540
    entry->path = NULL;
16541
    entry->stat = NULL;
16542
    entry->lstat = NULL;
16543
    entry->got_file_index = 0;
16544
16545
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16546
    if (!entry->name)
16547
        goto error;
16548
    int return_bytes = path->wide && PyBytes_Check(path->object);
16549
    if (return_bytes) {
16550
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16551
        if (!entry->name)
16552
            goto error;
16553
    }
16554
16555
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16556
    if (!joined_path)
16557
        goto error;
16558
16559
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16560
    PyMem_Free(joined_path);
16561
    if (!entry->path)
16562
        goto error;
16563
    if (return_bytes) {
16564
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16565
        if (!entry->path)
16566
            goto error;
16567
    }
16568
16569
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16570
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16571
16572
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16573
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16574
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16575
16576
    return (PyObject *)entry;
16577
16578
error:
16579
    Py_DECREF(entry);
16580
    return NULL;
16581
}
16582
16583
#else /* POSIX */
16584
16585
static char *
16586
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16587
0
{
16588
0
    Py_ssize_t path_len;
16589
0
    Py_ssize_t size;
16590
0
    char *result;
16591
16592
0
    if (!path_narrow) { /* Default arg: "." */
16593
0
        path_narrow = ".";
16594
0
        path_len = 1;
16595
0
    }
16596
0
    else {
16597
0
        path_len = strlen(path_narrow);
16598
0
    }
16599
16600
0
    if (filename_len == -1)
16601
0
        filename_len = strlen(filename);
16602
16603
    /* The +1's are for the path separator and the NUL */
16604
0
    size = path_len + 1 + filename_len + 1;
16605
0
    result = PyMem_New(char, size);
16606
0
    if (!result) {
16607
0
        PyErr_NoMemory();
16608
0
        return NULL;
16609
0
    }
16610
0
    strcpy(result, path_narrow);
16611
0
    if (path_len > 0 && result[path_len - 1] != '/')
16612
0
        result[path_len++] = '/';
16613
0
    strcpy(result + path_len, filename);
16614
0
    return result;
16615
0
}
16616
16617
static PyObject *
16618
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16619
                         Py_ssize_t name_len, ino_t d_ino
16620
#ifdef HAVE_DIRENT_D_TYPE
16621
                         , unsigned char d_type
16622
#endif
16623
                         )
16624
0
{
16625
0
    DirEntry *entry;
16626
0
    char *joined_path;
16627
16628
0
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16629
0
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16630
0
    if (!entry)
16631
0
        return NULL;
16632
0
    entry->name = NULL;
16633
0
    entry->path = NULL;
16634
0
    entry->stat = NULL;
16635
0
    entry->lstat = NULL;
16636
16637
0
    if (path->fd != -1) {
16638
0
        entry->dir_fd = path->fd;
16639
0
        joined_path = NULL;
16640
0
    }
16641
0
    else {
16642
0
        entry->dir_fd = DEFAULT_DIR_FD;
16643
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16644
0
        if (!joined_path)
16645
0
            goto error;
16646
0
    }
16647
16648
0
    if (!path->narrow || !PyBytes_Check(path->object)) {
16649
0
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16650
0
        if (joined_path)
16651
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16652
0
    }
16653
0
    else {
16654
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16655
0
        if (joined_path)
16656
0
            entry->path = PyBytes_FromString(joined_path);
16657
0
    }
16658
0
    PyMem_Free(joined_path);
16659
0
    if (!entry->name)
16660
0
        goto error;
16661
16662
0
    if (path->fd != -1) {
16663
0
        entry->path = Py_NewRef(entry->name);
16664
0
    }
16665
0
    else if (!entry->path)
16666
0
        goto error;
16667
16668
0
#ifdef HAVE_DIRENT_D_TYPE
16669
0
    entry->d_type = d_type;
16670
0
#endif
16671
0
    entry->d_ino = d_ino;
16672
16673
0
    return (PyObject *)entry;
16674
16675
0
error:
16676
0
    Py_XDECREF(entry);
16677
0
    return NULL;
16678
0
}
16679
16680
#endif
16681
16682
16683
typedef struct {
16684
    PyObject_HEAD
16685
    path_t path;
16686
#ifdef MS_WINDOWS
16687
    HANDLE handle;
16688
    WIN32_FIND_DATAW file_data;
16689
    int first_time;
16690
#else /* POSIX */
16691
    DIR *dirp;
16692
#endif
16693
#ifdef HAVE_FDOPENDIR
16694
    int fd;
16695
#endif
16696
} ScandirIterator;
16697
16698
0
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16699
16700
#ifdef MS_WINDOWS
16701
16702
static int
16703
ScandirIterator_is_closed(ScandirIterator *iterator)
16704
{
16705
    return iterator->handle == INVALID_HANDLE_VALUE;
16706
}
16707
16708
static void
16709
ScandirIterator_closedir(ScandirIterator *iterator)
16710
{
16711
    HANDLE handle = iterator->handle;
16712
16713
    if (handle == INVALID_HANDLE_VALUE)
16714
        return;
16715
16716
    iterator->handle = INVALID_HANDLE_VALUE;
16717
    Py_BEGIN_ALLOW_THREADS
16718
    FindClose(handle);
16719
    Py_END_ALLOW_THREADS
16720
}
16721
16722
static PyObject *
16723
ScandirIterator_iternext(PyObject *op)
16724
{
16725
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16726
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16727
    BOOL success;
16728
    PyObject *entry;
16729
16730
    /* Happens if the iterator is iterated twice, or closed explicitly */
16731
    if (iterator->handle == INVALID_HANDLE_VALUE)
16732
        return NULL;
16733
16734
    while (1) {
16735
        if (!iterator->first_time) {
16736
            Py_BEGIN_ALLOW_THREADS
16737
            success = FindNextFileW(iterator->handle, file_data);
16738
            Py_END_ALLOW_THREADS
16739
            if (!success) {
16740
                /* Error or no more files */
16741
                if (GetLastError() != ERROR_NO_MORE_FILES)
16742
                    path_error(&iterator->path);
16743
                break;
16744
            }
16745
        }
16746
        iterator->first_time = 0;
16747
16748
        /* Skip over . and .. */
16749
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16750
            wcscmp(file_data->cFileName, L"..") != 0)
16751
        {
16752
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16753
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16754
            if (!entry)
16755
                break;
16756
            return entry;
16757
        }
16758
16759
        /* Loop till we get a non-dot directory or finish iterating */
16760
    }
16761
16762
    /* Error or no more files */
16763
    ScandirIterator_closedir(iterator);
16764
    return NULL;
16765
}
16766
16767
#else /* POSIX */
16768
16769
static int
16770
ScandirIterator_is_closed(ScandirIterator *iterator)
16771
0
{
16772
0
    return !iterator->dirp;
16773
0
}
16774
16775
static void
16776
ScandirIterator_closedir(ScandirIterator *iterator)
16777
0
{
16778
0
    DIR *dirp = iterator->dirp;
16779
16780
0
    if (!dirp)
16781
0
        return;
16782
16783
0
    iterator->dirp = NULL;
16784
0
    Py_BEGIN_ALLOW_THREADS
16785
0
#ifdef HAVE_FDOPENDIR
16786
0
    if (iterator->path.fd != -1)
16787
0
        rewinddir(dirp);
16788
0
#endif
16789
0
    closedir(dirp);
16790
0
    Py_END_ALLOW_THREADS
16791
0
    return;
16792
0
}
16793
16794
static PyObject *
16795
ScandirIterator_iternext(PyObject *op)
16796
0
{
16797
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16798
0
    struct dirent *direntp;
16799
0
    Py_ssize_t name_len;
16800
0
    int is_dot;
16801
0
    PyObject *entry;
16802
16803
    /* Happens if the iterator is iterated twice, or closed explicitly */
16804
0
    if (!iterator->dirp)
16805
0
        return NULL;
16806
16807
0
    while (1) {
16808
0
        errno = 0;
16809
0
        Py_BEGIN_ALLOW_THREADS
16810
0
        direntp = readdir(iterator->dirp);
16811
0
        Py_END_ALLOW_THREADS
16812
16813
0
        if (!direntp) {
16814
            /* Error or no more files */
16815
0
            if (errno != 0)
16816
0
                path_error(&iterator->path);
16817
0
            break;
16818
0
        }
16819
16820
        /* Skip over . and .. */
16821
0
        name_len = NAMLEN(direntp);
16822
0
        is_dot = direntp->d_name[0] == '.' &&
16823
0
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16824
0
        if (!is_dot) {
16825
0
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16826
0
            entry = DirEntry_from_posix_info(module,
16827
0
                                             &iterator->path, direntp->d_name,
16828
0
                                             name_len, direntp->d_ino
16829
0
#ifdef HAVE_DIRENT_D_TYPE
16830
0
                                             , direntp->d_type
16831
0
#endif
16832
0
                                            );
16833
0
            if (!entry)
16834
0
                break;
16835
0
            return entry;
16836
0
        }
16837
16838
        /* Loop till we get a non-dot directory or finish iterating */
16839
0
    }
16840
16841
    /* Error or no more files */
16842
0
    ScandirIterator_closedir(iterator);
16843
0
    return NULL;
16844
0
}
16845
16846
#endif
16847
16848
static PyObject *
16849
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16850
0
{
16851
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16852
0
    ScandirIterator_closedir(self);
16853
0
    Py_RETURN_NONE;
16854
0
}
16855
16856
static PyObject *
16857
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16858
0
{
16859
0
    return Py_NewRef(self);
16860
0
}
16861
16862
static PyObject *
16863
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16864
0
{
16865
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16866
0
    ScandirIterator_closedir(self);
16867
0
    Py_RETURN_NONE;
16868
0
}
16869
16870
static void
16871
ScandirIterator_finalize(PyObject *op)
16872
0
{
16873
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16874
    /* Save the current exception, if any. */
16875
0
    PyObject *exc = PyErr_GetRaisedException();
16876
16877
0
    if (!ScandirIterator_is_closed(iterator)) {
16878
0
        ScandirIterator_closedir(iterator);
16879
16880
0
        if (PyErr_ResourceWarning(op, 1,
16881
0
                                  "unclosed scandir iterator %R", iterator))
16882
0
        {
16883
            /* Spurious errors can appear at shutdown */
16884
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16885
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16886
0
                                       "scandir iterator %R", iterator);
16887
0
            }
16888
0
        }
16889
0
    }
16890
16891
0
    path_cleanup(&iterator->path);
16892
16893
    /* Restore the saved exception. */
16894
0
    PyErr_SetRaisedException(exc);
16895
0
}
16896
16897
static void
16898
ScandirIterator_dealloc(PyObject *op)
16899
0
{
16900
0
    PyTypeObject *tp = Py_TYPE(op);
16901
0
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16902
0
        return;
16903
16904
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16905
0
    free_func(op);
16906
0
    Py_DECREF(tp);
16907
0
}
16908
16909
static PyMethodDef ScandirIterator_methods[] = {
16910
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16911
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16912
    {"close", ScandirIterator_close, METH_NOARGS},
16913
    {NULL}
16914
};
16915
16916
static PyType_Slot ScandirIteratorType_slots[] = {
16917
    {Py_tp_dealloc, ScandirIterator_dealloc},
16918
    {Py_tp_finalize, ScandirIterator_finalize},
16919
    {Py_tp_iter, PyObject_SelfIter},
16920
    {Py_tp_iternext, ScandirIterator_iternext},
16921
    {Py_tp_methods, ScandirIterator_methods},
16922
    {0, 0},
16923
};
16924
16925
static PyType_Spec ScandirIteratorType_spec = {
16926
    .name = MODNAME ".ScandirIterator",
16927
    .basicsize = sizeof(ScandirIterator),
16928
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16929
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16930
    .flags = (
16931
        Py_TPFLAGS_DEFAULT
16932
        | Py_TPFLAGS_HAVE_FINALIZE
16933
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16934
        | Py_TPFLAGS_IMMUTABLETYPE
16935
    ),
16936
    .slots = ScandirIteratorType_slots
16937
};
16938
16939
/*[clinic input]
16940
os.scandir
16941
16942
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16943
16944
Return an iterator of DirEntry objects for given path.
16945
16946
path can be specified as either str, bytes, or a path-like object.  If path
16947
is bytes, the names of yielded DirEntry objects will also be bytes; in
16948
all other circumstances they will be str.
16949
16950
If path is None, uses the path='.'.
16951
[clinic start generated code]*/
16952
16953
static PyObject *
16954
os_scandir_impl(PyObject *module, path_t *path)
16955
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16956
0
{
16957
0
    ScandirIterator *iterator;
16958
#ifdef MS_WINDOWS
16959
    wchar_t *path_strW;
16960
#else
16961
0
    const char *path_str;
16962
0
#ifdef HAVE_FDOPENDIR
16963
0
    int fd = -1;
16964
0
#endif
16965
0
#endif
16966
16967
0
    if (PySys_Audit("os.scandir", "O",
16968
0
                    path->object ? path->object : Py_None) < 0) {
16969
0
        return NULL;
16970
0
    }
16971
16972
0
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
16973
0
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
16974
0
    if (!iterator)
16975
0
        return NULL;
16976
16977
#ifdef MS_WINDOWS
16978
    iterator->handle = INVALID_HANDLE_VALUE;
16979
#else
16980
0
    iterator->dirp = NULL;
16981
0
#endif
16982
16983
    /* Move the ownership to iterator->path */
16984
0
    memcpy(&iterator->path, path, sizeof(path_t));
16985
0
    memset(path, 0, sizeof(path_t));
16986
16987
#ifdef MS_WINDOWS
16988
    iterator->first_time = 1;
16989
16990
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
16991
    if (!path_strW)
16992
        goto error;
16993
16994
    Py_BEGIN_ALLOW_THREADS
16995
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
16996
    Py_END_ALLOW_THREADS
16997
16998
    if (iterator->handle == INVALID_HANDLE_VALUE) {
16999
        path_error(&iterator->path);
17000
        PyMem_Free(path_strW);
17001
        goto error;
17002
    }
17003
    PyMem_Free(path_strW);
17004
#else /* POSIX */
17005
0
    errno = 0;
17006
0
#ifdef HAVE_FDOPENDIR
17007
0
    if (iterator->path.fd != -1) {
17008
0
      if (HAVE_FDOPENDIR_RUNTIME) {
17009
        /* closedir() closes the FD, so we duplicate it */
17010
0
        fd = _Py_dup(iterator->path.fd);
17011
0
        if (fd == -1)
17012
0
            goto error;
17013
17014
0
        Py_BEGIN_ALLOW_THREADS
17015
0
        iterator->dirp = fdopendir(fd);
17016
0
        Py_END_ALLOW_THREADS
17017
0
      } else {
17018
0
        PyErr_SetString(PyExc_TypeError,
17019
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17020
0
        return NULL;
17021
0
      }
17022
0
    }
17023
0
    else
17024
0
#endif
17025
0
    {
17026
0
        if (iterator->path.narrow)
17027
0
            path_str = iterator->path.narrow;
17028
0
        else
17029
0
            path_str = ".";
17030
17031
0
        Py_BEGIN_ALLOW_THREADS
17032
0
        iterator->dirp = opendir(path_str);
17033
0
        Py_END_ALLOW_THREADS
17034
0
    }
17035
17036
0
    if (!iterator->dirp) {
17037
0
        path_error(&iterator->path);
17038
0
#ifdef HAVE_FDOPENDIR
17039
0
        if (fd != -1) {
17040
0
            Py_BEGIN_ALLOW_THREADS
17041
0
            close(fd);
17042
0
            Py_END_ALLOW_THREADS
17043
0
        }
17044
0
#endif
17045
0
        goto error;
17046
0
    }
17047
0
#endif
17048
17049
0
    return (PyObject *)iterator;
17050
17051
0
error:
17052
0
    Py_DECREF(iterator);
17053
0
    return NULL;
17054
0
}
17055
17056
/*
17057
    Return the file system path representation of the object.
17058
17059
    If the object is str or bytes, then allow it to pass through with
17060
    an incremented refcount. If the object defines __fspath__(), then
17061
    return the result of that method. All other types raise a TypeError.
17062
*/
17063
PyObject *
17064
PyOS_FSPath(PyObject *path)
17065
36.4k
{
17066
    /* For error message reasons, this function is manually inlined in
17067
       path_converter(). */
17068
36.4k
    PyObject *func = NULL;
17069
36.4k
    PyObject *path_repr = NULL;
17070
17071
36.4k
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17072
36.4k
        return Py_NewRef(path);
17073
36.4k
    }
17074
17075
0
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17076
0
    if ((NULL == func) || (func == Py_None)) {
17077
0
        return PyErr_Format(PyExc_TypeError,
17078
0
                            "expected str, bytes or os.PathLike object, "
17079
0
                            "not %.200s",
17080
0
                            _PyType_Name(Py_TYPE(path)));
17081
0
    }
17082
17083
0
    path_repr = _PyObject_CallNoArgs(func);
17084
0
    Py_DECREF(func);
17085
0
    if (NULL == path_repr) {
17086
0
        return NULL;
17087
0
    }
17088
17089
0
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17090
0
        PyErr_Format(PyExc_TypeError,
17091
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17092
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17093
0
                     _PyType_Name(Py_TYPE(path_repr)));
17094
0
        Py_DECREF(path_repr);
17095
0
        return NULL;
17096
0
    }
17097
17098
0
    return path_repr;
17099
0
}
17100
17101
/*[clinic input]
17102
@permit_long_docstring_body
17103
os.fspath
17104
17105
    path: object
17106
17107
Return the file system path representation of the object.
17108
17109
If the object is str or bytes, then allow it to pass through as-is. If the
17110
object defines __fspath__(), then return the result of that method. All other
17111
types raise a TypeError.
17112
[clinic start generated code]*/
17113
17114
static PyObject *
17115
os_fspath_impl(PyObject *module, PyObject *path)
17116
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
17117
3.07k
{
17118
3.07k
    return PyOS_FSPath(path);
17119
3.07k
}
17120
17121
#ifdef HAVE_GETRANDOM_SYSCALL
17122
/*[clinic input]
17123
os.getrandom
17124
17125
    size: Py_ssize_t
17126
    flags: int=0
17127
17128
Obtain a series of random bytes.
17129
[clinic start generated code]*/
17130
17131
static PyObject *
17132
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17133
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17134
0
{
17135
0
    if (size < 0) {
17136
0
        errno = EINVAL;
17137
0
        return posix_error();
17138
0
    }
17139
17140
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17141
0
    if (writer == NULL) {
17142
0
        return NULL;
17143
0
    }
17144
0
    void *data = PyBytesWriter_GetData(writer);
17145
17146
0
    Py_ssize_t n;
17147
0
    while (1) {
17148
0
        n = syscall(SYS_getrandom, data, size, flags);
17149
0
        if (n < 0 && errno == EINTR) {
17150
0
            if (PyErr_CheckSignals() < 0) {
17151
0
                goto error;
17152
0
            }
17153
17154
            /* getrandom() was interrupted by a signal: retry */
17155
0
            continue;
17156
0
        }
17157
0
        break;
17158
0
    }
17159
17160
0
    if (n < 0) {
17161
0
        PyErr_SetFromErrno(PyExc_OSError);
17162
0
        goto error;
17163
0
    }
17164
17165
0
    return PyBytesWriter_FinishWithSize(writer, n);
17166
17167
0
error:
17168
0
    PyBytesWriter_Discard(writer);
17169
0
    return NULL;
17170
0
}
17171
#endif   /* HAVE_GETRANDOM_SYSCALL */
17172
17173
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17174
17175
/* bpo-36085: Helper functions for managing DLL search directories
17176
 * on win32
17177
 */
17178
17179
/*[clinic input]
17180
os._add_dll_directory
17181
17182
    path: path_t
17183
17184
Add a path to the DLL search path.
17185
17186
This search path is used when resolving dependencies for imported
17187
extension modules (the module itself is resolved through sys.path),
17188
and also by ctypes.
17189
17190
Returns an opaque value that may be passed to os.remove_dll_directory
17191
to remove this directory from the search path.
17192
[clinic start generated code]*/
17193
17194
static PyObject *
17195
os__add_dll_directory_impl(PyObject *module, path_t *path)
17196
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17197
{
17198
    DLL_DIRECTORY_COOKIE cookie = 0;
17199
    DWORD err = 0;
17200
17201
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17202
        return NULL;
17203
    }
17204
17205
    Py_BEGIN_ALLOW_THREADS
17206
    if (!(cookie = AddDllDirectory(path->wide))) {
17207
        err = GetLastError();
17208
    }
17209
    Py_END_ALLOW_THREADS
17210
17211
    if (err) {
17212
        return win32_error_object_err("add_dll_directory",
17213
                                      path->object, err);
17214
    }
17215
17216
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17217
}
17218
17219
/*[clinic input]
17220
os._remove_dll_directory
17221
17222
    cookie: object
17223
17224
Removes a path from the DLL search path.
17225
17226
The parameter is an opaque value that was returned from
17227
os.add_dll_directory. You can only remove directories that you added
17228
yourself.
17229
[clinic start generated code]*/
17230
17231
static PyObject *
17232
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17233
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17234
{
17235
    DLL_DIRECTORY_COOKIE cookieValue;
17236
    DWORD err = 0;
17237
17238
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17239
        PyErr_SetString(PyExc_TypeError,
17240
            "Provided cookie was not returned from os.add_dll_directory");
17241
        return NULL;
17242
    }
17243
17244
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17245
        cookie, "DLL directory cookie");
17246
17247
    Py_BEGIN_ALLOW_THREADS
17248
    if (!RemoveDllDirectory(cookieValue)) {
17249
        err = GetLastError();
17250
    }
17251
    Py_END_ALLOW_THREADS
17252
17253
    if (err) {
17254
        return win32_error_object_err("remove_dll_directory",
17255
                                      NULL, err);
17256
    }
17257
17258
    if (PyCapsule_SetName(cookie, NULL)) {
17259
        return NULL;
17260
    }
17261
17262
    Py_RETURN_NONE;
17263
}
17264
17265
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17266
17267
17268
/* Only check if WIFEXITED is available: expect that it comes
17269
   with WEXITSTATUS, WIFSIGNALED, etc.
17270
17271
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17272
   subprocess can safely call it during late Python finalization without
17273
   risking that used os attributes were set to None by finalize_modules(). */
17274
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17275
/*[clinic input]
17276
os.waitstatus_to_exitcode
17277
17278
    status as status_obj: object
17279
17280
Convert a wait status to an exit code.
17281
17282
On Unix:
17283
17284
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17285
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17286
* Otherwise, raise a ValueError.
17287
17288
On Windows, return status shifted right by 8 bits.
17289
17290
On Unix, if the process is being traced or if waitpid() was called with
17291
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
17292
This function must not be called if WIFSTOPPED(status) is true.
17293
[clinic start generated code]*/
17294
17295
static PyObject *
17296
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17297
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
17298
0
{
17299
0
#ifndef MS_WINDOWS
17300
0
    int status = PyLong_AsInt(status_obj);
17301
0
    if (status == -1 && PyErr_Occurred()) {
17302
0
        return NULL;
17303
0
    }
17304
17305
0
    WAIT_TYPE wait_status;
17306
0
    WAIT_STATUS_INT(wait_status) = status;
17307
0
    int exitcode;
17308
0
    if (WIFEXITED(wait_status)) {
17309
0
        exitcode = WEXITSTATUS(wait_status);
17310
        /* Sanity check to provide warranty on the function behavior.
17311
           It should not occur in practice */
17312
0
        if (exitcode < 0) {
17313
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17314
0
            return NULL;
17315
0
        }
17316
0
    }
17317
0
    else if (WIFSIGNALED(wait_status)) {
17318
0
        int signum = WTERMSIG(wait_status);
17319
        /* Sanity check to provide warranty on the function behavior.
17320
           It should not occurs in practice */
17321
0
        if (signum <= 0) {
17322
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17323
0
            return NULL;
17324
0
        }
17325
0
        exitcode = -signum;
17326
0
    } else if (WIFSTOPPED(wait_status)) {
17327
        /* Status only received if the process is being traced
17328
           or if waitpid() was called with WUNTRACED option. */
17329
0
        int signum = WSTOPSIG(wait_status);
17330
0
        PyErr_Format(PyExc_ValueError,
17331
0
                     "process stopped by delivery of signal %i",
17332
0
                     signum);
17333
0
        return NULL;
17334
0
    }
17335
0
    else {
17336
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17337
0
        return NULL;
17338
0
    }
17339
0
    return PyLong_FromLong(exitcode);
17340
#else
17341
    /* Windows implementation: see os.waitpid() implementation
17342
       which uses _cwait(). */
17343
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17344
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17345
        return NULL;
17346
    }
17347
17348
    unsigned long long exitcode = (status >> 8);
17349
    /* ExitProcess() accepts an UINT type:
17350
       reject exit code which doesn't fit in an UINT */
17351
    if (exitcode > UINT_MAX) {
17352
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17353
        return NULL;
17354
    }
17355
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17356
#endif
17357
0
}
17358
#endif
17359
17360
#if defined(MS_WINDOWS)
17361
/*[clinic input]
17362
os._supports_virtual_terminal
17363
17364
Checks if virtual terminal is supported in windows
17365
[clinic start generated code]*/
17366
17367
static PyObject *
17368
os__supports_virtual_terminal_impl(PyObject *module)
17369
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17370
{
17371
#ifdef HAVE_WINDOWS_CONSOLE_IO
17372
    DWORD mode = 0;
17373
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17374
    if (!GetConsoleMode(handle, &mode)) {
17375
        Py_RETURN_FALSE;
17376
    }
17377
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17378
#else
17379
    Py_RETURN_FALSE;
17380
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17381
}
17382
#endif
17383
17384
/*[clinic input]
17385
os._inputhook
17386
17387
Calls PyOS_InputHook dropping the GIL first
17388
[clinic start generated code]*/
17389
17390
static PyObject *
17391
os__inputhook_impl(PyObject *module)
17392
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17393
0
{
17394
0
     int result = 0;
17395
0
     if (PyOS_InputHook) {
17396
0
         Py_BEGIN_ALLOW_THREADS;
17397
0
         result = PyOS_InputHook();
17398
0
         Py_END_ALLOW_THREADS;
17399
0
     }
17400
0
     return PyLong_FromLong(result);
17401
0
}
17402
17403
/*[clinic input]
17404
os._is_inputhook_installed
17405
17406
Checks if PyOS_InputHook is set
17407
[clinic start generated code]*/
17408
17409
static PyObject *
17410
os__is_inputhook_installed_impl(PyObject *module)
17411
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17412
0
{
17413
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17414
0
}
17415
17416
/*[clinic input]
17417
os._create_environ
17418
17419
Create the environment dictionary.
17420
[clinic start generated code]*/
17421
17422
static PyObject *
17423
os__create_environ_impl(PyObject *module)
17424
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17425
0
{
17426
0
    return convertenviron();
17427
0
}
17428
17429
17430
#ifdef __EMSCRIPTEN__
17431
/*[clinic input]
17432
os._emscripten_debugger
17433
17434
Create a breakpoint for the JavaScript debugger. Emscripten only.
17435
[clinic start generated code]*/
17436
17437
static PyObject *
17438
os__emscripten_debugger_impl(PyObject *module)
17439
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17440
{
17441
    emscripten_debugger();
17442
    Py_RETURN_NONE;
17443
}
17444
17445
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17446
    console.warn(UTF8ToString(arg));
17447
});
17448
17449
/*[clinic input]
17450
os._emscripten_log
17451
   arg: str
17452
17453
Log something to the JS console. Emscripten only.
17454
[clinic start generated code]*/
17455
17456
static PyObject *
17457
os__emscripten_log_impl(PyObject *module, const char *arg)
17458
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17459
{
17460
    emscripten_log_impl_js(arg);
17461
    Py_RETURN_NONE;
17462
}
17463
#endif /* __EMSCRIPTEN__ */
17464
17465
17466
static PyMethodDef posix_methods[] = {
17467
    OS_STAT_METHODDEF
17468
    OS_STATX_METHODDEF
17469
    OS_ACCESS_METHODDEF
17470
    OS_TTYNAME_METHODDEF
17471
    OS_CHDIR_METHODDEF
17472
    OS_CHFLAGS_METHODDEF
17473
    OS_CHMOD_METHODDEF
17474
    OS_FCHMOD_METHODDEF
17475
    OS_LCHMOD_METHODDEF
17476
    OS_CHOWN_METHODDEF
17477
    OS_FCHOWN_METHODDEF
17478
    OS_LCHOWN_METHODDEF
17479
    OS_LCHFLAGS_METHODDEF
17480
    OS_CHROOT_METHODDEF
17481
    OS_CTERMID_METHODDEF
17482
    OS_GETCWD_METHODDEF
17483
    OS_GETCWDB_METHODDEF
17484
    OS_LINK_METHODDEF
17485
    OS_LISTDIR_METHODDEF
17486
    OS_LISTDRIVES_METHODDEF
17487
    OS_LISTMOUNTS_METHODDEF
17488
    OS_LISTVOLUMES_METHODDEF
17489
    OS_LSTAT_METHODDEF
17490
    OS_MKDIR_METHODDEF
17491
    OS_NICE_METHODDEF
17492
    OS_GETPRIORITY_METHODDEF
17493
    OS_SETPRIORITY_METHODDEF
17494
    OS_POSIX_SPAWN_METHODDEF
17495
    OS_POSIX_SPAWNP_METHODDEF
17496
    OS_READLINK_METHODDEF
17497
    OS_COPY_FILE_RANGE_METHODDEF
17498
    OS_SPLICE_METHODDEF
17499
    OS_RENAME_METHODDEF
17500
    OS_REPLACE_METHODDEF
17501
    OS_RMDIR_METHODDEF
17502
    OS_SYMLINK_METHODDEF
17503
    OS_SYSTEM_METHODDEF
17504
    OS_UMASK_METHODDEF
17505
    OS_UNAME_METHODDEF
17506
    OS_UNLINK_METHODDEF
17507
    OS_REMOVE_METHODDEF
17508
    OS_UTIME_METHODDEF
17509
    OS_TIMES_METHODDEF
17510
    OS__EXIT_METHODDEF
17511
    OS__FCOPYFILE_METHODDEF
17512
    OS_EXECV_METHODDEF
17513
    OS_EXECVE_METHODDEF
17514
    OS_SPAWNV_METHODDEF
17515
    OS_SPAWNVE_METHODDEF
17516
    OS_FORK1_METHODDEF
17517
    OS_FORK_METHODDEF
17518
    OS_REGISTER_AT_FORK_METHODDEF
17519
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17520
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17521
    OS_SCHED_GETPARAM_METHODDEF
17522
    OS_SCHED_GETSCHEDULER_METHODDEF
17523
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17524
    OS_SCHED_SETPARAM_METHODDEF
17525
    OS_SCHED_SETSCHEDULER_METHODDEF
17526
    OS_SCHED_YIELD_METHODDEF
17527
    OS_SCHED_SETAFFINITY_METHODDEF
17528
    OS_SCHED_GETAFFINITY_METHODDEF
17529
    OS_POSIX_OPENPT_METHODDEF
17530
    OS_GRANTPT_METHODDEF
17531
    OS_UNLOCKPT_METHODDEF
17532
    OS_PTSNAME_METHODDEF
17533
    OS_OPENPTY_METHODDEF
17534
    OS_LOGIN_TTY_METHODDEF
17535
    OS_FORKPTY_METHODDEF
17536
    OS_GETEGID_METHODDEF
17537
    OS_GETEUID_METHODDEF
17538
    OS_GETGID_METHODDEF
17539
    OS_GETGROUPLIST_METHODDEF
17540
    OS_GETGROUPS_METHODDEF
17541
    OS_GETPID_METHODDEF
17542
    OS_GETPGRP_METHODDEF
17543
    OS_GETPPID_METHODDEF
17544
    OS_GETUID_METHODDEF
17545
    OS_GETLOGIN_METHODDEF
17546
    OS_KILL_METHODDEF
17547
    OS_KILLPG_METHODDEF
17548
    OS_PLOCK_METHODDEF
17549
    OS_STARTFILE_METHODDEF
17550
    OS_SETUID_METHODDEF
17551
    OS_SETEUID_METHODDEF
17552
    OS_SETREUID_METHODDEF
17553
    OS_SETGID_METHODDEF
17554
    OS_SETEGID_METHODDEF
17555
    OS_SETREGID_METHODDEF
17556
    OS_SETGROUPS_METHODDEF
17557
    OS_INITGROUPS_METHODDEF
17558
    OS_GETPGID_METHODDEF
17559
    OS_SETPGRP_METHODDEF
17560
    OS_WAIT_METHODDEF
17561
    OS_WAIT3_METHODDEF
17562
    OS_WAIT4_METHODDEF
17563
    OS_WAITID_METHODDEF
17564
    OS_WAITPID_METHODDEF
17565
    OS_PIDFD_OPEN_METHODDEF
17566
    OS_GETSID_METHODDEF
17567
    OS_SETSID_METHODDEF
17568
    OS_SETPGID_METHODDEF
17569
    OS_TCGETPGRP_METHODDEF
17570
    OS_TCSETPGRP_METHODDEF
17571
    OS_OPEN_METHODDEF
17572
    OS_CLOSE_METHODDEF
17573
    OS_CLOSERANGE_METHODDEF
17574
    OS_DEVICE_ENCODING_METHODDEF
17575
    OS_DUP_METHODDEF
17576
    OS_DUP2_METHODDEF
17577
    OS_LOCKF_METHODDEF
17578
    OS_LSEEK_METHODDEF
17579
    OS_READ_METHODDEF
17580
    OS_READINTO_METHODDEF
17581
    OS_READV_METHODDEF
17582
    OS_PREAD_METHODDEF
17583
    OS_PREADV_METHODDEF
17584
    OS_WRITE_METHODDEF
17585
    OS_WRITEV_METHODDEF
17586
    OS_PWRITE_METHODDEF
17587
    OS_PWRITEV_METHODDEF
17588
    OS_SENDFILE_METHODDEF
17589
    OS_FSTAT_METHODDEF
17590
    OS_ISATTY_METHODDEF
17591
    OS_PIPE_METHODDEF
17592
    OS_PIPE2_METHODDEF
17593
    OS_MKFIFO_METHODDEF
17594
    OS_MKNOD_METHODDEF
17595
    OS_MAJOR_METHODDEF
17596
    OS_MINOR_METHODDEF
17597
    OS_MAKEDEV_METHODDEF
17598
    OS_FTRUNCATE_METHODDEF
17599
    OS_TRUNCATE_METHODDEF
17600
    OS_POSIX_FALLOCATE_METHODDEF
17601
    OS_POSIX_FADVISE_METHODDEF
17602
    OS_PUTENV_METHODDEF
17603
    OS_UNSETENV_METHODDEF
17604
    OS__CLEARENV_METHODDEF
17605
    OS_STRERROR_METHODDEF
17606
    OS_FCHDIR_METHODDEF
17607
    OS_FSYNC_METHODDEF
17608
    OS_SYNC_METHODDEF
17609
    OS_FDATASYNC_METHODDEF
17610
    OS_WCOREDUMP_METHODDEF
17611
    OS_WIFCONTINUED_METHODDEF
17612
    OS_WIFSTOPPED_METHODDEF
17613
    OS_WIFSIGNALED_METHODDEF
17614
    OS_WIFEXITED_METHODDEF
17615
    OS_WEXITSTATUS_METHODDEF
17616
    OS_WTERMSIG_METHODDEF
17617
    OS_WSTOPSIG_METHODDEF
17618
    OS_FSTATVFS_METHODDEF
17619
    OS_STATVFS_METHODDEF
17620
    OS_CONFSTR_METHODDEF
17621
    OS_SYSCONF_METHODDEF
17622
    OS_FPATHCONF_METHODDEF
17623
    OS_PATHCONF_METHODDEF
17624
    OS_ABORT_METHODDEF
17625
    OS__GETFULLPATHNAME_METHODDEF
17626
    OS__GETDISKUSAGE_METHODDEF
17627
    OS__GETFINALPATHNAME_METHODDEF
17628
    OS__FINDFIRSTFILE_METHODDEF
17629
    OS__GETVOLUMEPATHNAME_METHODDEF
17630
    OS__PATH_SPLITROOT_METHODDEF
17631
    OS__PATH_SPLITROOT_EX_METHODDEF
17632
    OS__PATH_NORMPATH_METHODDEF
17633
    OS_GETLOADAVG_METHODDEF
17634
    OS_URANDOM_METHODDEF
17635
    OS_SETRESUID_METHODDEF
17636
    OS_SETRESGID_METHODDEF
17637
    OS_GETRESUID_METHODDEF
17638
    OS_GETRESGID_METHODDEF
17639
17640
    OS_GETXATTR_METHODDEF
17641
    OS_SETXATTR_METHODDEF
17642
    OS_REMOVEXATTR_METHODDEF
17643
    OS_LISTXATTR_METHODDEF
17644
17645
    OS_GET_TERMINAL_SIZE_METHODDEF
17646
    OS_CPU_COUNT_METHODDEF
17647
    OS_GET_INHERITABLE_METHODDEF
17648
    OS_SET_INHERITABLE_METHODDEF
17649
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17650
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17651
    OS_GET_BLOCKING_METHODDEF
17652
    OS_SET_BLOCKING_METHODDEF
17653
    OS_SCANDIR_METHODDEF
17654
    OS_FSPATH_METHODDEF
17655
    OS_GETRANDOM_METHODDEF
17656
    OS_MEMFD_CREATE_METHODDEF
17657
    OS_EVENTFD_METHODDEF
17658
    OS_EVENTFD_READ_METHODDEF
17659
    OS_EVENTFD_WRITE_METHODDEF
17660
    OS__ADD_DLL_DIRECTORY_METHODDEF
17661
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17662
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17663
    OS_SETNS_METHODDEF
17664
    OS_UNSHARE_METHODDEF
17665
    OS_TIMERFD_CREATE_METHODDEF
17666
    OS_TIMERFD_SETTIME_METHODDEF
17667
    OS_TIMERFD_SETTIME_NS_METHODDEF
17668
    OS_TIMERFD_GETTIME_METHODDEF
17669
    OS_TIMERFD_GETTIME_NS_METHODDEF
17670
17671
    OS__PATH_ISDEVDRIVE_METHODDEF
17672
    OS__PATH_ISDIR_METHODDEF
17673
    OS__PATH_ISFILE_METHODDEF
17674
    OS__PATH_ISLINK_METHODDEF
17675
    OS__PATH_ISJUNCTION_METHODDEF
17676
    OS__PATH_EXISTS_METHODDEF
17677
    OS__PATH_LEXISTS_METHODDEF
17678
17679
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17680
    OS__INPUTHOOK_METHODDEF
17681
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17682
    OS__CREATE_ENVIRON_METHODDEF
17683
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17684
    OS__EMSCRIPTEN_LOG_METHODDEF
17685
    {NULL,              NULL}            /* Sentinel */
17686
};
17687
17688
static int
17689
all_ins(PyObject *m)
17690
16
{
17691
16
#ifdef F_OK
17692
16
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17693
16
#endif
17694
16
#ifdef R_OK
17695
16
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17696
16
#endif
17697
16
#ifdef W_OK
17698
16
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17699
16
#endif
17700
16
#ifdef X_OK
17701
16
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17702
16
#endif
17703
16
#ifdef NGROUPS_MAX
17704
16
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17705
16
#endif
17706
16
#ifdef TMP_MAX
17707
16
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17708
16
#endif
17709
16
#ifdef WCONTINUED
17710
16
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17711
16
#endif
17712
16
#ifdef WNOHANG
17713
16
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17714
16
#endif
17715
16
#ifdef WUNTRACED
17716
16
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17717
16
#endif
17718
16
#ifdef O_RDONLY
17719
16
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17720
16
#endif
17721
16
#ifdef O_WRONLY
17722
16
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17723
16
#endif
17724
16
#ifdef O_RDWR
17725
16
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17726
16
#endif
17727
16
#ifdef O_NDELAY
17728
16
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17729
16
#endif
17730
16
#ifdef O_NONBLOCK
17731
16
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17732
16
#endif
17733
16
#ifdef O_APPEND
17734
16
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17735
16
#endif
17736
16
#ifdef O_DSYNC
17737
16
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17738
16
#endif
17739
16
#ifdef O_RSYNC
17740
16
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17741
16
#endif
17742
16
#ifdef O_SYNC
17743
16
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17744
16
#endif
17745
16
#ifdef O_NOCTTY
17746
16
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17747
16
#endif
17748
16
#ifdef O_CREAT
17749
16
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17750
16
#endif
17751
16
#ifdef O_EXCL
17752
16
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17753
16
#endif
17754
16
#ifdef O_TRUNC
17755
16
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17756
16
#endif
17757
#ifdef O_BINARY
17758
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17759
#endif
17760
#ifdef O_TEXT
17761
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17762
#endif
17763
#ifdef O_XATTR
17764
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17765
#endif
17766
16
#ifdef O_LARGEFILE
17767
16
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17768
16
#endif
17769
16
#ifndef __GNU__
17770
#ifdef O_SHLOCK
17771
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17772
#endif
17773
#ifdef O_EXLOCK
17774
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17775
#endif
17776
16
#endif
17777
#ifdef O_EXEC
17778
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17779
#endif
17780
#ifdef O_SEARCH
17781
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17782
#endif
17783
16
#ifdef O_PATH
17784
16
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17785
16
#endif
17786
#ifdef O_TTY_INIT
17787
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17788
#endif
17789
16
#ifdef O_TMPFILE
17790
16
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17791
16
#endif
17792
16
#ifdef PRIO_PROCESS
17793
16
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17794
16
#endif
17795
16
#ifdef PRIO_PGRP
17796
16
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17797
16
#endif
17798
16
#ifdef PRIO_USER
17799
16
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17800
16
#endif
17801
#ifdef PRIO_DARWIN_THREAD
17802
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17803
#endif
17804
#ifdef PRIO_DARWIN_PROCESS
17805
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17806
#endif
17807
#ifdef PRIO_DARWIN_BG
17808
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17809
#endif
17810
#ifdef PRIO_DARWIN_NONUI
17811
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17812
#endif
17813
16
#ifdef O_CLOEXEC
17814
16
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17815
16
#endif
17816
16
#ifdef O_ACCMODE
17817
16
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17818
16
#endif
17819
#ifdef O_EVTONLY
17820
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17821
#endif
17822
16
#ifdef O_FSYNC
17823
16
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17824
16
#endif
17825
#ifdef O_SYMLINK
17826
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17827
#endif
17828
17829
16
#ifdef SEEK_HOLE
17830
16
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17831
16
#endif
17832
16
#ifdef SEEK_DATA
17833
16
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17834
16
#endif
17835
17836
/* MS Windows */
17837
#ifdef O_NOINHERIT
17838
    /* Don't inherit in child processes. */
17839
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17840
#endif
17841
#ifdef _O_SHORT_LIVED
17842
    /* Optimize for short life (keep in memory). */
17843
    /* MS forgot to define this one with a non-underscore form too. */
17844
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17845
#endif
17846
#ifdef O_TEMPORARY
17847
    /* Automatically delete when last handle is closed. */
17848
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17849
#endif
17850
#ifdef O_RANDOM
17851
    /* Optimize for random access. */
17852
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17853
#endif
17854
#ifdef O_SEQUENTIAL
17855
    /* Optimize for sequential access. */
17856
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17857
#endif
17858
17859
/* GNU extensions. */
17860
16
#ifdef O_ASYNC
17861
    /* Send a SIGIO signal whenever input or output
17862
       becomes available on file descriptor */
17863
16
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17864
16
#endif
17865
16
#ifdef O_DIRECT
17866
    /* Direct disk access. */
17867
16
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17868
16
#endif
17869
16
#ifdef O_DIRECTORY
17870
    /* Must be a directory.      */
17871
16
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17872
16
#endif
17873
16
#ifdef O_NOFOLLOW
17874
    /* Do not follow links.      */
17875
16
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17876
16
#endif
17877
#ifdef O_NOFOLLOW_ANY
17878
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17879
#endif
17880
#ifdef O_NOLINKS
17881
    /* Fails if link count of the named file is greater than 1 */
17882
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17883
#endif
17884
16
#ifdef O_NOATIME
17885
    /* Do not update the access time. */
17886
16
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17887
16
#endif
17888
17889
    /* These come from sysexits.h */
17890
16
#ifdef EX_OK
17891
16
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17892
16
#endif /* EX_OK */
17893
16
#ifdef EX_USAGE
17894
16
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17895
16
#endif /* EX_USAGE */
17896
16
#ifdef EX_DATAERR
17897
16
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17898
16
#endif /* EX_DATAERR */
17899
16
#ifdef EX_NOINPUT
17900
16
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17901
16
#endif /* EX_NOINPUT */
17902
16
#ifdef EX_NOUSER
17903
16
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17904
16
#endif /* EX_NOUSER */
17905
16
#ifdef EX_NOHOST
17906
16
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17907
16
#endif /* EX_NOHOST */
17908
16
#ifdef EX_UNAVAILABLE
17909
16
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17910
16
#endif /* EX_UNAVAILABLE */
17911
16
#ifdef EX_SOFTWARE
17912
16
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17913
16
#endif /* EX_SOFTWARE */
17914
16
#ifdef EX_OSERR
17915
16
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17916
16
#endif /* EX_OSERR */
17917
16
#ifdef EX_OSFILE
17918
16
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17919
16
#endif /* EX_OSFILE */
17920
16
#ifdef EX_CANTCREAT
17921
16
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17922
16
#endif /* EX_CANTCREAT */
17923
16
#ifdef EX_IOERR
17924
16
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17925
16
#endif /* EX_IOERR */
17926
16
#ifdef EX_TEMPFAIL
17927
16
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17928
16
#endif /* EX_TEMPFAIL */
17929
16
#ifdef EX_PROTOCOL
17930
16
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17931
16
#endif /* EX_PROTOCOL */
17932
16
#ifdef EX_NOPERM
17933
16
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17934
16
#endif /* EX_NOPERM */
17935
16
#ifdef EX_CONFIG
17936
16
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17937
16
#endif /* EX_CONFIG */
17938
#ifdef EX_NOTFOUND
17939
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17940
#endif /* EX_NOTFOUND */
17941
17942
    /* statvfs */
17943
16
#ifdef ST_RDONLY
17944
16
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17945
16
#endif /* ST_RDONLY */
17946
16
#ifdef ST_NOSUID
17947
16
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17948
16
#endif /* ST_NOSUID */
17949
17950
       /* GNU extensions */
17951
16
#ifdef ST_NODEV
17952
16
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17953
16
#endif /* ST_NODEV */
17954
16
#ifdef ST_NOEXEC
17955
16
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17956
16
#endif /* ST_NOEXEC */
17957
16
#ifdef ST_SYNCHRONOUS
17958
16
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17959
16
#endif /* ST_SYNCHRONOUS */
17960
16
#ifdef ST_MANDLOCK
17961
16
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17962
16
#endif /* ST_MANDLOCK */
17963
16
#ifdef ST_WRITE
17964
16
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17965
16
#endif /* ST_WRITE */
17966
16
#ifdef ST_APPEND
17967
16
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
17968
16
#endif /* ST_APPEND */
17969
16
#ifdef ST_NOATIME
17970
16
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
17971
16
#endif /* ST_NOATIME */
17972
16
#ifdef ST_NODIRATIME
17973
16
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
17974
16
#endif /* ST_NODIRATIME */
17975
16
#ifdef ST_RELATIME
17976
16
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
17977
16
#endif /* ST_RELATIME */
17978
17979
    /* FreeBSD sendfile() constants */
17980
#ifdef SF_NODISKIO
17981
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
17982
#endif
17983
    /* is obsolete since the 11.x release */
17984
#ifdef SF_MNOWAIT
17985
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
17986
#endif
17987
#ifdef SF_SYNC
17988
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
17989
#endif
17990
#ifdef SF_NOCACHE
17991
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
17992
#endif
17993
17994
16
#ifdef TFD_NONBLOCK
17995
16
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
17996
16
#endif
17997
16
#ifdef TFD_CLOEXEC
17998
16
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
17999
16
#endif
18000
16
#ifdef TFD_TIMER_ABSTIME
18001
16
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18002
16
#endif
18003
16
#ifdef TFD_TIMER_CANCEL_ON_SET
18004
16
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18005
16
#endif
18006
18007
    /* constants for posix_fadvise */
18008
16
#ifdef POSIX_FADV_NORMAL
18009
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18010
16
#endif
18011
16
#ifdef POSIX_FADV_SEQUENTIAL
18012
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18013
16
#endif
18014
16
#ifdef POSIX_FADV_RANDOM
18015
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18016
16
#endif
18017
16
#ifdef POSIX_FADV_NOREUSE
18018
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18019
16
#endif
18020
16
#ifdef POSIX_FADV_WILLNEED
18021
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18022
16
#endif
18023
16
#ifdef POSIX_FADV_DONTNEED
18024
16
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18025
16
#endif
18026
18027
    /* constants for waitid */
18028
16
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18029
16
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18030
16
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18031
16
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18032
16
#ifdef P_PIDFD
18033
16
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18034
16
#endif
18035
#ifdef PIDFD_NONBLOCK
18036
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18037
#endif
18038
16
#endif
18039
16
#ifdef WEXITED
18040
16
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18041
16
#endif
18042
16
#ifdef WNOWAIT
18043
16
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18044
16
#endif
18045
16
#ifdef WSTOPPED
18046
16
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18047
16
#endif
18048
16
#ifdef CLD_EXITED
18049
16
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18050
16
#endif
18051
16
#ifdef CLD_KILLED
18052
16
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18053
16
#endif
18054
16
#ifdef CLD_DUMPED
18055
16
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18056
16
#endif
18057
16
#ifdef CLD_TRAPPED
18058
16
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18059
16
#endif
18060
16
#ifdef CLD_STOPPED
18061
16
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18062
16
#endif
18063
16
#ifdef CLD_CONTINUED
18064
16
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18065
16
#endif
18066
18067
    /* constants for lockf */
18068
16
#ifdef F_LOCK
18069
16
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18070
16
#endif
18071
16
#ifdef F_TLOCK
18072
16
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18073
16
#endif
18074
16
#ifdef F_ULOCK
18075
16
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18076
16
#endif
18077
16
#ifdef F_TEST
18078
16
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18079
16
#endif
18080
18081
16
#ifdef RWF_DSYNC
18082
16
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18083
16
#endif
18084
16
#ifdef RWF_HIPRI
18085
16
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18086
16
#endif
18087
16
#ifdef RWF_SYNC
18088
16
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18089
16
#endif
18090
16
#ifdef RWF_NOWAIT
18091
16
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18092
16
#endif
18093
#ifdef RWF_DONTCACHE
18094
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18095
#endif
18096
16
#ifdef RWF_APPEND
18097
16
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18098
16
#endif
18099
18100
/* constants for splice */
18101
16
#if defined(HAVE_SPLICE) && defined(__linux__)
18102
16
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18103
16
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18104
16
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18105
16
#endif
18106
18107
/* constants for posix_spawn */
18108
16
#ifdef HAVE_POSIX_SPAWN
18109
16
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18110
16
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18111
16
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18112
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18113
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18114
#endif
18115
16
#endif
18116
18117
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18118
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18119
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18120
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18121
#endif
18122
#ifdef HAVE_SPAWNV
18123
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18124
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18125
#endif
18126
18127
16
#ifdef HAVE_SCHED_H
18128
16
#ifdef SCHED_OTHER
18129
16
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18130
16
#endif
18131
16
#ifdef SCHED_DEADLINE
18132
16
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18133
16
#endif
18134
16
#ifdef SCHED_FIFO
18135
16
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18136
16
#endif
18137
16
#ifdef SCHED_NORMAL
18138
16
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18139
16
#endif
18140
16
#ifdef SCHED_RR
18141
16
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18142
16
#endif
18143
#ifdef SCHED_SPORADIC
18144
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18145
#endif
18146
16
#ifdef SCHED_BATCH
18147
16
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18148
16
#endif
18149
16
#ifdef SCHED_IDLE
18150
16
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18151
16
#endif
18152
16
#ifdef SCHED_RESET_ON_FORK
18153
16
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18154
16
#endif
18155
#ifdef SCHED_SYS
18156
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18157
#endif
18158
#ifdef SCHED_IA
18159
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18160
#endif
18161
#ifdef SCHED_FSS
18162
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18163
#endif
18164
#ifdef SCHED_FX
18165
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18166
#endif
18167
18168
/* constants for namespaces */
18169
16
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18170
16
#ifdef CLONE_FS
18171
16
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18172
16
#endif
18173
16
#ifdef CLONE_FILES
18174
16
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18175
16
#endif
18176
16
#ifdef CLONE_NEWNS
18177
16
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18178
16
#endif
18179
16
#ifdef CLONE_NEWCGROUP
18180
16
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18181
16
#endif
18182
16
#ifdef CLONE_NEWUTS
18183
16
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18184
16
#endif
18185
16
#ifdef CLONE_NEWIPC
18186
16
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18187
16
#endif
18188
16
#ifdef CLONE_NEWUSER
18189
16
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18190
16
#endif
18191
16
#ifdef CLONE_NEWPID
18192
16
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18193
16
#endif
18194
16
#ifdef CLONE_NEWNET
18195
16
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18196
16
#endif
18197
#ifdef CLONE_NEWTIME
18198
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18199
#endif
18200
16
#ifdef CLONE_SYSVSEM
18201
16
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18202
16
#endif
18203
16
#ifdef CLONE_THREAD
18204
16
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18205
16
#endif
18206
16
#ifdef CLONE_SIGHAND
18207
16
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18208
16
#endif
18209
16
#ifdef CLONE_VM
18210
16
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18211
16
#endif
18212
16
#endif
18213
18214
16
#endif
18215
18216
16
#ifdef USE_XATTRS
18217
16
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18218
16
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18219
16
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18220
16
#endif
18221
18222
16
#if HAVE_DECL_RTLD_LAZY
18223
16
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18224
16
#endif
18225
16
#if HAVE_DECL_RTLD_NOW
18226
16
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18227
16
#endif
18228
16
#if HAVE_DECL_RTLD_GLOBAL
18229
16
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18230
16
#endif
18231
16
#if HAVE_DECL_RTLD_LOCAL
18232
16
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18233
16
#endif
18234
16
#if HAVE_DECL_RTLD_NODELETE
18235
16
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18236
16
#endif
18237
16
#if HAVE_DECL_RTLD_NOLOAD
18238
16
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18239
16
#endif
18240
16
#if HAVE_DECL_RTLD_DEEPBIND
18241
16
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18242
16
#endif
18243
#if HAVE_DECL_RTLD_MEMBER
18244
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18245
#endif
18246
18247
16
#ifdef HAVE_GETRANDOM_SYSCALL
18248
16
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18249
16
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18250
16
#endif
18251
16
#ifdef HAVE_MEMFD_CREATE
18252
16
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18253
16
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18254
16
#ifdef MFD_HUGETLB
18255
16
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18256
16
#endif
18257
16
#ifdef MFD_HUGE_SHIFT
18258
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18259
16
#endif
18260
16
#ifdef MFD_HUGE_MASK
18261
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18262
16
#endif
18263
16
#ifdef MFD_HUGE_64KB
18264
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18265
16
#endif
18266
16
#ifdef MFD_HUGE_512KB
18267
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18268
16
#endif
18269
16
#ifdef MFD_HUGE_1MB
18270
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18271
16
#endif
18272
16
#ifdef MFD_HUGE_2MB
18273
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18274
16
#endif
18275
16
#ifdef MFD_HUGE_8MB
18276
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18277
16
#endif
18278
16
#ifdef MFD_HUGE_16MB
18279
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18280
16
#endif
18281
16
#ifdef MFD_HUGE_32MB
18282
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18283
16
#endif
18284
16
#ifdef MFD_HUGE_256MB
18285
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18286
16
#endif
18287
16
#ifdef MFD_HUGE_512MB
18288
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18289
16
#endif
18290
16
#ifdef MFD_HUGE_1GB
18291
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18292
16
#endif
18293
16
#ifdef MFD_HUGE_2GB
18294
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18295
16
#endif
18296
16
#ifdef MFD_HUGE_16GB
18297
16
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18298
16
#endif
18299
16
#endif /* HAVE_MEMFD_CREATE */
18300
18301
16
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18302
16
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18303
16
#ifdef EFD_NONBLOCK
18304
16
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18305
16
#endif
18306
16
#ifdef EFD_SEMAPHORE
18307
16
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18308
16
#endif
18309
16
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18310
18311
16
#ifdef NODEV
18312
16
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18313
16
#endif
18314
18315
16
#ifdef AT_NO_AUTOMOUNT
18316
16
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18317
16
#endif
18318
18319
16
#ifdef HAVE_STATX
18320
16
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18321
16
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18322
16
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18323
16
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18324
16
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18325
16
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18326
16
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18327
16
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18328
16
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18329
16
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18330
16
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18331
16
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18332
16
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18333
#ifdef STATX_MNT_ID
18334
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18335
#endif
18336
#ifdef STATX_DIOALIGN
18337
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18338
#endif
18339
#ifdef STATX_MNT_ID_UNIQUE
18340
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18341
#endif
18342
#ifdef STATX_SUBVOL
18343
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18344
#endif
18345
#ifdef STATX_WRITE_ATOMIC
18346
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18347
#endif
18348
#ifdef STATX_DIO_READ_ALIGN
18349
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18350
#endif
18351
    /* STATX_ALL intentionally omitted because it is deprecated */
18352
16
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18353
16
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18354
16
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18355
    /* STATX_ATTR_* constants are in the stat module */
18356
16
#endif /* HAVE_STATX */
18357
18358
#if defined(__APPLE__)
18359
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18360
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18361
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18362
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18363
#endif
18364
18365
#ifdef MS_WINDOWS
18366
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18367
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18368
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18369
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18370
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18371
#endif
18372
18373
16
    return 0;
18374
16
}
18375
18376
18377
18378
#define PROBE(name, test) \
18379
   static int name(void)  \
18380
272
   {                      \
18381
272
      if (test) {        \
18382
272
          return 1;       \
18383
272
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
272
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_futimens
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_linkat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_openat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_renameat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18380
16
   {                      \
18381
16
      if (test) {        \
18382
16
          return 1;       \
18383
16
      } else {            \
18384
0
          return 0;       \
18385
0
      }                   \
18386
16
   }
18387
18388
#ifdef HAVE_FSTATAT
18389
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18390
#endif
18391
18392
#ifdef HAVE_FACCESSAT
18393
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18394
#endif
18395
18396
#ifdef HAVE_FCHMODAT
18397
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18398
#endif
18399
18400
#ifdef HAVE_FCHOWNAT
18401
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18402
#endif
18403
18404
#ifdef HAVE_LINKAT
18405
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18406
#endif
18407
18408
#ifdef HAVE_FDOPENDIR
18409
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18410
#endif
18411
18412
#ifdef HAVE_MKDIRAT
18413
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18414
#endif
18415
18416
#ifdef HAVE_MKFIFOAT
18417
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18418
#endif
18419
18420
#ifdef HAVE_MKNODAT
18421
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18422
#endif
18423
18424
#ifdef HAVE_RENAMEAT
18425
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18426
#endif
18427
18428
#ifdef HAVE_UNLINKAT
18429
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18430
#endif
18431
18432
#ifdef HAVE_OPENAT
18433
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18434
#endif
18435
18436
#ifdef HAVE_READLINKAT
18437
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18438
#endif
18439
18440
#ifdef HAVE_SYMLINKAT
18441
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18442
#endif
18443
18444
#ifdef HAVE_FUTIMENS
18445
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18446
#endif
18447
18448
#ifdef HAVE_UTIMENSAT
18449
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18450
#endif
18451
18452
#ifdef HAVE_PTSNAME_R
18453
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18454
#endif
18455
18456
18457
18458
static const struct have_function {
18459
    const char * const label;
18460
    int (*probe)(void);
18461
} have_functions[] = {
18462
18463
#ifdef HAVE_EVENTFD
18464
    {"HAVE_EVENTFD", NULL},
18465
#endif
18466
18467
#ifdef HAVE_TIMERFD_CREATE
18468
    {"HAVE_TIMERFD_CREATE", NULL},
18469
#endif
18470
18471
#ifdef HAVE_FACCESSAT
18472
    { "HAVE_FACCESSAT", probe_faccessat },
18473
#endif
18474
18475
#ifdef HAVE_FCHDIR
18476
    { "HAVE_FCHDIR", NULL },
18477
#endif
18478
18479
#ifdef HAVE_FCHMOD
18480
    { "HAVE_FCHMOD", NULL },
18481
#endif
18482
18483
#ifdef HAVE_FCHMODAT
18484
    { "HAVE_FCHMODAT", probe_fchmodat },
18485
#endif
18486
18487
#ifdef HAVE_FCHOWN
18488
    { "HAVE_FCHOWN", NULL },
18489
#endif
18490
18491
#ifdef HAVE_FCHOWNAT
18492
    { "HAVE_FCHOWNAT", probe_fchownat },
18493
#endif
18494
18495
#ifdef HAVE_FEXECVE
18496
    { "HAVE_FEXECVE", NULL },
18497
#endif
18498
18499
#ifdef HAVE_FDOPENDIR
18500
    { "HAVE_FDOPENDIR", probe_fdopendir },
18501
#endif
18502
18503
#ifdef HAVE_FPATHCONF
18504
    { "HAVE_FPATHCONF", NULL },
18505
#endif
18506
18507
#ifdef HAVE_FSTATAT
18508
    { "HAVE_FSTATAT", probe_fstatat },
18509
#endif
18510
18511
#ifdef HAVE_FSTATVFS
18512
    { "HAVE_FSTATVFS", NULL },
18513
#endif
18514
18515
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18516
    { "HAVE_FTRUNCATE", NULL },
18517
#endif
18518
18519
#ifdef HAVE_FUTIMENS
18520
    { "HAVE_FUTIMENS", probe_futimens },
18521
#endif
18522
18523
#ifdef HAVE_FUTIMES
18524
    { "HAVE_FUTIMES", NULL },
18525
#endif
18526
18527
#ifdef HAVE_FUTIMESAT
18528
    { "HAVE_FUTIMESAT", NULL },
18529
#endif
18530
18531
#ifdef HAVE_LINKAT
18532
    { "HAVE_LINKAT", probe_linkat },
18533
#endif
18534
18535
#ifdef HAVE_LCHFLAGS
18536
    { "HAVE_LCHFLAGS", NULL },
18537
#endif
18538
18539
#ifdef HAVE_LCHMOD
18540
    { "HAVE_LCHMOD", NULL },
18541
#endif
18542
18543
#ifdef HAVE_LCHOWN
18544
    { "HAVE_LCHOWN", NULL },
18545
#endif
18546
18547
#ifdef HAVE_LSTAT
18548
    { "HAVE_LSTAT", NULL },
18549
#endif
18550
18551
#ifdef HAVE_LUTIMES
18552
    { "HAVE_LUTIMES", NULL },
18553
#endif
18554
18555
#ifdef HAVE_MEMFD_CREATE
18556
    { "HAVE_MEMFD_CREATE", NULL },
18557
#endif
18558
18559
#ifdef HAVE_MKDIRAT
18560
    { "HAVE_MKDIRAT", probe_mkdirat },
18561
#endif
18562
18563
#ifdef HAVE_MKFIFOAT
18564
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18565
#endif
18566
18567
#ifdef HAVE_MKNODAT
18568
    { "HAVE_MKNODAT", probe_mknodat },
18569
#endif
18570
18571
#ifdef HAVE_OPENAT
18572
    { "HAVE_OPENAT", probe_openat },
18573
#endif
18574
18575
#ifdef HAVE_READLINKAT
18576
    { "HAVE_READLINKAT", probe_readlinkat },
18577
#endif
18578
18579
#ifdef HAVE_RENAMEAT
18580
    { "HAVE_RENAMEAT", probe_renameat },
18581
#endif
18582
18583
#ifdef HAVE_SYMLINKAT
18584
    { "HAVE_SYMLINKAT", probe_symlinkat },
18585
#endif
18586
18587
#ifdef HAVE_UNLINKAT
18588
    { "HAVE_UNLINKAT", probe_unlinkat },
18589
#endif
18590
18591
#ifdef HAVE_UTIMENSAT
18592
    { "HAVE_UTIMENSAT", probe_utimensat },
18593
#endif
18594
18595
#ifdef HAVE_PTSNAME_R
18596
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18597
#endif
18598
18599
#ifdef MS_WINDOWS
18600
    { "MS_WINDOWS", NULL },
18601
#endif
18602
18603
    { NULL, NULL }
18604
};
18605
18606
18607
static int
18608
posixmodule_exec(PyObject *m)
18609
16
{
18610
16
    _posixstate *state = get_posix_state(m);
18611
18612
16
#if defined(HAVE_PWRITEV)
18613
16
    if (HAVE_PWRITEV_RUNTIME) {} else {
18614
0
        PyObject* dct = PyModule_GetDict(m);
18615
18616
0
        if (dct == NULL) {
18617
0
            return -1;
18618
0
        }
18619
18620
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18621
0
            return -1;
18622
0
        }
18623
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18624
0
            return -1;
18625
0
        }
18626
0
    }
18627
16
#endif
18628
18629
16
#ifdef HAVE_STATX
18630
16
    if (statx == NULL) {
18631
0
        PyObject* dct = PyModule_GetDict(m);
18632
0
        if (dct == NULL) {
18633
0
            return -1;
18634
0
        }
18635
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18636
0
            return -1;
18637
0
        }
18638
0
    }
18639
16
    else {
18640
16
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18641
16
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18642
0
            return -1;
18643
0
        }
18644
16
    }
18645
16
#endif
18646
18647
    /* Initialize environ dictionary */
18648
16
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18649
0
        return -1;
18650
0
    }
18651
18652
16
    if (all_ins(m))
18653
0
        return -1;
18654
18655
16
    if (setup_confname_tables(m))
18656
0
        return -1;
18657
18658
16
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18659
0
        return -1;
18660
0
    }
18661
18662
16
#if defined(HAVE_WAITID)
18663
16
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18664
16
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18665
0
        return -1;
18666
0
    }
18667
16
#endif
18668
18669
16
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18670
16
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18671
16
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18672
16
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18673
16
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18674
0
        return -1;
18675
0
    }
18676
16
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18677
16
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18678
18679
16
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18680
16
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18681
0
        return -1;
18682
0
    }
18683
18684
16
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18685
16
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18686
16
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18687
0
        return -1;
18688
0
    }
18689
16
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18690
16
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18691
16
                          &os_sched_param_reduce_method) < 0)
18692
0
    {
18693
0
        return -1;
18694
0
    }
18695
16
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18696
16
#endif
18697
18698
    /* initialize TerminalSize_info */
18699
16
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18700
16
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18701
0
        return -1;
18702
0
    }
18703
18704
    /* initialize scandir types */
18705
16
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18706
16
    if (ScandirIteratorType == NULL) {
18707
0
        return -1;
18708
0
    }
18709
16
    state->ScandirIteratorType = ScandirIteratorType;
18710
18711
16
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18712
16
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18713
0
        return -1;
18714
0
    }
18715
18716
16
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18717
16
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18718
0
        return -1;
18719
0
    }
18720
18721
16
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18722
16
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18723
0
        return -1;
18724
0
    }
18725
18726
16
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18727
0
        return -1;
18728
16
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18729
16
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18730
16
    if (state->struct_rusage == NULL)
18731
0
        return -1;
18732
16
#endif
18733
16
    state->st_mode = PyUnicode_InternFromString("st_mode");
18734
16
    if (state->st_mode == NULL)
18735
0
        return -1;
18736
18737
    /* suppress "function not used" warnings */
18738
16
    {
18739
16
    int ignored;
18740
16
    fd_specified("", -1);
18741
16
    follow_symlinks_specified("", 1);
18742
16
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18743
16
    dir_fd_converter(Py_None, &ignored);
18744
16
    dir_fd_unavailable(Py_None, &ignored);
18745
16
    }
18746
18747
    /*
18748
     * provide list of locally available functions
18749
     * so os.py can populate support_* lists
18750
     */
18751
16
    PyObject *list = PyList_New(0);
18752
16
    if (!list) {
18753
0
        return -1;
18754
0
    }
18755
528
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18756
512
        PyObject *unicode;
18757
512
        if (trace->probe && !trace->probe()) continue;
18758
512
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18759
512
        if (!unicode)
18760
0
            return -1;
18761
512
        if (PyList_Append(list, unicode))
18762
0
            return -1;
18763
512
        Py_DECREF(unicode);
18764
512
    }
18765
18766
16
#ifndef MS_WINDOWS
18767
16
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18768
0
        PyErr_SetString(PyExc_RuntimeError,
18769
0
                        "cannot read ticks_per_second");
18770
0
        return -1;
18771
0
    }
18772
16
    assert(state->ticks_per_second >= 1);
18773
16
#endif
18774
18775
16
    return PyModule_Add(m, "_have_functions", list);
18776
16
}
18777
18778
18779
static PyModuleDef_Slot posixmodile_slots[] = {
18780
    {Py_mod_exec, posixmodule_exec},
18781
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18782
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18783
    {0, NULL}
18784
};
18785
18786
static struct PyModuleDef posixmodule = {
18787
    PyModuleDef_HEAD_INIT,
18788
    .m_name = MODNAME,
18789
    .m_doc = posix__doc__,
18790
    .m_size = sizeof(_posixstate),
18791
    .m_methods = posix_methods,
18792
    .m_slots = posixmodile_slots,
18793
    .m_traverse = _posix_traverse,
18794
    .m_clear = _posix_clear,
18795
    .m_free = _posix_free,
18796
};
18797
18798
PyMODINIT_FUNC
18799
INITFUNC(void)
18800
16
{
18801
16
    return PyModuleDef_Init(&posixmodule);
18802
16
}