Coverage Report

Created: 2025-11-11 06:44

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
9.71k
#  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
6.33k
#  define STAT stat
407
0
#  define LSTAT lstat
408
0
#  define FSTAT fstat
409
6.33k
#  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
22
#  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
9
{
798
9
    if (func == NULL)  /* nothing to register? do nothing. */
799
6
        return 0;
800
3
    if (*lst == NULL) {
801
3
        *lst = PyList_New(0);
802
3
        if (*lst == NULL)
803
0
            return -1;
804
3
    }
805
3
    return PyList_Append(*lst, func);
806
3
}
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.93k
{
835
5.93k
    if (uid == (uid_t)-1)
836
0
        return PyLong_FromLong(-1);
837
5.93k
    return PyLong_FromUnsignedLong(uid);
838
5.93k
}
839
840
PyObject *
841
_PyLong_FromGid(gid_t gid)
842
5.93k
{
843
5.93k
    if (gid == (gid_t)-1)
844
0
        return PyLong_FromLong(-1);
845
5.93k
    return PyLong_FromUnsignedLong(gid);
846
5.93k
}
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
11.8k
{
1066
11.8k
#ifdef NODEV
1067
11.8k
    if (dev == NODEV) {
1068
22
        return PyLong_FromLongLong((long long)dev);
1069
22
    }
1070
11.7k
#endif
1071
11.7k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1072
11.8k
}
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
27.5k
#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
44
{
1174
44
    if (o == Py_None) {
1175
44
        *(int *)p = DEFAULT_DIR_FD;
1176
44
        return 1;
1177
44
    }
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
44
}
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
6.77k
{
1222
6.77k
    void *state = _PyModule_GetState(module);
1223
6.77k
    assert(state != NULL);
1224
6.77k
    return (_posixstate *)state;
1225
6.77k
}
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
7.39k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1344
7.39k
     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
7.28k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1354
7.28k
                      suppress_value_error, allow_fd)
1355
#endif
1356
1357
static void
1358
path_cleanup(path_t *path)
1359
7.39k
{
1360
7.39k
    wchar_t *wide = (wchar_t *)path->wide;
1361
7.39k
    path->wide = NULL;
1362
7.39k
    PyMem_Free(wide);
1363
7.39k
    Py_CLEAR(path->object);
1364
7.39k
    Py_CLEAR(path->cleanup);
1365
7.39k
}
1366
1367
static int
1368
path_converter(PyObject *o, void *p)
1369
7.39k
{
1370
7.39k
    path_t *path = (path_t *)p;
1371
7.39k
    PyObject *bytes = NULL;
1372
7.39k
    Py_ssize_t length = 0;
1373
7.39k
    int is_index, is_bytes, is_unicode;
1374
7.39k
    const char *narrow;
1375
7.39k
    PyObject *wo = NULL;
1376
7.39k
    wchar_t *wide = NULL;
1377
1378
7.39k
#define FORMAT_EXCEPTION(exc, fmt) \
1379
7.39k
    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
7.39k
    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
7.39k
    path->object = path->cleanup = NULL;
1392
    /* path->object owns a reference to the original object */
1393
7.39k
    Py_INCREF(o);
1394
1395
7.39k
    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
7.39k
    is_index = path->allow_fd && PyIndex_Check(o);
1405
7.39k
    is_bytes = PyBytes_Check(o);
1406
7.39k
    is_unicode = PyUnicode_Check(o);
1407
1408
7.39k
    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
7.39k
    if (is_unicode) {
1441
7.39k
        if (path->make_wide) {
1442
110
            wide = PyUnicode_AsWideCharString(o, &length);
1443
110
            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
110
            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
110
            path->wide = wide;
1459
110
            path->narrow = NULL;
1460
110
            path->fd = -1;
1461
110
            wide = NULL;
1462
110
            goto success_exit;
1463
110
        }
1464
7.28k
        bytes = PyUnicode_EncodeFSDefault(o);
1465
7.28k
        if (!bytes) {
1466
0
            goto error_exit;
1467
0
        }
1468
7.28k
    }
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
7.28k
    length = PyBytes_GET_SIZE(bytes);
1496
7.28k
    narrow = PyBytes_AS_STRING(bytes);
1497
7.28k
    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
7.28k
    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
7.28k
    else {
1530
7.28k
        path->wide = NULL;
1531
7.28k
        path->narrow = narrow;
1532
7.28k
        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
7.28k
        else {
1538
7.28k
            path->cleanup = bytes;
1539
7.28k
        }
1540
7.28k
    }
1541
7.28k
    path->fd = -1;
1542
1543
7.39k
 success_exit:
1544
7.39k
    path->value_error = 0;
1545
7.39k
    path->length = length;
1546
7.39k
    path->object = o;
1547
7.39k
    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
22
{
1581
22
    int dir_fd;
1582
22
    if (!dir_fd_converter(o, &dir_fd))
1583
0
        return 0;
1584
22
    if (dir_fd != DEFAULT_DIR_FD) {
1585
0
        argument_unavailable_error(NULL, "dir_fd");
1586
0
        return 0;
1587
0
    }
1588
22
    *(int *)p = dir_fd;
1589
22
    return 1;
1590
22
}
1591
1592
static int
1593
fd_specified(const char *function_name, int fd)
1594
22
{
1595
22
    if (fd == -1)
1596
22
        return 0;
1597
1598
0
    argument_unavailable_error(function_name, "fd");
1599
0
    return 1;
1600
22
}
1601
1602
static int
1603
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1604
22
{
1605
22
    if (follow_symlinks)
1606
22
        return 0;
1607
1608
0
    argument_unavailable_error(function_name, "follow_symlinks");
1609
0
    return 1;
1610
22
}
1611
1612
static int
1613
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1614
6.33k
{
1615
6.33k
    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
6.33k
    return 0;
1622
6.33k
}
1623
1624
static int
1625
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1626
6.33k
{
1627
6.33k
    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
6.33k
    return 0;
1634
6.33k
}
1635
1636
static int
1637
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1638
                               int follow_symlinks)
1639
6.33k
{
1640
6.33k
    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
6.33k
    return 0;
1647
6.33k
}
1648
1649
static int
1650
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1651
                                   int follow_symlinks)
1652
22
{
1653
22
    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
22
    return 0;
1660
22
}
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
22
{
1780
22
    PyObject *d;
1781
#ifdef MS_WINDOWS
1782
    wchar_t **e;
1783
#else
1784
22
    char **e;
1785
22
#endif
1786
1787
22
    d = PyDict_New();
1788
22
    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
22
    e = environ;
1802
22
#endif
1803
22
    if (e == NULL)
1804
0
        return d;
1805
814
    for (; *e != NULL; e++) {
1806
792
        PyObject *k;
1807
792
        PyObject *v;
1808
#ifdef MS_WINDOWS
1809
        const wchar_t *p = wcschr(*e, L'=');
1810
#else
1811
792
        const char *p = strchr(*e, '=');
1812
792
#endif
1813
792
        if (p == NULL)
1814
0
            continue;
1815
#ifdef MS_WINDOWS
1816
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1817
#else
1818
792
        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1819
792
#endif
1820
792
        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
792
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1828
792
#endif
1829
792
        if (v == NULL) {
1830
0
            Py_DECREF(k);
1831
0
            Py_DECREF(d);
1832
0
            return NULL;
1833
0
        }
1834
792
        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
792
        Py_DECREF(k);
1841
792
        Py_DECREF(v);
1842
792
    }
1843
22
    return d;
1844
22
}
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
440
{
1895
440
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1896
440
}
1897
1898
static PyObject *
1899
path_object_error(PyObject *path)
1900
440
{
1901
#ifdef MS_WINDOWS
1902
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1903
                PyExc_OSError, 0, path);
1904
#else
1905
440
    return posix_path_object_error(path);
1906
440
#endif
1907
440
}
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
440
{
1923
440
    return path_object_error(path->object);
1924
440
}
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
861
{
2601
861
    _posixstate *state = get_posix_state(module);
2602
861
    Py_VISIT(state->billion);
2603
861
    Py_VISIT(state->DirEntryType);
2604
861
    Py_VISIT(state->ScandirIteratorType);
2605
861
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2606
861
    Py_VISIT(state->SchedParamType);
2607
861
#endif
2608
861
    Py_VISIT(state->StatResultType);
2609
861
#ifdef HAVE_STATX
2610
861
    Py_VISIT(state->StatxResultType);
2611
861
#endif
2612
861
    Py_VISIT(state->StatVFSResultType);
2613
861
    Py_VISIT(state->TerminalSizeType);
2614
861
    Py_VISIT(state->TimesResultType);
2615
861
    Py_VISIT(state->UnameResultType);
2616
861
#if defined(HAVE_WAITID)
2617
861
    Py_VISIT(state->WaitidResultType);
2618
861
#endif
2619
861
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2620
861
    Py_VISIT(state->struct_rusage);
2621
861
#endif
2622
861
    Py_VISIT(state->st_mode);
2623
861
    return 0;
2624
861
}
2625
2626
static void
2627
_posix_free(void *module)
2628
0
{
2629
0
   _posix_clear((PyObject *)module);
2630
0
}
2631
2632
2633
53.0k
#define SEC_TO_NS (1000000000LL)
2634
static PyObject *
2635
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2636
17.6k
{
2637
#if SIZEOF_TIME_T == 4
2638
    return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2639
#else
2640
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2641
17.6k
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2642
17.6k
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2643
17.6k
    }
2644
0
    else
2645
0
    {
2646
0
        PyObject *ns_total = NULL;
2647
0
        PyObject *s_in_ns = NULL;
2648
0
        PyObject *s = _PyLong_FromTime_t(sec);
2649
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2650
0
        if (s == NULL || ns_fractional == NULL) {
2651
0
            goto exit;
2652
0
        }
2653
2654
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2655
0
        if (s_in_ns == NULL) {
2656
0
            goto exit;
2657
0
        }
2658
2659
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2660
2661
0
    exit:
2662
0
        Py_XDECREF(s);
2663
0
        Py_XDECREF(ns_fractional);
2664
0
        Py_XDECREF(s_in_ns);
2665
0
        return ns_total;
2666
0
    }
2667
17.6k
#endif
2668
17.6k
}
2669
2670
static int
2671
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2672
          int ns_index, time_t sec, unsigned long nsec)
2673
17.6k
{
2674
17.6k
    assert(!PyErr_Occurred());
2675
17.6k
    assert(nsec < SEC_TO_NS);
2676
2677
17.6k
    if (s_index >= 0) {
2678
17.6k
        PyObject *s = _PyLong_FromTime_t(sec);
2679
17.6k
        if (s == NULL) {
2680
0
            return -1;
2681
0
        }
2682
17.6k
        PyStructSequence_SET_ITEM(v, s_index, s);
2683
17.6k
    }
2684
2685
17.6k
    if (f_index >= 0) {
2686
17.6k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2687
17.6k
        if (float_s == NULL) {
2688
0
            return -1;
2689
0
        }
2690
17.6k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2691
17.6k
    }
2692
2693
17.6k
    if (ns_index >= 0) {
2694
17.6k
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2695
17.6k
        if (ns_total == NULL) {
2696
0
            return -1;
2697
0
        }
2698
17.6k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2699
17.6k
    }
2700
2701
17.6k
    assert(!PyErr_Occurred());
2702
17.6k
    return 0;
2703
17.6k
}
2704
#undef SEC_TO_NS
2705
2706
#ifdef MS_WINDOWS
2707
static PyObject*
2708
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2709
{
2710
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2711
    if (!o_low || !high) {
2712
        return o_low;
2713
    }
2714
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2715
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2716
    if (!l64) {
2717
        Py_XDECREF(o_high);
2718
        Py_DECREF(o_low);
2719
        return NULL;
2720
    }
2721
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2722
    Py_DECREF(l64);
2723
    if (!o_high) {
2724
        Py_DECREF(o_low);
2725
        return NULL;
2726
    }
2727
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2728
    Py_DECREF(o_high);
2729
    return o_low;
2730
}
2731
#endif
2732
2733
/* pack a system stat C structure into the Python stat tuple
2734
   (used by posix_stat() and posix_fstat()) */
2735
static PyObject*
2736
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2737
5.89k
{
2738
5.89k
    assert(!PyErr_Occurred());
2739
2740
5.89k
    _posixstate *state = get_posix_state(module);
2741
5.89k
    PyObject *StatResultType = state->StatResultType;
2742
5.89k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2743
5.89k
    if (v == NULL) {
2744
0
        return NULL;
2745
0
    }
2746
2747
5.89k
#define SET_ITEM(pos, expr) \
2748
58.9k
    do { \
2749
58.9k
        PyObject *obj = (expr); \
2750
58.9k
        if (obj == NULL) { \
2751
0
            goto error; \
2752
0
        } \
2753
58.9k
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2754
58.9k
    } while (0)
2755
2756
5.89k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2757
#ifdef MS_WINDOWS
2758
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2759
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2760
#else
2761
5.89k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2762
5.89k
                  "stat.st_ino is larger than unsigned long long");
2763
5.89k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2764
5.89k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2765
5.89k
#endif
2766
5.89k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2767
#if defined(MS_WINDOWS)
2768
    SET_ITEM(4, PyLong_FromLong(0));
2769
    SET_ITEM(5, PyLong_FromLong(0));
2770
#else
2771
5.89k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2772
5.89k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2773
5.89k
#endif
2774
5.89k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2775
5.89k
                  "stat.st_size is larger than long long");
2776
5.89k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2777
2778
    // Set st_atime, st_mtime and st_ctime
2779
5.89k
    unsigned long ansec, mnsec, cnsec;
2780
5.89k
#if defined(HAVE_STAT_TV_NSEC)
2781
5.89k
    ansec = st->st_atim.tv_nsec;
2782
5.89k
    mnsec = st->st_mtim.tv_nsec;
2783
5.89k
    cnsec = st->st_ctim.tv_nsec;
2784
#elif defined(HAVE_STAT_TV_NSEC2)
2785
    ansec = st->st_atimespec.tv_nsec;
2786
    mnsec = st->st_mtimespec.tv_nsec;
2787
    cnsec = st->st_ctimespec.tv_nsec;
2788
#elif defined(HAVE_STAT_NSEC)
2789
    ansec = st->st_atime_nsec;
2790
    mnsec = st->st_mtime_nsec;
2791
    cnsec = st->st_ctime_nsec;
2792
#else
2793
    ansec = mnsec = cnsec = 0;
2794
#endif
2795
5.89k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2796
0
        goto error;
2797
0
    }
2798
5.89k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2799
0
        goto error;
2800
0
    }
2801
5.89k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2802
0
        goto error;
2803
0
    }
2804
2805
5.89k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2806
5.89k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2807
5.89k
#endif
2808
5.89k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2809
5.89k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2810
5.89k
#endif
2811
5.89k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2812
5.89k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2813
5.89k
#endif
2814
#ifdef HAVE_STRUCT_STAT_ST_GEN
2815
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2816
#endif
2817
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2818
    {
2819
      unsigned long bsec, bnsec;
2820
      bsec = (long)st->st_birthtime;
2821
#ifdef HAVE_STAT_TV_NSEC2
2822
      bnsec = st->st_birthtimespec.tv_nsec;
2823
#else
2824
      bnsec = 0;
2825
#endif
2826
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2827
    }
2828
#elif defined(MS_WINDOWS)
2829
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2830
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2831
        goto error;
2832
    }
2833
#endif
2834
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2835
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2836
#endif
2837
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2838
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2839
             PyLong_FromUnsignedLong(st->st_file_attributes));
2840
#endif
2841
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2842
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2843
#endif
2844
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2845
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2846
#endif
2847
2848
5.89k
    assert(!PyErr_Occurred());
2849
5.89k
    return v;
2850
2851
0
error:
2852
0
    Py_DECREF(v);
2853
0
    return NULL;
2854
2855
5.89k
#undef SET_ITEM
2856
5.89k
}
2857
2858
/* POSIX methods */
2859
2860
2861
static PyObject *
2862
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2863
              int dir_fd, int follow_symlinks)
2864
6.33k
{
2865
6.33k
    STRUCT_STAT st;
2866
6.33k
    int result;
2867
2868
6.33k
#ifdef HAVE_FSTATAT
2869
6.33k
    int fstatat_unavailable = 0;
2870
6.33k
#endif
2871
2872
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2873
    if (follow_symlinks_specified(function_name, follow_symlinks))
2874
        return NULL;
2875
#endif
2876
2877
6.33k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2878
6.33k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2879
6.33k
        fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2880
0
        return NULL;
2881
2882
6.33k
    Py_BEGIN_ALLOW_THREADS
2883
6.33k
    if (path->fd != -1)
2884
0
        result = FSTAT(path->fd, &st);
2885
#ifdef MS_WINDOWS
2886
    else if (follow_symlinks)
2887
        result = win32_stat(path->wide, &st);
2888
    else
2889
        result = win32_lstat(path->wide, &st);
2890
#else
2891
6.33k
    else
2892
6.33k
#if defined(HAVE_LSTAT)
2893
6.33k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2894
0
        result = LSTAT(path->narrow, &st);
2895
6.33k
    else
2896
6.33k
#endif /* HAVE_LSTAT */
2897
6.33k
#ifdef HAVE_FSTATAT
2898
6.33k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2899
0
        if (HAVE_FSTATAT_RUNTIME) {
2900
0
            result = fstatat(dir_fd, path->narrow, &st,
2901
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2902
2903
0
        } else {
2904
0
            fstatat_unavailable = 1;
2905
0
        }
2906
0
    } else
2907
6.33k
#endif /* HAVE_FSTATAT */
2908
6.33k
        result = STAT(path->narrow, &st);
2909
6.33k
#endif /* MS_WINDOWS */
2910
6.33k
    Py_END_ALLOW_THREADS
2911
2912
6.33k
#ifdef HAVE_FSTATAT
2913
6.33k
    if (fstatat_unavailable) {
2914
0
        argument_unavailable_error("stat", "dir_fd");
2915
0
        return NULL;
2916
0
    }
2917
6.33k
#endif
2918
2919
6.33k
    if (result != 0) {
2920
440
        return path_error(path);
2921
440
    }
2922
2923
5.89k
    return _pystat_fromstructstat(module, &st);
2924
6.33k
}
2925
2926
/*[python input]
2927
2928
for s in """
2929
2930
FACCESSAT
2931
FCHMODAT
2932
FCHOWNAT
2933
FSTATAT
2934
LINKAT
2935
MKDIRAT
2936
MKFIFOAT
2937
MKNODAT
2938
OPENAT
2939
READLINKAT
2940
SYMLINKAT
2941
UNLINKAT
2942
2943
""".strip().split():
2944
    s = s.strip()
2945
    print("""
2946
#ifdef HAVE_{s}
2947
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2948
#else
2949
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2950
#endif
2951
""".rstrip().format(s=s))
2952
2953
for s in """
2954
2955
FCHDIR
2956
FCHMOD
2957
FCHOWN
2958
FDOPENDIR
2959
FEXECVE
2960
FPATHCONF
2961
FSTATVFS
2962
FTRUNCATE
2963
2964
""".strip().split():
2965
    s = s.strip()
2966
    print("""
2967
#ifdef HAVE_{s}
2968
    #define PATH_HAVE_{s} 1
2969
#else
2970
    #define PATH_HAVE_{s} 0
2971
#endif
2972
2973
""".rstrip().format(s=s))
2974
[python start generated code]*/
2975
2976
#ifdef HAVE_FACCESSAT
2977
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2978
#else
2979
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2980
#endif
2981
2982
#ifdef HAVE_FCHMODAT
2983
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2984
#else
2985
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2986
#endif
2987
2988
#ifdef HAVE_FCHOWNAT
2989
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2990
#else
2991
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2992
#endif
2993
2994
#ifdef HAVE_FSTATAT
2995
0
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2996
#else
2997
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2998
#endif
2999
3000
#ifdef HAVE_LINKAT
3001
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
3002
#else
3003
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3004
#endif
3005
3006
#ifdef HAVE_MKDIRAT
3007
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3008
#else
3009
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3010
#endif
3011
3012
#ifdef HAVE_MKFIFOAT
3013
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3014
#else
3015
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3016
#endif
3017
3018
#ifdef HAVE_MKNODAT
3019
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3020
#else
3021
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3022
#endif
3023
3024
#ifdef HAVE_OPENAT
3025
0
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3026
#else
3027
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3028
#endif
3029
3030
#ifdef HAVE_READLINKAT
3031
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3032
#else
3033
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3034
#endif
3035
3036
#ifdef HAVE_SYMLINKAT
3037
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3038
#else
3039
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3040
#endif
3041
3042
#ifdef HAVE_UNLINKAT
3043
0
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3044
#else
3045
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3046
#endif
3047
3048
#ifdef HAVE_FCHDIR
3049
    #define PATH_HAVE_FCHDIR 1
3050
#else
3051
    #define PATH_HAVE_FCHDIR 0
3052
#endif
3053
3054
#ifdef HAVE_FCHMOD
3055
    #define PATH_HAVE_FCHMOD 1
3056
#else
3057
    #define PATH_HAVE_FCHMOD 0
3058
#endif
3059
3060
#ifdef HAVE_FCHOWN
3061
    #define PATH_HAVE_FCHOWN 1
3062
#else
3063
    #define PATH_HAVE_FCHOWN 0
3064
#endif
3065
3066
#ifdef HAVE_FDOPENDIR
3067
    #define PATH_HAVE_FDOPENDIR 1
3068
#else
3069
    #define PATH_HAVE_FDOPENDIR 0
3070
#endif
3071
3072
#ifdef HAVE_FEXECVE
3073
    #define PATH_HAVE_FEXECVE 1
3074
#else
3075
    #define PATH_HAVE_FEXECVE 0
3076
#endif
3077
3078
#ifdef HAVE_FPATHCONF
3079
    #define PATH_HAVE_FPATHCONF 1
3080
#else
3081
    #define PATH_HAVE_FPATHCONF 0
3082
#endif
3083
3084
#ifdef HAVE_FSTATVFS
3085
    #define PATH_HAVE_FSTATVFS 1
3086
#else
3087
    #define PATH_HAVE_FSTATVFS 0
3088
#endif
3089
3090
#ifdef HAVE_FTRUNCATE
3091
    #define PATH_HAVE_FTRUNCATE 1
3092
#else
3093
    #define PATH_HAVE_FTRUNCATE 0
3094
#endif
3095
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3096
3097
#ifdef MS_WINDOWS
3098
    #undef PATH_HAVE_FTRUNCATE
3099
    #define PATH_HAVE_FTRUNCATE 1
3100
    #undef PATH_HAVE_FCHMOD
3101
    #define PATH_HAVE_FCHMOD 1
3102
#endif
3103
3104
/*[python input]
3105
3106
class path_t_converter(CConverter):
3107
3108
    type = "path_t"
3109
    impl_by_reference = True
3110
    parse_by_reference = True
3111
3112
    converter = 'path_converter'
3113
3114
    def converter_init(self, *, allow_fd=False, make_wide=None,
3115
                       nonstrict=False, nullable=False,
3116
                       suppress_value_error=False):
3117
        # right now path_t doesn't support default values.
3118
        # to support a default value, you'll need to override initialize().
3119
        if self.default not in (unspecified, None):
3120
            fail("Can't specify a default to the path_t converter!")
3121
3122
        if self.c_default not in (None, 'Py_None'):
3123
            raise RuntimeError("Can't specify a c_default to the path_t converter!")
3124
3125
        self.nullable = nullable
3126
        self.nonstrict = nonstrict
3127
        self.make_wide = make_wide
3128
        self.suppress_value_error = suppress_value_error
3129
        self.allow_fd = allow_fd
3130
3131
    def pre_render(self):
3132
        def strify(value):
3133
            if isinstance(value, str):
3134
                return value
3135
            return str(int(bool(value)))
3136
3137
        # add self.py_name here when merging with posixmodule conversion
3138
        if self.make_wide is None:
3139
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3140
                self.function.name,
3141
                self.name,
3142
                strify(self.nullable),
3143
                strify(self.nonstrict),
3144
                strify(self.suppress_value_error),
3145
                strify(self.allow_fd),
3146
            )
3147
        else:
3148
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3149
                self.function.name,
3150
                self.name,
3151
                strify(self.nullable),
3152
                strify(self.nonstrict),
3153
                strify(self.make_wide),
3154
                strify(self.suppress_value_error),
3155
                strify(self.allow_fd),
3156
            )
3157
3158
    def cleanup(self):
3159
        return "path_cleanup(&" + self.name + ");\n"
3160
3161
3162
class dir_fd_converter(CConverter):
3163
    type = 'int'
3164
3165
    def converter_init(self, requires=None):
3166
        if self.default in (unspecified, None):
3167
            self.c_default = 'DEFAULT_DIR_FD'
3168
        if isinstance(requires, str):
3169
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3170
        else:
3171
            self.converter = 'dir_fd_converter'
3172
3173
class uid_t_converter(CConverter):
3174
    type = "uid_t"
3175
    converter = '_Py_Uid_Converter'
3176
3177
class gid_t_converter(CConverter):
3178
    type = "gid_t"
3179
    converter = '_Py_Gid_Converter'
3180
3181
class dev_t_converter(CConverter):
3182
    type = 'dev_t'
3183
    converter = '_Py_Dev_Converter'
3184
3185
class dev_t_return_converter(unsigned_long_return_converter):
3186
    type = 'dev_t'
3187
    conversion_fn = '_PyLong_FromDev'
3188
    unsigned_cast = '(dev_t)'
3189
3190
class pid_t_converter(CConverter):
3191
    type = 'pid_t'
3192
    format_unit = '" _Py_PARSE_PID "'
3193
3194
    def parse_arg(self, argname, displayname, *, limited_capi):
3195
        return self.format_code("""
3196
            {paramname} = PyLong_AsPid({argname});
3197
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3198
                goto exit;
3199
            }}}}
3200
            """, argname=argname)
3201
3202
class idtype_t_converter(CConverter):
3203
    type = 'idtype_t'
3204
    converter = 'idtype_t_converter'
3205
3206
class id_t_converter(CConverter):
3207
    type = 'id_t'
3208
    format_unit = '" _Py_PARSE_PID "'
3209
3210
    def parse_arg(self, argname, displayname, *, limited_capi):
3211
        return self.format_code("""
3212
            {paramname} = (id_t)PyLong_AsPid({argname});
3213
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3214
                goto exit;
3215
            }}}}
3216
            """, argname=argname)
3217
3218
class intptr_t_converter(CConverter):
3219
    type = 'intptr_t'
3220
    format_unit = '" _Py_PARSE_INTPTR "'
3221
3222
    def parse_arg(self, argname, displayname, *, limited_capi):
3223
        return self.format_code("""
3224
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3225
            if (!{paramname} && PyErr_Occurred()) {{{{
3226
                goto exit;
3227
            }}}}
3228
            """, argname=argname)
3229
3230
class Py_off_t_converter(CConverter):
3231
    type = 'Py_off_t'
3232
    converter = 'Py_off_t_converter'
3233
3234
class Py_off_t_return_converter(long_return_converter):
3235
    type = 'Py_off_t'
3236
    conversion_fn = 'PyLong_FromPy_off_t'
3237
3238
class confname_converter(CConverter):
3239
    type="int"
3240
    converter="conv_confname"
3241
3242
    def converter_init(self, *, table):
3243
        self.table = table
3244
3245
    def parse_arg(self, argname, displayname, *, limited_capi):
3246
        return self.format_code("""
3247
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3248
                goto exit;
3249
            }}}}
3250
        """, argname=argname, converter=self.converter, table=self.table)
3251
3252
[python start generated code]*/
3253
/*[python end generated code: output=da39a3ee5e6b4b0d input=d2759f2332cd39b3]*/
3254
3255
/*[clinic input]
3256
3257
os.stat
3258
3259
    path : path_t(allow_fd=True)
3260
        Path to be examined; can be string, bytes, a path-like object or
3261
        open-file-descriptor int.
3262
3263
    *
3264
3265
    dir_fd : dir_fd(requires='fstatat') = None
3266
        If not None, it should be a file descriptor open to a directory,
3267
        and path should be a relative string; path will then be relative to
3268
        that directory.
3269
3270
    follow_symlinks: bool = True
3271
        If False, and the last element of the path is a symbolic link,
3272
        stat will examine the symbolic link itself instead of the file
3273
        the link points to.
3274
3275
Perform a stat system call on the given path.
3276
3277
dir_fd and follow_symlinks may not be implemented
3278
  on your platform.  If they are unavailable, using them will raise a
3279
  NotImplementedError.
3280
3281
It's an error to use dir_fd or follow_symlinks when specifying path as
3282
  an open file descriptor.
3283
3284
[clinic start generated code]*/
3285
3286
static PyObject *
3287
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3288
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3289
6.33k
{
3290
6.33k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3291
6.33k
}
3292
3293
3294
/*[clinic input]
3295
@permit_long_summary
3296
os.lstat
3297
3298
    path : path_t
3299
3300
    *
3301
3302
    dir_fd : dir_fd(requires='fstatat') = None
3303
3304
Perform a stat system call on the given path, without following symbolic links.
3305
3306
Like stat(), but do not follow symbolic links.
3307
Equivalent to stat(path, follow_symlinks=False).
3308
[clinic start generated code]*/
3309
3310
static PyObject *
3311
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3312
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3313
0
{
3314
0
    int follow_symlinks = 0;
3315
0
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3316
0
}
3317
3318
3319
#ifdef HAVE_STATX
3320
typedef struct {
3321
    PyObject_HEAD
3322
    dev_t rdev, dev;
3323
    struct statx stx;
3324
} Py_statx_result;
3325
3326
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3327
3328
#define M(attr, type, offset, doc) \
3329
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3330
#define MM(attr, type, member, doc) \
3331
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3332
#define MX(attr, type, member, doc) \
3333
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3334
3335
static PyMemberDef pystatx_result_members[] = {
3336
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3337
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3338
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3339
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3340
        "Mask of supported bits in stx_attributes"),
3341
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3342
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3343
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3344
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3345
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3346
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3347
    {NULL},
3348
};
3349
3350
#undef MX
3351
#undef MM
3352
#undef M
3353
3354
3355
#define STATX_GET_UINT(ATTR, MASK) \
3356
    static PyObject* \
3357
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3358
0
    { \
3359
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3360
0
        if (!(self->stx.stx_mask & MASK)) { \
3361
0
            Py_RETURN_NONE; \
3362
0
        } \
3363
0
        unsigned long value = self->stx.ATTR; \
3364
0
        return PyLong_FromUnsignedLong(value); \
3365
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
3366
3367
STATX_GET_UINT(stx_uid, STATX_UID)
3368
STATX_GET_UINT(stx_gid, STATX_GID)
3369
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3370
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3371
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3372
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3373
#endif
3374
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3375
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3376
#endif
3377
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3378
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3379
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3380
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3381
#endif
3382
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3383
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3384
#endif
3385
3386
3387
static PyObject*
3388
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3389
0
{
3390
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3391
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3392
0
        Py_RETURN_NONE;
3393
0
    }
3394
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3395
0
}
3396
3397
3398
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3399
    static PyObject* \
3400
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3401
0
    { \
3402
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3403
0
        if (!(self->stx.stx_mask & MASK)) { \
3404
0
            Py_RETURN_NONE; \
3405
0
        } \
3406
0
        unsigned long long value = self->stx.ATTR; \
3407
0
        return PyLong_FromUnsignedLongLong(value); \
3408
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
3409
3410
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3411
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3412
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3413
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3414
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3415
#endif
3416
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3417
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3418
#endif
3419
3420
3421
#define STATX_GET_DOUBLE(ATTR, MASK) \
3422
    static PyObject* \
3423
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3424
0
    { \
3425
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3426
0
        if (!(self->stx.stx_mask & MASK)) { \
3427
0
            Py_RETURN_NONE; \
3428
0
        } \
3429
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3430
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3431
0
        return PyFloat_FromDouble(sec); \
3432
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
3433
3434
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3435
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3436
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3437
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3438
3439
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3440
    static PyObject* \
3441
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3442
0
    { \
3443
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3444
0
        if (!(self->stx.stx_mask & MASK)) { \
3445
0
            Py_RETURN_NONE; \
3446
0
        } \
3447
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3448
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3449
0
        assert(state != NULL); \
3450
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3451
0
    }
3452
3453
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3454
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3455
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3456
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3457
3458
#define G(attr, doc) \
3459
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3460
3461
static PyGetSetDef pystatx_result_getset[] = {
3462
    G(stx_mode, "protection bits"),
3463
    G(stx_nlink, "number of hard links"),
3464
    G(stx_uid, "user ID of owner"),
3465
    G(stx_gid, "group ID of owner"),
3466
    G(stx_ino, "inode"),
3467
    G(stx_size, "total size, in bytes"),
3468
    G(stx_blocks, "number of blocks allocated"),
3469
    G(stx_atime, "time of last access"),
3470
    G(stx_atime_ns, "time of last access in nanoseconds"),
3471
    G(stx_btime, "time of creation"),
3472
    G(stx_btime_ns, "time of creation in nanoseconds"),
3473
    G(stx_ctime, "time of last change"),
3474
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3475
    G(stx_mtime, "time of last modification"),
3476
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3477
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3478
    G(stx_mnt_id, "mount ID"),
3479
#endif
3480
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3481
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3482
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3483
#endif
3484
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3485
    G(stx_subvol, "subvolume ID"),
3486
#endif
3487
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3488
    G(stx_atomic_write_unit_min,
3489
      "minimum size for direct I/O with torn-write protection"),
3490
    G(stx_atomic_write_unit_max,
3491
        "maximum size for direct I/O with torn-write protection"),
3492
    G(stx_atomic_write_segments_max,
3493
        "maximum iovecs for direct I/O with torn-write protection"),
3494
#endif
3495
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3496
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3497
#endif
3498
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3499
    G(stx_atomic_write_unit_max_opt,
3500
        "maximum optimized size for direct I/O with torn-write protection"),
3501
#endif
3502
    {NULL},
3503
};
3504
3505
#undef G
3506
3507
static PyObject *
3508
pystatx_result_repr(PyObject *op)
3509
0
{
3510
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3511
0
    if (writer == NULL) {
3512
0
        return NULL;
3513
0
    }
3514
0
#define WRITE_ASCII(s) \
3515
0
    do { \
3516
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3517
0
            goto error; \
3518
0
        } \
3519
0
    } while (0)
3520
3521
0
    WRITE_ASCII("os.statx_result(");
3522
3523
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3524
0
        if (i > 0) {
3525
0
            WRITE_ASCII(", ");
3526
0
        }
3527
3528
0
        PyMemberDef *d = &pystatx_result_members[i];
3529
0
        WRITE_ASCII(d->name);
3530
0
        WRITE_ASCII("=");
3531
3532
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3533
0
        if (o == NULL) {
3534
0
            goto error;
3535
0
        }
3536
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3537
0
            Py_DECREF(o);
3538
0
            goto error;
3539
0
        }
3540
0
        Py_DECREF(o);
3541
0
    }
3542
3543
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3544
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3545
0
        PyObject *o = d->get(op, d->closure);
3546
0
        if (o == NULL) {
3547
0
            goto error;
3548
0
        }
3549
0
        if (o == Py_None) {
3550
0
            continue;
3551
0
        }
3552
3553
0
        WRITE_ASCII(", ");
3554
0
        WRITE_ASCII(d->name);
3555
0
        WRITE_ASCII("=");
3556
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3557
0
            Py_DECREF(o);
3558
0
            goto error;
3559
0
        }
3560
0
        Py_DECREF(o);
3561
0
    }
3562
3563
0
    WRITE_ASCII(")");
3564
0
    return PyUnicodeWriter_Finish(writer);
3565
0
#undef WRITE_ASCII
3566
3567
0
error:
3568
0
    PyUnicodeWriter_Discard(writer);
3569
0
    return NULL;
3570
0
}
3571
3572
static int
3573
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3574
0
{
3575
0
    Py_VISIT(Py_TYPE(self));
3576
0
    return 0;
3577
0
}
3578
3579
static void
3580
pystatx_result_dealloc(PyObject *op)
3581
0
{
3582
0
    Py_statx_result *self = (Py_statx_result *) op;
3583
0
    PyTypeObject *tp = Py_TYPE(self);
3584
0
    PyObject_GC_UnTrack(self);
3585
0
    tp->tp_free(self);
3586
0
    Py_DECREF(tp);
3587
0
}
3588
3589
static PyType_Slot pystatx_result_slots[] = {
3590
    {Py_tp_repr, pystatx_result_repr},
3591
    {Py_tp_traverse, pystatx_result_traverse},
3592
    {Py_tp_dealloc, pystatx_result_dealloc},
3593
    {Py_tp_members, pystatx_result_members},
3594
    {Py_tp_getset, pystatx_result_getset},
3595
    {0, NULL},
3596
};
3597
3598
static PyType_Spec pystatx_result_spec = {
3599
    .name = "os.statx_result",
3600
    .basicsize = sizeof(Py_statx_result),
3601
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3602
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3603
    .slots = pystatx_result_slots,
3604
};
3605
3606
/*[clinic input]
3607
3608
os.statx
3609
3610
    path : path_t(allow_fd=True)
3611
        Path to be examined; can be string, bytes, a path-like object or
3612
        open-file-descriptor int.
3613
3614
    mask: unsigned_int(bitwise=True)
3615
        A bitmask of STATX_* constants defining the requested information.
3616
3617
    *
3618
3619
    flags: int = 0
3620
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3621
3622
    dir_fd : dir_fd = None
3623
        If not None, it should be a file descriptor open to a directory,
3624
        and path should be a relative string; path will then be relative to
3625
        that directory.
3626
3627
    follow_symlinks: bool = True
3628
        If False, and the last element of the path is a symbolic link,
3629
        statx will examine the symbolic link itself instead of the file
3630
        the link points to.
3631
3632
Perform a statx system call on the given path.
3633
3634
It's an error to use dir_fd or follow_symlinks when specifying path as
3635
  an open file descriptor.
3636
3637
[clinic start generated code]*/
3638
3639
static PyObject *
3640
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3641
              int dir_fd, int follow_symlinks)
3642
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3643
0
{
3644
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3645
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3646
0
        fd_and_follow_symlinks_invalid("statx", path->fd, follow_symlinks)) {
3647
0
        return NULL;
3648
0
    }
3649
3650
    /* reject flags covered by kwargs, but allow unknown flags that may be
3651
       future AT_STATX_* extensions */
3652
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3653
0
        PyErr_Format(PyExc_ValueError,
3654
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3655
0
        return NULL;
3656
0
    }
3657
0
    if (flags & AT_EMPTY_PATH) {
3658
0
        PyErr_Format(PyExc_ValueError,
3659
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3660
0
        return NULL;
3661
0
    }
3662
3663
    /* Future bits may refer to members beyond the current size of struct
3664
       statx, so we need to mask them off to prevent memory corruption. */
3665
0
    mask &= _Py_STATX_KNOWN;
3666
3667
0
    _posixstate *state = get_posix_state(module);
3668
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3669
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3670
0
    if (v == NULL) {
3671
0
        return NULL;
3672
0
    }
3673
3674
0
    int result;
3675
0
    Py_BEGIN_ALLOW_THREADS
3676
0
    if (path->fd != -1) {
3677
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3678
0
    }
3679
0
    else {
3680
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3681
0
    }
3682
0
    Py_END_ALLOW_THREADS
3683
3684
0
    if (result != 0) {
3685
0
        Py_DECREF(v);
3686
0
        return path_error(path);
3687
0
    }
3688
3689
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3690
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3691
3692
0
    assert(!PyErr_Occurred());
3693
0
    return (PyObject *)v;
3694
0
}
3695
#endif /* HAVE_STATX */
3696
3697
3698
/*[clinic input]
3699
os.access -> bool
3700
3701
    path: path_t
3702
        Path to be tested; can be string, bytes, or a path-like object.
3703
3704
    mode: int
3705
        Operating-system mode bitfield.  Can be F_OK to test existence,
3706
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3707
3708
    *
3709
3710
    dir_fd : dir_fd(requires='faccessat') = None
3711
        If not None, it should be a file descriptor open to a directory,
3712
        and path should be relative; path will then be relative to that
3713
        directory.
3714
3715
    effective_ids: bool = False
3716
        If True, access will use the effective uid/gid instead of
3717
        the real uid/gid.
3718
3719
    follow_symlinks: bool = True
3720
        If False, and the last element of the path is a symbolic link,
3721
        access will examine the symbolic link itself instead of the file
3722
        the link points to.
3723
3724
Use the real uid/gid to test for access to a path.
3725
3726
{parameters}
3727
dir_fd, effective_ids, and follow_symlinks may not be implemented
3728
  on your platform.  If they are unavailable, using them will raise a
3729
  NotImplementedError.
3730
3731
Note that most operations will use the effective uid/gid, therefore this
3732
  routine can be used in a suid/sgid environment to test if the invoking
3733
  user has the specified access to the path.
3734
3735
[clinic start generated code]*/
3736
3737
static int
3738
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3739
               int effective_ids, int follow_symlinks)
3740
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3741
0
{
3742
0
    int return_value;
3743
3744
#ifdef MS_WINDOWS
3745
    DWORD attr;
3746
#else
3747
0
    int result;
3748
0
#endif
3749
3750
0
#ifdef HAVE_FACCESSAT
3751
0
    int faccessat_unavailable = 0;
3752
0
#endif
3753
3754
#ifndef HAVE_FACCESSAT
3755
    if (follow_symlinks_specified("access", follow_symlinks))
3756
        return -1;
3757
3758
    if (effective_ids) {
3759
        argument_unavailable_error("access", "effective_ids");
3760
        return -1;
3761
    }
3762
#endif
3763
3764
#ifdef MS_WINDOWS
3765
    Py_BEGIN_ALLOW_THREADS
3766
    attr = GetFileAttributesW(path->wide);
3767
    Py_END_ALLOW_THREADS
3768
3769
    /*
3770
     * Access is possible if
3771
     *   * we didn't get a -1, and
3772
     *     * write access wasn't requested,
3773
     *     * or the file isn't read-only,
3774
     *     * or it's a directory.
3775
     * (Directories cannot be read-only on Windows.)
3776
    */
3777
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3778
            (!(mode & 2) ||
3779
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3780
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3781
#else
3782
3783
0
    Py_BEGIN_ALLOW_THREADS
3784
0
#ifdef HAVE_FACCESSAT
3785
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3786
0
        effective_ids ||
3787
0
        !follow_symlinks) {
3788
3789
0
        if (HAVE_FACCESSAT_RUNTIME) {
3790
0
            int flags = 0;
3791
0
            if (!follow_symlinks)
3792
0
                flags |= AT_SYMLINK_NOFOLLOW;
3793
0
            if (effective_ids)
3794
0
                flags |= AT_EACCESS;
3795
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3796
0
        } else {
3797
0
            faccessat_unavailable = 1;
3798
0
        }
3799
0
    }
3800
0
    else
3801
0
#endif
3802
0
        result = access(path->narrow, mode);
3803
0
    Py_END_ALLOW_THREADS
3804
3805
0
#ifdef HAVE_FACCESSAT
3806
0
    if (faccessat_unavailable) {
3807
0
        if (dir_fd != DEFAULT_DIR_FD) {
3808
0
            argument_unavailable_error("access", "dir_fd");
3809
0
            return -1;
3810
0
        }
3811
0
        if (follow_symlinks_specified("access", follow_symlinks))
3812
0
            return -1;
3813
3814
0
        if (effective_ids) {
3815
0
            argument_unavailable_error("access", "effective_ids");
3816
0
            return -1;
3817
0
        }
3818
        /* should be unreachable */
3819
0
        return -1;
3820
0
    }
3821
0
#endif
3822
0
    return_value = !result;
3823
0
#endif
3824
3825
0
    return return_value;
3826
0
}
3827
3828
#ifndef F_OK
3829
#define F_OK 0
3830
#endif
3831
#ifndef R_OK
3832
#define R_OK 4
3833
#endif
3834
#ifndef W_OK
3835
#define W_OK 2
3836
#endif
3837
#ifndef X_OK
3838
#define X_OK 1
3839
#endif
3840
3841
3842
#ifdef HAVE_TTYNAME_R
3843
/*[clinic input]
3844
os.ttyname
3845
3846
    fd: int
3847
        Integer file descriptor handle.
3848
3849
    /
3850
3851
Return the name of the terminal device connected to 'fd'.
3852
[clinic start generated code]*/
3853
3854
static PyObject *
3855
os_ttyname_impl(PyObject *module, int fd)
3856
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3857
0
{
3858
3859
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3860
0
    if (size == -1) {
3861
0
        return posix_error();
3862
0
    }
3863
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3864
0
    if (buffer == NULL) {
3865
0
        return PyErr_NoMemory();
3866
0
    }
3867
0
    int ret = ttyname_r(fd, buffer, size);
3868
0
    if (ret != 0) {
3869
0
        PyMem_RawFree(buffer);
3870
0
        errno = ret;
3871
0
        return posix_error();
3872
0
    }
3873
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3874
0
    PyMem_RawFree(buffer);
3875
0
    return res;
3876
0
}
3877
#endif
3878
3879
#ifdef HAVE_CTERMID
3880
/*[clinic input]
3881
os.ctermid
3882
3883
Return the name of the controlling terminal for this process.
3884
[clinic start generated code]*/
3885
3886
static PyObject *
3887
os_ctermid_impl(PyObject *module)
3888
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3889
0
{
3890
0
    char *ret;
3891
0
    char buffer[L_ctermid];
3892
3893
#ifdef USE_CTERMID_R
3894
    ret = ctermid_r(buffer);
3895
#else
3896
0
    ret = ctermid(buffer);
3897
0
#endif
3898
0
    if (ret == NULL)
3899
0
        return posix_error();
3900
0
    return PyUnicode_DecodeFSDefault(buffer);
3901
0
}
3902
#endif /* HAVE_CTERMID */
3903
3904
3905
/*[clinic input]
3906
os.chdir
3907
3908
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3909
3910
Change the current working directory to the specified path.
3911
3912
path may always be specified as a string.
3913
On some platforms, path may also be specified as an open file descriptor.
3914
If this functionality is unavailable, using it raises an exception.
3915
[clinic start generated code]*/
3916
3917
static PyObject *
3918
os_chdir_impl(PyObject *module, path_t *path)
3919
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3920
0
{
3921
0
    int result;
3922
3923
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3924
0
        return NULL;
3925
0
    }
3926
3927
0
    Py_BEGIN_ALLOW_THREADS
3928
#ifdef MS_WINDOWS
3929
    /* on unix, success = 0, on windows, success = !0 */
3930
    result = !win32_wchdir(path->wide);
3931
#else
3932
0
#ifdef HAVE_FCHDIR
3933
0
    if (path->fd != -1)
3934
0
        result = fchdir(path->fd);
3935
0
    else
3936
0
#endif
3937
0
        result = chdir(path->narrow);
3938
0
#endif
3939
0
    Py_END_ALLOW_THREADS
3940
3941
0
    if (result) {
3942
0
        return path_error(path);
3943
0
    }
3944
3945
0
    Py_RETURN_NONE;
3946
0
}
3947
3948
3949
#ifdef HAVE_FCHDIR
3950
/*[clinic input]
3951
os.fchdir
3952
3953
    fd: fildes
3954
3955
Change to the directory of the given file descriptor.
3956
3957
fd must be opened on a directory, not a file.
3958
Equivalent to os.chdir(fd).
3959
3960
[clinic start generated code]*/
3961
3962
static PyObject *
3963
os_fchdir_impl(PyObject *module, int fd)
3964
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3965
0
{
3966
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3967
0
        return NULL;
3968
0
    }
3969
0
    return posix_fildes_fd(fd, fchdir);
3970
0
}
3971
#endif /* HAVE_FCHDIR */
3972
3973
#ifdef MS_WINDOWS
3974
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3975
#else
3976
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3977
#endif
3978
3979
#ifdef MS_WINDOWS
3980
static int
3981
win32_lchmod(LPCWSTR path, int mode)
3982
{
3983
    DWORD attr = GetFileAttributesW(path);
3984
    if (attr == INVALID_FILE_ATTRIBUTES) {
3985
        return 0;
3986
    }
3987
    if (mode & _S_IWRITE) {
3988
        attr &= ~FILE_ATTRIBUTE_READONLY;
3989
    }
3990
    else {
3991
        attr |= FILE_ATTRIBUTE_READONLY;
3992
    }
3993
    return SetFileAttributesW(path, attr);
3994
}
3995
3996
static int
3997
win32_hchmod(HANDLE hfile, int mode)
3998
{
3999
    FILE_BASIC_INFO info;
4000
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4001
                                      &info, sizeof(info)))
4002
    {
4003
        return 0;
4004
    }
4005
    if (mode & _S_IWRITE) {
4006
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4007
    }
4008
    else {
4009
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4010
    }
4011
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4012
                                      &info, sizeof(info));
4013
}
4014
4015
static int
4016
win32_fchmod(int fd, int mode)
4017
{
4018
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4019
    if (hfile == INVALID_HANDLE_VALUE) {
4020
        SetLastError(ERROR_INVALID_HANDLE);
4021
        return 0;
4022
    }
4023
    return win32_hchmod(hfile, mode);
4024
}
4025
4026
#endif /* MS_WINDOWS */
4027
4028
/*[clinic input]
4029
os.chmod
4030
4031
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4032
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
4033
        On some platforms, path may also be specified as an open file descriptor.
4034
        If this functionality is unavailable, using it raises an exception.
4035
4036
    mode: int
4037
        Operating-system mode bitfield.
4038
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4039
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4040
        Python.
4041
4042
    *
4043
4044
    dir_fd : dir_fd(requires='fchmodat') = None
4045
        If not None, it should be a file descriptor open to a directory,
4046
        and path should be relative; path will then be relative to that
4047
        directory.
4048
4049
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4050
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4051
        If False, and the last element of the path is a symbolic link,
4052
        chmod will modify the symbolic link itself instead of the file
4053
        the link points to.
4054
4055
Change the access permissions of a file.
4056
4057
It is an error to use dir_fd or follow_symlinks when specifying path as
4058
  an open file descriptor.
4059
dir_fd and follow_symlinks may not be implemented on your platform.
4060
  If they are unavailable, using them will raise a NotImplementedError.
4061
4062
[clinic start generated code]*/
4063
4064
static PyObject *
4065
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4066
              int follow_symlinks)
4067
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
4068
0
{
4069
0
    int result;
4070
4071
0
#ifdef HAVE_FCHMODAT
4072
0
    int fchmodat_nofollow_unsupported = 0;
4073
0
    int fchmodat_unsupported = 0;
4074
0
#endif
4075
4076
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4077
    if (follow_symlinks_specified("chmod", follow_symlinks))
4078
        return NULL;
4079
#endif
4080
4081
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4082
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4083
0
        return NULL;
4084
0
    }
4085
4086
#ifdef MS_WINDOWS
4087
    result = 0;
4088
    Py_BEGIN_ALLOW_THREADS
4089
    if (path->fd != -1) {
4090
        result = win32_fchmod(path->fd, mode);
4091
    }
4092
    else if (follow_symlinks) {
4093
        HANDLE hfile = CreateFileW(path->wide,
4094
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4095
                                   0, NULL,
4096
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4097
        if (hfile != INVALID_HANDLE_VALUE) {
4098
            result = win32_hchmod(hfile, mode);
4099
            (void)CloseHandle(hfile);
4100
        }
4101
    }
4102
    else {
4103
        result = win32_lchmod(path->wide, mode);
4104
    }
4105
    Py_END_ALLOW_THREADS
4106
    if (!result) {
4107
        return path_error(path);
4108
    }
4109
#else /* MS_WINDOWS */
4110
0
    Py_BEGIN_ALLOW_THREADS
4111
0
#ifdef HAVE_FCHMOD
4112
0
    if (path->fd != -1)
4113
0
        result = fchmod(path->fd, mode);
4114
0
    else
4115
0
#endif /* HAVE_CHMOD */
4116
#ifdef HAVE_LCHMOD
4117
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4118
        result = lchmod(path->narrow, mode);
4119
    else
4120
#endif /* HAVE_LCHMOD */
4121
0
#ifdef HAVE_FCHMODAT
4122
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4123
0
        if (HAVE_FCHMODAT_RUNTIME) {
4124
            /*
4125
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4126
             * The documentation specifically shows how to use it,
4127
             * and then says it isn't implemented yet.
4128
             * (true on linux with glibc 2.15, and openindiana 3.x)
4129
             *
4130
             * Once it is supported, os.chmod will automatically
4131
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4132
             * Until then, we need to be careful what exception we raise.
4133
             */
4134
0
            result = fchmodat(dir_fd, path->narrow, mode,
4135
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4136
            /*
4137
             * But wait!  We can't throw the exception without allowing threads,
4138
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4139
             */
4140
0
            fchmodat_nofollow_unsupported =
4141
0
                             result &&
4142
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4143
0
                             !follow_symlinks;
4144
0
        } else {
4145
0
            fchmodat_unsupported = 1;
4146
0
            fchmodat_nofollow_unsupported = 1;
4147
4148
0
            result = -1;
4149
0
        }
4150
0
    }
4151
0
    else
4152
0
#endif /* HAVE_FHCMODAT */
4153
0
    {
4154
0
#ifdef HAVE_CHMOD
4155
0
        result = chmod(path->narrow, mode);
4156
#elif defined(__wasi__)
4157
        // WASI SDK 15.0 does not support chmod.
4158
        // Ignore missing syscall for now.
4159
        result = 0;
4160
#else
4161
        result = -1;
4162
        errno = ENOSYS;
4163
#endif
4164
0
    }
4165
0
    Py_END_ALLOW_THREADS
4166
4167
0
    if (result) {
4168
0
#ifdef HAVE_FCHMODAT
4169
0
        if (fchmodat_unsupported) {
4170
0
            if (dir_fd != DEFAULT_DIR_FD) {
4171
0
                argument_unavailable_error("chmod", "dir_fd");
4172
0
                return NULL;
4173
0
            }
4174
0
        }
4175
4176
0
        if (fchmodat_nofollow_unsupported) {
4177
0
            if (dir_fd != DEFAULT_DIR_FD)
4178
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4179
0
                                                   dir_fd, follow_symlinks);
4180
0
            else
4181
0
                follow_symlinks_specified("chmod", follow_symlinks);
4182
0
            return NULL;
4183
0
        }
4184
0
        else
4185
0
#endif /* HAVE_FCHMODAT */
4186
0
        return path_error(path);
4187
0
    }
4188
0
#endif /* MS_WINDOWS */
4189
4190
0
    Py_RETURN_NONE;
4191
0
}
4192
4193
4194
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4195
/*[clinic input]
4196
os.fchmod
4197
4198
    fd: int
4199
        The file descriptor of the file to be modified.
4200
    mode: int
4201
        Operating-system mode bitfield.
4202
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4203
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4204
        Python.
4205
4206
Change the access permissions of the file given by file descriptor fd.
4207
4208
Equivalent to os.chmod(fd, mode).
4209
[clinic start generated code]*/
4210
4211
static PyObject *
4212
os_fchmod_impl(PyObject *module, int fd, int mode)
4213
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
4214
0
{
4215
0
    int res;
4216
4217
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4218
0
        return NULL;
4219
0
    }
4220
4221
#ifdef MS_WINDOWS
4222
    res = 0;
4223
    Py_BEGIN_ALLOW_THREADS
4224
    res = win32_fchmod(fd, mode);
4225
    Py_END_ALLOW_THREADS
4226
    if (!res) {
4227
        return PyErr_SetFromWindowsErr(0);
4228
    }
4229
#else /* MS_WINDOWS */
4230
0
    int async_err = 0;
4231
0
    do {
4232
0
        Py_BEGIN_ALLOW_THREADS
4233
0
        res = fchmod(fd, mode);
4234
0
        Py_END_ALLOW_THREADS
4235
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4236
0
    if (res != 0)
4237
0
        return (!async_err) ? posix_error() : NULL;
4238
0
#endif /* MS_WINDOWS */
4239
4240
0
    Py_RETURN_NONE;
4241
0
}
4242
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4243
4244
4245
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4246
/*[clinic input]
4247
os.lchmod
4248
4249
    path: path_t
4250
    mode: int
4251
4252
Change the access permissions of a file, without following symbolic links.
4253
4254
If path is a symlink, this affects the link itself rather than the target.
4255
Equivalent to chmod(path, mode, follow_symlinks=False)."
4256
[clinic start generated code]*/
4257
4258
static PyObject *
4259
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4260
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
4261
{
4262
    int res;
4263
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4264
        return NULL;
4265
    }
4266
#ifdef MS_WINDOWS
4267
    Py_BEGIN_ALLOW_THREADS
4268
    res = win32_lchmod(path->wide, mode);
4269
    Py_END_ALLOW_THREADS
4270
    if (!res) {
4271
        path_error(path);
4272
        return NULL;
4273
    }
4274
#else /* MS_WINDOWS */
4275
    Py_BEGIN_ALLOW_THREADS
4276
    res = lchmod(path->narrow, mode);
4277
    Py_END_ALLOW_THREADS
4278
    if (res < 0) {
4279
        path_error(path);
4280
        return NULL;
4281
    }
4282
#endif /* MS_WINDOWS */
4283
    Py_RETURN_NONE;
4284
}
4285
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4286
4287
4288
#ifdef HAVE_CHFLAGS
4289
/*[clinic input]
4290
os.chflags
4291
4292
    path: path_t
4293
    flags: unsigned_long(bitwise=True)
4294
    follow_symlinks: bool=True
4295
4296
Set file flags.
4297
4298
If follow_symlinks is False, and the last element of the path is a symbolic
4299
  link, chflags will change flags on the symbolic link itself instead of the
4300
  file the link points to.
4301
follow_symlinks may not be implemented on your platform.  If it is
4302
unavailable, using it will raise a NotImplementedError.
4303
4304
[clinic start generated code]*/
4305
4306
static PyObject *
4307
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4308
                int follow_symlinks)
4309
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
4310
{
4311
    int result;
4312
4313
#ifndef HAVE_LCHFLAGS
4314
    if (follow_symlinks_specified("chflags", follow_symlinks))
4315
        return NULL;
4316
#endif
4317
4318
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4319
        return NULL;
4320
    }
4321
4322
    Py_BEGIN_ALLOW_THREADS
4323
#ifdef HAVE_LCHFLAGS
4324
    if (!follow_symlinks)
4325
        result = lchflags(path->narrow, flags);
4326
    else
4327
#endif
4328
        result = chflags(path->narrow, flags);
4329
    Py_END_ALLOW_THREADS
4330
4331
    if (result)
4332
        return path_error(path);
4333
4334
    Py_RETURN_NONE;
4335
}
4336
#endif /* HAVE_CHFLAGS */
4337
4338
4339
#ifdef HAVE_LCHFLAGS
4340
/*[clinic input]
4341
os.lchflags
4342
4343
    path: path_t
4344
    flags: unsigned_long(bitwise=True)
4345
4346
Set file flags.
4347
4348
This function will not follow symbolic links.
4349
Equivalent to chflags(path, flags, follow_symlinks=False).
4350
[clinic start generated code]*/
4351
4352
static PyObject *
4353
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4354
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4355
{
4356
    int res;
4357
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4358
        return NULL;
4359
    }
4360
    Py_BEGIN_ALLOW_THREADS
4361
    res = lchflags(path->narrow, flags);
4362
    Py_END_ALLOW_THREADS
4363
    if (res < 0) {
4364
        return path_error(path);
4365
    }
4366
    Py_RETURN_NONE;
4367
}
4368
#endif /* HAVE_LCHFLAGS */
4369
4370
4371
#ifdef HAVE_CHROOT
4372
/*[clinic input]
4373
os.chroot
4374
    path: path_t
4375
4376
Change root directory to path.
4377
4378
[clinic start generated code]*/
4379
4380
static PyObject *
4381
os_chroot_impl(PyObject *module, path_t *path)
4382
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4383
0
{
4384
0
    int res;
4385
0
    Py_BEGIN_ALLOW_THREADS
4386
0
    res = chroot(path->narrow);
4387
0
    Py_END_ALLOW_THREADS
4388
0
    if (res < 0)
4389
0
        return path_error(path);
4390
0
    Py_RETURN_NONE;
4391
0
}
4392
#endif /* HAVE_CHROOT */
4393
4394
4395
#ifdef HAVE_FSYNC
4396
/*[clinic input]
4397
os.fsync
4398
4399
    fd: fildes
4400
4401
Force write of fd to disk.
4402
[clinic start generated code]*/
4403
4404
static PyObject *
4405
os_fsync_impl(PyObject *module, int fd)
4406
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4407
0
{
4408
0
    return posix_fildes_fd(fd, fsync);
4409
0
}
4410
#endif /* HAVE_FSYNC */
4411
4412
4413
#ifdef HAVE_SYNC
4414
/*[clinic input]
4415
os.sync
4416
4417
Force write of everything to disk.
4418
[clinic start generated code]*/
4419
4420
static PyObject *
4421
os_sync_impl(PyObject *module)
4422
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4423
0
{
4424
0
    Py_BEGIN_ALLOW_THREADS
4425
0
    sync();
4426
0
    Py_END_ALLOW_THREADS
4427
0
    Py_RETURN_NONE;
4428
0
}
4429
#endif /* HAVE_SYNC */
4430
4431
4432
#ifdef HAVE_FDATASYNC
4433
#ifdef __hpux
4434
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4435
#endif
4436
4437
/*[clinic input]
4438
os.fdatasync
4439
4440
    fd: fildes
4441
4442
Force write of fd to disk without forcing update of metadata.
4443
[clinic start generated code]*/
4444
4445
static PyObject *
4446
os_fdatasync_impl(PyObject *module, int fd)
4447
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4448
0
{
4449
0
    return posix_fildes_fd(fd, fdatasync);
4450
0
}
4451
#endif /* HAVE_FDATASYNC */
4452
4453
4454
#ifdef HAVE_CHOWN
4455
/*[clinic input]
4456
os.chown
4457
4458
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4459
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4460
4461
    uid: uid_t
4462
4463
    gid: gid_t
4464
4465
    *
4466
4467
    dir_fd : dir_fd(requires='fchownat') = None
4468
        If not None, it should be a file descriptor open to a directory,
4469
        and path should be relative; path will then be relative to that
4470
        directory.
4471
4472
    follow_symlinks: bool = True
4473
        If False, and the last element of the path is a symbolic link,
4474
        stat will examine the symbolic link itself instead of the file
4475
        the link points to.
4476
4477
Change the owner and group id of path to the numeric uid and gid.\
4478
4479
path may always be specified as a string.
4480
On some platforms, path may also be specified as an open file descriptor.
4481
  If this functionality is unavailable, using it raises an exception.
4482
If dir_fd is not None, it should be a file descriptor open to a directory,
4483
  and path should be relative; path will then be relative to that directory.
4484
If follow_symlinks is False, and the last element of the path is a symbolic
4485
  link, chown will modify the symbolic link itself instead of the file the
4486
  link points to.
4487
It is an error to use dir_fd or follow_symlinks when specifying path as
4488
  an open file descriptor.
4489
dir_fd and follow_symlinks may not be implemented on your platform.
4490
  If they are unavailable, using them will raise a NotImplementedError.
4491
4492
[clinic start generated code]*/
4493
4494
static PyObject *
4495
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4496
              int dir_fd, int follow_symlinks)
4497
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4498
0
{
4499
0
    int result;
4500
4501
0
#if defined(HAVE_FCHOWNAT)
4502
0
    int fchownat_unsupported = 0;
4503
0
#endif
4504
4505
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4506
    if (follow_symlinks_specified("chown", follow_symlinks))
4507
        return NULL;
4508
#endif
4509
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4510
0
        fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
4511
0
        return NULL;
4512
4513
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4514
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4515
0
        return NULL;
4516
0
    }
4517
4518
0
    Py_BEGIN_ALLOW_THREADS
4519
0
#ifdef HAVE_FCHOWN
4520
0
    if (path->fd != -1)
4521
0
        result = fchown(path->fd, uid, gid);
4522
0
    else
4523
0
#endif
4524
0
#ifdef HAVE_LCHOWN
4525
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4526
0
        result = lchown(path->narrow, uid, gid);
4527
0
    else
4528
0
#endif
4529
0
#ifdef HAVE_FCHOWNAT
4530
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4531
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4532
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4533
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4534
0
      } else {
4535
0
         fchownat_unsupported = 1;
4536
0
      }
4537
0
    } else
4538
0
#endif
4539
0
        result = chown(path->narrow, uid, gid);
4540
0
    Py_END_ALLOW_THREADS
4541
4542
0
#ifdef HAVE_FCHOWNAT
4543
0
    if (fchownat_unsupported) {
4544
        /* This would be incorrect if the current platform
4545
         * doesn't support lchown.
4546
         */
4547
0
        argument_unavailable_error(NULL, "dir_fd");
4548
0
        return NULL;
4549
0
    }
4550
0
#endif
4551
4552
0
    if (result)
4553
0
        return path_error(path);
4554
4555
0
    Py_RETURN_NONE;
4556
0
}
4557
#endif /* HAVE_CHOWN */
4558
4559
4560
#ifdef HAVE_FCHOWN
4561
/*[clinic input]
4562
os.fchown
4563
4564
    fd: int
4565
    uid: uid_t
4566
    gid: gid_t
4567
4568
Change the owner and group id of the file specified by file descriptor.
4569
4570
Equivalent to os.chown(fd, uid, gid).
4571
4572
[clinic start generated code]*/
4573
4574
static PyObject *
4575
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4576
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4577
0
{
4578
0
    int res;
4579
0
    int async_err = 0;
4580
4581
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4582
0
        return NULL;
4583
0
    }
4584
4585
0
    do {
4586
0
        Py_BEGIN_ALLOW_THREADS
4587
0
        res = fchown(fd, uid, gid);
4588
0
        Py_END_ALLOW_THREADS
4589
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4590
0
    if (res != 0)
4591
0
        return (!async_err) ? posix_error() : NULL;
4592
4593
0
    Py_RETURN_NONE;
4594
0
}
4595
#endif /* HAVE_FCHOWN */
4596
4597
4598
#ifdef HAVE_LCHOWN
4599
/*[clinic input]
4600
os.lchown
4601
4602
    path : path_t
4603
    uid: uid_t
4604
    gid: gid_t
4605
4606
Change the owner and group id of path to the numeric uid and gid.
4607
4608
This function will not follow symbolic links.
4609
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4610
[clinic start generated code]*/
4611
4612
static PyObject *
4613
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4614
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4615
0
{
4616
0
    int res;
4617
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4618
0
        return NULL;
4619
0
    }
4620
0
    Py_BEGIN_ALLOW_THREADS
4621
0
    res = lchown(path->narrow, uid, gid);
4622
0
    Py_END_ALLOW_THREADS
4623
0
    if (res < 0) {
4624
0
        return path_error(path);
4625
0
    }
4626
0
    Py_RETURN_NONE;
4627
0
}
4628
#endif /* HAVE_LCHOWN */
4629
4630
4631
static PyObject *
4632
posix_getcwd(int use_bytes)
4633
0
{
4634
#ifdef MS_WINDOWS
4635
    wchar_t wbuf[MAXPATHLEN];
4636
    wchar_t *wbuf2 = wbuf;
4637
    DWORD len;
4638
4639
    Py_BEGIN_ALLOW_THREADS
4640
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4641
    /* If the buffer is large enough, len does not include the
4642
       terminating \0. If the buffer is too small, len includes
4643
       the space needed for the terminator. */
4644
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4645
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4646
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4647
        }
4648
        else {
4649
            wbuf2 = NULL;
4650
        }
4651
        if (wbuf2) {
4652
            len = GetCurrentDirectoryW(len, wbuf2);
4653
        }
4654
    }
4655
    Py_END_ALLOW_THREADS
4656
4657
    if (!wbuf2) {
4658
        PyErr_NoMemory();
4659
        return NULL;
4660
    }
4661
    if (!len) {
4662
        PyErr_SetFromWindowsErr(0);
4663
        if (wbuf2 != wbuf)
4664
            PyMem_RawFree(wbuf2);
4665
        return NULL;
4666
    }
4667
4668
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4669
    if (wbuf2 != wbuf) {
4670
        PyMem_RawFree(wbuf2);
4671
    }
4672
4673
    if (use_bytes) {
4674
        if (resobj == NULL) {
4675
            return NULL;
4676
        }
4677
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4678
    }
4679
4680
    return resobj;
4681
#else
4682
0
    const size_t chunk = 1024;
4683
4684
0
    char *buf = NULL;
4685
0
    char *cwd = NULL;
4686
0
    size_t buflen = 0;
4687
4688
0
    Py_BEGIN_ALLOW_THREADS
4689
0
    do {
4690
0
        char *newbuf;
4691
0
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4692
0
            buflen += chunk;
4693
0
            newbuf = PyMem_RawRealloc(buf, buflen);
4694
0
        }
4695
0
        else {
4696
0
            newbuf = NULL;
4697
0
        }
4698
0
        if (newbuf == NULL) {
4699
0
            PyMem_RawFree(buf);
4700
0
            buf = NULL;
4701
0
            break;
4702
0
        }
4703
0
        buf = newbuf;
4704
4705
0
        cwd = getcwd(buf, buflen);
4706
0
    } while (cwd == NULL && errno == ERANGE);
4707
0
    Py_END_ALLOW_THREADS
4708
4709
0
    if (buf == NULL) {
4710
0
        return PyErr_NoMemory();
4711
0
    }
4712
0
    if (cwd == NULL) {
4713
0
        posix_error();
4714
0
        PyMem_RawFree(buf);
4715
0
        return NULL;
4716
0
    }
4717
4718
0
    PyObject *obj;
4719
0
    if (use_bytes) {
4720
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4721
0
    }
4722
0
    else {
4723
0
        obj = PyUnicode_DecodeFSDefault(buf);
4724
0
    }
4725
0
#ifdef __linux__
4726
0
    if (buf[0] != '/') {
4727
        /*
4728
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4729
         * relative pathname starting with '(unreachable)'. We detect this
4730
         * and fail with ENOENT, matching newer glibc behaviour.
4731
         */
4732
0
        errno = ENOENT;
4733
0
        path_object_error(obj);
4734
0
        PyMem_RawFree(buf);
4735
0
        return NULL;
4736
0
    }
4737
0
#endif
4738
0
    assert(buf[0] == '/');
4739
0
    PyMem_RawFree(buf);
4740
4741
0
    return obj;
4742
0
#endif   /* !MS_WINDOWS */
4743
0
}
4744
4745
4746
/*[clinic input]
4747
os.getcwd
4748
4749
Return a unicode string representing the current working directory.
4750
[clinic start generated code]*/
4751
4752
static PyObject *
4753
os_getcwd_impl(PyObject *module)
4754
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4755
0
{
4756
0
    return posix_getcwd(0);
4757
0
}
4758
4759
4760
/*[clinic input]
4761
os.getcwdb
4762
4763
Return a bytes string representing the current working directory.
4764
[clinic start generated code]*/
4765
4766
static PyObject *
4767
os_getcwdb_impl(PyObject *module)
4768
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4769
0
{
4770
0
    return posix_getcwd(1);
4771
0
}
4772
4773
4774
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4775
#define HAVE_LINK 1
4776
#endif
4777
4778
#ifdef HAVE_LINK
4779
/*[clinic input]
4780
4781
@permit_long_docstring_body
4782
os.link
4783
4784
    src : path_t
4785
    dst : path_t
4786
    *
4787
    src_dir_fd : dir_fd = None
4788
    dst_dir_fd : dir_fd = None
4789
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4790
4791
Create a hard link to a file.
4792
4793
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4794
  descriptor open to a directory, and the respective path string (src or dst)
4795
  should be relative; the path will then be relative to that directory.
4796
If follow_symlinks is False, and the last element of src is a symbolic
4797
  link, link will create a link to the symbolic link itself instead of the
4798
  file the link points to.
4799
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4800
  platform.  If they are unavailable, using them will raise a
4801
  NotImplementedError.
4802
[clinic start generated code]*/
4803
4804
static PyObject *
4805
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4806
             int dst_dir_fd, int follow_symlinks)
4807
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4808
0
{
4809
#ifdef MS_WINDOWS
4810
    BOOL result = FALSE;
4811
#else
4812
0
    int result;
4813
0
#endif
4814
4815
0
#ifdef HAVE_LINKAT
4816
0
    if (HAVE_LINKAT_RUNTIME) {
4817
0
        if (follow_symlinks < 0) {
4818
0
            follow_symlinks = 1;
4819
0
        }
4820
0
    }
4821
0
    else
4822
0
#endif
4823
0
    {
4824
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4825
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4826
0
            return NULL;
4827
0
        }
4828
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4829
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4830
0
#if defined(MS_WINDOWS) || defined(__linux__)
4831
0
        if (follow_symlinks == 1) {
4832
0
            argument_unavailable_error("link", "follow_symlinks=True");
4833
0
            return NULL;
4834
0
        }
4835
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4836
        if (follow_symlinks == 0) {
4837
            argument_unavailable_error("link", "follow_symlinks=False");
4838
            return NULL;
4839
        }
4840
#else
4841
        if (follow_symlinks >= 0) {
4842
            argument_unavailable_error("link", "follow_symlinks");
4843
            return NULL;
4844
        }
4845
#endif
4846
0
    }
4847
4848
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4849
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4850
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4851
0
        return NULL;
4852
0
    }
4853
4854
#ifdef MS_WINDOWS
4855
    Py_BEGIN_ALLOW_THREADS
4856
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4857
    Py_END_ALLOW_THREADS
4858
4859
    if (!result)
4860
        return path_error2(src, dst);
4861
#else
4862
0
    Py_BEGIN_ALLOW_THREADS
4863
0
#ifdef HAVE_LINKAT
4864
0
    if (HAVE_LINKAT_RUNTIME) {
4865
0
        result = linkat(src_dir_fd, src->narrow,
4866
0
            dst_dir_fd, dst->narrow,
4867
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4868
0
    }
4869
0
    else
4870
0
#endif
4871
0
    {
4872
        /* linkat not available */
4873
0
        result = link(src->narrow, dst->narrow);
4874
0
    }
4875
0
    Py_END_ALLOW_THREADS
4876
4877
0
    if (result)
4878
0
        return path_error2(src, dst);
4879
0
#endif /* MS_WINDOWS */
4880
4881
0
    Py_RETURN_NONE;
4882
0
}
4883
#endif
4884
4885
4886
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4887
static PyObject *
4888
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4889
{
4890
    PyObject *v;
4891
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4892
    BOOL result, return_bytes;
4893
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4894
    /* only claim to have space for MAX_PATH */
4895
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4896
    wchar_t *wnamebuf = NULL;
4897
4898
    WIN32_FIND_DATAW wFileData;
4899
    const wchar_t *po_wchars;
4900
4901
    if (!path->wide) { /* Default arg: "." */
4902
        po_wchars = L".";
4903
        len = 1;
4904
        return_bytes = 0;
4905
    } else {
4906
        po_wchars = path->wide;
4907
        len = wcslen(path->wide);
4908
        return_bytes = PyBytes_Check(path->object);
4909
    }
4910
    /* The +5 is so we can append "\\*.*\0" */
4911
    wnamebuf = PyMem_New(wchar_t, len + 5);
4912
    if (!wnamebuf) {
4913
        PyErr_NoMemory();
4914
        goto exit;
4915
    }
4916
    wcscpy(wnamebuf, po_wchars);
4917
    if (len > 0) {
4918
        wchar_t wch = wnamebuf[len-1];
4919
        if (wch != SEP && wch != ALTSEP && wch != L':')
4920
            wnamebuf[len++] = SEP;
4921
        wcscpy(wnamebuf + len, L"*.*");
4922
    }
4923
    if ((list = PyList_New(0)) == NULL) {
4924
        goto exit;
4925
    }
4926
    Py_BEGIN_ALLOW_THREADS
4927
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4928
    Py_END_ALLOW_THREADS
4929
    if (hFindFile == INVALID_HANDLE_VALUE) {
4930
        int error = GetLastError();
4931
        if (error == ERROR_FILE_NOT_FOUND)
4932
            goto exit;
4933
        path_error(path);
4934
        Py_CLEAR(list);
4935
        goto exit;
4936
    }
4937
    do {
4938
        /* Skip over . and .. */
4939
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4940
            wcscmp(wFileData.cFileName, L"..") != 0) {
4941
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4942
                                       wcslen(wFileData.cFileName));
4943
            if (return_bytes && v) {
4944
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4945
            }
4946
            if (v == NULL) {
4947
                Py_CLEAR(list);
4948
                break;
4949
            }
4950
            if (PyList_Append(list, v) != 0) {
4951
                Py_DECREF(v);
4952
                Py_CLEAR(list);
4953
                break;
4954
            }
4955
            Py_DECREF(v);
4956
        }
4957
        Py_BEGIN_ALLOW_THREADS
4958
        result = FindNextFileW(hFindFile, &wFileData);
4959
        Py_END_ALLOW_THREADS
4960
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4961
           it got to the end of the directory. */
4962
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4963
            path_error(path);
4964
            Py_CLEAR(list);
4965
            goto exit;
4966
        }
4967
    } while (result == TRUE);
4968
4969
exit:
4970
    if (hFindFile != INVALID_HANDLE_VALUE) {
4971
        if (FindClose(hFindFile) == FALSE) {
4972
            if (list != NULL) {
4973
                path_error(path);
4974
                Py_CLEAR(list);
4975
            }
4976
        }
4977
    }
4978
    PyMem_Free(wnamebuf);
4979
4980
    return list;
4981
}  /* end of _listdir_windows_no_opendir */
4982
4983
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4984
4985
static PyObject *
4986
_posix_listdir(path_t *path, PyObject *list)
4987
167
{
4988
167
    PyObject *v;
4989
167
    DIR *dirp = NULL;
4990
167
    struct dirent *ep;
4991
167
    int return_str; /* if false, return bytes */
4992
167
#ifdef HAVE_FDOPENDIR
4993
167
    int fd = -1;
4994
167
#endif
4995
4996
167
    errno = 0;
4997
167
#ifdef HAVE_FDOPENDIR
4998
167
    if (path->fd != -1) {
4999
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5000
        /* closedir() closes the FD, so we duplicate it */
5001
0
        fd = _Py_dup(path->fd);
5002
0
        if (fd == -1)
5003
0
            return NULL;
5004
5005
0
        return_str = 1;
5006
5007
0
        Py_BEGIN_ALLOW_THREADS
5008
0
        dirp = fdopendir(fd);
5009
0
        Py_END_ALLOW_THREADS
5010
0
      } else {
5011
0
        PyErr_SetString(PyExc_TypeError,
5012
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5013
0
        return NULL;
5014
0
      }
5015
0
    }
5016
167
    else
5017
167
#endif
5018
167
    {
5019
167
        const char *name;
5020
167
        if (path->narrow) {
5021
167
            name = path->narrow;
5022
            /* only return bytes if they specified a bytes object */
5023
167
            return_str = !PyBytes_Check(path->object);
5024
167
        }
5025
0
        else {
5026
0
            name = ".";
5027
0
            return_str = 1;
5028
0
        }
5029
5030
167
        Py_BEGIN_ALLOW_THREADS
5031
167
        dirp = opendir(name);
5032
167
        Py_END_ALLOW_THREADS
5033
167
    }
5034
5035
167
    if (dirp == NULL) {
5036
0
        path_error(path);
5037
0
        list = NULL;
5038
0
#ifdef HAVE_FDOPENDIR
5039
0
        if (fd != -1) {
5040
0
            Py_BEGIN_ALLOW_THREADS
5041
0
            close(fd);
5042
0
            Py_END_ALLOW_THREADS
5043
0
        }
5044
0
#endif
5045
0
        goto exit;
5046
0
    }
5047
167
    if ((list = PyList_New(0)) == NULL) {
5048
0
        goto exit;
5049
0
    }
5050
9.71k
    for (;;) {
5051
9.71k
        errno = 0;
5052
9.71k
        Py_BEGIN_ALLOW_THREADS
5053
9.71k
        ep = readdir(dirp);
5054
9.71k
        Py_END_ALLOW_THREADS
5055
9.71k
        if (ep == NULL) {
5056
167
            if (errno == 0) {
5057
167
                break;
5058
167
            } else {
5059
0
                path_error(path);
5060
0
                Py_CLEAR(list);
5061
0
                goto exit;
5062
0
            }
5063
167
        }
5064
9.55k
        if (ep->d_name[0] == '.' &&
5065
334
            (NAMLEN(ep) == 1 ||
5066
167
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5067
334
            continue;
5068
9.21k
        if (return_str)
5069
9.21k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5070
0
        else
5071
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5072
9.21k
        if (v == NULL) {
5073
0
            Py_CLEAR(list);
5074
0
            break;
5075
0
        }
5076
9.21k
        if (PyList_Append(list, v) != 0) {
5077
0
            Py_DECREF(v);
5078
0
            Py_CLEAR(list);
5079
0
            break;
5080
0
        }
5081
9.21k
        Py_DECREF(v);
5082
9.21k
    }
5083
5084
167
exit:
5085
167
    if (dirp != NULL) {
5086
167
        Py_BEGIN_ALLOW_THREADS
5087
167
#ifdef HAVE_FDOPENDIR
5088
167
        if (fd > -1)
5089
0
            rewinddir(dirp);
5090
167
#endif
5091
167
        closedir(dirp);
5092
167
        Py_END_ALLOW_THREADS
5093
167
    }
5094
5095
167
    return list;
5096
167
}  /* end of _posix_listdir */
5097
#endif  /* which OS */
5098
5099
5100
/*[clinic input]
5101
@permit_long_docstring_body
5102
os.listdir
5103
5104
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5105
5106
Return a list containing the names of the files in the directory.
5107
5108
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
5109
  the filenames returned will also be bytes; in all other circumstances
5110
  the filenames returned will be str.
5111
If path is None, uses the path='.'.
5112
On some platforms, path may also be specified as an open file descriptor;\
5113
  the file descriptor must refer to a directory.
5114
  If this functionality is unavailable, using it raises NotImplementedError.
5115
5116
The list is in arbitrary order.  It does not include the special
5117
entries '.' and '..' even if they are present in the directory.
5118
5119
5120
[clinic start generated code]*/
5121
5122
static PyObject *
5123
os_listdir_impl(PyObject *module, path_t *path)
5124
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
5125
167
{
5126
167
    if (PySys_Audit("os.listdir", "O",
5127
167
                    path->object ? path->object : Py_None) < 0) {
5128
0
        return NULL;
5129
0
    }
5130
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5131
    return _listdir_windows_no_opendir(path, NULL);
5132
#else
5133
167
    return _posix_listdir(path, NULL);
5134
167
#endif
5135
167
}
5136
5137
5138
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5139
5140
/*[clinic input]
5141
os.listdrives
5142
5143
Return a list containing the names of drives in the system.
5144
5145
A drive name typically looks like 'C:\\'.
5146
5147
[clinic start generated code]*/
5148
5149
static PyObject *
5150
os_listdrives_impl(PyObject *module)
5151
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5152
{
5153
    /* Number of possible drives is limited, so 256 should always be enough.
5154
       On the day when it is not, listmounts() will have to be used. */
5155
    wchar_t buffer[256];
5156
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5157
    PyObject *result = NULL;
5158
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5159
        return NULL;
5160
    }
5161
5162
    Py_BEGIN_ALLOW_THREADS;
5163
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5164
    Py_END_ALLOW_THREADS;
5165
5166
    if (!buflen) {
5167
        PyErr_SetFromWindowsErr(0);
5168
        return NULL;
5169
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5170
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5171
        return NULL;
5172
    }
5173
5174
    /* buflen includes a null terminator, so remove it */
5175
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5176
    if (str) {
5177
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5178
        if (nullchar) {
5179
            result = PyUnicode_Split(str, nullchar, -1);
5180
            Py_DECREF(nullchar);
5181
        }
5182
        Py_DECREF(str);
5183
    }
5184
    return result;
5185
}
5186
5187
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5188
5189
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5190
5191
/*[clinic input]
5192
os.listvolumes
5193
5194
Return a list containing the volumes in the system.
5195
5196
Volumes are typically represented as a GUID path.
5197
5198
[clinic start generated code]*/
5199
5200
static PyObject *
5201
os_listvolumes_impl(PyObject *module)
5202
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5203
{
5204
    PyObject *result = PyList_New(0);
5205
    HANDLE find = INVALID_HANDLE_VALUE;
5206
    wchar_t buffer[MAX_PATH + 1];
5207
    if (!result) {
5208
        return NULL;
5209
    }
5210
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5211
        Py_DECREF(result);
5212
        return NULL;
5213
    }
5214
5215
    int err = 0;
5216
    Py_BEGIN_ALLOW_THREADS;
5217
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5218
    if (find == INVALID_HANDLE_VALUE) {
5219
        err = GetLastError();
5220
    }
5221
    Py_END_ALLOW_THREADS;
5222
5223
    while (!err) {
5224
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5225
        if (!s || PyList_Append(result, s) < 0) {
5226
            Py_XDECREF(s);
5227
            Py_CLEAR(result);
5228
            break;
5229
        }
5230
        Py_DECREF(s);
5231
5232
        Py_BEGIN_ALLOW_THREADS;
5233
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5234
            err = GetLastError();
5235
        }
5236
        Py_END_ALLOW_THREADS;
5237
    }
5238
5239
    if (find != INVALID_HANDLE_VALUE) {
5240
        Py_BEGIN_ALLOW_THREADS;
5241
        FindVolumeClose(find);
5242
        Py_END_ALLOW_THREADS;
5243
    }
5244
    if (err && err != ERROR_NO_MORE_FILES) {
5245
        PyErr_SetFromWindowsErr(err);
5246
        Py_XDECREF(result);
5247
        result = NULL;
5248
    }
5249
    return result;
5250
}
5251
5252
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5253
5254
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5255
5256
/*[clinic input]
5257
os.listmounts
5258
5259
    volume: path_t
5260
5261
Return a list containing mount points for a particular volume.
5262
5263
'volume' should be a GUID path as returned from os.listvolumes.
5264
5265
[clinic start generated code]*/
5266
5267
static PyObject *
5268
os_listmounts_impl(PyObject *module, path_t *volume)
5269
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5270
{
5271
    wchar_t default_buffer[MAX_PATH + 1];
5272
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5273
    LPWSTR buffer = default_buffer;
5274
    DWORD attributes;
5275
    PyObject *str = NULL;
5276
    PyObject *nullchar = NULL;
5277
    PyObject *result = NULL;
5278
5279
    /* Ensure we have a valid volume path before continuing */
5280
    Py_BEGIN_ALLOW_THREADS
5281
    attributes = GetFileAttributesW(volume->wide);
5282
    Py_END_ALLOW_THREADS
5283
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5284
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5285
    {
5286
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5287
    }
5288
5289
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5290
        return NULL;
5291
    }
5292
5293
    while (1) {
5294
        BOOL success;
5295
        Py_BEGIN_ALLOW_THREADS
5296
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5297
                                                   buflen, &buflen);
5298
        Py_END_ALLOW_THREADS
5299
        if (success) {
5300
            break;
5301
        }
5302
        if (GetLastError() != ERROR_MORE_DATA) {
5303
            PyErr_SetFromWindowsErr(0);
5304
            goto exit;
5305
        }
5306
        if (buffer != default_buffer) {
5307
            PyMem_Free((void *)buffer);
5308
        }
5309
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5310
        if (!buffer) {
5311
            PyErr_NoMemory();
5312
            goto exit;
5313
        }
5314
    }
5315
    if (buflen < 2) {
5316
        result = PyList_New(0);
5317
        goto exit;
5318
    }
5319
    // buflen includes two null terminators, one for the last string
5320
    // and one for the array of strings.
5321
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5322
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5323
    if (str && nullchar) {
5324
        result = PyUnicode_Split(str, nullchar, -1);
5325
    }
5326
exit:
5327
    if (buffer != default_buffer) {
5328
        PyMem_Free(buffer);
5329
    }
5330
    Py_XDECREF(nullchar);
5331
    Py_XDECREF(str);
5332
    return result;
5333
}
5334
5335
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5336
5337
#ifdef MS_WINDOWS
5338
5339
/*[clinic input]
5340
os._path_isdevdrive
5341
5342
    path: path_t
5343
5344
Determines whether the specified path is on a Windows Dev Drive.
5345
5346
[clinic start generated code]*/
5347
5348
static PyObject *
5349
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5350
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5351
{
5352
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5353
    /* This flag will be documented at
5354
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5355
       after release, and will be available in the latest WinSDK.
5356
       We include the flag to avoid a specific version dependency
5357
       on the latest WinSDK. */
5358
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5359
#endif
5360
    int err = 0;
5361
    PyObject *r = NULL;
5362
    wchar_t volume[MAX_PATH];
5363
5364
    Py_BEGIN_ALLOW_THREADS
5365
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5366
        /* invalid path of some kind */
5367
        /* Note that this also includes the case where a volume is mounted
5368
           in a path longer than 260 characters. This is likely to be rare
5369
           and problematic for other reasons, so a (soft) failure in this
5370
           check seems okay. */
5371
        err = GetLastError();
5372
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5373
        /* only care about local dev drives */
5374
        r = Py_False;
5375
    } else {
5376
        HANDLE hVolume = CreateFileW(
5377
            volume,
5378
            FILE_READ_ATTRIBUTES,
5379
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5380
            NULL,
5381
            OPEN_EXISTING,
5382
            FILE_FLAG_BACKUP_SEMANTICS,
5383
            NULL
5384
        );
5385
        if (hVolume == INVALID_HANDLE_VALUE) {
5386
            err = GetLastError();
5387
        } else {
5388
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5389
            volumeState.Version = 1;
5390
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5391
            if (!DeviceIoControl(
5392
                hVolume,
5393
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5394
                &volumeState,
5395
                sizeof(volumeState),
5396
                &volumeState,
5397
                sizeof(volumeState),
5398
                NULL,
5399
                NULL
5400
            )) {
5401
                err = GetLastError();
5402
            }
5403
            CloseHandle(hVolume);
5404
            if (err == ERROR_INVALID_PARAMETER) {
5405
                /* not supported on this platform */
5406
                r = Py_False;
5407
            } else if (!err) {
5408
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5409
                    ? Py_True : Py_False;
5410
            }
5411
        }
5412
    }
5413
    Py_END_ALLOW_THREADS
5414
5415
    if (err) {
5416
        PyErr_SetFromWindowsErr(err);
5417
        return NULL;
5418
    }
5419
5420
    if (r) {
5421
        return Py_NewRef(r);
5422
    }
5423
5424
    return NULL;
5425
}
5426
5427
5428
int
5429
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5430
{
5431
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5432
    DWORD result;
5433
5434
    result = GetFullPathNameW(path,
5435
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5436
                              NULL);
5437
    if (!result) {
5438
        return -1;
5439
    }
5440
5441
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5442
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5443
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5444
        }
5445
        else {
5446
            woutbufp = NULL;
5447
        }
5448
        if (!woutbufp) {
5449
            *abspath_p = NULL;
5450
            return 0;
5451
        }
5452
5453
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5454
        if (!result) {
5455
            PyMem_RawFree(woutbufp);
5456
            return -1;
5457
        }
5458
    }
5459
5460
    if (woutbufp != woutbuf) {
5461
        *abspath_p = woutbufp;
5462
        return 0;
5463
    }
5464
5465
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5466
    return 0;
5467
}
5468
5469
5470
/* A helper function for abspath on win32 */
5471
/*[clinic input]
5472
os._getfullpathname
5473
5474
    path: path_t
5475
    /
5476
5477
[clinic start generated code]*/
5478
5479
static PyObject *
5480
os__getfullpathname_impl(PyObject *module, path_t *path)
5481
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5482
{
5483
    wchar_t *abspath;
5484
5485
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5486
        return win32_error_object("GetFullPathNameW", path->object);
5487
    }
5488
    if (abspath == NULL) {
5489
        return PyErr_NoMemory();
5490
    }
5491
5492
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5493
    PyMem_RawFree(abspath);
5494
    if (str == NULL) {
5495
        return NULL;
5496
    }
5497
    if (PyBytes_Check(path->object)) {
5498
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5499
    }
5500
    return str;
5501
}
5502
5503
5504
/*[clinic input]
5505
os._getfinalpathname
5506
5507
    path: path_t
5508
    /
5509
5510
A helper function for samepath on windows.
5511
[clinic start generated code]*/
5512
5513
static PyObject *
5514
os__getfinalpathname_impl(PyObject *module, path_t *path)
5515
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5516
{
5517
    HANDLE hFile;
5518
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5519
    int buf_size = Py_ARRAY_LENGTH(buf);
5520
    int result_length;
5521
    PyObject *result;
5522
5523
    Py_BEGIN_ALLOW_THREADS
5524
    hFile = CreateFileW(
5525
        path->wide,
5526
        0, /* desired access */
5527
        0, /* share mode */
5528
        NULL, /* security attributes */
5529
        OPEN_EXISTING,
5530
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5531
        FILE_FLAG_BACKUP_SEMANTICS,
5532
        NULL);
5533
    Py_END_ALLOW_THREADS
5534
5535
    if (hFile == INVALID_HANDLE_VALUE) {
5536
        return win32_error_object("CreateFileW", path->object);
5537
    }
5538
5539
    /* We have a good handle to the target, use it to determine the
5540
       target path name. */
5541
    while (1) {
5542
        Py_BEGIN_ALLOW_THREADS
5543
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5544
                                                  buf_size, VOLUME_NAME_DOS);
5545
        Py_END_ALLOW_THREADS
5546
5547
        if (!result_length) {
5548
            result = win32_error_object("GetFinalPathNameByHandleW",
5549
                                         path->object);
5550
            goto cleanup;
5551
        }
5552
5553
        if (result_length < buf_size) {
5554
            break;
5555
        }
5556
5557
        wchar_t *tmp;
5558
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5559
                            result_length * sizeof(*tmp));
5560
        if (!tmp) {
5561
            result = PyErr_NoMemory();
5562
            goto cleanup;
5563
        }
5564
5565
        buf_size = result_length;
5566
        target_path = tmp;
5567
    }
5568
5569
    result = PyUnicode_FromWideChar(target_path, result_length);
5570
    if (result && PyBytes_Check(path->object)) {
5571
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5572
    }
5573
5574
cleanup:
5575
    if (target_path != buf) {
5576
        PyMem_Free(target_path);
5577
    }
5578
    CloseHandle(hFile);
5579
    return result;
5580
}
5581
5582
/*[clinic input]
5583
os._findfirstfile
5584
    path: path_t
5585
    /
5586
A function to get the real file name without accessing the file in Windows.
5587
[clinic start generated code]*/
5588
5589
static PyObject *
5590
os__findfirstfile_impl(PyObject *module, path_t *path)
5591
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5592
{
5593
    PyObject *result;
5594
    HANDLE hFindFile;
5595
    WIN32_FIND_DATAW wFileData;
5596
    WCHAR *wRealFileName;
5597
5598
    Py_BEGIN_ALLOW_THREADS
5599
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5600
    Py_END_ALLOW_THREADS
5601
5602
    if (hFindFile == INVALID_HANDLE_VALUE) {
5603
        path_error(path);
5604
        return NULL;
5605
    }
5606
5607
    wRealFileName = wFileData.cFileName;
5608
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5609
    FindClose(hFindFile);
5610
    return result;
5611
}
5612
5613
5614
/*[clinic input]
5615
os._getvolumepathname
5616
5617
    path: path_t
5618
5619
A helper function for ismount on Win32.
5620
[clinic start generated code]*/
5621
5622
static PyObject *
5623
os__getvolumepathname_impl(PyObject *module, path_t *path)
5624
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5625
{
5626
    PyObject *result;
5627
    wchar_t *mountpath=NULL;
5628
    size_t buflen;
5629
    BOOL ret;
5630
5631
    /* Volume path should be shorter than entire path */
5632
    buflen = Py_MAX(path->length, MAX_PATH);
5633
5634
    if (buflen > PY_DWORD_MAX) {
5635
        PyErr_SetString(PyExc_OverflowError, "path too long");
5636
        return NULL;
5637
    }
5638
5639
    mountpath = PyMem_New(wchar_t, buflen);
5640
    if (mountpath == NULL)
5641
        return PyErr_NoMemory();
5642
5643
    Py_BEGIN_ALLOW_THREADS
5644
    ret = GetVolumePathNameW(path->wide, mountpath,
5645
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5646
    Py_END_ALLOW_THREADS
5647
5648
    if (!ret) {
5649
        result = win32_error_object("_getvolumepathname", path->object);
5650
        goto exit;
5651
    }
5652
    result = PyUnicode_FromWideChar(mountpath, -1);
5653
    if (PyBytes_Check(path->object))
5654
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5655
5656
exit:
5657
    PyMem_Free(mountpath);
5658
    return result;
5659
}
5660
5661
5662
/*[clinic input]
5663
os._path_splitroot
5664
5665
    path: path_t,
5666
    /
5667
5668
Removes everything after the root on Win32.
5669
[clinic start generated code]*/
5670
5671
static PyObject *
5672
os__path_splitroot_impl(PyObject *module, path_t *path)
5673
/*[clinic end generated code: output=ab7f1a88b654581c input=42831e41f8458f6d]*/
5674
{
5675
    wchar_t *buffer;
5676
    wchar_t *end;
5677
    PyObject *result = NULL;
5678
    HRESULT ret;
5679
5680
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5681
    if (!buffer) {
5682
        return NULL;
5683
    }
5684
    wcscpy(buffer, path->wide);
5685
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5686
        *p = L'\\';
5687
    }
5688
5689
    Py_BEGIN_ALLOW_THREADS
5690
    ret = PathCchSkipRoot(buffer, &end);
5691
    Py_END_ALLOW_THREADS
5692
    if (FAILED(ret)) {
5693
        result = Py_BuildValue("sO", "", path->object);
5694
    } else if (end != buffer) {
5695
        size_t rootLen = (size_t)(end - buffer);
5696
        result = Py_BuildValue("NN",
5697
            PyUnicode_FromWideChar(path->wide, rootLen),
5698
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5699
        );
5700
    } else {
5701
        result = Py_BuildValue("Os", path->object, "");
5702
    }
5703
    PyMem_Free(buffer);
5704
5705
    return result;
5706
}
5707
5708
5709
#define PY_IFREG  1 // Regular file
5710
#define PY_IFDIR  2 // Directory
5711
#define PY_IFLNK  4 // Symlink
5712
#define PY_IFMNT  8 // Mount Point (junction)
5713
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5714
#define PY_IFRRP 32 // Regular Reparse Point
5715
5716
static inline BOOL
5717
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5718
{
5719
    switch (testedType) {
5720
    case PY_IFREG:
5721
        return diskDevice && attributes &&
5722
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5723
    case PY_IFDIR:
5724
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5725
    case PY_IFLNK:
5726
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5727
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5728
    case PY_IFMNT:
5729
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5730
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5731
    case PY_IFLRP:
5732
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5733
               IsReparseTagNameSurrogate(reparseTag);
5734
    case PY_IFRRP:
5735
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5736
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5737
    }
5738
5739
    return FALSE;
5740
}
5741
5742
static BOOL
5743
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5744
{
5745
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5746
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5747
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5748
5749
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5750
    if (diskOnly && !diskDevice) {
5751
        return FALSE;
5752
    }
5753
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5754
        FILE_ATTRIBUTE_TAG_INFO info;
5755
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5756
                                            sizeof(info)) &&
5757
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5758
                         testedType);
5759
    }
5760
    FILE_BASIC_INFO info;
5761
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5762
                                        sizeof(info)) &&
5763
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5764
}
5765
5766
static BOOL
5767
_testFileTypeByName(LPCWSTR path, int testedType)
5768
{
5769
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5770
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5771
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5772
5773
    FILE_STAT_BASIC_INFORMATION info;
5774
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5775
                                     sizeof(info)))
5776
    {
5777
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5778
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5779
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5780
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5781
                                diskDevice, testedType);
5782
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5783
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5784
        {
5785
            return result;
5786
        }
5787
    }
5788
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5789
                GetLastError()))
5790
    {
5791
        return FALSE;
5792
    }
5793
5794
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5795
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5796
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5797
    }
5798
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5799
                               OPEN_EXISTING, flags, NULL);
5800
    if (hfile != INVALID_HANDLE_VALUE) {
5801
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5802
        CloseHandle(hfile);
5803
        return result;
5804
    }
5805
5806
    switch (GetLastError()) {
5807
    case ERROR_ACCESS_DENIED:
5808
    case ERROR_SHARING_VIOLATION:
5809
    case ERROR_CANT_ACCESS_FILE:
5810
    case ERROR_INVALID_PARAMETER:
5811
        int rc;
5812
        STRUCT_STAT st;
5813
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5814
            rc = STAT(path, &st);
5815
        }
5816
        else {
5817
            // PY_IFRRP is not generally supported in this case, except for
5818
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5819
            rc = LSTAT(path, &st);
5820
        }
5821
        if (!rc) {
5822
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5823
                             st.st_mode & S_IFREG, testedType);
5824
        }
5825
    }
5826
5827
    return FALSE;
5828
}
5829
5830
5831
static BOOL
5832
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5833
{
5834
    FILE_STAT_BASIC_INFORMATION info;
5835
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5836
                                     sizeof(info)))
5837
    {
5838
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5839
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5840
        {
5841
            return TRUE;
5842
        }
5843
    }
5844
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5845
                    GetLastError()))
5846
    {
5847
        return FALSE;
5848
    }
5849
5850
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5851
    if (!followLinks) {
5852
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5853
    }
5854
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5855
                               OPEN_EXISTING, flags, NULL);
5856
    if (hfile != INVALID_HANDLE_VALUE) {
5857
        if (followLinks) {
5858
            CloseHandle(hfile);
5859
            return TRUE;
5860
        }
5861
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5862
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5863
        CloseHandle(hfile);
5864
        if (!result) {
5865
            return TRUE;
5866
        }
5867
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5868
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5869
        if (hfile != INVALID_HANDLE_VALUE) {
5870
            CloseHandle(hfile);
5871
            return TRUE;
5872
        }
5873
    }
5874
5875
    switch (GetLastError()) {
5876
    case ERROR_ACCESS_DENIED:
5877
    case ERROR_SHARING_VIOLATION:
5878
    case ERROR_CANT_ACCESS_FILE:
5879
    case ERROR_INVALID_PARAMETER:
5880
        STRUCT_STAT _st;
5881
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5882
    }
5883
5884
    return FALSE;
5885
}
5886
5887
5888
static BOOL
5889
_testFileExists(path_t *path, BOOL followLinks)
5890
{
5891
    BOOL result = FALSE;
5892
    if (path->value_error) {
5893
        return FALSE;
5894
    }
5895
5896
    Py_BEGIN_ALLOW_THREADS
5897
    if (path->fd != -1) {
5898
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5899
        if (hfile != INVALID_HANDLE_VALUE) {
5900
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5901
                result = TRUE;
5902
            }
5903
        }
5904
    }
5905
    else if (path->wide) {
5906
        result = _testFileExistsByName(path->wide, followLinks);
5907
    }
5908
    Py_END_ALLOW_THREADS
5909
5910
    return result;
5911
}
5912
5913
5914
static BOOL
5915
_testFileType(path_t *path, int testedType)
5916
{
5917
    BOOL result = FALSE;
5918
    if (path->value_error) {
5919
        return FALSE;
5920
    }
5921
5922
    Py_BEGIN_ALLOW_THREADS
5923
    if (path->fd != -1) {
5924
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5925
        if (hfile != INVALID_HANDLE_VALUE) {
5926
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5927
        }
5928
    }
5929
    else if (path->wide) {
5930
        result = _testFileTypeByName(path->wide, testedType);
5931
    }
5932
    Py_END_ALLOW_THREADS
5933
5934
    return result;
5935
}
5936
5937
5938
/*[clinic input]
5939
os._path_exists -> bool
5940
5941
    path: path_t(allow_fd=True, suppress_value_error=True)
5942
5943
Test whether a path exists.  Returns False for broken symbolic links.
5944
5945
[clinic start generated code]*/
5946
5947
static int
5948
os__path_exists_impl(PyObject *module, path_t *path)
5949
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5950
{
5951
    return _testFileExists(path, TRUE);
5952
}
5953
5954
5955
/*[clinic input]
5956
os._path_lexists -> bool
5957
5958
    path: path_t(allow_fd=True, suppress_value_error=True)
5959
5960
Test whether a path exists.  Returns True for broken symbolic links.
5961
5962
[clinic start generated code]*/
5963
5964
static int
5965
os__path_lexists_impl(PyObject *module, path_t *path)
5966
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5967
{
5968
    return _testFileExists(path, FALSE);
5969
}
5970
5971
5972
/*[clinic input]
5973
os._path_isdir -> bool
5974
5975
    path: path_t(allow_fd=True, suppress_value_error=True),
5976
    /
5977
5978
Return true if the pathname refers to an existing directory.
5979
5980
[clinic start generated code]*/
5981
5982
static int
5983
os__path_isdir_impl(PyObject *module, path_t *path)
5984
/*[clinic end generated code: output=d5786196f9e2fa7a input=0d3fd790564d244b]*/
5985
{
5986
    return _testFileType(path, PY_IFDIR);
5987
}
5988
5989
5990
/*[clinic input]
5991
os._path_isfile -> bool
5992
5993
    path: path_t(allow_fd=True, suppress_value_error=True)
5994
5995
Test whether a path is a regular file
5996
5997
[clinic start generated code]*/
5998
5999
static int
6000
os__path_isfile_impl(PyObject *module, path_t *path)
6001
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6002
{
6003
    return _testFileType(path, PY_IFREG);
6004
}
6005
6006
6007
/*[clinic input]
6008
os._path_islink -> bool
6009
6010
    path: path_t(allow_fd=True, suppress_value_error=True)
6011
6012
Test whether a path is a symbolic link
6013
6014
[clinic start generated code]*/
6015
6016
static int
6017
os__path_islink_impl(PyObject *module, path_t *path)
6018
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6019
{
6020
    return _testFileType(path, PY_IFLNK);
6021
}
6022
6023
6024
/*[clinic input]
6025
os._path_isjunction -> bool
6026
6027
    path: path_t(allow_fd=True, suppress_value_error=True)
6028
6029
Test whether a path is a junction
6030
6031
[clinic start generated code]*/
6032
6033
static int
6034
os__path_isjunction_impl(PyObject *module, path_t *path)
6035
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6036
{
6037
    return _testFileType(path, PY_IFMNT);
6038
}
6039
6040
#undef PY_IFREG
6041
#undef PY_IFDIR
6042
#undef PY_IFLNK
6043
#undef PY_IFMNT
6044
#undef PY_IFLRP
6045
#undef PY_IFRRP
6046
6047
#endif /* MS_WINDOWS */
6048
6049
6050
/*[clinic input]
6051
os._path_splitroot_ex
6052
6053
    path: path_t(make_wide=True, nonstrict=True),
6054
    /
6055
6056
Split a pathname into drive, root and tail.
6057
6058
The tail contains anything after the root.
6059
[clinic start generated code]*/
6060
6061
static PyObject *
6062
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6063
/*[clinic end generated code: output=4b0072b6cdf4b611 input=4ac47b394d68bd21]*/
6064
0
{
6065
0
    Py_ssize_t drvsize, rootsize;
6066
0
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6067
6068
0
    const wchar_t *buffer = path->wide;
6069
0
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6070
0
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6071
0
    if (drv == NULL) {
6072
0
        goto exit;
6073
0
    }
6074
0
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6075
0
    if (root == NULL) {
6076
0
        goto exit;
6077
0
    }
6078
0
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6079
0
                                  path->length - drvsize - rootsize);
6080
0
    if (tail == NULL) {
6081
0
        goto exit;
6082
0
    }
6083
0
    if (PyBytes_Check(path->object)) {
6084
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6085
0
        if (drv == NULL) {
6086
0
            goto exit;
6087
0
        }
6088
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6089
0
        if (root == NULL) {
6090
0
            goto exit;
6091
0
        }
6092
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6093
0
        if (tail == NULL) {
6094
0
            goto exit;
6095
0
        }
6096
0
    }
6097
0
    result = PyTuple_Pack(3, drv, root, tail);
6098
0
exit:
6099
0
    Py_XDECREF(drv);
6100
0
    Py_XDECREF(root);
6101
0
    Py_XDECREF(tail);
6102
0
    return result;
6103
0
}
6104
6105
6106
/*[clinic input]
6107
os._path_normpath
6108
6109
    path: path_t(make_wide=True, nonstrict=True)
6110
6111
Normalize path, eliminating double slashes, etc.
6112
[clinic start generated code]*/
6113
6114
static PyObject *
6115
os__path_normpath_impl(PyObject *module, path_t *path)
6116
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6117
110
{
6118
110
    PyObject *result;
6119
110
    Py_ssize_t norm_len;
6120
110
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6121
110
                                               path->length, &norm_len);
6122
110
    if (!norm_len) {
6123
0
        result = PyUnicode_FromOrdinal('.');
6124
0
    }
6125
110
    else {
6126
110
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6127
110
    }
6128
110
    if (PyBytes_Check(path->object)) {
6129
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6130
0
    }
6131
110
    return result;
6132
110
}
6133
6134
/*[clinic input]
6135
os.mkdir
6136
6137
    path : path_t
6138
6139
    mode: int = 0o777
6140
6141
    *
6142
6143
    dir_fd : dir_fd(requires='mkdirat') = None
6144
6145
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
6146
6147
Create a directory.
6148
6149
If dir_fd is not None, it should be a file descriptor open to a directory,
6150
  and path should be relative; path will then be relative to that directory.
6151
dir_fd may not be implemented on your platform.
6152
  If it is unavailable, using it will raise a NotImplementedError.
6153
6154
The mode argument is ignored on Windows. Where it is used, the current umask
6155
value is first masked out.
6156
[clinic start generated code]*/
6157
6158
static PyObject *
6159
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6160
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
6161
0
{
6162
0
    int result;
6163
#ifdef MS_WINDOWS
6164
    int error = 0;
6165
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6166
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6167
#endif
6168
0
#ifdef HAVE_MKDIRAT
6169
0
    int mkdirat_unavailable = 0;
6170
0
#endif
6171
6172
0
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6173
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6174
0
        return NULL;
6175
0
    }
6176
6177
#ifdef MS_WINDOWS
6178
    Py_BEGIN_ALLOW_THREADS
6179
    // For API sets that don't support these APIs, we have no choice
6180
    // but to silently create a directory with default ACL.
6181
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6182
    if (mode == 0700 /* 0o700 */) {
6183
        ULONG sdSize;
6184
        pSecAttr = &secAttr;
6185
        // Set a discretionary ACL (D) that is protected (P) and includes
6186
        // inheritable (OICI) entries that allow (A) full control (FA) to
6187
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6188
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6189
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6190
            SDDL_REVISION_1,
6191
            &secAttr.lpSecurityDescriptor,
6192
            &sdSize
6193
        )) {
6194
            error = GetLastError();
6195
        }
6196
    }
6197
#endif
6198
    if (!error) {
6199
        result = CreateDirectoryW(path->wide, pSecAttr);
6200
        if (secAttr.lpSecurityDescriptor &&
6201
            // uncommonly, LocalFree returns non-zero on error, but still uses
6202
            // GetLastError() to see what the error code is
6203
            LocalFree(secAttr.lpSecurityDescriptor)) {
6204
            error = GetLastError();
6205
        }
6206
    }
6207
    Py_END_ALLOW_THREADS
6208
6209
    if (error) {
6210
        return PyErr_SetFromWindowsErr(error);
6211
    }
6212
    if (!result) {
6213
        return path_error(path);
6214
    }
6215
#else
6216
0
    Py_BEGIN_ALLOW_THREADS
6217
0
#if HAVE_MKDIRAT
6218
0
    if (dir_fd != DEFAULT_DIR_FD) {
6219
0
      if (HAVE_MKDIRAT_RUNTIME) {
6220
0
        result = mkdirat(dir_fd, path->narrow, mode);
6221
6222
0
      } else {
6223
0
        mkdirat_unavailable = 1;
6224
0
      }
6225
0
    } else
6226
0
#endif
6227
#if defined(__WATCOMC__) && !defined(__QNX__)
6228
        result = mkdir(path->narrow);
6229
#else
6230
0
        result = mkdir(path->narrow, mode);
6231
0
#endif
6232
0
    Py_END_ALLOW_THREADS
6233
6234
0
#if HAVE_MKDIRAT
6235
0
    if (mkdirat_unavailable) {
6236
0
        argument_unavailable_error(NULL, "dir_fd");
6237
0
        return NULL;
6238
0
    }
6239
0
#endif
6240
6241
0
    if (result < 0)
6242
0
        return path_error(path);
6243
0
#endif /* MS_WINDOWS */
6244
0
    Py_RETURN_NONE;
6245
0
}
6246
6247
6248
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6249
#if defined(HAVE_SYS_RESOURCE_H)
6250
#include <sys/resource.h>
6251
#endif
6252
6253
6254
#ifdef HAVE_NICE
6255
/*[clinic input]
6256
os.nice
6257
6258
    increment: int
6259
    /
6260
6261
Add increment to the priority of process and return the new priority.
6262
[clinic start generated code]*/
6263
6264
static PyObject *
6265
os_nice_impl(PyObject *module, int increment)
6266
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6267
0
{
6268
0
    int value;
6269
6270
    /* There are two flavours of 'nice': one that returns the new
6271
       priority (as required by almost all standards out there) and the
6272
       Linux/FreeBSD one, which returns '0' on success and advices
6273
       the use of getpriority() to get the new priority.
6274
6275
       If we are of the nice family that returns the new priority, we
6276
       need to clear errno before the call, and check if errno is filled
6277
       before calling posix_error() on a returnvalue of -1, because the
6278
       -1 may be the actual new priority! */
6279
6280
0
    errno = 0;
6281
0
    value = nice(increment);
6282
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6283
    if (value == 0)
6284
        value = getpriority(PRIO_PROCESS, 0);
6285
#endif
6286
0
    if (value == -1 && errno != 0)
6287
        /* either nice() or getpriority() returned an error */
6288
0
        return posix_error();
6289
0
    return PyLong_FromLong((long) value);
6290
0
}
6291
#endif /* HAVE_NICE */
6292
6293
6294
#ifdef HAVE_GETPRIORITY
6295
/*[clinic input]
6296
os.getpriority
6297
6298
    which: int
6299
    who: int
6300
6301
Return program scheduling priority.
6302
[clinic start generated code]*/
6303
6304
static PyObject *
6305
os_getpriority_impl(PyObject *module, int which, int who)
6306
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6307
0
{
6308
0
    int retval;
6309
6310
0
    errno = 0;
6311
0
    retval = getpriority(which, who);
6312
0
    if (errno != 0)
6313
0
        return posix_error();
6314
0
    return PyLong_FromLong((long)retval);
6315
0
}
6316
#endif /* HAVE_GETPRIORITY */
6317
6318
6319
#ifdef HAVE_SETPRIORITY
6320
/*[clinic input]
6321
os.setpriority
6322
6323
    which: int
6324
    who: int
6325
    priority: int
6326
6327
Set program scheduling priority.
6328
[clinic start generated code]*/
6329
6330
static PyObject *
6331
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6332
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6333
0
{
6334
0
    int retval;
6335
6336
0
    retval = setpriority(which, who, priority);
6337
0
    if (retval == -1)
6338
0
        return posix_error();
6339
0
    Py_RETURN_NONE;
6340
0
}
6341
#endif /* HAVE_SETPRIORITY */
6342
6343
6344
static PyObject *
6345
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6346
260
{
6347
260
    const char *function_name = is_replace ? "replace" : "rename";
6348
260
    int dir_fd_specified;
6349
6350
260
#ifdef HAVE_RENAMEAT
6351
260
    int renameat_unavailable = 0;
6352
260
#endif
6353
6354
#ifdef MS_WINDOWS
6355
    BOOL result;
6356
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6357
#else
6358
260
    int result;
6359
260
#endif
6360
6361
260
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6362
260
                       (dst_dir_fd != DEFAULT_DIR_FD);
6363
#ifndef HAVE_RENAMEAT
6364
    if (dir_fd_specified) {
6365
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6366
        return NULL;
6367
    }
6368
#endif
6369
6370
260
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6371
260
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6372
260
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6373
0
        return NULL;
6374
0
    }
6375
6376
#ifdef MS_WINDOWS
6377
    Py_BEGIN_ALLOW_THREADS
6378
    result = MoveFileExW(src->wide, dst->wide, flags);
6379
    Py_END_ALLOW_THREADS
6380
6381
    if (!result)
6382
        return path_error2(src, dst);
6383
6384
#else
6385
260
    Py_BEGIN_ALLOW_THREADS
6386
260
#ifdef HAVE_RENAMEAT
6387
260
    if (dir_fd_specified) {
6388
0
        if (HAVE_RENAMEAT_RUNTIME) {
6389
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6390
0
        } else {
6391
0
            renameat_unavailable = 1;
6392
0
        }
6393
0
    } else
6394
260
#endif
6395
260
    result = rename(src->narrow, dst->narrow);
6396
260
    Py_END_ALLOW_THREADS
6397
6398
6399
260
#ifdef HAVE_RENAMEAT
6400
260
    if (renameat_unavailable) {
6401
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6402
0
        return NULL;
6403
0
    }
6404
260
#endif
6405
6406
260
    if (result)
6407
0
        return path_error2(src, dst);
6408
260
#endif
6409
260
    Py_RETURN_NONE;
6410
260
}
6411
6412
6413
/*[clinic input]
6414
@permit_long_docstring_body
6415
os.rename
6416
6417
    src : path_t
6418
    dst : path_t
6419
    *
6420
    src_dir_fd : dir_fd = None
6421
    dst_dir_fd : dir_fd = None
6422
6423
Rename a file or directory.
6424
6425
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6426
  descriptor open to a directory, and the respective path string (src or dst)
6427
  should be relative; the path will then be relative to that directory.
6428
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6429
  If they are unavailable, using them will raise a NotImplementedError.
6430
[clinic start generated code]*/
6431
6432
static PyObject *
6433
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6434
               int dst_dir_fd)
6435
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6436
0
{
6437
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6438
0
}
6439
6440
6441
/*[clinic input]
6442
@permit_long_docstring_body
6443
os.replace = os.rename
6444
6445
Rename a file or directory, overwriting the destination.
6446
6447
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6448
  descriptor open to a directory, and the respective path string (src or dst)
6449
  should be relative; the path will then be relative to that directory.
6450
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6451
  If they are unavailable, using them will raise a NotImplementedError.
6452
[clinic start generated code]*/
6453
6454
static PyObject *
6455
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6456
                int dst_dir_fd)
6457
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6458
260
{
6459
260
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6460
260
}
6461
6462
6463
/*[clinic input]
6464
os.rmdir
6465
6466
    path: path_t
6467
    *
6468
    dir_fd: dir_fd(requires='unlinkat') = None
6469
6470
Remove a directory.
6471
6472
If dir_fd is not None, it should be a file descriptor open to a directory,
6473
  and path should be relative; path will then be relative to that directory.
6474
dir_fd may not be implemented on your platform.
6475
  If it is unavailable, using it will raise a NotImplementedError.
6476
[clinic start generated code]*/
6477
6478
static PyObject *
6479
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6480
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6481
0
{
6482
0
    int result;
6483
0
#ifdef HAVE_UNLINKAT
6484
0
    int unlinkat_unavailable = 0;
6485
0
#endif
6486
6487
0
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6488
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6489
0
        return NULL;
6490
0
    }
6491
6492
0
    Py_BEGIN_ALLOW_THREADS
6493
#ifdef MS_WINDOWS
6494
    /* Windows, success=1, UNIX, success=0 */
6495
    result = !RemoveDirectoryW(path->wide);
6496
#else
6497
0
#ifdef HAVE_UNLINKAT
6498
0
    if (dir_fd != DEFAULT_DIR_FD) {
6499
0
      if (HAVE_UNLINKAT_RUNTIME) {
6500
0
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6501
0
      } else {
6502
0
        unlinkat_unavailable = 1;
6503
0
        result = -1;
6504
0
      }
6505
0
    } else
6506
0
#endif
6507
0
        result = rmdir(path->narrow);
6508
0
#endif
6509
0
    Py_END_ALLOW_THREADS
6510
6511
0
#ifdef HAVE_UNLINKAT
6512
0
    if (unlinkat_unavailable) {
6513
0
        argument_unavailable_error("rmdir", "dir_fd");
6514
0
        return NULL;
6515
0
    }
6516
0
#endif
6517
6518
0
    if (result)
6519
0
        return path_error(path);
6520
6521
0
    Py_RETURN_NONE;
6522
0
}
6523
6524
6525
#ifdef HAVE_SYSTEM
6526
#ifdef MS_WINDOWS
6527
/*[clinic input]
6528
os.system -> long
6529
6530
    command: Py_UNICODE
6531
6532
Execute the command in a subshell.
6533
[clinic start generated code]*/
6534
6535
static long
6536
os_system_impl(PyObject *module, const wchar_t *command)
6537
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6538
{
6539
    long result;
6540
6541
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6542
        return -1;
6543
    }
6544
6545
    Py_BEGIN_ALLOW_THREADS
6546
    _Py_BEGIN_SUPPRESS_IPH
6547
    result = _wsystem(command);
6548
    _Py_END_SUPPRESS_IPH
6549
    Py_END_ALLOW_THREADS
6550
    return result;
6551
}
6552
#else /* MS_WINDOWS */
6553
/*[clinic input]
6554
os.system -> long
6555
6556
    command: unicode_fs_encoded
6557
6558
Execute the command in a subshell.
6559
[clinic start generated code]*/
6560
6561
static long
6562
os_system_impl(PyObject *module, PyObject *command)
6563
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6564
0
{
6565
0
    long result;
6566
0
    const char *bytes = PyBytes_AsString(command);
6567
6568
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6569
0
        return -1;
6570
0
    }
6571
6572
0
    Py_BEGIN_ALLOW_THREADS
6573
0
    result = system(bytes);
6574
0
    Py_END_ALLOW_THREADS
6575
0
    return result;
6576
0
}
6577
#endif
6578
#endif /* HAVE_SYSTEM */
6579
6580
6581
#ifdef HAVE_UMASK
6582
/*[clinic input]
6583
os.umask
6584
6585
    mask: int
6586
    /
6587
6588
Set the current numeric umask and return the previous umask.
6589
[clinic start generated code]*/
6590
6591
static PyObject *
6592
os_umask_impl(PyObject *module, int mask)
6593
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6594
0
{
6595
0
    int i = (int)umask(mask);
6596
0
    if (i < 0)
6597
0
        return posix_error();
6598
0
    return PyLong_FromLong((long)i);
6599
0
}
6600
#endif
6601
6602
#ifdef MS_WINDOWS
6603
6604
/* override the default DeleteFileW behavior so that directory
6605
symlinks can be removed with this function, the same as with
6606
Unix symlinks */
6607
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6608
{
6609
    WIN32_FILE_ATTRIBUTE_DATA info;
6610
    WIN32_FIND_DATAW find_data;
6611
    HANDLE find_data_handle;
6612
    int is_directory = 0;
6613
    int is_link = 0;
6614
6615
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6616
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6617
6618
        /* Get WIN32_FIND_DATA structure for the path to determine if
6619
           it is a symlink */
6620
        if(is_directory &&
6621
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6622
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6623
6624
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6625
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6626
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6627
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6628
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6629
                FindClose(find_data_handle);
6630
            }
6631
        }
6632
    }
6633
6634
    if (is_directory && is_link)
6635
        return RemoveDirectoryW(lpFileName);
6636
6637
    return DeleteFileW(lpFileName);
6638
}
6639
#endif /* MS_WINDOWS */
6640
6641
6642
/*[clinic input]
6643
os.unlink
6644
6645
    path: path_t
6646
    *
6647
    dir_fd: dir_fd(requires='unlinkat')=None
6648
6649
Remove a file (same as remove()).
6650
6651
If dir_fd is not None, it should be a file descriptor open to a directory,
6652
  and path should be relative; path will then be relative to that directory.
6653
dir_fd may not be implemented on your platform.
6654
  If it is unavailable, using it will raise a NotImplementedError.
6655
6656
[clinic start generated code]*/
6657
6658
static PyObject *
6659
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6660
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6661
0
{
6662
0
    int result;
6663
0
#ifdef HAVE_UNLINKAT
6664
0
    int unlinkat_unavailable = 0;
6665
0
#endif
6666
6667
0
    if (PySys_Audit("os.remove", "Oi", path->object,
6668
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6669
0
        return NULL;
6670
0
    }
6671
6672
0
    Py_BEGIN_ALLOW_THREADS
6673
0
    _Py_BEGIN_SUPPRESS_IPH
6674
#ifdef MS_WINDOWS
6675
    /* Windows, success=1, UNIX, success=0 */
6676
    result = !Py_DeleteFileW(path->wide);
6677
#else
6678
0
#ifdef HAVE_UNLINKAT
6679
0
    if (dir_fd != DEFAULT_DIR_FD) {
6680
0
      if (HAVE_UNLINKAT_RUNTIME) {
6681
6682
0
        result = unlinkat(dir_fd, path->narrow, 0);
6683
0
      } else {
6684
0
        unlinkat_unavailable = 1;
6685
0
      }
6686
0
    } else
6687
0
#endif /* HAVE_UNLINKAT */
6688
0
        result = unlink(path->narrow);
6689
0
#endif
6690
0
    _Py_END_SUPPRESS_IPH
6691
0
    Py_END_ALLOW_THREADS
6692
6693
0
#ifdef HAVE_UNLINKAT
6694
0
    if (unlinkat_unavailable) {
6695
0
        argument_unavailable_error(NULL, "dir_fd");
6696
0
        return NULL;
6697
0
    }
6698
0
#endif
6699
6700
0
    if (result)
6701
0
        return path_error(path);
6702
6703
0
    Py_RETURN_NONE;
6704
0
}
6705
6706
6707
/*[clinic input]
6708
os.remove = os.unlink
6709
6710
Remove a file (same as unlink()).
6711
6712
If dir_fd is not None, it should be a file descriptor open to a directory,
6713
  and path should be relative; path will then be relative to that directory.
6714
dir_fd may not be implemented on your platform.
6715
  If it is unavailable, using it will raise a NotImplementedError.
6716
[clinic start generated code]*/
6717
6718
static PyObject *
6719
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6720
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6721
0
{
6722
0
    return os_unlink_impl(module, path, dir_fd);
6723
0
}
6724
6725
6726
static PyStructSequence_Field uname_result_fields[] = {
6727
    {"sysname",    "operating system name"},
6728
    {"nodename",   "name of machine on network (implementation-defined)"},
6729
    {"release",    "operating system release"},
6730
    {"version",    "operating system version"},
6731
    {"machine",    "hardware identifier"},
6732
    {NULL}
6733
};
6734
6735
PyDoc_STRVAR(uname_result__doc__,
6736
"uname_result: Result from os.uname().\n\n\
6737
This object may be accessed either as a tuple of\n\
6738
  (sysname, nodename, release, version, machine),\n\
6739
or via the attributes sysname, nodename, release, version, and machine.\n\
6740
\n\
6741
See os.uname for more information.");
6742
6743
static PyStructSequence_Desc uname_result_desc = {
6744
    MODNAME ".uname_result", /* name */
6745
    uname_result__doc__, /* doc */
6746
    uname_result_fields,
6747
    5
6748
};
6749
6750
#ifdef HAVE_UNAME
6751
/*[clinic input]
6752
os.uname
6753
6754
Return an object identifying the current operating system.
6755
6756
The object behaves like a named tuple with the following fields:
6757
  (sysname, nodename, release, version, machine)
6758
6759
[clinic start generated code]*/
6760
6761
static PyObject *
6762
os_uname_impl(PyObject *module)
6763
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6764
0
{
6765
0
    struct utsname u;
6766
0
    int res;
6767
0
    PyObject *value;
6768
6769
0
    Py_BEGIN_ALLOW_THREADS
6770
0
    res = uname(&u);
6771
0
    Py_END_ALLOW_THREADS
6772
0
    if (res < 0)
6773
0
        return posix_error();
6774
6775
0
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6776
0
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6777
0
    if (value == NULL)
6778
0
        return NULL;
6779
6780
0
#define SET(i, field) \
6781
0
    { \
6782
0
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6783
0
    if (!o) { \
6784
0
        Py_DECREF(value); \
6785
0
        return NULL; \
6786
0
    } \
6787
0
    PyStructSequence_SET_ITEM(value, i, o); \
6788
0
    } \
6789
0
6790
0
    SET(0, u.sysname);
6791
0
    SET(1, u.nodename);
6792
0
    SET(2, u.release);
6793
0
    SET(3, u.version);
6794
0
    SET(4, u.machine);
6795
6796
0
#undef SET
6797
6798
0
    return value;
6799
0
}
6800
#endif /* HAVE_UNAME */
6801
6802
6803
6804
typedef struct {
6805
    int    now;
6806
    time_t atime_s;
6807
    long   atime_ns;
6808
    time_t mtime_s;
6809
    long   mtime_ns;
6810
} utime_t;
6811
6812
/*
6813
 * these macros assume that "ut" is a pointer to a utime_t
6814
 * they also intentionally leak the declaration of a pointer named "time"
6815
 */
6816
#define UTIME_TO_TIMESPEC \
6817
0
    struct timespec ts[2]; \
6818
0
    struct timespec *time; \
6819
0
    if (ut->now) \
6820
0
        time = NULL; \
6821
0
    else { \
6822
0
        ts[0].tv_sec = ut->atime_s; \
6823
0
        ts[0].tv_nsec = ut->atime_ns; \
6824
0
        ts[1].tv_sec = ut->mtime_s; \
6825
0
        ts[1].tv_nsec = ut->mtime_ns; \
6826
0
        time = ts; \
6827
0
    } \
6828
6829
#define UTIME_TO_TIMEVAL \
6830
0
    struct timeval tv[2]; \
6831
0
    struct timeval *time; \
6832
0
    if (ut->now) \
6833
0
        time = NULL; \
6834
0
    else { \
6835
0
        tv[0].tv_sec = ut->atime_s; \
6836
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6837
0
        tv[1].tv_sec = ut->mtime_s; \
6838
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6839
0
        time = tv; \
6840
0
    } \
6841
6842
#define UTIME_TO_UTIMBUF \
6843
    struct utimbuf u; \
6844
    struct utimbuf *time; \
6845
    if (ut->now) \
6846
        time = NULL; \
6847
    else { \
6848
        u.actime = ut->atime_s; \
6849
        u.modtime = ut->mtime_s; \
6850
        time = &u; \
6851
    }
6852
6853
#define UTIME_TO_TIME_T \
6854
    time_t timet[2]; \
6855
    time_t *time; \
6856
    if (ut->now) \
6857
        time = NULL; \
6858
    else { \
6859
        timet[0] = ut->atime_s; \
6860
        timet[1] = ut->mtime_s; \
6861
        time = timet; \
6862
    } \
6863
6864
6865
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6866
6867
static int
6868
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6869
0
{
6870
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6871
    if (HAVE_UTIMENSAT_RUNTIME) {
6872
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6873
        UTIME_TO_TIMESPEC;
6874
        return utimensat(dir_fd, path, time, flags);
6875
    }  else {
6876
        errno = ENOSYS;
6877
        return -1;
6878
    }
6879
#elif defined(HAVE_UTIMENSAT)
6880
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6881
0
    UTIME_TO_TIMESPEC;
6882
0
    return utimensat(dir_fd, path, time, flags);
6883
#elif defined(HAVE_FUTIMESAT)
6884
    UTIME_TO_TIMEVAL;
6885
    /*
6886
     * follow_symlinks will never be false here;
6887
     * we only allow !follow_symlinks and dir_fd together
6888
     * if we have utimensat()
6889
     */
6890
    assert(follow_symlinks);
6891
    return futimesat(dir_fd, path, time);
6892
#endif
6893
0
}
6894
6895
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6896
#else
6897
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6898
#endif
6899
6900
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6901
6902
static int
6903
utime_fd(utime_t *ut, int fd)
6904
0
{
6905
0
#ifdef HAVE_FUTIMENS
6906
6907
0
    if (HAVE_FUTIMENS_RUNTIME) {
6908
6909
0
    UTIME_TO_TIMESPEC;
6910
0
    return futimens(fd, time);
6911
6912
0
    } else
6913
#ifndef HAVE_FUTIMES
6914
    {
6915
        /* Not sure if this can happen */
6916
        PyErr_SetString(
6917
            PyExc_RuntimeError,
6918
            "neither futimens nor futimes are supported"
6919
            " on this system");
6920
        return -1;
6921
    }
6922
#endif
6923
6924
0
#endif
6925
0
#ifdef HAVE_FUTIMES
6926
0
    {
6927
0
    UTIME_TO_TIMEVAL;
6928
0
    return futimes(fd, time);
6929
0
    }
6930
0
#endif
6931
0
}
6932
6933
    #define PATH_UTIME_HAVE_FD 1
6934
#else
6935
    #define PATH_UTIME_HAVE_FD 0
6936
#endif
6937
6938
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6939
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6940
#endif
6941
6942
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6943
6944
static int
6945
utime_nofollow_symlinks(utime_t *ut, const char *path)
6946
0
{
6947
0
#ifdef HAVE_UTIMENSAT
6948
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6949
0
        UTIME_TO_TIMESPEC;
6950
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6951
0
    } else
6952
#ifndef HAVE_LUTIMES
6953
    {
6954
        /* Not sure if this can happen */
6955
        PyErr_SetString(
6956
            PyExc_RuntimeError,
6957
            "neither utimensat nor lutimes are supported"
6958
            " on this system");
6959
        return -1;
6960
    }
6961
#endif
6962
0
#endif
6963
6964
0
#ifdef HAVE_LUTIMES
6965
0
    {
6966
0
    UTIME_TO_TIMEVAL;
6967
0
    return lutimes(path, time);
6968
0
    }
6969
0
#endif
6970
0
}
6971
6972
#endif
6973
6974
#ifndef MS_WINDOWS
6975
6976
static int
6977
utime_default(utime_t *ut, const char *path)
6978
0
{
6979
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6980
    if (HAVE_UTIMENSAT_RUNTIME) {
6981
        UTIME_TO_TIMESPEC;
6982
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6983
    } else {
6984
        UTIME_TO_TIMEVAL;
6985
        return utimes(path, time);
6986
    }
6987
#elif defined(HAVE_UTIMENSAT)
6988
0
    UTIME_TO_TIMESPEC;
6989
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6990
#elif defined(HAVE_UTIMES)
6991
    UTIME_TO_TIMEVAL;
6992
    return utimes(path, time);
6993
#elif defined(HAVE_UTIME_H)
6994
    UTIME_TO_UTIMBUF;
6995
    return utime(path, time);
6996
#else
6997
    UTIME_TO_TIME_T;
6998
    return utime(path, time);
6999
#endif
7000
0
}
7001
7002
#endif
7003
7004
static int
7005
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7006
0
{
7007
0
    int result = 0;
7008
0
    PyObject *divmod;
7009
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7010
0
    if (!divmod)
7011
0
        goto exit;
7012
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7013
0
        PyErr_Format(PyExc_TypeError,
7014
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7015
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7016
0
        goto exit;
7017
0
    }
7018
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7019
0
    if ((*s == -1) && PyErr_Occurred())
7020
0
        goto exit;
7021
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7022
0
    if ((*ns == -1) && PyErr_Occurred())
7023
0
        goto exit;
7024
7025
0
    result = 1;
7026
0
exit:
7027
0
    Py_XDECREF(divmod);
7028
0
    return result;
7029
0
}
7030
7031
7032
/*[clinic input]
7033
os.utime
7034
7035
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7036
    times: object = None
7037
    *
7038
    ns: object = NULL
7039
    dir_fd: dir_fd(requires='futimensat') = None
7040
    follow_symlinks: bool=True
7041
7042
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
7043
7044
Set the access and modified time of path.
7045
7046
path may always be specified as a string.
7047
On some platforms, path may also be specified as an open file descriptor.
7048
  If this functionality is unavailable, using it raises an exception.
7049
7050
If times is not None, it must be a tuple (atime, mtime);
7051
    atime and mtime should be expressed as float seconds since the epoch.
7052
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7053
    atime_ns and mtime_ns should be expressed as integer nanoseconds
7054
    since the epoch.
7055
If times is None and ns is unspecified, utime uses the current time.
7056
Specifying tuples for both times and ns is an error.
7057
7058
If dir_fd is not None, it should be a file descriptor open to a directory,
7059
  and path should be relative; path will then be relative to that directory.
7060
If follow_symlinks is False, and the last element of the path is a symbolic
7061
  link, utime will modify the symbolic link itself instead of the file the
7062
  link points to.
7063
It is an error to use dir_fd or follow_symlinks when specifying path
7064
  as an open file descriptor.
7065
dir_fd and follow_symlinks may not be available on your platform.
7066
  If they are unavailable, using them will raise a NotImplementedError.
7067
7068
[clinic start generated code]*/
7069
7070
static PyObject *
7071
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7072
              int dir_fd, int follow_symlinks)
7073
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
7074
0
{
7075
#ifdef MS_WINDOWS
7076
    HANDLE hFile;
7077
    FILETIME atime, mtime;
7078
#else
7079
0
    int result;
7080
0
#endif
7081
7082
0
    utime_t utime;
7083
7084
0
    memset(&utime, 0, sizeof(utime_t));
7085
7086
0
    if (times != Py_None && ns) {
7087
0
        PyErr_SetString(PyExc_ValueError,
7088
0
                     "utime: you may specify either 'times'"
7089
0
                     " or 'ns' but not both");
7090
0
        return NULL;
7091
0
    }
7092
7093
0
    if (times != Py_None) {
7094
0
        time_t a_sec, m_sec;
7095
0
        long a_nsec, m_nsec;
7096
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7097
0
            PyErr_SetString(PyExc_TypeError,
7098
0
                         "utime: 'times' must be either"
7099
0
                         " a tuple of two numbers or None");
7100
0
            return NULL;
7101
0
        }
7102
0
        utime.now = 0;
7103
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7104
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7105
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7106
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7107
0
            return NULL;
7108
0
        }
7109
0
        utime.atime_s = a_sec;
7110
0
        utime.atime_ns = a_nsec;
7111
0
        utime.mtime_s = m_sec;
7112
0
        utime.mtime_ns = m_nsec;
7113
0
    }
7114
0
    else if (ns) {
7115
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7116
0
            PyErr_SetString(PyExc_TypeError,
7117
0
                         "utime: 'ns' must be a tuple of two ints");
7118
0
            return NULL;
7119
0
        }
7120
0
        utime.now = 0;
7121
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7122
0
                                      &utime.atime_s, &utime.atime_ns) ||
7123
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7124
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7125
0
            return NULL;
7126
0
        }
7127
0
    }
7128
0
    else {
7129
        /* times and ns are both None/unspecified. use "now". */
7130
0
        utime.now = 1;
7131
0
    }
7132
7133
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7134
    if (follow_symlinks_specified("utime", follow_symlinks))
7135
        return NULL;
7136
#endif
7137
7138
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7139
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7140
0
        fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
7141
0
        return NULL;
7142
7143
#if !defined(HAVE_UTIMENSAT)
7144
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7145
        PyErr_SetString(PyExc_ValueError,
7146
                     "utime: cannot use dir_fd and follow_symlinks "
7147
                     "together on this platform");
7148
        return NULL;
7149
    }
7150
#endif
7151
7152
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7153
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7154
0
        return NULL;
7155
0
    }
7156
7157
#ifdef MS_WINDOWS
7158
    Py_BEGIN_ALLOW_THREADS
7159
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7160
                        NULL, OPEN_EXISTING,
7161
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7162
    Py_END_ALLOW_THREADS
7163
    if (hFile == INVALID_HANDLE_VALUE) {
7164
        path_error(path);
7165
        return NULL;
7166
    }
7167
7168
    if (utime.now) {
7169
        GetSystemTimeAsFileTime(&mtime);
7170
        atime = mtime;
7171
    }
7172
    else {
7173
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7174
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7175
    }
7176
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7177
        path_error(path);
7178
        CloseHandle(hFile);
7179
        return NULL;
7180
    }
7181
    CloseHandle(hFile);
7182
#else /* MS_WINDOWS */
7183
0
    Py_BEGIN_ALLOW_THREADS
7184
7185
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7186
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7187
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7188
0
    else
7189
0
#endif
7190
7191
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7192
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7193
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7194
7195
0
    } else
7196
0
#endif
7197
7198
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7199
0
    if (path->fd != -1)
7200
0
        result = utime_fd(&utime, path->fd);
7201
0
    else
7202
0
#endif
7203
7204
0
    result = utime_default(&utime, path->narrow);
7205
7206
0
    Py_END_ALLOW_THREADS
7207
7208
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7209
    /* See utime_dir_fd implementation */
7210
    if (result == -1 && errno == ENOSYS) {
7211
        argument_unavailable_error(NULL, "dir_fd");
7212
        return NULL;
7213
    }
7214
#endif
7215
7216
0
    if (result < 0) {
7217
0
        path_error(path);
7218
0
        return NULL;
7219
0
    }
7220
7221
0
#endif /* MS_WINDOWS */
7222
7223
0
    Py_RETURN_NONE;
7224
0
}
7225
7226
/* Process operations */
7227
7228
7229
/*[clinic input]
7230
os._exit
7231
7232
    status: int
7233
7234
Exit to the system with specified status, without normal exit processing.
7235
[clinic start generated code]*/
7236
7237
static PyObject *
7238
os__exit_impl(PyObject *module, int status)
7239
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
7240
0
{
7241
0
    _exit(status);
7242
0
    return NULL; /* Make gcc -Wall happy */
7243
0
}
7244
7245
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7246
#define EXECV_CHAR wchar_t
7247
#else
7248
0
#define EXECV_CHAR char
7249
#endif
7250
7251
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7252
static void
7253
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7254
0
{
7255
0
    Py_ssize_t i;
7256
0
    for (i = 0; i < count; i++)
7257
0
        PyMem_Free(array[i]);
7258
0
    PyMem_Free(array);
7259
0
}
7260
7261
static int
7262
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7263
0
{
7264
0
    Py_ssize_t size;
7265
0
    PyObject *ub;
7266
0
    int result = 0;
7267
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7268
    if (!PyUnicode_FSDecoder(o, &ub))
7269
        return 0;
7270
    *out = PyUnicode_AsWideCharString(ub, &size);
7271
    if (*out)
7272
        result = 1;
7273
#else
7274
0
    if (!PyUnicode_FSConverter(o, &ub))
7275
0
        return 0;
7276
0
    size = PyBytes_GET_SIZE(ub);
7277
0
    *out = PyMem_Malloc(size + 1);
7278
0
    if (*out) {
7279
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7280
0
        result = 1;
7281
0
    } else
7282
0
        PyErr_NoMemory();
7283
0
#endif
7284
0
    Py_DECREF(ub);
7285
0
    return result;
7286
0
}
7287
#endif
7288
7289
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7290
static EXECV_CHAR**
7291
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7292
0
{
7293
0
    Py_ssize_t i, pos, envc;
7294
0
    PyObject *keys=NULL, *vals=NULL;
7295
0
    PyObject *key2, *val2, *keyval;
7296
0
    EXECV_CHAR **envlist;
7297
7298
0
    i = PyMapping_Size(env);
7299
0
    if (i < 0)
7300
0
        return NULL;
7301
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7302
0
    if (envlist == NULL) {
7303
0
        PyErr_NoMemory();
7304
0
        return NULL;
7305
0
    }
7306
0
    envc = 0;
7307
0
    keys = PyMapping_Keys(env);
7308
0
    if (!keys)
7309
0
        goto error;
7310
0
    vals = PyMapping_Values(env);
7311
0
    if (!vals)
7312
0
        goto error;
7313
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7314
0
        PyErr_Format(PyExc_TypeError,
7315
0
                     "env.keys() or env.values() is not a list");
7316
0
        goto error;
7317
0
    }
7318
7319
0
    for (pos = 0; pos < i; pos++) {
7320
0
        PyObject *key = PyList_GetItem(keys, pos);  // Borrowed ref.
7321
0
        if (key == NULL) {
7322
0
            goto error;
7323
0
        }
7324
0
        PyObject *val = PyList_GetItem(vals, pos);  // Borrowed ref.
7325
0
        if (val == NULL) {
7326
0
            goto error;
7327
0
        }
7328
7329
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7330
        if (!PyUnicode_FSDecoder(key, &key2))
7331
            goto error;
7332
        if (!PyUnicode_FSDecoder(val, &val2)) {
7333
            Py_DECREF(key2);
7334
            goto error;
7335
        }
7336
        /* Search from index 1 because on Windows starting '=' is allowed for
7337
           defining hidden environment variables. */
7338
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7339
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7340
        {
7341
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7342
            Py_DECREF(key2);
7343
            Py_DECREF(val2);
7344
            goto error;
7345
        }
7346
        keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7347
#else
7348
0
        if (!PyUnicode_FSConverter(key, &key2))
7349
0
            goto error;
7350
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7351
0
            Py_DECREF(key2);
7352
0
            goto error;
7353
0
        }
7354
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7355
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7356
0
        {
7357
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7358
0
            Py_DECREF(key2);
7359
0
            Py_DECREF(val2);
7360
0
            goto error;
7361
0
        }
7362
0
        keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7363
0
                                             PyBytes_AS_STRING(val2));
7364
0
#endif
7365
0
        Py_DECREF(key2);
7366
0
        Py_DECREF(val2);
7367
0
        if (!keyval)
7368
0
            goto error;
7369
7370
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7371
0
            Py_DECREF(keyval);
7372
0
            goto error;
7373
0
        }
7374
7375
0
        Py_DECREF(keyval);
7376
0
    }
7377
0
    Py_DECREF(vals);
7378
0
    Py_DECREF(keys);
7379
7380
0
    envlist[envc] = 0;
7381
0
    *envc_ptr = envc;
7382
0
    return envlist;
7383
7384
0
error:
7385
0
    Py_XDECREF(keys);
7386
0
    Py_XDECREF(vals);
7387
0
    free_string_array(envlist, envc);
7388
0
    return NULL;
7389
0
}
7390
7391
static EXECV_CHAR**
7392
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7393
0
{
7394
0
    int i;
7395
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7396
0
    if (argvlist == NULL) {
7397
0
        PyErr_NoMemory();
7398
0
        return NULL;
7399
0
    }
7400
0
    for (i = 0; i < *argc; i++) {
7401
0
        PyObject* item = PySequence_ITEM(argv, i);
7402
0
        if (item == NULL)
7403
0
            goto fail;
7404
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7405
0
            Py_DECREF(item);
7406
0
            goto fail;
7407
0
        }
7408
0
        Py_DECREF(item);
7409
0
    }
7410
0
    argvlist[*argc] = NULL;
7411
0
    return argvlist;
7412
0
fail:
7413
0
    *argc = i;
7414
0
    free_string_array(argvlist, *argc);
7415
0
    return NULL;
7416
0
}
7417
7418
#endif
7419
7420
7421
#ifdef HAVE_EXECV
7422
/*[clinic input]
7423
os.execv
7424
7425
    path: path_t
7426
        Path of executable file.
7427
    argv: object
7428
        Tuple or list of strings.
7429
    /
7430
7431
Execute an executable path with arguments, replacing current process.
7432
[clinic start generated code]*/
7433
7434
static PyObject *
7435
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7436
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7437
0
{
7438
0
    EXECV_CHAR **argvlist;
7439
0
    Py_ssize_t argc;
7440
7441
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7442
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7443
0
        PyErr_SetString(PyExc_RuntimeError,
7444
0
                        "exec not supported for isolated subinterpreters");
7445
0
        return NULL;
7446
0
    }
7447
7448
    /* execv has two arguments: (path, argv), where
7449
       argv is a list or tuple of strings. */
7450
7451
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7452
0
        PyErr_SetString(PyExc_TypeError,
7453
0
                        "execv() arg 2 must be a tuple or list");
7454
0
        return NULL;
7455
0
    }
7456
0
    argc = PySequence_Size(argv);
7457
0
    if (argc < 1) {
7458
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7459
0
        return NULL;
7460
0
    }
7461
7462
0
    argvlist = parse_arglist(argv, &argc);
7463
0
    if (argvlist == NULL) {
7464
0
        return NULL;
7465
0
    }
7466
0
    if (!argvlist[0][0]) {
7467
0
        PyErr_SetString(PyExc_ValueError,
7468
0
            "execv() arg 2 first element cannot be empty");
7469
0
        free_string_array(argvlist, argc);
7470
0
        return NULL;
7471
0
    }
7472
7473
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7474
0
        free_string_array(argvlist, argc);
7475
0
        return NULL;
7476
0
    }
7477
7478
0
    _Py_BEGIN_SUPPRESS_IPH
7479
#ifdef HAVE_WEXECV
7480
    _wexecv(path->wide, argvlist);
7481
#else
7482
0
    execv(path->narrow, argvlist);
7483
0
#endif
7484
0
    _Py_END_SUPPRESS_IPH
7485
7486
    /* If we get here it's definitely an error */
7487
7488
0
    posix_error();
7489
0
    free_string_array(argvlist, argc);
7490
0
    return NULL;
7491
0
}
7492
7493
7494
/*[clinic input]
7495
os.execve
7496
7497
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7498
        Path of executable file.
7499
    argv: object
7500
        Tuple or list of strings.
7501
    env: object
7502
        Dictionary of strings mapping to strings.
7503
7504
Execute an executable path with arguments, replacing current process.
7505
[clinic start generated code]*/
7506
7507
static PyObject *
7508
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7509
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7510
0
{
7511
0
    EXECV_CHAR **argvlist = NULL;
7512
0
    EXECV_CHAR **envlist;
7513
0
    Py_ssize_t argc, envc;
7514
7515
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7516
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7517
0
        PyErr_SetString(PyExc_RuntimeError,
7518
0
                        "exec not supported for isolated subinterpreters");
7519
0
        return NULL;
7520
0
    }
7521
7522
    /* execve has three arguments: (path, argv, env), where
7523
       argv is a list or tuple of strings and env is a dictionary
7524
       like posix.environ. */
7525
7526
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7527
0
        PyErr_SetString(PyExc_TypeError,
7528
0
                        "execve: argv must be a tuple or list");
7529
0
        goto fail_0;
7530
0
    }
7531
0
    argc = PySequence_Size(argv);
7532
0
    if (argc < 1) {
7533
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7534
0
        return NULL;
7535
0
    }
7536
7537
0
    if (!PyMapping_Check(env)) {
7538
0
        PyErr_SetString(PyExc_TypeError,
7539
0
                        "execve: environment must be a mapping object");
7540
0
        goto fail_0;
7541
0
    }
7542
7543
0
    argvlist = parse_arglist(argv, &argc);
7544
0
    if (argvlist == NULL) {
7545
0
        goto fail_0;
7546
0
    }
7547
0
    if (!argvlist[0][0]) {
7548
0
        PyErr_SetString(PyExc_ValueError,
7549
0
            "execve: argv first element cannot be empty");
7550
0
        goto fail_0;
7551
0
    }
7552
7553
0
    envlist = parse_envlist(env, &envc);
7554
0
    if (envlist == NULL)
7555
0
        goto fail_0;
7556
7557
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7558
0
        goto fail_1;
7559
0
    }
7560
7561
0
    _Py_BEGIN_SUPPRESS_IPH
7562
0
#ifdef HAVE_FEXECVE
7563
0
    if (path->fd > -1)
7564
0
        fexecve(path->fd, argvlist, envlist);
7565
0
    else
7566
0
#endif
7567
#ifdef HAVE_WEXECV
7568
        _wexecve(path->wide, argvlist, envlist);
7569
#else
7570
0
        execve(path->narrow, argvlist, envlist);
7571
0
#endif
7572
0
    _Py_END_SUPPRESS_IPH
7573
7574
    /* If we get here it's definitely an error */
7575
7576
0
    posix_path_error(path);
7577
0
  fail_1:
7578
0
    free_string_array(envlist, envc);
7579
0
  fail_0:
7580
0
    if (argvlist)
7581
0
        free_string_array(argvlist, argc);
7582
0
    return NULL;
7583
0
}
7584
7585
#endif /* HAVE_EXECV */
7586
7587
#ifdef HAVE_POSIX_SPAWN
7588
7589
enum posix_spawn_file_actions_identifier {
7590
    POSIX_SPAWN_OPEN,
7591
    POSIX_SPAWN_CLOSE,
7592
    POSIX_SPAWN_DUP2
7593
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7594
    ,POSIX_SPAWN_CLOSEFROM
7595
#endif
7596
};
7597
7598
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7599
static int
7600
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7601
#endif
7602
7603
static int
7604
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7605
                        int resetids, int setsid, PyObject *setsigmask,
7606
                        PyObject *setsigdef, PyObject *scheduler,
7607
                        posix_spawnattr_t *attrp)
7608
0
{
7609
0
    long all_flags = 0;
7610
7611
0
    errno = posix_spawnattr_init(attrp);
7612
0
    if (errno) {
7613
0
        posix_error();
7614
0
        return -1;
7615
0
    }
7616
7617
0
    if (setpgroup) {
7618
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7619
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7620
0
            goto fail;
7621
0
        }
7622
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7623
0
        if (errno) {
7624
0
            posix_error();
7625
0
            goto fail;
7626
0
        }
7627
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7628
0
    }
7629
7630
0
    if (resetids) {
7631
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7632
0
    }
7633
7634
0
    if (setsid) {
7635
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7636
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7637
#endif
7638
0
#ifdef POSIX_SPAWN_SETSID
7639
0
        all_flags |= POSIX_SPAWN_SETSID;
7640
#elif defined(POSIX_SPAWN_SETSID_NP)
7641
        all_flags |= POSIX_SPAWN_SETSID_NP;
7642
#else
7643
        argument_unavailable_error(func_name, "setsid");
7644
        return -1;
7645
#endif
7646
7647
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7648
        } else {
7649
            argument_unavailable_error(func_name, "setsid");
7650
            return -1;
7651
        }
7652
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7653
7654
0
    }
7655
7656
0
#ifdef HAVE_SIGSET_T
7657
0
   if (setsigmask) {
7658
0
        sigset_t set;
7659
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7660
0
            goto fail;
7661
0
        }
7662
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7663
0
        if (errno) {
7664
0
            posix_error();
7665
0
            goto fail;
7666
0
        }
7667
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7668
0
    }
7669
7670
0
    if (setsigdef) {
7671
0
        sigset_t set;
7672
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7673
0
            goto fail;
7674
0
        }
7675
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7676
0
        if (errno) {
7677
0
            posix_error();
7678
0
            goto fail;
7679
0
        }
7680
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7681
0
    }
7682
#else
7683
    if (setsigmask || setsigdef) {
7684
        PyErr_SetString(PyExc_NotImplementedError,
7685
                        "sigset is not supported on this platform");
7686
        goto fail;
7687
    }
7688
#endif
7689
7690
0
    if (scheduler) {
7691
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7692
0
        PyObject *py_schedpolicy;
7693
0
        PyObject *schedparam_obj;
7694
0
        struct sched_param schedparam;
7695
7696
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7697
0
                        ";A scheduler tuple must have two elements",
7698
0
                        &py_schedpolicy, &schedparam_obj)) {
7699
0
            goto fail;
7700
0
        }
7701
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7702
0
            goto fail;
7703
0
        }
7704
0
        if (py_schedpolicy != Py_None) {
7705
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7706
7707
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7708
0
                goto fail;
7709
0
            }
7710
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7711
0
            if (errno) {
7712
0
                posix_error();
7713
0
                goto fail;
7714
0
            }
7715
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7716
0
        }
7717
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7718
0
        if (errno) {
7719
0
            posix_error();
7720
0
            goto fail;
7721
0
        }
7722
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7723
#else
7724
        PyErr_SetString(PyExc_NotImplementedError,
7725
                "The scheduler option is not supported in this system.");
7726
        goto fail;
7727
#endif
7728
0
    }
7729
7730
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7731
0
    if (errno) {
7732
0
        posix_error();
7733
0
        goto fail;
7734
0
    }
7735
7736
0
    return 0;
7737
7738
0
fail:
7739
0
    (void)posix_spawnattr_destroy(attrp);
7740
0
    return -1;
7741
0
}
7742
7743
static int
7744
parse_file_actions(PyObject *file_actions,
7745
                   posix_spawn_file_actions_t *file_actionsp,
7746
                   PyObject *temp_buffer)
7747
0
{
7748
0
    PyObject *seq;
7749
0
    PyObject *file_action = NULL;
7750
0
    PyObject *tag_obj;
7751
7752
0
    seq = PySequence_Fast(file_actions,
7753
0
                          "file_actions must be a sequence or None");
7754
0
    if (seq == NULL) {
7755
0
        return -1;
7756
0
    }
7757
7758
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7759
0
    if (errno) {
7760
0
        posix_error();
7761
0
        Py_DECREF(seq);
7762
0
        return -1;
7763
0
    }
7764
7765
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7766
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7767
0
        Py_INCREF(file_action);
7768
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7769
0
            PyErr_SetString(PyExc_TypeError,
7770
0
                "Each file_actions element must be a non-empty tuple");
7771
0
            goto fail;
7772
0
        }
7773
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7774
0
        if (tag == -1 && PyErr_Occurred()) {
7775
0
            goto fail;
7776
0
        }
7777
7778
        /* Populate the file_actions object */
7779
0
        switch (tag) {
7780
0
            case POSIX_SPAWN_OPEN: {
7781
0
                int fd, oflag;
7782
0
                PyObject *path;
7783
0
                unsigned long mode;
7784
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7785
0
                        ";A open file_action tuple must have 5 elements",
7786
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7787
0
                        &oflag, &mode))
7788
0
                {
7789
0
                    goto fail;
7790
0
                }
7791
0
                if (PyList_Append(temp_buffer, path)) {
7792
0
                    Py_DECREF(path);
7793
0
                    goto fail;
7794
0
                }
7795
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7796
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7797
0
                if (errno) {
7798
0
                    posix_error();
7799
0
                    Py_DECREF(path);
7800
0
                    goto fail;
7801
0
                }
7802
0
                Py_DECREF(path);
7803
0
                break;
7804
0
            }
7805
0
            case POSIX_SPAWN_CLOSE: {
7806
0
                int fd;
7807
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7808
0
                        ";A close file_action tuple must have 2 elements",
7809
0
                        &tag_obj, &fd))
7810
0
                {
7811
0
                    goto fail;
7812
0
                }
7813
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7814
0
                if (errno) {
7815
0
                    posix_error();
7816
0
                    goto fail;
7817
0
                }
7818
0
                break;
7819
0
            }
7820
0
            case POSIX_SPAWN_DUP2: {
7821
0
                int fd1, fd2;
7822
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7823
0
                        ";A dup2 file_action tuple must have 3 elements",
7824
0
                        &tag_obj, &fd1, &fd2))
7825
0
                {
7826
0
                    goto fail;
7827
0
                }
7828
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7829
0
                                                         fd1, fd2);
7830
0
                if (errno) {
7831
0
                    posix_error();
7832
0
                    goto fail;
7833
0
                }
7834
0
                break;
7835
0
            }
7836
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7837
            case POSIX_SPAWN_CLOSEFROM: {
7838
                int fd;
7839
                if (!PyArg_ParseTuple(file_action, "Oi"
7840
                        ";A closefrom file_action tuple must have 2 elements",
7841
                        &tag_obj, &fd))
7842
                {
7843
                    goto fail;
7844
                }
7845
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7846
                                                                 fd);
7847
                if (errno) {
7848
                    posix_error();
7849
                    goto fail;
7850
                }
7851
                break;
7852
            }
7853
#endif
7854
0
            default: {
7855
0
                PyErr_SetString(PyExc_TypeError,
7856
0
                                "Unknown file_actions identifier");
7857
0
                goto fail;
7858
0
            }
7859
0
        }
7860
0
        Py_DECREF(file_action);
7861
0
    }
7862
7863
0
    Py_DECREF(seq);
7864
0
    return 0;
7865
7866
0
fail:
7867
0
    Py_DECREF(seq);
7868
0
    Py_DECREF(file_action);
7869
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7870
0
    return -1;
7871
0
}
7872
7873
7874
static PyObject *
7875
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7876
               PyObject *env, PyObject *file_actions,
7877
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7878
               PyObject *setsigdef, PyObject *scheduler)
7879
0
{
7880
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7881
0
    EXECV_CHAR **argvlist = NULL;
7882
0
    EXECV_CHAR **envlist = NULL;
7883
0
    posix_spawn_file_actions_t file_actions_buf;
7884
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7885
0
    posix_spawnattr_t attr;
7886
0
    posix_spawnattr_t *attrp = NULL;
7887
0
    Py_ssize_t argc, envc;
7888
0
    PyObject *result = NULL;
7889
0
    PyObject *temp_buffer = NULL;
7890
0
    pid_t pid;
7891
0
    int err_code;
7892
7893
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7894
       argv is a list or tuple of strings and env is a dictionary
7895
       like posix.environ. */
7896
7897
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7898
0
        PyErr_Format(PyExc_TypeError,
7899
0
                     "%s: argv must be a tuple or list", func_name);
7900
0
        goto exit;
7901
0
    }
7902
0
    argc = PySequence_Size(argv);
7903
0
    if (argc < 1) {
7904
0
        PyErr_Format(PyExc_ValueError,
7905
0
                     "%s: argv must not be empty", func_name);
7906
0
        return NULL;
7907
0
    }
7908
7909
0
    if (!PyMapping_Check(env) && env != Py_None) {
7910
0
        PyErr_Format(PyExc_TypeError,
7911
0
                     "%s: environment must be a mapping object or None", func_name);
7912
0
        goto exit;
7913
0
    }
7914
7915
0
    argvlist = parse_arglist(argv, &argc);
7916
0
    if (argvlist == NULL) {
7917
0
        goto exit;
7918
0
    }
7919
0
    if (!argvlist[0][0]) {
7920
0
        PyErr_Format(PyExc_ValueError,
7921
0
                     "%s: argv first element cannot be empty", func_name);
7922
0
        goto exit;
7923
0
    }
7924
7925
#ifdef USE_DARWIN_NS_GET_ENVIRON
7926
    // There is no environ global in this situation.
7927
    char **environ = NULL;
7928
#endif
7929
7930
0
    if (env == Py_None) {
7931
#ifdef USE_DARWIN_NS_GET_ENVIRON
7932
        environ = *_NSGetEnviron();
7933
#endif
7934
0
        envlist = environ;
7935
0
    } else {
7936
0
        envlist = parse_envlist(env, &envc);
7937
0
        if (envlist == NULL) {
7938
0
            goto exit;
7939
0
        }
7940
0
    }
7941
7942
0
    if (file_actions != NULL && file_actions != Py_None) {
7943
        /* There is a bug in old versions of glibc that makes some of the
7944
         * helper functions for manipulating file actions not copy the provided
7945
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7946
         * copy the value of path for some old versions of glibc (<2.20).
7947
         * The use of temp_buffer here is a workaround that keeps the
7948
         * python objects that own the buffers alive until posix_spawn gets called.
7949
         * Check https://bugs.python.org/issue33630 and
7950
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7951
0
        temp_buffer = PyList_New(0);
7952
0
        if (!temp_buffer) {
7953
0
            goto exit;
7954
0
        }
7955
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7956
0
            goto exit;
7957
0
        }
7958
0
        file_actionsp = &file_actions_buf;
7959
0
    }
7960
7961
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7962
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7963
0
        goto exit;
7964
0
    }
7965
0
    attrp = &attr;
7966
7967
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7968
0
        goto exit;
7969
0
    }
7970
7971
0
    _Py_BEGIN_SUPPRESS_IPH
7972
0
#ifdef HAVE_POSIX_SPAWNP
7973
0
    if (use_posix_spawnp) {
7974
0
        err_code = posix_spawnp(&pid, path->narrow,
7975
0
                                file_actionsp, attrp, argvlist, envlist);
7976
0
    }
7977
0
    else
7978
0
#endif /* HAVE_POSIX_SPAWNP */
7979
0
    {
7980
0
        err_code = posix_spawn(&pid, path->narrow,
7981
0
                               file_actionsp, attrp, argvlist, envlist);
7982
0
    }
7983
0
    _Py_END_SUPPRESS_IPH
7984
7985
0
    if (err_code) {
7986
0
        errno = err_code;
7987
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
7988
0
        goto exit;
7989
0
    }
7990
#ifdef _Py_MEMORY_SANITIZER
7991
    __msan_unpoison(&pid, sizeof(pid));
7992
#endif
7993
0
    result = PyLong_FromPid(pid);
7994
7995
0
exit:
7996
0
    if (file_actionsp) {
7997
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
7998
0
    }
7999
0
    if (attrp) {
8000
0
        (void)posix_spawnattr_destroy(attrp);
8001
0
    }
8002
0
    if (envlist && envlist != environ) {
8003
0
        free_string_array(envlist, envc);
8004
0
    }
8005
0
    if (argvlist) {
8006
0
        free_string_array(argvlist, argc);
8007
0
    }
8008
0
    Py_XDECREF(temp_buffer);
8009
0
    return result;
8010
0
}
8011
8012
8013
/*[clinic input]
8014
8015
os.posix_spawn
8016
    path: path_t
8017
        Path of executable file.
8018
    argv: object
8019
        Tuple or list of strings.
8020
    env: object
8021
        Dictionary of strings mapping to strings.
8022
    /
8023
    *
8024
    file_actions: object(c_default='NULL') = ()
8025
        A sequence of file action tuples.
8026
    setpgroup: object = NULL
8027
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8028
    resetids: bool = False
8029
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8030
    setsid: bool = False
8031
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8032
    setsigmask: object(c_default='NULL') = ()
8033
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8034
    setsigdef: object(c_default='NULL') = ()
8035
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8036
    scheduler: object = NULL
8037
        A tuple with the scheduler policy (optional) and parameters.
8038
8039
Execute the program specified by path in a new process.
8040
[clinic start generated code]*/
8041
8042
static PyObject *
8043
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8044
                    PyObject *env, PyObject *file_actions,
8045
                    PyObject *setpgroup, int resetids, int setsid,
8046
                    PyObject *setsigmask, PyObject *setsigdef,
8047
                    PyObject *scheduler)
8048
/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
8049
0
{
8050
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8051
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8052
0
                          scheduler);
8053
0
}
8054
 #endif /* HAVE_POSIX_SPAWN */
8055
8056
8057
8058
#ifdef HAVE_POSIX_SPAWNP
8059
/*[clinic input]
8060
8061
os.posix_spawnp
8062
    path: path_t
8063
        Path of executable file.
8064
    argv: object
8065
        Tuple or list of strings.
8066
    env: object
8067
        Dictionary of strings mapping to strings.
8068
    /
8069
    *
8070
    file_actions: object(c_default='NULL') = ()
8071
        A sequence of file action tuples.
8072
    setpgroup: object = NULL
8073
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8074
    resetids: bool = False
8075
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8076
    setsid: bool = False
8077
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8078
    setsigmask: object(c_default='NULL') = ()
8079
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8080
    setsigdef: object(c_default='NULL') = ()
8081
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8082
    scheduler: object = NULL
8083
        A tuple with the scheduler policy (optional) and parameters.
8084
8085
Execute the program specified by path in a new process.
8086
[clinic start generated code]*/
8087
8088
static PyObject *
8089
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8090
                     PyObject *env, PyObject *file_actions,
8091
                     PyObject *setpgroup, int resetids, int setsid,
8092
                     PyObject *setsigmask, PyObject *setsigdef,
8093
                     PyObject *scheduler)
8094
/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
8095
0
{
8096
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8097
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8098
0
                          scheduler);
8099
0
}
8100
#endif /* HAVE_POSIX_SPAWNP */
8101
8102
#ifdef HAVE_RTPSPAWN
8103
static intptr_t
8104
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8105
               const char  *envp[])
8106
{
8107
     RTP_ID rtpid;
8108
     int status;
8109
     pid_t res;
8110
     int async_err = 0;
8111
8112
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8113
        uStackSize=0 cannot be used, the default stack size is too small for
8114
        Python. */
8115
     if (envp) {
8116
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8117
                          100, 0x1000000, 0, VX_FP_TASK);
8118
     }
8119
     else {
8120
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8121
                          100, 0x1000000, 0, VX_FP_TASK);
8122
     }
8123
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8124
         do {
8125
             res = waitpid((pid_t)rtpid, &status, 0);
8126
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8127
8128
         if (res < 0)
8129
             return RTP_ID_ERROR;
8130
         return ((intptr_t)status);
8131
     }
8132
     return ((intptr_t)rtpid);
8133
}
8134
#endif
8135
8136
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8137
/*[clinic input]
8138
os.spawnv
8139
8140
    mode: int
8141
        Mode of process creation.
8142
    path: path_t
8143
        Path of executable file.
8144
    argv: object
8145
        Tuple or list of strings.
8146
    /
8147
8148
Execute the program specified by path in a new process.
8149
[clinic start generated code]*/
8150
8151
static PyObject *
8152
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8153
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8154
{
8155
    EXECV_CHAR **argvlist;
8156
    int i;
8157
    Py_ssize_t argc;
8158
    intptr_t spawnval;
8159
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8160
8161
    /* spawnv has three arguments: (mode, path, argv), where
8162
       argv is a list or tuple of strings. */
8163
8164
    if (PyList_Check(argv)) {
8165
        argc = PyList_Size(argv);
8166
        getitem = PyList_GetItem;
8167
    }
8168
    else if (PyTuple_Check(argv)) {
8169
        argc = PyTuple_Size(argv);
8170
        getitem = PyTuple_GetItem;
8171
    }
8172
    else {
8173
        PyErr_SetString(PyExc_TypeError,
8174
                        "spawnv() arg 2 must be a tuple or list");
8175
        return NULL;
8176
    }
8177
    if (argc == 0) {
8178
        PyErr_SetString(PyExc_ValueError,
8179
            "spawnv() arg 2 cannot be empty");
8180
        return NULL;
8181
    }
8182
8183
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8184
    if (argvlist == NULL) {
8185
        return PyErr_NoMemory();
8186
    }
8187
    for (i = 0; i < argc; i++) {
8188
        if (!fsconvert_strdup((*getitem)(argv, i),
8189
                              &argvlist[i])) {
8190
            free_string_array(argvlist, i);
8191
            PyErr_SetString(
8192
                PyExc_TypeError,
8193
                "spawnv() arg 2 must contain only strings");
8194
            return NULL;
8195
        }
8196
        if (i == 0 && !argvlist[0][0]) {
8197
            free_string_array(argvlist, i + 1);
8198
            PyErr_SetString(
8199
                PyExc_ValueError,
8200
                "spawnv() arg 2 first element cannot be empty");
8201
            return NULL;
8202
        }
8203
    }
8204
    argvlist[argc] = NULL;
8205
8206
#if !defined(HAVE_RTPSPAWN)
8207
    if (mode == _OLD_P_OVERLAY)
8208
        mode = _P_OVERLAY;
8209
#endif
8210
8211
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8212
                    Py_None) < 0) {
8213
        free_string_array(argvlist, argc);
8214
        return NULL;
8215
    }
8216
8217
    Py_BEGIN_ALLOW_THREADS
8218
    _Py_BEGIN_SUPPRESS_IPH
8219
#ifdef HAVE_WSPAWNV
8220
    spawnval = _wspawnv(mode, path->wide, argvlist);
8221
#elif defined(HAVE_RTPSPAWN)
8222
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8223
#else
8224
    spawnval = _spawnv(mode, path->narrow, argvlist);
8225
#endif
8226
    _Py_END_SUPPRESS_IPH
8227
    Py_END_ALLOW_THREADS
8228
8229
    int saved_errno = errno;
8230
    free_string_array(argvlist, argc);
8231
8232
    if (spawnval == -1) {
8233
        errno = saved_errno;
8234
        posix_error();
8235
        return NULL;
8236
    }
8237
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8238
}
8239
8240
/*[clinic input]
8241
os.spawnve
8242
8243
    mode: int
8244
        Mode of process creation.
8245
    path: path_t
8246
        Path of executable file.
8247
    argv: object
8248
        Tuple or list of strings.
8249
    env: object
8250
        Dictionary of strings mapping to strings.
8251
    /
8252
8253
Execute the program specified by path in a new process.
8254
[clinic start generated code]*/
8255
8256
static PyObject *
8257
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8258
                PyObject *env)
8259
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8260
{
8261
    EXECV_CHAR **argvlist;
8262
    EXECV_CHAR **envlist;
8263
    PyObject *res = NULL;
8264
    Py_ssize_t argc, i, envc;
8265
    intptr_t spawnval;
8266
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8267
    Py_ssize_t lastarg = 0;
8268
8269
    /* spawnve has four arguments: (mode, path, argv, env), where
8270
       argv is a list or tuple of strings and env is a dictionary
8271
       like posix.environ. */
8272
8273
    if (PyList_Check(argv)) {
8274
        argc = PyList_Size(argv);
8275
        getitem = PyList_GetItem;
8276
    }
8277
    else if (PyTuple_Check(argv)) {
8278
        argc = PyTuple_Size(argv);
8279
        getitem = PyTuple_GetItem;
8280
    }
8281
    else {
8282
        PyErr_SetString(PyExc_TypeError,
8283
                        "spawnve() arg 2 must be a tuple or list");
8284
        goto fail_0;
8285
    }
8286
    if (argc == 0) {
8287
        PyErr_SetString(PyExc_ValueError,
8288
            "spawnve() arg 2 cannot be empty");
8289
        goto fail_0;
8290
    }
8291
    if (!PyMapping_Check(env)) {
8292
        PyErr_SetString(PyExc_TypeError,
8293
                        "spawnve() arg 3 must be a mapping object");
8294
        goto fail_0;
8295
    }
8296
8297
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8298
    if (argvlist == NULL) {
8299
        PyErr_NoMemory();
8300
        goto fail_0;
8301
    }
8302
    for (i = 0; i < argc; i++) {
8303
        if (!fsconvert_strdup((*getitem)(argv, i),
8304
                              &argvlist[i]))
8305
        {
8306
            lastarg = i;
8307
            goto fail_1;
8308
        }
8309
        if (i == 0 && !argvlist[0][0]) {
8310
            lastarg = i + 1;
8311
            PyErr_SetString(
8312
                PyExc_ValueError,
8313
                "spawnv() arg 2 first element cannot be empty");
8314
            goto fail_1;
8315
        }
8316
    }
8317
    lastarg = argc;
8318
    argvlist[argc] = NULL;
8319
8320
    envlist = parse_envlist(env, &envc);
8321
    if (envlist == NULL)
8322
        goto fail_1;
8323
8324
#if !defined(HAVE_RTPSPAWN)
8325
    if (mode == _OLD_P_OVERLAY)
8326
        mode = _P_OVERLAY;
8327
#endif
8328
8329
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8330
        goto fail_2;
8331
    }
8332
8333
    Py_BEGIN_ALLOW_THREADS
8334
    _Py_BEGIN_SUPPRESS_IPH
8335
#ifdef HAVE_WSPAWNV
8336
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8337
#elif defined(HAVE_RTPSPAWN)
8338
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8339
                           (const char **)envlist);
8340
#else
8341
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8342
#endif
8343
    _Py_END_SUPPRESS_IPH
8344
    Py_END_ALLOW_THREADS
8345
8346
    if (spawnval == -1)
8347
        (void) posix_error();
8348
    else
8349
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8350
8351
  fail_2:
8352
    while (--envc >= 0) {
8353
        PyMem_Free(envlist[envc]);
8354
    }
8355
    PyMem_Free(envlist);
8356
  fail_1:
8357
    free_string_array(argvlist, lastarg);
8358
  fail_0:
8359
    return res;
8360
}
8361
8362
#endif /* HAVE_SPAWNV */
8363
8364
#ifdef HAVE_FORK
8365
8366
/* Helper function to validate arguments.
8367
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8368
   If obj is non-NULL it must be callable.  */
8369
static int
8370
check_null_or_callable(PyObject *obj, const char* obj_name)
8371
9
{
8372
9
    if (obj && !PyCallable_Check(obj)) {
8373
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8374
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8375
0
        return -1;
8376
0
    }
8377
9
    return 0;
8378
9
}
8379
8380
/*[clinic input]
8381
os.register_at_fork
8382
8383
    *
8384
    before: object=NULL
8385
        A callable to be called in the parent before the fork() syscall.
8386
    after_in_child: object=NULL
8387
        A callable to be called in the child after fork().
8388
    after_in_parent: object=NULL
8389
        A callable to be called in the parent after fork().
8390
8391
Register callables to be called when forking a new process.
8392
8393
'before' callbacks are called in reverse order.
8394
'after_in_child' and 'after_in_parent' callbacks are called in order.
8395
8396
[clinic start generated code]*/
8397
8398
static PyObject *
8399
os_register_at_fork_impl(PyObject *module, PyObject *before,
8400
                         PyObject *after_in_child, PyObject *after_in_parent)
8401
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8402
3
{
8403
3
    PyInterpreterState *interp;
8404
8405
3
    if (!before && !after_in_child && !after_in_parent) {
8406
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8407
0
        return NULL;
8408
0
    }
8409
3
    if (check_null_or_callable(before, "before") ||
8410
3
        check_null_or_callable(after_in_child, "after_in_child") ||
8411
3
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8412
0
        return NULL;
8413
0
    }
8414
3
    interp = _PyInterpreterState_GET();
8415
8416
3
    if (register_at_forker(&interp->before_forkers, before)) {
8417
0
        return NULL;
8418
0
    }
8419
3
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8420
0
        return NULL;
8421
0
    }
8422
3
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8423
0
        return NULL;
8424
0
    }
8425
3
    Py_RETURN_NONE;
8426
3
}
8427
#endif /* HAVE_FORK */
8428
8429
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8430
// Common code to raise a warning if we detect there is more than one thread
8431
// running in the process. Best effort, silent if unable to count threads.
8432
// Constraint: Quick. Never overcounts. Never leaves an error set.
8433
//
8434
// This should only be called from the parent process after
8435
// PyOS_AfterFork_Parent().
8436
static int
8437
warn_about_fork_with_threads(const char* name)
8438
0
{
8439
    // It's not safe to issue the warning while the world is stopped, because
8440
    // other threads might be holding locks that we need, which would deadlock.
8441
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8442
8443
    // TODO: Consider making an `os` module API to return the current number
8444
    // of threads in the process. That'd presumably use this platform code but
8445
    // raise an error rather than using the inaccurate fallback.
8446
0
    Py_ssize_t num_python_threads = 0;
8447
#if defined(__APPLE__) && defined(HAVE_GETPID)
8448
    mach_port_t macos_self = mach_task_self();
8449
    mach_port_t macos_task;
8450
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8451
        thread_array_t macos_threads;
8452
        mach_msg_type_number_t macos_n_threads;
8453
        if (task_threads(macos_task, &macos_threads,
8454
                         &macos_n_threads) == KERN_SUCCESS) {
8455
            num_python_threads = macos_n_threads;
8456
        }
8457
    }
8458
#elif defined(__linux__)
8459
    // Linux /proc/self/stat 20th field is the number of threads.
8460
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8461
0
    if (proc_stat) {
8462
0
        size_t n;
8463
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8464
        // observed on the author's workstation.
8465
0
        char stat_line[160];
8466
0
        n = fread(&stat_line, 1, 159, proc_stat);
8467
0
        stat_line[n] = '\0';
8468
0
        fclose(proc_stat);
8469
8470
0
        char *saveptr = NULL;
8471
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8472
0
        unsigned int idx;
8473
0
        for (idx = 19; idx && field; --idx) {
8474
0
            field = strtok_r(NULL, " ", &saveptr);
8475
0
        }
8476
0
        if (idx == 0 && field) {  // found the 20th field
8477
0
            num_python_threads = atoi(field);  // 0 on error
8478
0
        }
8479
0
    }
8480
0
#endif
8481
0
    if (num_python_threads <= 0) {
8482
        // Fall back to just the number our threading module knows about.
8483
        // An incomplete view of the world, but better than nothing.
8484
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8485
0
        if (!threading) {
8486
0
            PyErr_Clear();
8487
0
            return 0;
8488
0
        }
8489
0
        PyObject *threading_active =
8490
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8491
0
        if (!threading_active) {
8492
0
            PyErr_Clear();
8493
0
            Py_DECREF(threading);
8494
0
            return 0;
8495
0
        }
8496
0
        PyObject *threading_limbo =
8497
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8498
0
        if (!threading_limbo) {
8499
0
            PyErr_Clear();
8500
0
            Py_DECREF(threading);
8501
0
            Py_DECREF(threading_active);
8502
0
            return 0;
8503
0
        }
8504
0
        Py_DECREF(threading);
8505
        // Duplicating what threading.active_count() does but without holding
8506
        // threading._active_limbo_lock so our count could be inaccurate if
8507
        // these dicts are mid-update from another thread.  Not a big deal.
8508
        // Worst case if someone replaced threading._active or threading._limbo
8509
        // with non-dicts, we get -1 from *Length() below and undercount.
8510
        // Nobody should, but we're best effort so we clear errors and move on.
8511
0
        num_python_threads = (PyMapping_Length(threading_active)
8512
0
                              + PyMapping_Length(threading_limbo));
8513
0
        PyErr_Clear();
8514
0
        Py_DECREF(threading_active);
8515
0
        Py_DECREF(threading_limbo);
8516
0
    }
8517
0
    if (num_python_threads > 1) {
8518
0
        return PyErr_WarnFormat(
8519
0
                PyExc_DeprecationWarning, 1,
8520
0
#ifdef HAVE_GETPID
8521
0
                "This process (pid=%d) is multi-threaded, "
8522
#else
8523
                "This process is multi-threaded, "
8524
#endif
8525
0
                "use of %s() may lead to deadlocks in the child.",
8526
0
#ifdef HAVE_GETPID
8527
0
                getpid(),
8528
0
#endif
8529
0
                name);
8530
0
    }
8531
0
    return 0;
8532
0
}
8533
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8534
8535
#ifdef HAVE_FORK1
8536
/*[clinic input]
8537
os.fork1
8538
8539
Fork a child process with a single multiplexed (i.e., not bound) thread.
8540
8541
Return 0 to child process and PID of child to parent process.
8542
[clinic start generated code]*/
8543
8544
static PyObject *
8545
os_fork1_impl(PyObject *module)
8546
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8547
{
8548
    pid_t pid;
8549
8550
    PyInterpreterState *interp = _PyInterpreterState_GET();
8551
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8552
        PyErr_SetString(PyExc_PythonFinalizationError,
8553
                        "can't fork at interpreter shutdown");
8554
        return NULL;
8555
    }
8556
    if (!_Py_IsMainInterpreter(interp)) {
8557
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8558
        return NULL;
8559
    }
8560
    PyOS_BeforeFork();
8561
    pid = fork1();
8562
    int saved_errno = errno;
8563
    if (pid == 0) {
8564
        /* child: this clobbers and resets the import lock. */
8565
        PyOS_AfterFork_Child();
8566
    } else {
8567
        /* parent: release the import lock. */
8568
        PyOS_AfterFork_Parent();
8569
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8570
        if (warn_about_fork_with_threads("fork1") < 0) {
8571
            return NULL;
8572
        }
8573
    }
8574
    if (pid == -1) {
8575
        errno = saved_errno;
8576
        return posix_error();
8577
    }
8578
    return PyLong_FromPid(pid);
8579
}
8580
#endif /* HAVE_FORK1 */
8581
8582
8583
#ifdef HAVE_FORK
8584
/*[clinic input]
8585
os.fork
8586
8587
Fork a child process.
8588
8589
Return 0 to child process and PID of child to parent process.
8590
[clinic start generated code]*/
8591
8592
static PyObject *
8593
os_fork_impl(PyObject *module)
8594
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8595
0
{
8596
0
    pid_t pid;
8597
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8598
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8599
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8600
0
                        "can't fork at interpreter shutdown");
8601
0
        return NULL;
8602
0
    }
8603
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8604
0
        PyErr_SetString(PyExc_RuntimeError,
8605
0
                        "fork not supported for isolated subinterpreters");
8606
0
        return NULL;
8607
0
    }
8608
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8609
0
        return NULL;
8610
0
    }
8611
0
    PyOS_BeforeFork();
8612
0
    pid = fork();
8613
0
    int saved_errno = errno;
8614
0
    if (pid == 0) {
8615
        /* child: this clobbers and resets the import lock. */
8616
0
        PyOS_AfterFork_Child();
8617
0
    } else {
8618
        /* parent: release the import lock. */
8619
0
        PyOS_AfterFork_Parent();
8620
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8621
0
        if (warn_about_fork_with_threads("fork") < 0)
8622
0
            return NULL;
8623
0
    }
8624
0
    if (pid == -1) {
8625
0
        errno = saved_errno;
8626
0
        return posix_error();
8627
0
    }
8628
0
    return PyLong_FromPid(pid);
8629
0
}
8630
#endif /* HAVE_FORK */
8631
8632
8633
#ifdef HAVE_SCHED_H
8634
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8635
/*[clinic input]
8636
os.sched_get_priority_max
8637
8638
    policy: int
8639
8640
Get the maximum scheduling priority for policy.
8641
[clinic start generated code]*/
8642
8643
static PyObject *
8644
os_sched_get_priority_max_impl(PyObject *module, int policy)
8645
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8646
0
{
8647
    /* make sure that errno is cleared before the call */
8648
0
    errno = 0;
8649
0
    int max = sched_get_priority_max(policy);
8650
0
    if (max == -1 && errno)
8651
0
        return posix_error();
8652
0
    return PyLong_FromLong(max);
8653
0
}
8654
8655
8656
/*[clinic input]
8657
os.sched_get_priority_min
8658
8659
    policy: int
8660
8661
Get the minimum scheduling priority for policy.
8662
[clinic start generated code]*/
8663
8664
static PyObject *
8665
os_sched_get_priority_min_impl(PyObject *module, int policy)
8666
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8667
0
{
8668
    /* make sure that errno is cleared before the call */
8669
0
    errno = 0;
8670
0
    int min = sched_get_priority_min(policy);
8671
0
    if (min == -1 && errno)
8672
0
        return posix_error();
8673
0
    return PyLong_FromLong(min);
8674
0
}
8675
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8676
8677
8678
#ifdef HAVE_SCHED_SETSCHEDULER
8679
/*[clinic input]
8680
os.sched_getscheduler
8681
    pid: pid_t
8682
    /
8683
8684
Get the scheduling policy for the process identified by pid.
8685
8686
Passing 0 for pid returns the scheduling policy for the calling process.
8687
[clinic start generated code]*/
8688
8689
static PyObject *
8690
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8691
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8692
0
{
8693
0
    int policy;
8694
8695
0
    policy = sched_getscheduler(pid);
8696
0
    if (policy < 0)
8697
0
        return posix_error();
8698
0
    return PyLong_FromLong(policy);
8699
0
}
8700
#endif /* HAVE_SCHED_SETSCHEDULER */
8701
8702
8703
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8704
/*[clinic input]
8705
class os.sched_param "PyObject *" "SchedParamType"
8706
8707
@classmethod
8708
os.sched_param.__new__
8709
8710
    sched_priority: object
8711
        A scheduling parameter.
8712
8713
Currently has only one field: sched_priority
8714
[clinic start generated code]*/
8715
8716
static PyObject *
8717
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8718
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8719
0
{
8720
0
    PyObject *res;
8721
8722
0
    res = PyStructSequence_New(type);
8723
0
    if (!res)
8724
0
        return NULL;
8725
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8726
0
    return res;
8727
0
}
8728
8729
static PyObject *
8730
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8731
0
{
8732
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8733
0
}
8734
8735
static PyMethodDef os_sched_param_reduce_method = {
8736
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8737
};
8738
8739
PyDoc_VAR(os_sched_param__doc__);
8740
8741
static PyStructSequence_Field sched_param_fields[] = {
8742
    {"sched_priority", "the scheduling priority"},
8743
    {0}
8744
};
8745
8746
static PyStructSequence_Desc sched_param_desc = {
8747
    MODNAME ".sched_param", /* name */
8748
    os_sched_param__doc__, /* doc */
8749
    sched_param_fields,
8750
    1
8751
};
8752
8753
static int
8754
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8755
0
{
8756
0
    long priority;
8757
8758
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8759
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8760
0
        return 0;
8761
0
    }
8762
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8763
0
    if (priority == -1 && PyErr_Occurred())
8764
0
        return 0;
8765
0
    if (priority > INT_MAX || priority < INT_MIN) {
8766
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8767
0
        return 0;
8768
0
    }
8769
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8770
0
    return 1;
8771
0
}
8772
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8773
8774
8775
#ifdef HAVE_SCHED_SETSCHEDULER
8776
/*[clinic input]
8777
os.sched_setscheduler
8778
8779
    pid: pid_t
8780
    policy: int
8781
    param as param_obj: object
8782
    /
8783
8784
Set the scheduling policy for the process identified by pid.
8785
8786
If pid is 0, the calling process is changed.
8787
param is an instance of sched_param.
8788
[clinic start generated code]*/
8789
8790
static PyObject *
8791
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8792
                           PyObject *param_obj)
8793
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8794
0
{
8795
0
    struct sched_param param;
8796
0
    if (!convert_sched_param(module, param_obj, &param)) {
8797
0
        return NULL;
8798
0
    }
8799
8800
    /*
8801
    ** sched_setscheduler() returns 0 in Linux, but the previous
8802
    ** scheduling policy under Solaris/Illumos, and others.
8803
    ** On error, -1 is returned in all Operating Systems.
8804
    */
8805
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8806
0
        return posix_error();
8807
0
    Py_RETURN_NONE;
8808
0
}
8809
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8810
8811
8812
#ifdef HAVE_SCHED_SETPARAM
8813
/*[clinic input]
8814
os.sched_getparam
8815
    pid: pid_t
8816
    /
8817
8818
Returns scheduling parameters for the process identified by pid.
8819
8820
If pid is 0, returns parameters for the calling process.
8821
Return value is an instance of sched_param.
8822
[clinic start generated code]*/
8823
8824
static PyObject *
8825
os_sched_getparam_impl(PyObject *module, pid_t pid)
8826
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8827
0
{
8828
0
    struct sched_param param;
8829
0
    PyObject *result;
8830
0
    PyObject *priority;
8831
8832
0
    if (sched_getparam(pid, &param))
8833
0
        return posix_error();
8834
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8835
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8836
0
    if (!result)
8837
0
        return NULL;
8838
0
    priority = PyLong_FromLong(param.sched_priority);
8839
0
    if (!priority) {
8840
0
        Py_DECREF(result);
8841
0
        return NULL;
8842
0
    }
8843
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8844
0
    return result;
8845
0
}
8846
8847
8848
/*[clinic input]
8849
os.sched_setparam
8850
    pid: pid_t
8851
    param as param_obj: object
8852
    /
8853
8854
Set scheduling parameters for the process identified by pid.
8855
8856
If pid is 0, sets parameters for the calling process.
8857
param should be an instance of sched_param.
8858
[clinic start generated code]*/
8859
8860
static PyObject *
8861
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8862
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8863
0
{
8864
0
    struct sched_param param;
8865
0
    if (!convert_sched_param(module, param_obj, &param)) {
8866
0
        return NULL;
8867
0
    }
8868
8869
0
    if (sched_setparam(pid, &param))
8870
0
        return posix_error();
8871
0
    Py_RETURN_NONE;
8872
0
}
8873
#endif /* HAVE_SCHED_SETPARAM */
8874
8875
8876
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8877
/*[clinic input]
8878
@permit_long_summary
8879
os.sched_rr_get_interval -> double
8880
    pid: pid_t
8881
    /
8882
8883
Return the round-robin quantum for the process identified by pid, in seconds.
8884
8885
Value returned is a float.
8886
[clinic start generated code]*/
8887
8888
static double
8889
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8890
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8891
0
{
8892
0
    struct timespec interval;
8893
0
    if (sched_rr_get_interval(pid, &interval)) {
8894
0
        posix_error();
8895
0
        return -1.0;
8896
0
    }
8897
#ifdef _Py_MEMORY_SANITIZER
8898
    __msan_unpoison(&interval, sizeof(interval));
8899
#endif
8900
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8901
0
}
8902
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8903
8904
8905
/*[clinic input]
8906
os.sched_yield
8907
8908
Voluntarily relinquish the CPU.
8909
[clinic start generated code]*/
8910
8911
static PyObject *
8912
os_sched_yield_impl(PyObject *module)
8913
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8914
0
{
8915
0
    int result;
8916
0
    Py_BEGIN_ALLOW_THREADS
8917
0
    result = sched_yield();
8918
0
    Py_END_ALLOW_THREADS
8919
0
    if (result < 0) {
8920
0
        return posix_error();
8921
0
    }
8922
0
    Py_RETURN_NONE;
8923
0
}
8924
8925
#ifdef HAVE_SCHED_SETAFFINITY
8926
/* The minimum number of CPUs allocated in a cpu_set_t */
8927
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8928
8929
/*[clinic input]
8930
os.sched_setaffinity
8931
    pid: pid_t
8932
    mask : object
8933
    /
8934
8935
Set the CPU affinity of the process identified by pid to mask.
8936
8937
mask should be an iterable of integers identifying CPUs.
8938
[clinic start generated code]*/
8939
8940
static PyObject *
8941
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8942
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8943
0
{
8944
0
    int ncpus;
8945
0
    size_t setsize;
8946
0
    cpu_set_t *cpu_set = NULL;
8947
0
    PyObject *iterator = NULL, *item;
8948
8949
0
    iterator = PyObject_GetIter(mask);
8950
0
    if (iterator == NULL)
8951
0
        return NULL;
8952
8953
0
    ncpus = NCPUS_START;
8954
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8955
0
    cpu_set = CPU_ALLOC(ncpus);
8956
0
    if (cpu_set == NULL) {
8957
0
        PyErr_NoMemory();
8958
0
        goto error;
8959
0
    }
8960
0
    CPU_ZERO_S(setsize, cpu_set);
8961
8962
0
    while ((item = PyIter_Next(iterator))) {
8963
0
        long cpu;
8964
0
        if (!PyIndex_Check(item)) {
8965
0
            PyErr_Format(PyExc_TypeError,
8966
0
                        "expected an iterator of ints, "
8967
0
                        "but iterator yielded %R",
8968
0
                        Py_TYPE(item));
8969
0
            Py_DECREF(item);
8970
0
            goto error;
8971
0
        }
8972
0
        cpu = PyLong_AsLong(item);
8973
0
        Py_DECREF(item);
8974
0
        if (cpu < 0) {
8975
0
            if (!PyErr_Occurred())
8976
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
8977
0
            goto error;
8978
0
        }
8979
0
        if (cpu > INT_MAX - 1) {
8980
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
8981
0
            goto error;
8982
0
        }
8983
0
        if (cpu >= ncpus) {
8984
            /* Grow CPU mask to fit the CPU number */
8985
0
            int newncpus = ncpus;
8986
0
            cpu_set_t *newmask;
8987
0
            size_t newsetsize;
8988
0
            while (newncpus <= cpu) {
8989
0
                if (newncpus > INT_MAX / 2)
8990
0
                    newncpus = cpu + 1;
8991
0
                else
8992
0
                    newncpus = newncpus * 2;
8993
0
            }
8994
0
            newmask = CPU_ALLOC(newncpus);
8995
0
            if (newmask == NULL) {
8996
0
                PyErr_NoMemory();
8997
0
                goto error;
8998
0
            }
8999
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9000
0
            CPU_ZERO_S(newsetsize, newmask);
9001
0
            memcpy(newmask, cpu_set, setsize);
9002
0
            CPU_FREE(cpu_set);
9003
0
            setsize = newsetsize;
9004
0
            cpu_set = newmask;
9005
0
            ncpus = newncpus;
9006
0
        }
9007
0
        CPU_SET_S(cpu, setsize, cpu_set);
9008
0
    }
9009
0
    if (PyErr_Occurred()) {
9010
0
        goto error;
9011
0
    }
9012
0
    Py_CLEAR(iterator);
9013
9014
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9015
0
        posix_error();
9016
0
        goto error;
9017
0
    }
9018
0
    CPU_FREE(cpu_set);
9019
0
    Py_RETURN_NONE;
9020
9021
0
error:
9022
0
    if (cpu_set)
9023
0
        CPU_FREE(cpu_set);
9024
0
    Py_XDECREF(iterator);
9025
0
    return NULL;
9026
0
}
9027
9028
9029
/*[clinic input]
9030
@permit_long_summary
9031
os.sched_getaffinity
9032
    pid: pid_t
9033
    /
9034
9035
Return the affinity of the process identified by pid (or the current process if zero).
9036
9037
The affinity is returned as a set of CPU identifiers.
9038
[clinic start generated code]*/
9039
9040
static PyObject *
9041
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9042
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9043
0
{
9044
0
    int ncpus = NCPUS_START;
9045
0
    size_t setsize;
9046
0
    cpu_set_t *mask;
9047
9048
0
    while (1) {
9049
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9050
0
        mask = CPU_ALLOC(ncpus);
9051
0
        if (mask == NULL) {
9052
0
            return PyErr_NoMemory();
9053
0
        }
9054
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9055
0
            break;
9056
0
        }
9057
0
        CPU_FREE(mask);
9058
0
        if (errno != EINVAL) {
9059
0
            return posix_error();
9060
0
        }
9061
0
        if (ncpus > INT_MAX / 2) {
9062
0
            PyErr_SetString(PyExc_OverflowError,
9063
0
                            "could not allocate a large enough CPU set");
9064
0
            return NULL;
9065
0
        }
9066
0
        ncpus *= 2;
9067
0
    }
9068
9069
0
    PyObject *res = PySet_New(NULL);
9070
0
    if (res == NULL) {
9071
0
        goto error;
9072
0
    }
9073
9074
0
    int cpu = 0;
9075
0
    int count = CPU_COUNT_S(setsize, mask);
9076
0
    for (; count; cpu++) {
9077
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9078
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9079
0
            --count;
9080
0
            if (cpu_num == NULL) {
9081
0
                goto error;
9082
0
            }
9083
0
            if (PySet_Add(res, cpu_num)) {
9084
0
                Py_DECREF(cpu_num);
9085
0
                goto error;
9086
0
            }
9087
0
            Py_DECREF(cpu_num);
9088
0
        }
9089
0
    }
9090
0
    CPU_FREE(mask);
9091
0
    return res;
9092
9093
0
error:
9094
0
    if (mask) {
9095
0
        CPU_FREE(mask);
9096
0
    }
9097
0
    Py_XDECREF(res);
9098
0
    return NULL;
9099
0
}
9100
#endif /* HAVE_SCHED_SETAFFINITY */
9101
9102
#endif /* HAVE_SCHED_H */
9103
9104
9105
#ifdef HAVE_POSIX_OPENPT
9106
/*[clinic input]
9107
os.posix_openpt -> int
9108
9109
    oflag: int
9110
    /
9111
9112
Open and return a file descriptor for a master pseudo-terminal device.
9113
9114
Performs a posix_openpt() C function call. The oflag argument is used to
9115
set file status flags and file access modes as specified in the manual page
9116
of posix_openpt() of your system.
9117
[clinic start generated code]*/
9118
9119
static int
9120
os_posix_openpt_impl(PyObject *module, int oflag)
9121
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
9122
0
{
9123
0
    int fd;
9124
9125
0
#if defined(O_CLOEXEC)
9126
0
    oflag |= O_CLOEXEC;
9127
0
#endif
9128
9129
0
    fd = posix_openpt(oflag);
9130
0
    if (fd == -1) {
9131
0
        posix_error();
9132
0
        return -1;
9133
0
    }
9134
9135
    // Just in case, likely a no-op given O_CLOEXEC above.
9136
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9137
0
        close(fd);
9138
0
        return -1;
9139
0
    }
9140
9141
0
    return fd;
9142
0
}
9143
#endif /* HAVE_POSIX_OPENPT */
9144
9145
#ifdef HAVE_GRANTPT
9146
/*[clinic input]
9147
os.grantpt
9148
9149
    fd: fildes
9150
        File descriptor of a master pseudo-terminal device.
9151
    /
9152
9153
Grant access to the slave pseudo-terminal device.
9154
9155
Performs a grantpt() C function call.
9156
[clinic start generated code]*/
9157
9158
static PyObject *
9159
os_grantpt_impl(PyObject *module, int fd)
9160
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9161
0
{
9162
0
    int ret;
9163
0
    int saved_errno;
9164
0
    PyOS_sighandler_t sig_saved;
9165
9166
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9167
9168
0
    ret = grantpt(fd);
9169
0
    if (ret == -1)
9170
0
        saved_errno = errno;
9171
9172
0
    PyOS_setsig(SIGCHLD, sig_saved);
9173
9174
0
    if (ret == -1) {
9175
0
        errno = saved_errno;
9176
0
        return posix_error();
9177
0
    }
9178
9179
0
    Py_RETURN_NONE;
9180
0
}
9181
#endif /* HAVE_GRANTPT */
9182
9183
#ifdef HAVE_UNLOCKPT
9184
/*[clinic input]
9185
os.unlockpt
9186
9187
    fd: fildes
9188
        File descriptor of a master pseudo-terminal device.
9189
    /
9190
9191
Unlock a pseudo-terminal master/slave pair.
9192
9193
Performs an unlockpt() C function call.
9194
[clinic start generated code]*/
9195
9196
static PyObject *
9197
os_unlockpt_impl(PyObject *module, int fd)
9198
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9199
0
{
9200
0
    if (unlockpt(fd) == -1)
9201
0
        return posix_error();
9202
9203
0
    Py_RETURN_NONE;
9204
0
}
9205
#endif /* HAVE_UNLOCKPT */
9206
9207
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9208
static PyObject *
9209
py_ptsname(int fd)
9210
0
{
9211
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9212
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9213
0
    errno = 0;
9214
0
    char *name = ptsname(fd);
9215
0
    if (name == NULL) {
9216
0
        return posix_error();
9217
0
    }
9218
0
    return PyUnicode_DecodeFSDefault(name);
9219
0
}
9220
9221
/*[clinic input]
9222
os.ptsname
9223
9224
    fd: fildes
9225
        File descriptor of a master pseudo-terminal device.
9226
    /
9227
9228
Return the name of the slave pseudo-terminal device.
9229
9230
If the ptsname_r() C function is available, it is called;
9231
otherwise, performs a ptsname() C function call.
9232
[clinic start generated code]*/
9233
9234
static PyObject *
9235
os_ptsname_impl(PyObject *module, int fd)
9236
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9237
0
{
9238
0
#ifdef HAVE_PTSNAME_R
9239
0
    int ret;
9240
0
    char name[MAXPATHLEN+1];
9241
9242
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9243
0
        ret = ptsname_r(fd, name, sizeof(name));
9244
0
    }
9245
0
    else {
9246
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9247
0
        return py_ptsname(fd);
9248
0
    }
9249
0
    if (ret != 0) {
9250
0
        errno = ret;
9251
0
        return posix_error();
9252
0
    }
9253
9254
0
    return PyUnicode_DecodeFSDefault(name);
9255
#else
9256
    return py_ptsname(fd);
9257
#endif /* HAVE_PTSNAME_R */
9258
0
}
9259
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9260
9261
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9262
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9263
#  define DEV_PTY_FILE "/dev/ptc"
9264
#  define HAVE_DEV_PTMX
9265
#else
9266
#  define DEV_PTY_FILE "/dev/ptmx"
9267
#endif
9268
9269
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9270
#ifdef HAVE_PTY_H
9271
#include <pty.h>
9272
#elif defined(HAVE_LIBUTIL_H)
9273
#include <libutil.h>
9274
#elif defined(HAVE_UTIL_H)
9275
#include <util.h>
9276
#endif /* HAVE_PTY_H */
9277
#ifdef HAVE_UTMP_H
9278
#include <utmp.h>
9279
#endif /* HAVE_UTMP_H */
9280
#ifdef HAVE_STROPTS_H
9281
#include <stropts.h>
9282
#endif
9283
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9284
9285
9286
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9287
/*[clinic input]
9288
os.openpty
9289
9290
Open a pseudo-terminal.
9291
9292
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9293
for both the master and slave ends.
9294
[clinic start generated code]*/
9295
9296
static PyObject *
9297
os_openpty_impl(PyObject *module)
9298
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9299
0
{
9300
0
    int master_fd = -1, slave_fd = -1;
9301
#ifndef HAVE_OPENPTY
9302
    char * slave_name;
9303
#endif
9304
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9305
    PyOS_sighandler_t sig_saved;
9306
#if defined(__sun) && defined(__SVR4)
9307
    extern char *ptsname(int fildes);
9308
#endif
9309
#endif
9310
9311
0
#ifdef HAVE_OPENPTY
9312
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9313
0
        goto posix_error;
9314
9315
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9316
0
        goto error;
9317
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9318
0
        goto error;
9319
9320
#elif defined(HAVE__GETPTY)
9321
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9322
    if (slave_name == NULL)
9323
        goto posix_error;
9324
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9325
        goto error;
9326
9327
    slave_fd = _Py_open(slave_name, O_RDWR);
9328
    if (slave_fd < 0)
9329
        goto error;
9330
9331
#else
9332
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9333
    if (master_fd < 0)
9334
        goto posix_error;
9335
9336
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9337
9338
    /* change permission of slave */
9339
    if (grantpt(master_fd) < 0) {
9340
        int saved_errno = errno;
9341
        PyOS_setsig(SIGCHLD, sig_saved);
9342
        errno = saved_errno;
9343
        goto posix_error;
9344
    }
9345
9346
    /* unlock slave */
9347
    if (unlockpt(master_fd) < 0) {
9348
        int saved_errno = errno;
9349
        PyOS_setsig(SIGCHLD, sig_saved);
9350
        errno = saved_errno;
9351
        goto posix_error;
9352
    }
9353
9354
    PyOS_setsig(SIGCHLD, sig_saved);
9355
9356
    slave_name = ptsname(master_fd); /* get name of slave */
9357
    if (slave_name == NULL)
9358
        goto posix_error;
9359
9360
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9361
    if (slave_fd == -1)
9362
        goto error;
9363
9364
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9365
        goto posix_error;
9366
9367
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
9368
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9369
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9370
#ifndef __hpux
9371
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9372
#endif /* __hpux */
9373
#endif /* HAVE_CYGWIN */
9374
#endif /* HAVE_OPENPTY */
9375
9376
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9377
9378
0
posix_error:
9379
0
    posix_error();
9380
0
error:
9381
0
    if (master_fd != -1)
9382
0
        close(master_fd);
9383
0
    if (slave_fd != -1)
9384
0
        close(slave_fd);
9385
0
    return NULL;
9386
0
}
9387
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9388
9389
9390
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9391
#define HAVE_FALLBACK_LOGIN_TTY 1
9392
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9393
9394
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9395
/*[clinic input]
9396
os.login_tty
9397
9398
    fd: fildes
9399
    /
9400
9401
Prepare the tty of which fd is a file descriptor for a new login session.
9402
9403
Make the calling process a session leader; make the tty the
9404
controlling tty, the stdin, the stdout, and the stderr of the
9405
calling process; close fd.
9406
[clinic start generated code]*/
9407
9408
static PyObject *
9409
os_login_tty_impl(PyObject *module, int fd)
9410
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
9411
0
{
9412
0
#ifdef HAVE_LOGIN_TTY
9413
0
    if (login_tty(fd) == -1) {
9414
0
        return posix_error();
9415
0
    }
9416
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9417
    /* Establish a new session. */
9418
    if (setsid() == -1) {
9419
        return posix_error();
9420
    }
9421
9422
    /* The tty becomes the controlling terminal. */
9423
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9424
        return posix_error();
9425
    }
9426
9427
    /* The tty becomes stdin/stdout/stderr */
9428
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9429
        return posix_error();
9430
    }
9431
    if (fd > 2) {
9432
        close(fd);
9433
    }
9434
#endif /* HAVE_LOGIN_TTY */
9435
0
    Py_RETURN_NONE;
9436
0
}
9437
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9438
9439
9440
#ifdef HAVE_FORKPTY
9441
/*[clinic input]
9442
os.forkpty
9443
9444
Fork a new process with a new pseudo-terminal as controlling tty.
9445
9446
Returns a tuple of (pid, master_fd).
9447
Like fork(), return pid of 0 to the child process,
9448
and pid of child to the parent process.
9449
To both, return fd of newly opened pseudo-terminal.
9450
The master_fd is non-inheritable.
9451
[clinic start generated code]*/
9452
9453
static PyObject *
9454
os_forkpty_impl(PyObject *module)
9455
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9456
0
{
9457
0
    int master_fd = -1;
9458
0
    pid_t pid;
9459
9460
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9461
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9462
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9463
0
                        "can't fork at interpreter shutdown");
9464
0
        return NULL;
9465
0
    }
9466
0
    if (!_Py_IsMainInterpreter(interp)) {
9467
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9468
0
        return NULL;
9469
0
    }
9470
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9471
0
        return NULL;
9472
0
    }
9473
0
    PyOS_BeforeFork();
9474
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9475
0
    if (pid == 0) {
9476
        /* child: this clobbers and resets the import lock. */
9477
0
        PyOS_AfterFork_Child();
9478
0
    } else {
9479
        /* parent: release the import lock. */
9480
0
        PyOS_AfterFork_Parent();
9481
        /* set O_CLOEXEC on master_fd */
9482
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9483
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9484
0
                                   "non-inheritable in forkpty()");
9485
0
        }
9486
9487
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9488
0
        if (warn_about_fork_with_threads("forkpty") < 0)
9489
0
            return NULL;
9490
0
    }
9491
0
    if (pid == -1) {
9492
0
        return posix_error();
9493
0
    }
9494
9495
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9496
0
}
9497
#endif /* HAVE_FORKPTY */
9498
9499
9500
#ifdef HAVE_GETEGID
9501
/*[clinic input]
9502
os.getegid
9503
9504
Return the current process's effective group id.
9505
[clinic start generated code]*/
9506
9507
static PyObject *
9508
os_getegid_impl(PyObject *module)
9509
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9510
22
{
9511
22
    return _PyLong_FromGid(getegid());
9512
22
}
9513
#endif /* HAVE_GETEGID */
9514
9515
9516
#ifdef HAVE_GETEUID
9517
/*[clinic input]
9518
os.geteuid
9519
9520
Return the current process's effective user id.
9521
[clinic start generated code]*/
9522
9523
static PyObject *
9524
os_geteuid_impl(PyObject *module)
9525
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9526
22
{
9527
22
    return _PyLong_FromUid(geteuid());
9528
22
}
9529
#endif /* HAVE_GETEUID */
9530
9531
9532
#ifdef HAVE_GETGID
9533
/*[clinic input]
9534
os.getgid
9535
9536
Return the current process's group id.
9537
[clinic start generated code]*/
9538
9539
static PyObject *
9540
os_getgid_impl(PyObject *module)
9541
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9542
22
{
9543
22
    return _PyLong_FromGid(getgid());
9544
22
}
9545
#endif /* HAVE_GETGID */
9546
9547
9548
#if defined(HAVE_GETPID)
9549
/*[clinic input]
9550
os.getpid
9551
9552
Return the current process id.
9553
[clinic start generated code]*/
9554
9555
static PyObject *
9556
os_getpid_impl(PyObject *module)
9557
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9558
0
{
9559
0
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9560
0
    return PyLong_FromPid(getpid());
9561
#else
9562
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9563
#endif
9564
0
}
9565
#endif /* defined(HAVE_GETPID) */
9566
9567
#ifdef NGROUPS_MAX
9568
0
#define MAX_GROUPS NGROUPS_MAX
9569
#else
9570
    /* defined to be 16 on Solaris7, so this should be a small number */
9571
#define MAX_GROUPS 64
9572
#endif
9573
9574
#ifdef HAVE_GETGROUPLIST
9575
9576
#ifdef __APPLE__
9577
/*[clinic input]
9578
os.getgrouplist
9579
9580
    user: str
9581
        username to lookup
9582
    group as basegid: int
9583
        base group id of the user
9584
    /
9585
9586
Returns a list of groups to which a user belongs.
9587
[clinic start generated code]*/
9588
9589
static PyObject *
9590
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9591
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9592
#else
9593
/*[clinic input]
9594
os.getgrouplist
9595
9596
    user: str
9597
        username to lookup
9598
    group as basegid: gid_t
9599
        base group id of the user
9600
    /
9601
9602
Returns a list of groups to which a user belongs.
9603
[clinic start generated code]*/
9604
9605
static PyObject *
9606
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9607
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9608
#endif
9609
0
{
9610
0
    int i, ngroups;
9611
0
    PyObject *list;
9612
#ifdef __APPLE__
9613
    int *groups;
9614
#else
9615
0
    gid_t *groups;
9616
0
#endif
9617
9618
    /*
9619
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9620
     * number of supplemental groups a users can belong to.
9621
     * We have to increment it by one because
9622
     * getgrouplist() returns both the supplemental groups
9623
     * and the primary group, i.e. all of the groups the
9624
     * user belongs to.
9625
     */
9626
0
    ngroups = 1 + MAX_GROUPS;
9627
9628
0
    while (1) {
9629
#ifdef __APPLE__
9630
        groups = PyMem_New(int, ngroups);
9631
#else
9632
0
        groups = PyMem_New(gid_t, ngroups);
9633
0
#endif
9634
0
        if (groups == NULL) {
9635
0
            return PyErr_NoMemory();
9636
0
        }
9637
9638
0
        int old_ngroups = ngroups;
9639
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9640
            /* Success */
9641
0
            break;
9642
0
        }
9643
9644
        /* getgrouplist() fails if the group list is too small */
9645
0
        PyMem_Free(groups);
9646
9647
0
        if (ngroups > old_ngroups) {
9648
            /* If the group list is too small, the glibc implementation of
9649
               getgrouplist() sets ngroups to the total number of groups and
9650
               returns -1. */
9651
0
        }
9652
0
        else {
9653
            /* Double the group list size */
9654
0
            if (ngroups > INT_MAX / 2) {
9655
0
                return PyErr_NoMemory();
9656
0
            }
9657
0
            ngroups *= 2;
9658
0
        }
9659
9660
        /* Retry getgrouplist() with a larger group list */
9661
0
    }
9662
9663
#ifdef _Py_MEMORY_SANITIZER
9664
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9665
    __msan_unpoison(&ngroups, sizeof(ngroups));
9666
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9667
#endif
9668
9669
0
    list = PyList_New(ngroups);
9670
0
    if (list == NULL) {
9671
0
        PyMem_Free(groups);
9672
0
        return NULL;
9673
0
    }
9674
9675
0
    for (i = 0; i < ngroups; i++) {
9676
#ifdef __APPLE__
9677
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9678
#else
9679
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9680
0
#endif
9681
0
        if (o == NULL) {
9682
0
            Py_DECREF(list);
9683
0
            PyMem_Free(groups);
9684
0
            return NULL;
9685
0
        }
9686
0
        PyList_SET_ITEM(list, i, o);
9687
0
    }
9688
9689
0
    PyMem_Free(groups);
9690
9691
0
    return list;
9692
0
}
9693
#endif /* HAVE_GETGROUPLIST */
9694
9695
9696
#ifdef HAVE_GETGROUPS
9697
/*[clinic input]
9698
os.getgroups
9699
9700
Return list of supplemental group IDs for the process.
9701
[clinic start generated code]*/
9702
9703
static PyObject *
9704
os_getgroups_impl(PyObject *module)
9705
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9706
0
{
9707
    // Call getgroups with length 0 to get the actual number of groups
9708
0
    int n = getgroups(0, NULL);
9709
0
    if (n < 0) {
9710
0
        return posix_error();
9711
0
    }
9712
9713
0
    if (n == 0) {
9714
0
        return PyList_New(0);
9715
0
    }
9716
9717
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9718
0
    if (grouplist == NULL) {
9719
0
        return PyErr_NoMemory();
9720
0
    }
9721
9722
0
    n = getgroups(n, grouplist);
9723
0
    if (n == -1) {
9724
0
        posix_error();
9725
0
        PyMem_Free(grouplist);
9726
0
        return NULL;
9727
0
    }
9728
9729
0
    PyObject *result = PyList_New(n);
9730
0
    if (result == NULL) {
9731
0
        goto error;
9732
0
    }
9733
9734
0
    for (int i = 0; i < n; ++i) {
9735
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9736
0
        if (group == NULL) {
9737
0
            goto error;
9738
0
        }
9739
0
        PyList_SET_ITEM(result, i, group);
9740
0
    }
9741
0
    PyMem_Free(grouplist);
9742
9743
0
    return result;
9744
9745
0
error:
9746
0
    PyMem_Free(grouplist);
9747
0
    Py_XDECREF(result);
9748
0
    return NULL;
9749
0
}
9750
#endif /* HAVE_GETGROUPS */
9751
9752
#ifdef HAVE_INITGROUPS
9753
#ifdef __APPLE__
9754
/*[clinic input]
9755
os.initgroups
9756
9757
    username as oname: unicode_fs_encoded
9758
    gid: int
9759
    /
9760
9761
Initialize the group access list.
9762
9763
Call the system initgroups() to initialize the group access list with all of
9764
the groups of which the specified username is a member, plus the specified
9765
group id.
9766
[clinic start generated code]*/
9767
9768
static PyObject *
9769
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9770
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9771
#else
9772
/*[clinic input]
9773
os.initgroups
9774
9775
    username as oname: unicode_fs_encoded
9776
    gid: gid_t
9777
    /
9778
9779
Initialize the group access list.
9780
9781
Call the system initgroups() to initialize the group access list with all of
9782
the groups of which the specified username is a member, plus the specified
9783
group id.
9784
[clinic start generated code]*/
9785
9786
static PyObject *
9787
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9788
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9789
#endif
9790
0
{
9791
0
    const char *username = PyBytes_AS_STRING(oname);
9792
9793
0
    if (initgroups(username, gid) == -1)
9794
0
        return PyErr_SetFromErrno(PyExc_OSError);
9795
9796
0
    Py_RETURN_NONE;
9797
0
}
9798
#endif /* HAVE_INITGROUPS */
9799
9800
9801
#ifdef HAVE_GETPGID
9802
/*[clinic input]
9803
os.getpgid
9804
9805
    pid: pid_t
9806
9807
Call the system call getpgid(), and return the result.
9808
[clinic start generated code]*/
9809
9810
static PyObject *
9811
os_getpgid_impl(PyObject *module, pid_t pid)
9812
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9813
0
{
9814
0
    pid_t pgid = getpgid(pid);
9815
0
    if (pgid < 0)
9816
0
        return posix_error();
9817
0
    return PyLong_FromPid(pgid);
9818
0
}
9819
#endif /* HAVE_GETPGID */
9820
9821
9822
#ifdef HAVE_GETPGRP
9823
/*[clinic input]
9824
os.getpgrp
9825
9826
Return the current process group id.
9827
[clinic start generated code]*/
9828
9829
static PyObject *
9830
os_getpgrp_impl(PyObject *module)
9831
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9832
0
{
9833
#ifdef GETPGRP_HAVE_ARG
9834
    return PyLong_FromPid(getpgrp(0));
9835
#else /* GETPGRP_HAVE_ARG */
9836
0
    return PyLong_FromPid(getpgrp());
9837
0
#endif /* GETPGRP_HAVE_ARG */
9838
0
}
9839
#endif /* HAVE_GETPGRP */
9840
9841
9842
#ifdef HAVE_SETPGRP
9843
/*[clinic input]
9844
os.setpgrp
9845
9846
Make the current process the leader of its process group.
9847
[clinic start generated code]*/
9848
9849
static PyObject *
9850
os_setpgrp_impl(PyObject *module)
9851
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9852
0
{
9853
#ifdef SETPGRP_HAVE_ARG
9854
    if (setpgrp(0, 0) < 0)
9855
#else /* SETPGRP_HAVE_ARG */
9856
0
    if (setpgrp() < 0)
9857
0
#endif /* SETPGRP_HAVE_ARG */
9858
0
        return posix_error();
9859
0
    Py_RETURN_NONE;
9860
0
}
9861
#endif /* HAVE_SETPGRP */
9862
9863
#ifdef HAVE_GETPPID
9864
9865
#ifdef MS_WINDOWS
9866
#include <winternl.h>
9867
#include <ProcessSnapshot.h>
9868
9869
// The structure definition in winternl.h may be incomplete.
9870
// This structure is the full version from the MSDN documentation.
9871
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9872
    NTSTATUS ExitStatus;
9873
    PVOID PebBaseAddress;
9874
    ULONG_PTR AffinityMask;
9875
    LONG BasePriority;
9876
    ULONG_PTR UniqueProcessId;
9877
    ULONG_PTR InheritedFromUniqueProcessId;
9878
} PROCESS_BASIC_INFORMATION_FULL;
9879
9880
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9881
    IN    HANDLE           ProcessHandle,
9882
    IN    PROCESSINFOCLASS ProcessInformationClass,
9883
    OUT   PVOID            ProcessInformation,
9884
    IN    ULONG            ProcessInformationLength,
9885
    OUT   PULONG           ReturnLength OPTIONAL);
9886
9887
// This function returns the process ID of the parent process.
9888
// Returns 0 on failure.
9889
static ULONG
9890
win32_getppid_fast(void)
9891
{
9892
    NTSTATUS status;
9893
    HMODULE ntdll;
9894
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9895
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9896
    static ULONG cached_ppid = 0;
9897
9898
    if (cached_ppid) {
9899
        // No need to query the kernel again.
9900
        return cached_ppid;
9901
    }
9902
9903
    ntdll = GetModuleHandleW(L"ntdll.dll");
9904
    if (!ntdll) {
9905
        return 0;
9906
    }
9907
9908
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9909
    if (!pNtQueryInformationProcess) {
9910
        return 0;
9911
    }
9912
9913
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9914
                                        ProcessBasicInformation,
9915
                                        &basic_information,
9916
                                        sizeof(basic_information),
9917
                                        NULL);
9918
9919
    if (!NT_SUCCESS(status)) {
9920
        return 0;
9921
    }
9922
9923
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9924
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9925
    // zero and (ULONG) -1.
9926
9927
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9928
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9929
    {
9930
        return 0;
9931
    }
9932
9933
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9934
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9935
    // process. This process ID will be correctly returned even if the parent process has
9936
    // exited or been terminated.
9937
9938
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9939
    return cached_ppid;
9940
}
9941
9942
static PyObject*
9943
win32_getppid(void)
9944
{
9945
    DWORD error;
9946
    PyObject* result = NULL;
9947
    HANDLE process = GetCurrentProcess();
9948
    HPSS snapshot = NULL;
9949
    ULONG pid;
9950
9951
    pid = win32_getppid_fast();
9952
    if (pid != 0) {
9953
        return PyLong_FromUnsignedLong(pid);
9954
    }
9955
9956
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9957
9958
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9959
    if (error != ERROR_SUCCESS) {
9960
        return PyErr_SetFromWindowsErr(error);
9961
    }
9962
9963
    PSS_PROCESS_INFORMATION info;
9964
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
9965
                             sizeof(info));
9966
    if (error == ERROR_SUCCESS) {
9967
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
9968
    }
9969
    else {
9970
        result = PyErr_SetFromWindowsErr(error);
9971
    }
9972
9973
    PssFreeSnapshot(process, snapshot);
9974
    return result;
9975
}
9976
#endif /*MS_WINDOWS*/
9977
9978
9979
/*[clinic input]
9980
os.getppid
9981
9982
Return the parent's process id.
9983
9984
If the parent process has already exited, Windows machines will still
9985
return its id; others systems will return the id of the 'init' process (1).
9986
[clinic start generated code]*/
9987
9988
static PyObject *
9989
os_getppid_impl(PyObject *module)
9990
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
9991
0
{
9992
#ifdef MS_WINDOWS
9993
    return win32_getppid();
9994
#else
9995
0
    return PyLong_FromPid(getppid());
9996
0
#endif
9997
0
}
9998
#endif /* HAVE_GETPPID */
9999
10000
10001
#ifdef HAVE_GETLOGIN
10002
/*[clinic input]
10003
os.getlogin
10004
10005
Return the actual login name.
10006
[clinic start generated code]*/
10007
10008
static PyObject *
10009
os_getlogin_impl(PyObject *module)
10010
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10011
0
{
10012
0
    PyObject *result = NULL;
10013
#ifdef MS_WINDOWS
10014
    wchar_t user_name[UNLEN + 1];
10015
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10016
10017
    if (GetUserNameW(user_name, &num_chars)) {
10018
        /* num_chars is the number of unicode chars plus null terminator */
10019
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10020
    }
10021
    else
10022
        result = PyErr_SetFromWindowsErr(GetLastError());
10023
#elif defined (HAVE_GETLOGIN_R)
10024
# if defined (HAVE_MAXLOGNAME)
10025
    char name[MAXLOGNAME + 1];
10026
# elif defined (HAVE_UT_NAMESIZE)
10027
    char name[UT_NAMESIZE + 1];
10028
# else
10029
    char name[256];
10030
# endif
10031
0
    int err = getlogin_r(name, sizeof(name));
10032
0
    if (err) {
10033
0
        int old_errno = errno;
10034
0
        errno = err;
10035
0
        posix_error();
10036
0
        errno = old_errno;
10037
0
    }
10038
0
    else {
10039
0
        result = PyUnicode_DecodeFSDefault(name);
10040
0
    }
10041
#else
10042
    char *name;
10043
    int old_errno = errno;
10044
10045
    errno = 0;
10046
    name = getlogin();
10047
    if (name == NULL) {
10048
        if (errno)
10049
            posix_error();
10050
        else
10051
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10052
    }
10053
    else
10054
        result = PyUnicode_DecodeFSDefault(name);
10055
    errno = old_errno;
10056
#endif
10057
0
    return result;
10058
0
}
10059
#endif /* HAVE_GETLOGIN */
10060
10061
10062
#ifdef HAVE_GETUID
10063
/*[clinic input]
10064
os.getuid
10065
10066
Return the current process's user id.
10067
[clinic start generated code]*/
10068
10069
static PyObject *
10070
os_getuid_impl(PyObject *module)
10071
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10072
22
{
10073
22
    return _PyLong_FromUid(getuid());
10074
22
}
10075
#endif /* HAVE_GETUID */
10076
10077
10078
#ifdef MS_WINDOWS
10079
#define HAVE_KILL
10080
#endif /* MS_WINDOWS */
10081
10082
#ifdef HAVE_KILL
10083
/*[clinic input]
10084
os.kill
10085
10086
    pid: pid_t
10087
    signal: Py_ssize_t
10088
    /
10089
10090
Kill a process with a signal.
10091
[clinic start generated code]*/
10092
10093
static PyObject *
10094
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10095
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10096
0
{
10097
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10098
0
        return NULL;
10099
0
    }
10100
0
#ifndef MS_WINDOWS
10101
0
    if (kill(pid, (int)signal) == -1) {
10102
0
        return posix_error();
10103
0
    }
10104
10105
    // Check immediately if the signal was sent to the current process.
10106
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10107
    // is cheap.
10108
0
    if (PyErr_CheckSignals()) {
10109
0
        return NULL;
10110
0
    }
10111
10112
0
    Py_RETURN_NONE;
10113
#else /* !MS_WINDOWS */
10114
    DWORD sig = (DWORD)signal;
10115
10116
#ifdef HAVE_WINDOWS_CONSOLE_IO
10117
    /* Console processes which share a common console can be sent CTRL+C or
10118
       CTRL+BREAK events, provided they handle said events. */
10119
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10120
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10121
            return PyErr_SetFromWindowsErr(0);
10122
        }
10123
        Py_RETURN_NONE;
10124
    }
10125
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10126
10127
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10128
       attempt to open and terminate the process. */
10129
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10130
    if (handle == NULL) {
10131
        return PyErr_SetFromWindowsErr(0);
10132
    }
10133
10134
    BOOL res = TerminateProcess(handle, sig);
10135
    CloseHandle(handle);
10136
    if (res == 0) {
10137
        return PyErr_SetFromWindowsErr(0);
10138
    }
10139
10140
    Py_RETURN_NONE;
10141
#endif /* !MS_WINDOWS */
10142
0
}
10143
#endif /* HAVE_KILL */
10144
10145
10146
#ifdef HAVE_KILLPG
10147
/*[clinic input]
10148
os.killpg
10149
10150
    pgid: pid_t
10151
    signal: int
10152
    /
10153
10154
Kill a process group with a signal.
10155
[clinic start generated code]*/
10156
10157
static PyObject *
10158
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10159
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10160
0
{
10161
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10162
0
        return NULL;
10163
0
    }
10164
    /* XXX some man pages make the `pgid` parameter an int, others
10165
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10166
       take the same type. Moreover, pid_t is always at least as wide as
10167
       int (else compilation of this module fails), which is safe. */
10168
0
    if (killpg(pgid, signal) == -1)
10169
0
        return posix_error();
10170
0
    Py_RETURN_NONE;
10171
0
}
10172
#endif /* HAVE_KILLPG */
10173
10174
10175
#ifdef HAVE_PLOCK
10176
#ifdef HAVE_SYS_LOCK_H
10177
#include <sys/lock.h>
10178
#endif
10179
10180
/*[clinic input]
10181
os.plock
10182
    op: int
10183
    /
10184
10185
Lock program segments into memory.");
10186
[clinic start generated code]*/
10187
10188
static PyObject *
10189
os_plock_impl(PyObject *module, int op)
10190
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10191
{
10192
    if (plock(op) == -1)
10193
        return posix_error();
10194
    Py_RETURN_NONE;
10195
}
10196
#endif /* HAVE_PLOCK */
10197
10198
10199
#ifdef HAVE_SETUID
10200
/*[clinic input]
10201
os.setuid
10202
10203
    uid: uid_t
10204
    /
10205
10206
Set the current process's user id.
10207
[clinic start generated code]*/
10208
10209
static PyObject *
10210
os_setuid_impl(PyObject *module, uid_t uid)
10211
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10212
0
{
10213
0
    if (setuid(uid) < 0)
10214
0
        return posix_error();
10215
0
    Py_RETURN_NONE;
10216
0
}
10217
#endif /* HAVE_SETUID */
10218
10219
10220
#ifdef HAVE_SETEUID
10221
/*[clinic input]
10222
os.seteuid
10223
10224
    euid: uid_t
10225
    /
10226
10227
Set the current process's effective user id.
10228
[clinic start generated code]*/
10229
10230
static PyObject *
10231
os_seteuid_impl(PyObject *module, uid_t euid)
10232
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10233
0
{
10234
0
    if (seteuid(euid) < 0)
10235
0
        return posix_error();
10236
0
    Py_RETURN_NONE;
10237
0
}
10238
#endif /* HAVE_SETEUID */
10239
10240
10241
#ifdef HAVE_SETEGID
10242
/*[clinic input]
10243
os.setegid
10244
10245
    egid: gid_t
10246
    /
10247
10248
Set the current process's effective group id.
10249
[clinic start generated code]*/
10250
10251
static PyObject *
10252
os_setegid_impl(PyObject *module, gid_t egid)
10253
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10254
0
{
10255
0
    if (setegid(egid) < 0)
10256
0
        return posix_error();
10257
0
    Py_RETURN_NONE;
10258
0
}
10259
#endif /* HAVE_SETEGID */
10260
10261
10262
#ifdef HAVE_SETREUID
10263
/*[clinic input]
10264
os.setreuid
10265
10266
    ruid: uid_t
10267
    euid: uid_t
10268
    /
10269
10270
Set the current process's real and effective user ids.
10271
[clinic start generated code]*/
10272
10273
static PyObject *
10274
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10275
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10276
0
{
10277
0
    if (setreuid(ruid, euid) < 0) {
10278
0
        return posix_error();
10279
0
    } else {
10280
0
        Py_RETURN_NONE;
10281
0
    }
10282
0
}
10283
#endif /* HAVE_SETREUID */
10284
10285
10286
#ifdef HAVE_SETREGID
10287
/*[clinic input]
10288
os.setregid
10289
10290
    rgid: gid_t
10291
    egid: gid_t
10292
    /
10293
10294
Set the current process's real and effective group ids.
10295
[clinic start generated code]*/
10296
10297
static PyObject *
10298
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10299
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10300
0
{
10301
0
    if (setregid(rgid, egid) < 0)
10302
0
        return posix_error();
10303
0
    Py_RETURN_NONE;
10304
0
}
10305
#endif /* HAVE_SETREGID */
10306
10307
10308
#ifdef HAVE_SETGID
10309
/*[clinic input]
10310
os.setgid
10311
    gid: gid_t
10312
    /
10313
10314
Set the current process's group id.
10315
[clinic start generated code]*/
10316
10317
static PyObject *
10318
os_setgid_impl(PyObject *module, gid_t gid)
10319
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10320
0
{
10321
0
    if (setgid(gid) < 0)
10322
0
        return posix_error();
10323
0
    Py_RETURN_NONE;
10324
0
}
10325
#endif /* HAVE_SETGID */
10326
10327
10328
#ifdef HAVE_SETGROUPS
10329
/*[clinic input]
10330
os.setgroups
10331
10332
    groups: object
10333
    /
10334
10335
Set the groups of the current process to list.
10336
[clinic start generated code]*/
10337
10338
static PyObject *
10339
os_setgroups(PyObject *module, PyObject *groups)
10340
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10341
0
{
10342
0
    if (!PySequence_Check(groups)) {
10343
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10344
0
        return NULL;
10345
0
    }
10346
0
    Py_ssize_t len = PySequence_Size(groups);
10347
0
    if (len < 0) {
10348
0
        return NULL;
10349
0
    }
10350
0
    if (len > MAX_GROUPS) {
10351
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10352
0
        return NULL;
10353
0
    }
10354
10355
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10356
0
    if (grouplist == NULL) {
10357
0
        PyErr_NoMemory();
10358
0
        return NULL;
10359
0
    }
10360
0
    for (Py_ssize_t i = 0; i < len; i++) {
10361
0
        PyObject *elem;
10362
0
        elem = PySequence_GetItem(groups, i);
10363
0
        if (!elem) {
10364
0
            PyMem_Free(grouplist);
10365
0
            return NULL;
10366
0
        }
10367
0
        if (!PyIndex_Check(elem)) {
10368
0
            PyErr_SetString(PyExc_TypeError,
10369
0
                            "groups must be integers");
10370
0
            Py_DECREF(elem);
10371
0
            PyMem_Free(grouplist);
10372
0
            return NULL;
10373
0
        } else {
10374
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10375
0
                Py_DECREF(elem);
10376
0
                PyMem_Free(grouplist);
10377
0
                return NULL;
10378
0
            }
10379
0
        }
10380
0
        Py_DECREF(elem);
10381
0
    }
10382
10383
0
    if (setgroups(len, grouplist) < 0) {
10384
0
        posix_error();
10385
0
        PyMem_Free(grouplist);
10386
0
        return NULL;
10387
0
    }
10388
0
    PyMem_Free(grouplist);
10389
0
    Py_RETURN_NONE;
10390
0
}
10391
#endif /* HAVE_SETGROUPS */
10392
10393
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10394
static PyObject *
10395
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10396
0
{
10397
0
    PyObject *result;
10398
0
    PyObject *struct_rusage;
10399
10400
0
    if (pid == -1)
10401
0
        return posix_error();
10402
10403
    // If wait succeeded but no child was ready to report status, ru will not
10404
    // have been populated.
10405
0
    if (pid == 0) {
10406
0
        memset(ru, 0, sizeof(*ru));
10407
0
    }
10408
10409
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10410
0
    if (struct_rusage == NULL)
10411
0
        return NULL;
10412
10413
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10414
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10415
0
    Py_DECREF(struct_rusage);
10416
0
    if (!result)
10417
0
        return NULL;
10418
10419
0
    int pos = 0;
10420
10421
0
#ifndef doubletime
10422
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10423
0
#endif
10424
10425
0
#define SET_RESULT(CALL)                                     \
10426
0
    do {                                                     \
10427
0
        PyObject *item = (CALL);                             \
10428
0
        if (item == NULL) {                                  \
10429
0
            Py_DECREF(result);                               \
10430
0
            return NULL;                                     \
10431
0
        }                                                    \
10432
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10433
0
    } while(0)
10434
10435
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10436
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10437
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10438
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10439
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10440
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10441
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10442
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10443
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10444
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10445
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10446
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10447
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10448
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10449
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10450
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10451
0
#undef SET_RESULT
10452
10453
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10454
0
}
10455
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10456
10457
10458
#ifdef HAVE_WAIT3
10459
/*[clinic input]
10460
os.wait3
10461
10462
    options: int
10463
Wait for completion of a child process.
10464
10465
Returns a tuple of information about the child process:
10466
  (pid, status, rusage)
10467
[clinic start generated code]*/
10468
10469
static PyObject *
10470
os_wait3_impl(PyObject *module, int options)
10471
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10472
0
{
10473
0
    pid_t pid;
10474
0
    struct rusage ru;
10475
0
    int async_err = 0;
10476
0
    WAIT_TYPE status;
10477
0
    WAIT_STATUS_INT(status) = 0;
10478
10479
0
    do {
10480
0
        Py_BEGIN_ALLOW_THREADS
10481
0
        pid = wait3(&status, options, &ru);
10482
0
        Py_END_ALLOW_THREADS
10483
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10484
0
    if (pid < 0)
10485
0
        return (!async_err) ? posix_error() : NULL;
10486
10487
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10488
0
}
10489
#endif /* HAVE_WAIT3 */
10490
10491
10492
#ifdef HAVE_WAIT4
10493
/*[clinic input]
10494
10495
os.wait4
10496
10497
    pid: pid_t
10498
    options: int
10499
10500
Wait for completion of a specific child process.
10501
10502
Returns a tuple of information about the child process:
10503
  (pid, status, rusage)
10504
[clinic start generated code]*/
10505
10506
static PyObject *
10507
os_wait4_impl(PyObject *module, pid_t pid, int options)
10508
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10509
0
{
10510
0
    pid_t res;
10511
0
    struct rusage ru;
10512
0
    int async_err = 0;
10513
0
    WAIT_TYPE status;
10514
0
    WAIT_STATUS_INT(status) = 0;
10515
10516
0
    do {
10517
0
        Py_BEGIN_ALLOW_THREADS
10518
0
        res = wait4(pid, &status, options, &ru);
10519
0
        Py_END_ALLOW_THREADS
10520
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10521
0
    if (res < 0)
10522
0
        return (!async_err) ? posix_error() : NULL;
10523
10524
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10525
0
}
10526
#endif /* HAVE_WAIT4 */
10527
10528
10529
#if defined(HAVE_WAITID)
10530
/*[clinic input]
10531
os.waitid
10532
10533
    idtype: idtype_t
10534
        Must be one of be P_PID, P_PGID or P_ALL.
10535
    id: id_t
10536
        The id to wait on.
10537
    options: int
10538
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10539
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10540
    /
10541
10542
Returns the result of waiting for a process or processes.
10543
10544
Returns either waitid_result or None if WNOHANG is specified and there are
10545
no children in a waitable state.
10546
[clinic start generated code]*/
10547
10548
static PyObject *
10549
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10550
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10551
0
{
10552
0
    PyObject *result;
10553
0
    int res;
10554
0
    int async_err = 0;
10555
0
    siginfo_t si;
10556
0
    si.si_pid = 0;
10557
10558
0
    do {
10559
0
        Py_BEGIN_ALLOW_THREADS
10560
0
        res = waitid(idtype, id, &si, options);
10561
0
        Py_END_ALLOW_THREADS
10562
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10563
0
    if (res < 0)
10564
0
        return (!async_err) ? posix_error() : NULL;
10565
10566
0
    if (si.si_pid == 0)
10567
0
        Py_RETURN_NONE;
10568
10569
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10570
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10571
0
    if (!result)
10572
0
        return NULL;
10573
10574
0
    int pos = 0;
10575
10576
0
#define SET_RESULT(CALL)                                     \
10577
0
    do {                                                     \
10578
0
        PyObject *item = (CALL);                             \
10579
0
        if (item == NULL) {                                  \
10580
0
            Py_DECREF(result);                               \
10581
0
            return NULL;                                     \
10582
0
        }                                                    \
10583
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10584
0
    } while(0)
10585
10586
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10587
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10588
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10589
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10590
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10591
10592
0
#undef SET_RESULT
10593
10594
0
    return result;
10595
0
}
10596
#endif /* defined(HAVE_WAITID) */
10597
10598
10599
#if defined(HAVE_WAITPID)
10600
/*[clinic input]
10601
os.waitpid
10602
    pid: pid_t
10603
    options: int
10604
    /
10605
10606
Wait for completion of a given child process.
10607
10608
Returns a tuple of information regarding the child process:
10609
    (pid, status)
10610
10611
The options argument is ignored on Windows.
10612
[clinic start generated code]*/
10613
10614
static PyObject *
10615
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10616
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10617
0
{
10618
0
    pid_t res;
10619
0
    int async_err = 0;
10620
0
    WAIT_TYPE status;
10621
0
    WAIT_STATUS_INT(status) = 0;
10622
10623
0
    do {
10624
0
        Py_BEGIN_ALLOW_THREADS
10625
0
        res = waitpid(pid, &status, options);
10626
0
        Py_END_ALLOW_THREADS
10627
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10628
0
    if (res < 0)
10629
0
        return (!async_err) ? posix_error() : NULL;
10630
10631
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10632
0
}
10633
#elif defined(HAVE_CWAIT)
10634
/* MS C has a variant of waitpid() that's usable for most purposes. */
10635
/*[clinic input]
10636
os.waitpid
10637
    pid: intptr_t
10638
    options: int
10639
    /
10640
10641
Wait for completion of a given process.
10642
10643
Returns a tuple of information regarding the process:
10644
    (pid, status << 8)
10645
10646
The options argument is ignored on Windows.
10647
[clinic start generated code]*/
10648
10649
static PyObject *
10650
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10651
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10652
{
10653
    int status;
10654
    intptr_t res;
10655
    int async_err = 0;
10656
10657
    do {
10658
        Py_BEGIN_ALLOW_THREADS
10659
        _Py_BEGIN_SUPPRESS_IPH
10660
        res = _cwait(&status, pid, options);
10661
        _Py_END_SUPPRESS_IPH
10662
        Py_END_ALLOW_THREADS
10663
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10664
    if (res < 0)
10665
        return (!async_err) ? posix_error() : NULL;
10666
10667
    unsigned long long ustatus = (unsigned int)status;
10668
10669
    /* shift the status left a byte so this is more like the POSIX waitpid */
10670
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10671
}
10672
#endif
10673
10674
10675
#ifdef HAVE_WAIT
10676
/*[clinic input]
10677
os.wait
10678
10679
Wait for completion of a child process.
10680
10681
Returns a tuple of information about the child process:
10682
    (pid, status)
10683
[clinic start generated code]*/
10684
10685
static PyObject *
10686
os_wait_impl(PyObject *module)
10687
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10688
0
{
10689
0
    pid_t pid;
10690
0
    int async_err = 0;
10691
0
    WAIT_TYPE status;
10692
0
    WAIT_STATUS_INT(status) = 0;
10693
10694
0
    do {
10695
0
        Py_BEGIN_ALLOW_THREADS
10696
0
        pid = wait(&status);
10697
0
        Py_END_ALLOW_THREADS
10698
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10699
0
    if (pid < 0)
10700
0
        return (!async_err) ? posix_error() : NULL;
10701
10702
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10703
0
}
10704
#endif /* HAVE_WAIT */
10705
10706
10707
// This system call always crashes on older Android versions.
10708
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10709
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10710
/*[clinic input]
10711
os.pidfd_open
10712
  pid: pid_t
10713
  flags: unsigned_int = 0
10714
10715
Return a file descriptor referring to the process *pid*.
10716
10717
The descriptor can be used to perform process management without races and
10718
signals.
10719
[clinic start generated code]*/
10720
10721
static PyObject *
10722
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10723
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10724
0
{
10725
0
    int fd = syscall(__NR_pidfd_open, pid, flags);
10726
0
    if (fd < 0) {
10727
0
        return posix_error();
10728
0
    }
10729
0
    return PyLong_FromLong(fd);
10730
0
}
10731
#endif
10732
10733
10734
#ifdef HAVE_SETNS
10735
/*[clinic input]
10736
os.setns
10737
  fd: fildes
10738
    A file descriptor to a namespace.
10739
  nstype: int = 0
10740
    Type of namespace.
10741
10742
Move the calling thread into different namespaces.
10743
[clinic start generated code]*/
10744
10745
static PyObject *
10746
os_setns_impl(PyObject *module, int fd, int nstype)
10747
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10748
0
{
10749
0
    int res;
10750
10751
0
    Py_BEGIN_ALLOW_THREADS
10752
0
    res = setns(fd, nstype);
10753
0
    Py_END_ALLOW_THREADS
10754
10755
0
    if (res != 0) {
10756
0
        return posix_error();
10757
0
    }
10758
10759
0
    Py_RETURN_NONE;
10760
0
}
10761
#endif
10762
10763
10764
#ifdef HAVE_UNSHARE
10765
/*[clinic input]
10766
os.unshare
10767
  flags: int
10768
    Namespaces to be unshared.
10769
10770
Disassociate parts of a process (or thread) execution context.
10771
[clinic start generated code]*/
10772
10773
static PyObject *
10774
os_unshare_impl(PyObject *module, int flags)
10775
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10776
0
{
10777
0
    int res;
10778
10779
0
    Py_BEGIN_ALLOW_THREADS
10780
0
    res = unshare(flags);
10781
0
    Py_END_ALLOW_THREADS
10782
10783
0
    if (res != 0) {
10784
0
        return posix_error();
10785
0
    }
10786
10787
0
    Py_RETURN_NONE;
10788
0
}
10789
#endif
10790
10791
10792
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10793
/*[clinic input]
10794
os.readlink
10795
10796
    path: path_t
10797
    *
10798
    dir_fd: dir_fd(requires='readlinkat') = None
10799
10800
Return a string representing the path to which the symbolic link points.
10801
10802
If dir_fd is not None, it should be a file descriptor open to a directory,
10803
and path should be relative; path will then be relative to that directory.
10804
10805
dir_fd may not be implemented on your platform.  If it is unavailable,
10806
using it will raise a NotImplementedError.
10807
[clinic start generated code]*/
10808
10809
static PyObject *
10810
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10811
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10812
0
{
10813
0
#if defined(HAVE_READLINK)
10814
0
    char buffer[MAXPATHLEN+1];
10815
0
    ssize_t length;
10816
0
#ifdef HAVE_READLINKAT
10817
0
    int readlinkat_unavailable = 0;
10818
0
#endif
10819
10820
0
    Py_BEGIN_ALLOW_THREADS
10821
0
#ifdef HAVE_READLINKAT
10822
0
    if (dir_fd != DEFAULT_DIR_FD) {
10823
0
        if (HAVE_READLINKAT_RUNTIME) {
10824
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10825
0
        } else {
10826
0
            readlinkat_unavailable = 1;
10827
0
        }
10828
0
    } else
10829
0
#endif
10830
0
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10831
0
    Py_END_ALLOW_THREADS
10832
10833
0
#ifdef HAVE_READLINKAT
10834
0
    if (readlinkat_unavailable) {
10835
0
        argument_unavailable_error(NULL, "dir_fd");
10836
0
        return NULL;
10837
0
    }
10838
0
#endif
10839
10840
0
    if (length < 0) {
10841
0
        return path_error(path);
10842
0
    }
10843
0
    buffer[length] = '\0';
10844
10845
0
    if (PyUnicode_Check(path->object))
10846
0
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10847
0
    else
10848
0
        return PyBytes_FromStringAndSize(buffer, length);
10849
#elif defined(MS_WINDOWS)
10850
    DWORD n_bytes_returned;
10851
    DWORD io_result = 0;
10852
    HANDLE reparse_point_handle;
10853
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10854
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10855
    PyObject *result = NULL;
10856
10857
    /* First get a handle to the reparse point */
10858
    Py_BEGIN_ALLOW_THREADS
10859
    reparse_point_handle = CreateFileW(
10860
        path->wide,
10861
        0,
10862
        0,
10863
        0,
10864
        OPEN_EXISTING,
10865
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10866
        0);
10867
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10868
        /* New call DeviceIoControl to read the reparse point */
10869
        io_result = DeviceIoControl(
10870
            reparse_point_handle,
10871
            FSCTL_GET_REPARSE_POINT,
10872
            0, 0, /* in buffer */
10873
            target_buffer, sizeof(target_buffer),
10874
            &n_bytes_returned,
10875
            0 /* we're not using OVERLAPPED_IO */
10876
            );
10877
        CloseHandle(reparse_point_handle);
10878
    }
10879
    Py_END_ALLOW_THREADS
10880
10881
    if (io_result == 0) {
10882
        return path_error(path);
10883
    }
10884
10885
    wchar_t *name = NULL;
10886
    Py_ssize_t nameLen = 0;
10887
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10888
    {
10889
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10890
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10891
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10892
    }
10893
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10894
    {
10895
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10896
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10897
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10898
    }
10899
    else
10900
    {
10901
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10902
    }
10903
    if (name) {
10904
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10905
            /* Our buffer is mutable, so this is okay */
10906
            name[1] = L'\\';
10907
        }
10908
        result = PyUnicode_FromWideChar(name, nameLen);
10909
        if (result && PyBytes_Check(path->object)) {
10910
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10911
        }
10912
    }
10913
    return result;
10914
#endif
10915
0
}
10916
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10917
10918
#if defined(MS_WINDOWS)
10919
10920
/* Remove the last portion of the path - return 0 on success */
10921
static int
10922
_dirnameW(WCHAR *path)
10923
{
10924
    WCHAR *ptr;
10925
    size_t length = wcsnlen_s(path, MAX_PATH);
10926
    if (length == MAX_PATH) {
10927
        return -1;
10928
    }
10929
10930
    /* walk the path from the end until a backslash is encountered */
10931
    for(ptr = path + length; ptr != path; ptr--) {
10932
        if (*ptr == L'\\' || *ptr == L'/') {
10933
            break;
10934
        }
10935
    }
10936
    *ptr = 0;
10937
    return 0;
10938
}
10939
10940
#endif
10941
10942
#ifdef HAVE_SYMLINK
10943
10944
#if defined(MS_WINDOWS)
10945
10946
/* Is this path absolute? */
10947
static int
10948
_is_absW(const WCHAR *path)
10949
{
10950
    return path[0] == L'\\' || path[0] == L'/' ||
10951
        (path[0] && path[1] == L':');
10952
}
10953
10954
/* join root and rest with a backslash - return 0 on success */
10955
static int
10956
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10957
{
10958
    if (_is_absW(rest)) {
10959
        return wcscpy_s(dest_path, MAX_PATH, rest);
10960
    }
10961
10962
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
10963
        return -1;
10964
    }
10965
10966
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
10967
        return -1;
10968
    }
10969
10970
    return wcscat_s(dest_path, MAX_PATH, rest);
10971
}
10972
10973
/* Return True if the path at src relative to dest is a directory */
10974
static int
10975
_check_dirW(LPCWSTR src, LPCWSTR dest)
10976
{
10977
    WIN32_FILE_ATTRIBUTE_DATA src_info;
10978
    WCHAR dest_parent[MAX_PATH];
10979
    WCHAR src_resolved[MAX_PATH] = L"";
10980
10981
    /* dest_parent = os.path.dirname(dest) */
10982
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
10983
        _dirnameW(dest_parent)) {
10984
        return 0;
10985
    }
10986
    /* src_resolved = os.path.join(dest_parent, src) */
10987
    if (_joinW(src_resolved, dest_parent, src)) {
10988
        return 0;
10989
    }
10990
    return (
10991
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
10992
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
10993
    );
10994
}
10995
#endif
10996
10997
10998
/*[clinic input]
10999
os.symlink
11000
    src: path_t
11001
    dst: path_t
11002
    target_is_directory: bool = False
11003
    *
11004
    dir_fd: dir_fd(requires='symlinkat')=None
11005
11006
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
11007
11008
Create a symbolic link pointing to src named dst.
11009
11010
target_is_directory is required on Windows if the target is to be
11011
  interpreted as a directory.  (On Windows, symlink requires
11012
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
11013
  target_is_directory is ignored on non-Windows platforms.
11014
11015
If dir_fd is not None, it should be a file descriptor open to a directory,
11016
  and path should be relative; path will then be relative to that directory.
11017
dir_fd may not be implemented on your platform.
11018
  If it is unavailable, using it will raise a NotImplementedError.
11019
11020
[clinic start generated code]*/
11021
11022
static PyObject *
11023
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11024
                int target_is_directory, int dir_fd)
11025
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
11026
0
{
11027
#ifdef MS_WINDOWS
11028
    DWORD result;
11029
    DWORD flags = 0;
11030
11031
    /* Assumed true, set to false if detected to not be available. */
11032
    static int windows_has_symlink_unprivileged_flag = TRUE;
11033
#else
11034
0
    int result;
11035
0
#ifdef HAVE_SYMLINKAT
11036
0
    int symlinkat_unavailable = 0;
11037
0
#endif
11038
0
#endif
11039
11040
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11041
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11042
0
        return NULL;
11043
0
    }
11044
11045
#ifdef MS_WINDOWS
11046
11047
    if (windows_has_symlink_unprivileged_flag) {
11048
        /* Allow non-admin symlinks if system allows it. */
11049
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11050
    }
11051
11052
    Py_BEGIN_ALLOW_THREADS
11053
    _Py_BEGIN_SUPPRESS_IPH
11054
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11055
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11056
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11057
    }
11058
11059
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11060
    _Py_END_SUPPRESS_IPH
11061
    Py_END_ALLOW_THREADS
11062
11063
    if (windows_has_symlink_unprivileged_flag && !result &&
11064
        ERROR_INVALID_PARAMETER == GetLastError()) {
11065
11066
        Py_BEGIN_ALLOW_THREADS
11067
        _Py_BEGIN_SUPPRESS_IPH
11068
        /* This error might be caused by
11069
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11070
        Try again, and update windows_has_symlink_unprivileged_flag if we
11071
        are successful this time.
11072
11073
        NOTE: There is a risk of a race condition here if there are other
11074
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11075
        another process (or thread) changes that condition in between our
11076
        calls to CreateSymbolicLink.
11077
        */
11078
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11079
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11080
        _Py_END_SUPPRESS_IPH
11081
        Py_END_ALLOW_THREADS
11082
11083
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11084
            windows_has_symlink_unprivileged_flag = FALSE;
11085
        }
11086
    }
11087
11088
    if (!result)
11089
        return path_error2(src, dst);
11090
11091
#else
11092
11093
0
    Py_BEGIN_ALLOW_THREADS
11094
0
#ifdef HAVE_SYMLINKAT
11095
0
    if (dir_fd != DEFAULT_DIR_FD) {
11096
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11097
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11098
0
        } else {
11099
0
            symlinkat_unavailable = 1;
11100
0
        }
11101
0
    } else
11102
0
#endif
11103
0
        result = symlink(src->narrow, dst->narrow);
11104
0
    Py_END_ALLOW_THREADS
11105
11106
0
#ifdef HAVE_SYMLINKAT
11107
0
    if (symlinkat_unavailable) {
11108
0
          argument_unavailable_error(NULL, "dir_fd");
11109
0
          return NULL;
11110
0
    }
11111
0
#endif
11112
11113
0
    if (result)
11114
0
        return path_error2(src, dst);
11115
0
#endif
11116
11117
0
    Py_RETURN_NONE;
11118
0
}
11119
#endif /* HAVE_SYMLINK */
11120
11121
11122
static PyStructSequence_Field times_result_fields[] = {
11123
    {"user",    "user time"},
11124
    {"system",   "system time"},
11125
    {"children_user",    "user time of children"},
11126
    {"children_system",    "system time of children"},
11127
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11128
    {NULL}
11129
};
11130
11131
PyDoc_STRVAR(times_result__doc__,
11132
"times_result: Result from os.times().\n\n\
11133
This object may be accessed either as a tuple of\n\
11134
  (user, system, children_user, children_system, elapsed),\n\
11135
or via the attributes user, system, children_user, children_system,\n\
11136
and elapsed.\n\
11137
\n\
11138
See os.times for more information.");
11139
11140
static PyStructSequence_Desc times_result_desc = {
11141
    MODNAME ".times_result", /* name */
11142
    times_result__doc__, /* doc */
11143
    times_result_fields,
11144
    5
11145
};
11146
11147
static PyObject *
11148
build_times_result(PyObject *module, double user, double system,
11149
    double children_user, double children_system,
11150
    double elapsed)
11151
0
{
11152
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11153
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11154
0
    if (value == NULL)
11155
0
        return NULL;
11156
11157
0
#define SET(i, field) \
11158
0
    { \
11159
0
    PyObject *o = PyFloat_FromDouble(field); \
11160
0
    if (!o) { \
11161
0
        Py_DECREF(value); \
11162
0
        return NULL; \
11163
0
    } \
11164
0
    PyStructSequence_SET_ITEM(value, i, o); \
11165
0
    } \
11166
0
11167
0
    SET(0, user);
11168
0
    SET(1, system);
11169
0
    SET(2, children_user);
11170
0
    SET(3, children_system);
11171
0
    SET(4, elapsed);
11172
11173
0
#undef SET
11174
11175
0
    return value;
11176
0
}
11177
11178
11179
/*[clinic input]
11180
os.times
11181
11182
Return a collection containing process timing information.
11183
11184
The object returned behaves like a named tuple with these fields:
11185
  (utime, stime, cutime, cstime, elapsed_time)
11186
All fields are floating-point numbers.
11187
[clinic start generated code]*/
11188
11189
static PyObject *
11190
os_times_impl(PyObject *module)
11191
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11192
0
{
11193
#ifdef MS_WINDOWS
11194
    FILETIME create, exit, kernel, user;
11195
    HANDLE hProc;
11196
    hProc = GetCurrentProcess();
11197
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11198
    /* The fields of a FILETIME structure are the hi and lo part
11199
       of a 64-bit value expressed in 100 nanosecond units.
11200
       1e7 is one second in such units; 1e-7 the inverse.
11201
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11202
    */
11203
    return build_times_result(module,
11204
        (double)(user.dwHighDateTime*429.4967296 +
11205
                 user.dwLowDateTime*1e-7),
11206
        (double)(kernel.dwHighDateTime*429.4967296 +
11207
                 kernel.dwLowDateTime*1e-7),
11208
        (double)0,
11209
        (double)0,
11210
        (double)0);
11211
#else /* MS_WINDOWS */
11212
0
    _posixstate *state = get_posix_state(module);
11213
0
    long ticks_per_second = state->ticks_per_second;
11214
11215
0
    struct tms process;
11216
0
    clock_t elapsed;
11217
0
    errno = 0;
11218
0
    elapsed = times(&process);
11219
0
    if (elapsed == (clock_t) -1) {
11220
0
        return posix_error();
11221
0
    }
11222
11223
0
    return build_times_result(module,
11224
0
        (double)process.tms_utime / ticks_per_second,
11225
0
        (double)process.tms_stime / ticks_per_second,
11226
0
        (double)process.tms_cutime / ticks_per_second,
11227
0
        (double)process.tms_cstime / ticks_per_second,
11228
0
        (double)elapsed / ticks_per_second);
11229
0
#endif /* MS_WINDOWS */
11230
0
}
11231
11232
11233
#if defined(HAVE_TIMERFD_CREATE)
11234
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11235
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11236
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11237
11238
static PyObject *
11239
build_itimerspec(const struct itimerspec* curr_value)
11240
0
{
11241
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11242
0
                                                          curr_value->it_value.tv_nsec);
11243
0
    PyObject *value = PyFloat_FromDouble(_value);
11244
0
    if (value == NULL) {
11245
0
        return NULL;
11246
0
    }
11247
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11248
0
                                                   curr_value->it_interval.tv_nsec);
11249
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11250
0
    if (interval == NULL) {
11251
0
        Py_DECREF(value);
11252
0
        return NULL;
11253
0
    }
11254
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
11255
0
    Py_DECREF(interval);
11256
0
    Py_DECREF(value);
11257
0
    return tuple;
11258
0
}
11259
11260
static PyObject *
11261
build_itimerspec_ns(const struct itimerspec* curr_value)
11262
0
{
11263
0
    PyTime_t value, interval;
11264
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11265
0
        return NULL;
11266
0
    }
11267
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11268
0
        return NULL;
11269
0
    }
11270
0
    return Py_BuildValue("LL", value, interval);
11271
0
}
11272
11273
/*[clinic input]
11274
os.timerfd_create
11275
11276
    clockid: int
11277
        A valid clock ID constant as timer file descriptor.
11278
11279
        time.CLOCK_REALTIME
11280
        time.CLOCK_MONOTONIC
11281
        time.CLOCK_BOOTTIME
11282
    /
11283
    *
11284
    flags: int = 0
11285
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11286
11287
        os.TFD_NONBLOCK
11288
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11289
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11290
11291
        os.TFD_CLOEXEC
11292
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11293
11294
Create and return a timer file descriptor.
11295
[clinic start generated code]*/
11296
11297
static PyObject *
11298
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11299
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11300
11301
0
{
11302
0
    int fd;
11303
0
    Py_BEGIN_ALLOW_THREADS
11304
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11305
0
    fd = timerfd_create(clockid, flags);
11306
0
    Py_END_ALLOW_THREADS
11307
0
    if (fd == -1) {
11308
0
        return PyErr_SetFromErrno(PyExc_OSError);
11309
0
    }
11310
0
    return PyLong_FromLong(fd);
11311
0
}
11312
11313
/*[clinic input]
11314
os.timerfd_settime
11315
11316
    fd: fildes
11317
        A timer file descriptor.
11318
    /
11319
    *
11320
    flags: int = 0
11321
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11322
    initial as initial_double: double = 0.0
11323
        The initial expiration time, in seconds.
11324
    interval as interval_double: double = 0.0
11325
        The timer's interval, in seconds.
11326
11327
Alter a timer file descriptor's internal timer in seconds.
11328
[clinic start generated code]*/
11329
11330
static PyObject *
11331
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11332
                        double initial_double, double interval_double)
11333
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11334
0
{
11335
0
    PyTime_t initial, interval;
11336
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11337
0
                                  &initial) < 0) {
11338
0
        return NULL;
11339
0
    }
11340
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11341
0
                                  &interval) < 0) {
11342
0
        return NULL;
11343
0
    }
11344
11345
0
    struct itimerspec new_value, old_value;
11346
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11347
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11348
0
        return NULL;
11349
0
    }
11350
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11351
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11352
0
        return NULL;
11353
0
    }
11354
11355
0
    int result;
11356
0
    Py_BEGIN_ALLOW_THREADS
11357
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11358
0
    Py_END_ALLOW_THREADS
11359
0
    if (result == -1) {
11360
0
        return PyErr_SetFromErrno(PyExc_OSError);
11361
0
    }
11362
0
    return build_itimerspec(&old_value);
11363
0
}
11364
11365
11366
/*[clinic input]
11367
os.timerfd_settime_ns
11368
11369
    fd: fildes
11370
        A timer file descriptor.
11371
    /
11372
    *
11373
    flags: int = 0
11374
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11375
    initial: long_long = 0
11376
        initial expiration timing in seconds.
11377
    interval: long_long = 0
11378
        interval for the timer in seconds.
11379
11380
Alter a timer file descriptor's internal timer in nanoseconds.
11381
[clinic start generated code]*/
11382
11383
static PyObject *
11384
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11385
                           long long initial, long long interval)
11386
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11387
0
{
11388
0
    struct itimerspec new_value;
11389
0
    struct itimerspec old_value;
11390
0
    int result;
11391
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11392
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11393
0
        return NULL;
11394
0
    }
11395
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11396
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11397
0
        return NULL;
11398
0
    }
11399
0
    Py_BEGIN_ALLOW_THREADS
11400
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11401
0
    Py_END_ALLOW_THREADS
11402
0
    if (result == -1) {
11403
0
        return PyErr_SetFromErrno(PyExc_OSError);
11404
0
    }
11405
0
    return build_itimerspec_ns(&old_value);
11406
0
}
11407
11408
/*[clinic input]
11409
@permit_long_summary
11410
os.timerfd_gettime
11411
11412
    fd: fildes
11413
        A timer file descriptor.
11414
    /
11415
11416
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11417
[clinic start generated code]*/
11418
11419
static PyObject *
11420
os_timerfd_gettime_impl(PyObject *module, int fd)
11421
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11422
0
{
11423
0
    struct itimerspec curr_value;
11424
0
    int result;
11425
0
    Py_BEGIN_ALLOW_THREADS
11426
0
    result = timerfd_gettime(fd, &curr_value);
11427
0
    Py_END_ALLOW_THREADS
11428
0
    if (result == -1) {
11429
0
        return PyErr_SetFromErrno(PyExc_OSError);
11430
0
    }
11431
0
    return build_itimerspec(&curr_value);
11432
0
}
11433
11434
11435
/*[clinic input]
11436
@permit_long_summary
11437
os.timerfd_gettime_ns
11438
11439
    fd: fildes
11440
        A timer file descriptor.
11441
    /
11442
11443
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11444
[clinic start generated code]*/
11445
11446
static PyObject *
11447
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11448
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11449
0
{
11450
0
    struct itimerspec curr_value;
11451
0
    int result;
11452
0
    Py_BEGIN_ALLOW_THREADS
11453
0
    result = timerfd_gettime(fd, &curr_value);
11454
0
    Py_END_ALLOW_THREADS
11455
0
    if (result == -1) {
11456
0
        return PyErr_SetFromErrno(PyExc_OSError);
11457
0
    }
11458
0
    return build_itimerspec_ns(&curr_value);
11459
0
}
11460
11461
#undef ONE_SECOND_IN_NS
11462
#undef EXTRACT_NSEC
11463
11464
#endif  /* HAVE_TIMERFD_CREATE */
11465
11466
#ifdef HAVE_GETSID
11467
/*[clinic input]
11468
os.getsid
11469
11470
    pid: pid_t
11471
    /
11472
11473
Call the system call getsid(pid) and return the result.
11474
[clinic start generated code]*/
11475
11476
static PyObject *
11477
os_getsid_impl(PyObject *module, pid_t pid)
11478
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11479
0
{
11480
0
    int sid;
11481
0
    sid = getsid(pid);
11482
0
    if (sid < 0)
11483
0
        return posix_error();
11484
0
    return PyLong_FromLong((long)sid);
11485
0
}
11486
#endif /* HAVE_GETSID */
11487
11488
11489
#ifdef HAVE_SETSID
11490
/*[clinic input]
11491
os.setsid
11492
11493
Call the system call setsid().
11494
[clinic start generated code]*/
11495
11496
static PyObject *
11497
os_setsid_impl(PyObject *module)
11498
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11499
0
{
11500
0
    if (setsid() < 0)
11501
0
        return posix_error();
11502
0
    Py_RETURN_NONE;
11503
0
}
11504
#endif /* HAVE_SETSID */
11505
11506
11507
#ifdef HAVE_SETPGID
11508
/*[clinic input]
11509
os.setpgid
11510
11511
    pid: pid_t
11512
    pgrp: pid_t
11513
    /
11514
11515
Call the system call setpgid(pid, pgrp).
11516
[clinic start generated code]*/
11517
11518
static PyObject *
11519
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11520
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11521
0
{
11522
0
    if (setpgid(pid, pgrp) < 0)
11523
0
        return posix_error();
11524
0
    Py_RETURN_NONE;
11525
0
}
11526
#endif /* HAVE_SETPGID */
11527
11528
11529
#ifdef HAVE_TCGETPGRP
11530
/*[clinic input]
11531
os.tcgetpgrp
11532
11533
    fd: int
11534
    /
11535
11536
Return the process group associated with the terminal specified by fd.
11537
[clinic start generated code]*/
11538
11539
static PyObject *
11540
os_tcgetpgrp_impl(PyObject *module, int fd)
11541
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11542
0
{
11543
0
    pid_t pgid = tcgetpgrp(fd);
11544
0
    if (pgid < 0)
11545
0
        return posix_error();
11546
0
    return PyLong_FromPid(pgid);
11547
0
}
11548
#endif /* HAVE_TCGETPGRP */
11549
11550
11551
#ifdef HAVE_TCSETPGRP
11552
/*[clinic input]
11553
os.tcsetpgrp
11554
11555
    fd: int
11556
    pgid: pid_t
11557
    /
11558
11559
Set the process group associated with the terminal specified by fd.
11560
[clinic start generated code]*/
11561
11562
static PyObject *
11563
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11564
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11565
0
{
11566
0
    if (tcsetpgrp(fd, pgid) < 0)
11567
0
        return posix_error();
11568
0
    Py_RETURN_NONE;
11569
0
}
11570
#endif /* HAVE_TCSETPGRP */
11571
11572
/* Functions acting on file descriptors */
11573
11574
#ifdef O_CLOEXEC
11575
extern int _Py_open_cloexec_works;
11576
#endif
11577
11578
11579
/*[clinic input]
11580
os.open -> int
11581
    path: path_t
11582
    flags: int
11583
    mode: int = 0o777
11584
    *
11585
    dir_fd: dir_fd(requires='openat') = None
11586
11587
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11588
11589
Open a file for low level IO.  Returns a file descriptor (integer).
11590
11591
If dir_fd is not None, it should be a file descriptor open to a directory,
11592
  and path should be relative; path will then be relative to that directory.
11593
dir_fd may not be implemented on your platform.
11594
  If it is unavailable, using it will raise a NotImplementedError.
11595
[clinic start generated code]*/
11596
11597
static int
11598
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11599
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11600
260
{
11601
260
    int fd;
11602
260
    int async_err = 0;
11603
260
#ifdef HAVE_OPENAT
11604
260
    int openat_unavailable = 0;
11605
260
#endif
11606
11607
260
#ifdef O_CLOEXEC
11608
260
    int *atomic_flag_works = &_Py_open_cloexec_works;
11609
#elif !defined(MS_WINDOWS)
11610
    int *atomic_flag_works = NULL;
11611
#endif
11612
11613
#ifdef MS_WINDOWS
11614
    flags |= O_NOINHERIT;
11615
#elif defined(O_CLOEXEC)
11616
260
    flags |= O_CLOEXEC;
11617
260
#endif
11618
11619
260
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11620
0
        return -1;
11621
0
    }
11622
11623
260
    _Py_BEGIN_SUPPRESS_IPH
11624
260
    do {
11625
260
        Py_BEGIN_ALLOW_THREADS
11626
#ifdef MS_WINDOWS
11627
        fd = _wopen(path->wide, flags, mode);
11628
#else
11629
260
#ifdef HAVE_OPENAT
11630
260
        if (dir_fd != DEFAULT_DIR_FD) {
11631
0
            if (HAVE_OPENAT_RUNTIME) {
11632
0
                fd = openat(dir_fd, path->narrow, flags, mode);
11633
11634
0
            } else {
11635
0
                openat_unavailable = 1;
11636
0
                fd = -1;
11637
0
            }
11638
0
        } else
11639
260
#endif /* HAVE_OPENAT */
11640
260
            fd = open(path->narrow, flags, mode);
11641
260
#endif /* !MS_WINDOWS */
11642
260
        Py_END_ALLOW_THREADS
11643
260
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11644
260
    _Py_END_SUPPRESS_IPH
11645
11646
260
#ifdef HAVE_OPENAT
11647
260
    if (openat_unavailable) {
11648
0
        argument_unavailable_error(NULL, "dir_fd");
11649
0
        return -1;
11650
0
    }
11651
260
#endif
11652
11653
260
    if (fd < 0) {
11654
0
        if (!async_err)
11655
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11656
0
        return -1;
11657
0
    }
11658
11659
260
#ifndef MS_WINDOWS
11660
260
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11661
0
        close(fd);
11662
0
        return -1;
11663
0
    }
11664
260
#endif
11665
11666
260
    return fd;
11667
260
}
11668
11669
11670
/*[clinic input]
11671
os.close
11672
11673
    fd: int
11674
11675
Close a file descriptor.
11676
[clinic start generated code]*/
11677
11678
static PyObject *
11679
os_close_impl(PyObject *module, int fd)
11680
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11681
0
{
11682
0
    int res;
11683
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11684
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11685
     * for more details.
11686
     */
11687
0
    Py_BEGIN_ALLOW_THREADS
11688
0
    _Py_BEGIN_SUPPRESS_IPH
11689
0
    res = close(fd);
11690
0
    _Py_END_SUPPRESS_IPH
11691
0
    Py_END_ALLOW_THREADS
11692
0
    if (res < 0)
11693
0
        return posix_error();
11694
0
    Py_RETURN_NONE;
11695
0
}
11696
11697
/*[clinic input]
11698
os.closerange
11699
11700
    fd_low: int
11701
    fd_high: int
11702
    /
11703
11704
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11705
[clinic start generated code]*/
11706
11707
static PyObject *
11708
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11709
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11710
0
{
11711
0
    Py_BEGIN_ALLOW_THREADS
11712
0
    _Py_closerange(fd_low, fd_high - 1);
11713
0
    Py_END_ALLOW_THREADS
11714
0
    Py_RETURN_NONE;
11715
0
}
11716
11717
11718
/*[clinic input]
11719
os.dup -> int
11720
11721
    fd: int
11722
    /
11723
11724
Return a duplicate of a file descriptor.
11725
[clinic start generated code]*/
11726
11727
static int
11728
os_dup_impl(PyObject *module, int fd)
11729
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11730
0
{
11731
0
    return _Py_dup(fd);
11732
0
}
11733
11734
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11735
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11736
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11737
/*[clinic input]
11738
os.dup2 -> int
11739
    fd: int
11740
    fd2: int
11741
    inheritable: bool=True
11742
11743
Duplicate file descriptor.
11744
[clinic start generated code]*/
11745
11746
static int
11747
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11748
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11749
0
{
11750
0
    int res = 0;
11751
0
#if defined(HAVE_DUP3) && \
11752
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11753
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11754
0
    static int dup3_works = -1;
11755
0
#endif
11756
11757
    /* dup2() can fail with EINTR if the target FD is already open, because it
11758
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11759
     * upon close(), and therefore below.
11760
     */
11761
#ifdef MS_WINDOWS
11762
    Py_BEGIN_ALLOW_THREADS
11763
    _Py_BEGIN_SUPPRESS_IPH
11764
    res = dup2(fd, fd2);
11765
    _Py_END_SUPPRESS_IPH
11766
    Py_END_ALLOW_THREADS
11767
    if (res < 0) {
11768
        posix_error();
11769
        return -1;
11770
    }
11771
    res = fd2; // msvcrt dup2 returns 0 on success.
11772
11773
    /* Character files like console cannot be make non-inheritable */
11774
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11775
        close(fd2);
11776
        return -1;
11777
    }
11778
11779
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11780
    Py_BEGIN_ALLOW_THREADS
11781
    if (!inheritable)
11782
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11783
    else
11784
        res = dup2(fd, fd2);
11785
    Py_END_ALLOW_THREADS
11786
    if (res < 0) {
11787
        posix_error();
11788
        return -1;
11789
    }
11790
11791
#else
11792
11793
0
#ifdef HAVE_DUP3
11794
0
    if (!inheritable && dup3_works != 0) {
11795
0
        Py_BEGIN_ALLOW_THREADS
11796
0
        res = dup3(fd, fd2, O_CLOEXEC);
11797
0
        Py_END_ALLOW_THREADS
11798
0
        if (res < 0) {
11799
0
            if (dup3_works == -1)
11800
0
                dup3_works = (errno != ENOSYS);
11801
0
            if (dup3_works) {
11802
0
                posix_error();
11803
0
                return -1;
11804
0
            }
11805
0
        }
11806
0
    }
11807
11808
0
    if (inheritable || dup3_works == 0)
11809
0
    {
11810
0
#endif
11811
0
        Py_BEGIN_ALLOW_THREADS
11812
0
        res = dup2(fd, fd2);
11813
0
        Py_END_ALLOW_THREADS
11814
0
        if (res < 0) {
11815
0
            posix_error();
11816
0
            return -1;
11817
0
        }
11818
11819
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11820
0
            close(fd2);
11821
0
            return -1;
11822
0
        }
11823
0
#ifdef HAVE_DUP3
11824
0
    }
11825
0
#endif
11826
11827
0
#endif
11828
11829
0
    return res;
11830
0
}
11831
#endif
11832
11833
11834
#ifdef HAVE_LOCKF
11835
/*[clinic input]
11836
os.lockf
11837
11838
    fd: int
11839
        An open file descriptor.
11840
    command: int
11841
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11842
    length: Py_off_t
11843
        The number of bytes to lock, starting at the current position.
11844
    /
11845
11846
Apply, test or remove a POSIX lock on an open file descriptor.
11847
11848
[clinic start generated code]*/
11849
11850
static PyObject *
11851
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11852
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11853
0
{
11854
0
    int res;
11855
11856
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11857
0
        return NULL;
11858
0
    }
11859
11860
0
    Py_BEGIN_ALLOW_THREADS
11861
0
    res = lockf(fd, command, length);
11862
0
    Py_END_ALLOW_THREADS
11863
11864
0
    if (res < 0)
11865
0
        return posix_error();
11866
11867
0
    Py_RETURN_NONE;
11868
0
}
11869
#endif /* HAVE_LOCKF */
11870
11871
11872
/*[clinic input]
11873
@permit_long_docstring_body
11874
os.lseek -> Py_off_t
11875
11876
    fd: int
11877
        An open file descriptor, as returned by os.open().
11878
    position: Py_off_t
11879
        Position, interpreted relative to 'whence'.
11880
    whence as how: int
11881
        The relative position to seek from. Valid values are:
11882
        - SEEK_SET: seek from the start of the file.
11883
        - SEEK_CUR: seek from the current file position.
11884
        - SEEK_END: seek from the end of the file.
11885
    /
11886
11887
Set the position of a file descriptor.  Return the new position.
11888
11889
The return value is the number of bytes relative to the beginning of the file.
11890
[clinic start generated code]*/
11891
11892
static Py_off_t
11893
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11894
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11895
0
{
11896
0
    Py_off_t result;
11897
11898
0
#ifdef SEEK_SET
11899
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11900
0
    switch (how) {
11901
0
        case 0: how = SEEK_SET; break;
11902
0
        case 1: how = SEEK_CUR; break;
11903
0
        case 2: how = SEEK_END; break;
11904
0
    }
11905
0
#endif /* SEEK_END */
11906
11907
0
    Py_BEGIN_ALLOW_THREADS
11908
0
    _Py_BEGIN_SUPPRESS_IPH
11909
#ifdef MS_WINDOWS
11910
    result = _lseeki64(fd, position, how);
11911
#else
11912
0
    result = lseek(fd, position, how);
11913
0
#endif
11914
0
    _Py_END_SUPPRESS_IPH
11915
0
    Py_END_ALLOW_THREADS
11916
0
    if (result < 0)
11917
0
        posix_error();
11918
11919
0
    return result;
11920
0
}
11921
11922
11923
/*[clinic input]
11924
os.read
11925
    fd: int
11926
    length: Py_ssize_t
11927
    /
11928
11929
Read from a file descriptor.  Returns a bytes object.
11930
[clinic start generated code]*/
11931
11932
static PyObject *
11933
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11934
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11935
0
{
11936
0
    if (length < 0) {
11937
0
        errno = EINVAL;
11938
0
        return posix_error();
11939
0
    }
11940
11941
0
    length = Py_MIN(length, _PY_READ_MAX);
11942
11943
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11944
0
    if (writer == NULL) {
11945
0
        return NULL;
11946
0
    }
11947
11948
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11949
0
    if (n == -1) {
11950
0
        PyBytesWriter_Discard(writer);
11951
0
        return NULL;
11952
0
    }
11953
11954
0
    return PyBytesWriter_FinishWithSize(writer, n);
11955
0
}
11956
11957
/*[clinic input]
11958
@permit_long_docstring_body
11959
os.readinto -> Py_ssize_t
11960
    fd: int
11961
    buffer: Py_buffer(accept={rwbuffer})
11962
    /
11963
11964
Read into a buffer object from a file descriptor.
11965
11966
The buffer should be mutable and bytes-like. On success, returns the number of
11967
bytes read. Less bytes may be read than the size of the buffer. The underlying
11968
system call will be retried when interrupted by a signal, unless the signal
11969
handler raises an exception. Other errors will not be retried and an error will
11970
be raised.
11971
11972
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
11973
(which can be used to check for errors without reading data). Never returns
11974
negative.
11975
[clinic start generated code]*/
11976
11977
static Py_ssize_t
11978
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
11979
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
11980
0
{
11981
0
    assert(buffer->len >= 0);
11982
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
11983
    /* Ensure negative is never returned without an error. Simplifies calling
11984
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
11985
        error. */
11986
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
11987
0
    return result;
11988
0
}
11989
11990
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
11991
                                || defined(__APPLE__))) \
11992
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
11993
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
11994
static int
11995
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
11996
0
{
11997
0
    Py_ssize_t i, j;
11998
11999
0
    *iov = PyMem_New(struct iovec, cnt);
12000
0
    if (*iov == NULL) {
12001
0
        PyErr_NoMemory();
12002
0
        return -1;
12003
0
    }
12004
12005
0
    *buf = PyMem_New(Py_buffer, cnt);
12006
0
    if (*buf == NULL) {
12007
0
        PyMem_Free(*iov);
12008
0
        PyErr_NoMemory();
12009
0
        return -1;
12010
0
    }
12011
12012
0
    for (i = 0; i < cnt; i++) {
12013
0
        PyObject *item = PySequence_GetItem(seq, i);
12014
0
        if (item == NULL)
12015
0
            goto fail;
12016
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12017
0
            Py_DECREF(item);
12018
0
            goto fail;
12019
0
        }
12020
0
        Py_DECREF(item);
12021
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12022
0
        (*iov)[i].iov_len = (*buf)[i].len;
12023
0
    }
12024
0
    return 0;
12025
12026
0
fail:
12027
0
    PyMem_Free(*iov);
12028
0
    for (j = 0; j < i; j++) {
12029
0
        PyBuffer_Release(&(*buf)[j]);
12030
0
    }
12031
0
    PyMem_Free(*buf);
12032
0
    return -1;
12033
0
}
12034
12035
static void
12036
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12037
0
{
12038
0
    int i;
12039
0
    PyMem_Free(iov);
12040
0
    for (i = 0; i < cnt; i++) {
12041
0
        PyBuffer_Release(&buf[i]);
12042
0
    }
12043
0
    PyMem_Free(buf);
12044
0
}
12045
#endif
12046
12047
12048
#ifdef HAVE_READV
12049
/*[clinic input]
12050
os.readv -> Py_ssize_t
12051
12052
    fd: int
12053
    buffers: object
12054
    /
12055
12056
Read from a file descriptor fd into an iterable of buffers.
12057
12058
The buffers should be mutable buffers accepting bytes.
12059
readv will transfer data into each buffer until it is full
12060
and then move on to the next buffer in the sequence to hold
12061
the rest of the data.
12062
12063
readv returns the total number of bytes read,
12064
which may be less than the total capacity of all the buffers.
12065
[clinic start generated code]*/
12066
12067
static Py_ssize_t
12068
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12069
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12070
0
{
12071
0
    Py_ssize_t cnt, n;
12072
0
    int async_err = 0;
12073
0
    struct iovec *iov;
12074
0
    Py_buffer *buf;
12075
12076
0
    if (!PySequence_Check(buffers)) {
12077
0
        PyErr_SetString(PyExc_TypeError,
12078
0
            "readv() arg 2 must be a sequence");
12079
0
        return -1;
12080
0
    }
12081
12082
0
    cnt = PySequence_Size(buffers);
12083
0
    if (cnt < 0)
12084
0
        return -1;
12085
12086
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12087
0
        return -1;
12088
12089
0
    do {
12090
0
        Py_BEGIN_ALLOW_THREADS
12091
0
        n = readv(fd, iov, cnt);
12092
0
        Py_END_ALLOW_THREADS
12093
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12094
12095
0
    int saved_errno = errno;
12096
0
    iov_cleanup(iov, buf, cnt);
12097
0
    if (n < 0) {
12098
0
        if (!async_err) {
12099
0
            errno = saved_errno;
12100
0
            posix_error();
12101
0
        }
12102
0
        return -1;
12103
0
    }
12104
12105
0
    return n;
12106
0
}
12107
#endif /* HAVE_READV */
12108
12109
12110
#ifdef HAVE_PREAD
12111
/*[clinic input]
12112
@permit_long_summary
12113
os.pread
12114
12115
    fd: int
12116
    length: Py_ssize_t
12117
    offset: Py_off_t
12118
    /
12119
12120
Read a number of bytes from a file descriptor starting at a particular offset.
12121
12122
Read length bytes from file descriptor fd, starting at offset bytes from
12123
the beginning of the file.  The file offset remains unchanged.
12124
[clinic start generated code]*/
12125
12126
static PyObject *
12127
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12128
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12129
0
{
12130
0
    Py_ssize_t n;
12131
0
    int async_err = 0;
12132
12133
0
    if (length < 0) {
12134
0
        errno = EINVAL;
12135
0
        return posix_error();
12136
0
    }
12137
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12138
0
    if (writer == NULL) {
12139
0
        return NULL;
12140
0
    }
12141
12142
0
    do {
12143
0
        Py_BEGIN_ALLOW_THREADS
12144
0
        _Py_BEGIN_SUPPRESS_IPH
12145
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12146
0
        _Py_END_SUPPRESS_IPH
12147
0
        Py_END_ALLOW_THREADS
12148
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12149
12150
0
    if (n < 0) {
12151
0
        if (!async_err) {
12152
0
            posix_error();
12153
0
        }
12154
0
        PyBytesWriter_Discard(writer);
12155
0
        return NULL;
12156
0
    }
12157
0
    return PyBytesWriter_FinishWithSize(writer, n);
12158
0
}
12159
#endif /* HAVE_PREAD */
12160
12161
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12162
/*[clinic input]
12163
@permit_long_docstring_body
12164
os.preadv -> Py_ssize_t
12165
12166
    fd: int
12167
    buffers: object
12168
    offset: Py_off_t
12169
    flags: int = 0
12170
    /
12171
12172
Reads from a file descriptor into a number of mutable bytes-like objects.
12173
12174
Combines the functionality of readv() and pread(). As readv(), it will
12175
transfer data into each buffer until it is full and then move on to the next
12176
buffer in the sequence to hold the rest of the data. Its fourth argument,
12177
specifies the file offset at which the input operation is to be performed. It
12178
will return the total number of bytes read (which can be less than the total
12179
capacity of all the objects).
12180
12181
The flags argument contains a bitwise OR of zero or more of the following flags:
12182
12183
- RWF_HIPRI
12184
- RWF_NOWAIT
12185
- RWF_DONTCACHE
12186
12187
Using non-zero flags requires Linux 4.6 or newer.
12188
[clinic start generated code]*/
12189
12190
static Py_ssize_t
12191
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12192
               int flags)
12193
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
12194
0
{
12195
0
    Py_ssize_t cnt, n;
12196
0
    int async_err = 0;
12197
0
    struct iovec *iov;
12198
0
    Py_buffer *buf;
12199
12200
0
    if (!PySequence_Check(buffers)) {
12201
0
        PyErr_SetString(PyExc_TypeError,
12202
0
            "preadv2() arg 2 must be a sequence");
12203
0
        return -1;
12204
0
    }
12205
12206
0
    cnt = PySequence_Size(buffers);
12207
0
    if (cnt < 0) {
12208
0
        return -1;
12209
0
    }
12210
12211
#ifndef HAVE_PREADV2
12212
    if(flags != 0) {
12213
        argument_unavailable_error("preadv2", "flags");
12214
        return -1;
12215
    }
12216
#endif
12217
12218
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12219
0
        return -1;
12220
0
    }
12221
0
#ifdef HAVE_PREADV2
12222
0
    do {
12223
0
        Py_BEGIN_ALLOW_THREADS
12224
0
        _Py_BEGIN_SUPPRESS_IPH
12225
0
        n = preadv2(fd, iov, cnt, offset, flags);
12226
0
        _Py_END_SUPPRESS_IPH
12227
0
        Py_END_ALLOW_THREADS
12228
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12229
#else
12230
    do {
12231
#if defined(__APPLE__) && defined(__clang__)
12232
/* This entire function will be removed from the module dict when the API
12233
 * is not available.
12234
 */
12235
#pragma clang diagnostic push
12236
#pragma clang diagnostic ignored "-Wunguarded-availability"
12237
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12238
#endif
12239
        Py_BEGIN_ALLOW_THREADS
12240
        _Py_BEGIN_SUPPRESS_IPH
12241
        n = preadv(fd, iov, cnt, offset);
12242
        _Py_END_SUPPRESS_IPH
12243
        Py_END_ALLOW_THREADS
12244
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12245
12246
#if defined(__APPLE__) && defined(__clang__)
12247
#pragma clang diagnostic pop
12248
#endif
12249
12250
#endif
12251
12252
0
    int saved_errno = errno;
12253
0
    iov_cleanup(iov, buf, cnt);
12254
0
    if (n < 0) {
12255
0
        if (!async_err) {
12256
0
            errno = saved_errno;
12257
0
            posix_error();
12258
0
        }
12259
0
        return -1;
12260
0
    }
12261
12262
0
    return n;
12263
0
}
12264
#endif /* HAVE_PREADV */
12265
12266
12267
/*[clinic input]
12268
os.write -> Py_ssize_t
12269
12270
    fd: int
12271
    data: Py_buffer
12272
    /
12273
12274
Write a bytes object to a file descriptor.
12275
[clinic start generated code]*/
12276
12277
static Py_ssize_t
12278
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12279
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12280
0
{
12281
0
    return _Py_write(fd, data->buf, data->len);
12282
0
}
12283
12284
#ifdef HAVE_SENDFILE
12285
#ifdef __APPLE__
12286
/*[clinic input]
12287
os.sendfile
12288
12289
    out_fd: int
12290
    in_fd: int
12291
    offset: Py_off_t
12292
    count as sbytes: Py_off_t
12293
    headers: object(c_default="NULL") = ()
12294
    trailers: object(c_default="NULL") = ()
12295
    flags: int = 0
12296
12297
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12298
[clinic start generated code]*/
12299
12300
static PyObject *
12301
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12302
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12303
                 int flags)
12304
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12305
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12306
/*[clinic input]
12307
os.sendfile
12308
12309
    out_fd: int
12310
    in_fd: int
12311
    offset: Py_off_t
12312
    count: Py_ssize_t(allow_negative=False)
12313
    headers: object(c_default="NULL") = ()
12314
    trailers: object(c_default="NULL") = ()
12315
    flags: int = 0
12316
12317
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12318
[clinic start generated code]*/
12319
12320
static PyObject *
12321
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12322
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12323
                 int flags)
12324
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12325
#else
12326
/*[clinic input]
12327
os.sendfile
12328
12329
    out_fd: int
12330
    in_fd: int
12331
    offset as offobj: object
12332
    count: Py_ssize_t(allow_negative=False)
12333
12334
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12335
[clinic start generated code]*/
12336
12337
static PyObject *
12338
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12339
                 Py_ssize_t count)
12340
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12341
#endif
12342
0
{
12343
0
    Py_ssize_t ret;
12344
0
    int async_err = 0;
12345
12346
#ifdef __APPLE__
12347
    if(sbytes < 0) {
12348
        PyErr_SetString(PyExc_ValueError,
12349
                        "count cannot be negative");
12350
        return NULL;
12351
    }
12352
#else
12353
0
    assert(count >= 0);
12354
0
#endif
12355
12356
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12357
#ifndef __APPLE__
12358
    off_t sbytes;
12359
#endif
12360
    Py_buffer *hbuf, *tbuf;
12361
    struct sf_hdtr sf;
12362
12363
    sf.headers = NULL;
12364
    sf.trailers = NULL;
12365
12366
    if (headers != NULL) {
12367
        if (!PySequence_Check(headers)) {
12368
            PyErr_SetString(PyExc_TypeError,
12369
                "sendfile() headers must be a sequence");
12370
            return NULL;
12371
        } else {
12372
            Py_ssize_t i = PySequence_Size(headers);
12373
            if (i < 0)
12374
                return NULL;
12375
            if (i > INT_MAX) {
12376
                PyErr_SetString(PyExc_OverflowError,
12377
                    "sendfile() header is too large");
12378
                return NULL;
12379
            }
12380
            if (i > 0) {
12381
                sf.hdr_cnt = (int)i;
12382
                if (iov_setup(&(sf.headers), &hbuf,
12383
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12384
                    return NULL;
12385
#ifdef __APPLE__
12386
                for (i = 0; i < sf.hdr_cnt; i++) {
12387
                    Py_ssize_t blen = sf.headers[i].iov_len;
12388
# define OFF_T_MAX 0x7fffffffffffffff
12389
                    if (sbytes >= OFF_T_MAX - blen) {
12390
                        PyErr_SetString(PyExc_OverflowError,
12391
                            "sendfile() header is too large");
12392
                        return NULL;
12393
                    }
12394
                    sbytes += blen;
12395
                }
12396
#endif
12397
            }
12398
        }
12399
    }
12400
    if (trailers != NULL) {
12401
        if (!PySequence_Check(trailers)) {
12402
            PyErr_SetString(PyExc_TypeError,
12403
                "sendfile() trailers must be a sequence");
12404
            return NULL;
12405
        } else {
12406
            Py_ssize_t i = PySequence_Size(trailers);
12407
            if (i < 0)
12408
                return NULL;
12409
            if (i > INT_MAX) {
12410
                PyErr_SetString(PyExc_OverflowError,
12411
                    "sendfile() trailer is too large");
12412
                return NULL;
12413
            }
12414
            if (i > 0) {
12415
                sf.trl_cnt = (int)i;
12416
                if (iov_setup(&(sf.trailers), &tbuf,
12417
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12418
                    return NULL;
12419
            }
12420
        }
12421
    }
12422
12423
    _Py_BEGIN_SUPPRESS_IPH
12424
    do {
12425
        Py_BEGIN_ALLOW_THREADS
12426
#ifdef __APPLE__
12427
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12428
#else
12429
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12430
#endif
12431
        Py_END_ALLOW_THREADS
12432
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12433
    _Py_END_SUPPRESS_IPH
12434
12435
    int saved_errno = errno;
12436
    if (sf.headers != NULL)
12437
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12438
    if (sf.trailers != NULL)
12439
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12440
12441
    if (ret < 0) {
12442
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12443
            if (sbytes != 0) {
12444
                // some data has been sent
12445
                goto done;
12446
            }
12447
            // no data has been sent; upper application is supposed
12448
            // to retry on EAGAIN or EBUSY
12449
        }
12450
        if (!async_err) {
12451
            errno = saved_errno;
12452
            posix_error();
12453
        }
12454
        return NULL;
12455
    }
12456
    goto done;
12457
12458
done:
12459
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12460
        return PyLong_FromLong(sbytes);
12461
    #else
12462
        return PyLong_FromLongLong(sbytes);
12463
    #endif
12464
12465
#else
12466
0
#ifdef __linux__
12467
0
    if (offobj == Py_None) {
12468
0
        do {
12469
0
            Py_BEGIN_ALLOW_THREADS
12470
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12471
0
            Py_END_ALLOW_THREADS
12472
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12473
0
        if (ret < 0)
12474
0
            return (!async_err) ? posix_error() : NULL;
12475
0
        return PyLong_FromSsize_t(ret);
12476
0
    }
12477
0
#endif
12478
0
    off_t offset;
12479
0
    if (!Py_off_t_converter(offobj, &offset))
12480
0
        return NULL;
12481
12482
#if defined(__sun) && defined(__SVR4)
12483
    // On Solaris, sendfile raises EINVAL rather than returning 0
12484
    // when the offset is equal or bigger than the in_fd size.
12485
    struct stat st;
12486
12487
    do {
12488
        Py_BEGIN_ALLOW_THREADS
12489
        ret = fstat(in_fd, &st);
12490
        Py_END_ALLOW_THREADS
12491
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12492
    if (ret < 0)
12493
        return (!async_err) ? posix_error() : NULL;
12494
12495
    if (offset >= st.st_size) {
12496
        return PyLong_FromLong(0);
12497
    }
12498
12499
    // On illumos specifically sendfile() may perform a partial write but
12500
    // return -1/an error (in one confirmed case the destination socket
12501
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12502
    // code to check if the offset parameter was modified by sendfile().
12503
    //
12504
    // We need this variable to track said change.
12505
    off_t original_offset = offset;
12506
#endif
12507
12508
0
    do {
12509
0
        Py_BEGIN_ALLOW_THREADS
12510
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12511
#if defined(__sun) && defined(__SVR4)
12512
        // This handles illumos-specific sendfile() partial write behavior,
12513
        // see a comment above for more details.
12514
        if (ret < 0 && offset != original_offset) {
12515
            ret = offset - original_offset;
12516
        }
12517
#endif
12518
0
        Py_END_ALLOW_THREADS
12519
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12520
0
    if (ret < 0)
12521
0
        return (!async_err) ? posix_error() : NULL;
12522
0
    return PyLong_FromSsize_t(ret);
12523
0
#endif
12524
0
}
12525
#endif /* HAVE_SENDFILE */
12526
12527
12528
#if defined(__APPLE__)
12529
/*[clinic input]
12530
os._fcopyfile
12531
12532
    in_fd: int
12533
    out_fd: int
12534
    flags: int
12535
    /
12536
12537
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12538
[clinic start generated code]*/
12539
12540
static PyObject *
12541
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12542
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12543
{
12544
    int ret;
12545
12546
    Py_BEGIN_ALLOW_THREADS
12547
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12548
    Py_END_ALLOW_THREADS
12549
    if (ret < 0)
12550
        return posix_error();
12551
    Py_RETURN_NONE;
12552
}
12553
#endif
12554
12555
12556
/*[clinic input]
12557
os.fstat
12558
12559
    fd : int
12560
12561
Perform a stat system call on the given file descriptor.
12562
12563
Like stat(), but for an open file descriptor.
12564
Equivalent to os.stat(fd).
12565
[clinic start generated code]*/
12566
12567
static PyObject *
12568
os_fstat_impl(PyObject *module, int fd)
12569
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12570
0
{
12571
0
    STRUCT_STAT st;
12572
0
    int res;
12573
0
    int async_err = 0;
12574
12575
0
    do {
12576
0
        Py_BEGIN_ALLOW_THREADS
12577
0
        res = FSTAT(fd, &st);
12578
0
        Py_END_ALLOW_THREADS
12579
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12580
0
    if (res != 0) {
12581
#ifdef MS_WINDOWS
12582
        return PyErr_SetFromWindowsErr(0);
12583
#else
12584
0
        return (!async_err) ? posix_error() : NULL;
12585
0
#endif
12586
0
    }
12587
12588
0
    return _pystat_fromstructstat(module, &st);
12589
0
}
12590
12591
12592
/*[clinic input]
12593
os.isatty -> bool
12594
    fd: int
12595
    /
12596
12597
Return True if the fd is connected to a terminal.
12598
12599
Return True if the file descriptor is an open file descriptor
12600
connected to the slave end of a terminal.
12601
[clinic start generated code]*/
12602
12603
static int
12604
os_isatty_impl(PyObject *module, int fd)
12605
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12606
0
{
12607
0
    int return_value;
12608
0
    Py_BEGIN_ALLOW_THREADS
12609
0
    _Py_BEGIN_SUPPRESS_IPH
12610
0
    return_value = isatty(fd);
12611
0
    _Py_END_SUPPRESS_IPH
12612
0
    Py_END_ALLOW_THREADS
12613
0
    return return_value;
12614
0
}
12615
12616
12617
#ifdef HAVE_PIPE
12618
/*[clinic input]
12619
os.pipe
12620
12621
Create a pipe.
12622
12623
Returns a tuple of two file descriptors:
12624
  (read_fd, write_fd)
12625
[clinic start generated code]*/
12626
12627
static PyObject *
12628
os_pipe_impl(PyObject *module)
12629
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12630
0
{
12631
0
    int fds[2];
12632
#ifdef MS_WINDOWS
12633
    HANDLE read, write;
12634
    SECURITY_ATTRIBUTES attr;
12635
    BOOL ok;
12636
#else
12637
0
    int res;
12638
0
#endif
12639
12640
#ifdef MS_WINDOWS
12641
    attr.nLength = sizeof(attr);
12642
    attr.lpSecurityDescriptor = NULL;
12643
    attr.bInheritHandle = FALSE;
12644
12645
    Py_BEGIN_ALLOW_THREADS
12646
    ok = CreatePipe(&read, &write, &attr, 0);
12647
    if (ok) {
12648
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12649
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12650
        if (fds[0] == -1 || fds[1] == -1) {
12651
            CloseHandle(read);
12652
            CloseHandle(write);
12653
            ok = 0;
12654
        }
12655
    }
12656
    Py_END_ALLOW_THREADS
12657
12658
    if (!ok)
12659
        return PyErr_SetFromWindowsErr(0);
12660
#else
12661
12662
0
#ifdef HAVE_PIPE2
12663
0
    Py_BEGIN_ALLOW_THREADS
12664
0
    res = pipe2(fds, O_CLOEXEC);
12665
0
    Py_END_ALLOW_THREADS
12666
12667
0
    if (res != 0 && errno == ENOSYS)
12668
0
    {
12669
0
#endif
12670
0
        Py_BEGIN_ALLOW_THREADS
12671
0
        res = pipe(fds);
12672
0
        Py_END_ALLOW_THREADS
12673
12674
0
        if (res == 0) {
12675
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12676
0
                close(fds[0]);
12677
0
                close(fds[1]);
12678
0
                return NULL;
12679
0
            }
12680
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12681
0
                close(fds[0]);
12682
0
                close(fds[1]);
12683
0
                return NULL;
12684
0
            }
12685
0
        }
12686
0
#ifdef HAVE_PIPE2
12687
0
    }
12688
0
#endif
12689
12690
0
    if (res != 0)
12691
0
        return PyErr_SetFromErrno(PyExc_OSError);
12692
0
#endif /* !MS_WINDOWS */
12693
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12694
0
}
12695
#endif  /* HAVE_PIPE */
12696
12697
12698
#ifdef HAVE_PIPE2
12699
/*[clinic input]
12700
os.pipe2
12701
12702
    flags: int
12703
    /
12704
12705
Create a pipe with flags set atomically.
12706
12707
Returns a tuple of two file descriptors:
12708
  (read_fd, write_fd)
12709
12710
flags can be constructed by ORing together one or more of these values:
12711
O_NONBLOCK, O_CLOEXEC.
12712
[clinic start generated code]*/
12713
12714
static PyObject *
12715
os_pipe2_impl(PyObject *module, int flags)
12716
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12717
0
{
12718
0
    int fds[2];
12719
0
    int res;
12720
12721
0
    res = pipe2(fds, flags);
12722
0
    if (res != 0)
12723
0
        return posix_error();
12724
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12725
0
}
12726
#endif /* HAVE_PIPE2 */
12727
12728
12729
#ifdef HAVE_WRITEV
12730
/*[clinic input]
12731
os.writev -> Py_ssize_t
12732
    fd: int
12733
    buffers: object
12734
    /
12735
12736
Iterate over buffers, and write the contents of each to a file descriptor.
12737
12738
Returns the total number of bytes written.
12739
buffers must be a sequence of bytes-like objects.
12740
[clinic start generated code]*/
12741
12742
static Py_ssize_t
12743
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12744
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12745
0
{
12746
0
    Py_ssize_t cnt;
12747
0
    Py_ssize_t result;
12748
0
    int async_err = 0;
12749
0
    struct iovec *iov;
12750
0
    Py_buffer *buf;
12751
12752
0
    if (!PySequence_Check(buffers)) {
12753
0
        PyErr_SetString(PyExc_TypeError,
12754
0
            "writev() arg 2 must be a sequence");
12755
0
        return -1;
12756
0
    }
12757
0
    cnt = PySequence_Size(buffers);
12758
0
    if (cnt < 0)
12759
0
        return -1;
12760
12761
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12762
0
        return -1;
12763
0
    }
12764
12765
0
    do {
12766
0
        Py_BEGIN_ALLOW_THREADS
12767
0
        result = writev(fd, iov, cnt);
12768
0
        Py_END_ALLOW_THREADS
12769
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12770
12771
0
    if (result < 0 && !async_err)
12772
0
        posix_error();
12773
12774
0
    iov_cleanup(iov, buf, cnt);
12775
0
    return result;
12776
0
}
12777
#endif /* HAVE_WRITEV */
12778
12779
12780
#ifdef HAVE_PWRITE
12781
/*[clinic input]
12782
os.pwrite -> Py_ssize_t
12783
12784
    fd: int
12785
    buffer: Py_buffer
12786
    offset: Py_off_t
12787
    /
12788
12789
Write bytes to a file descriptor starting at a particular offset.
12790
12791
Write buffer to fd, starting at offset bytes from the beginning of
12792
the file.  Returns the number of bytes written.  Does not change the
12793
current file offset.
12794
[clinic start generated code]*/
12795
12796
static Py_ssize_t
12797
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12798
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12799
0
{
12800
0
    Py_ssize_t size;
12801
0
    int async_err = 0;
12802
12803
0
    do {
12804
0
        Py_BEGIN_ALLOW_THREADS
12805
0
        _Py_BEGIN_SUPPRESS_IPH
12806
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12807
0
        _Py_END_SUPPRESS_IPH
12808
0
        Py_END_ALLOW_THREADS
12809
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12810
12811
0
    if (size < 0 && !async_err)
12812
0
        posix_error();
12813
0
    return size;
12814
0
}
12815
#endif /* HAVE_PWRITE */
12816
12817
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12818
/*[clinic input]
12819
@permit_long_summary
12820
@permit_long_docstring_body
12821
os.pwritev -> Py_ssize_t
12822
12823
    fd: int
12824
    buffers: object
12825
    offset: Py_off_t
12826
    flags: int = 0
12827
    /
12828
12829
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12830
12831
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12832
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12833
buffer is written before proceeding to second, and so on. The operating system may
12834
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12835
This function writes the contents of each object to the file descriptor and returns
12836
the total number of bytes written.
12837
12838
The flags argument contains a bitwise OR of zero or more of the following flags:
12839
12840
- RWF_DSYNC
12841
- RWF_SYNC
12842
- RWF_APPEND
12843
- RWF_DONTCACHE
12844
12845
Using non-zero flags requires Linux 4.7 or newer.
12846
[clinic start generated code]*/
12847
12848
static Py_ssize_t
12849
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12850
                int flags)
12851
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=664a67626d485665]*/
12852
0
{
12853
0
    Py_ssize_t cnt;
12854
0
    Py_ssize_t result;
12855
0
    int async_err = 0;
12856
0
    struct iovec *iov;
12857
0
    Py_buffer *buf;
12858
12859
0
    if (!PySequence_Check(buffers)) {
12860
0
        PyErr_SetString(PyExc_TypeError,
12861
0
            "pwritev() arg 2 must be a sequence");
12862
0
        return -1;
12863
0
    }
12864
12865
0
    cnt = PySequence_Size(buffers);
12866
0
    if (cnt < 0) {
12867
0
        return -1;
12868
0
    }
12869
12870
#ifndef HAVE_PWRITEV2
12871
    if(flags != 0) {
12872
        argument_unavailable_error("pwritev2", "flags");
12873
        return -1;
12874
    }
12875
#endif
12876
12877
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12878
0
        return -1;
12879
0
    }
12880
0
#ifdef HAVE_PWRITEV2
12881
0
    do {
12882
0
        Py_BEGIN_ALLOW_THREADS
12883
0
        _Py_BEGIN_SUPPRESS_IPH
12884
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12885
0
        _Py_END_SUPPRESS_IPH
12886
0
        Py_END_ALLOW_THREADS
12887
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12888
#else
12889
12890
#if defined(__APPLE__) && defined(__clang__)
12891
/* This entire function will be removed from the module dict when the API
12892
 * is not available.
12893
 */
12894
#pragma clang diagnostic push
12895
#pragma clang diagnostic ignored "-Wunguarded-availability"
12896
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12897
#endif
12898
    do {
12899
        Py_BEGIN_ALLOW_THREADS
12900
        _Py_BEGIN_SUPPRESS_IPH
12901
        result = pwritev(fd, iov, cnt, offset);
12902
        _Py_END_SUPPRESS_IPH
12903
        Py_END_ALLOW_THREADS
12904
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12905
12906
#if defined(__APPLE__) && defined(__clang__)
12907
#pragma clang diagnostic pop
12908
#endif
12909
12910
#endif
12911
12912
0
    if (result < 0) {
12913
0
        if (!async_err) {
12914
0
            posix_error();
12915
0
        }
12916
0
        result = -1;
12917
0
    }
12918
0
    iov_cleanup(iov, buf, cnt);
12919
12920
0
    return result;
12921
0
}
12922
#endif /* HAVE_PWRITEV */
12923
12924
#ifdef HAVE_COPY_FILE_RANGE
12925
/*[clinic input]
12926
12927
os.copy_file_range
12928
    src: int
12929
        Source file descriptor.
12930
    dst: int
12931
        Destination file descriptor.
12932
    count: Py_ssize_t(allow_negative=False)
12933
        Number of bytes to copy.
12934
    offset_src: object = None
12935
        Starting offset in src.
12936
    offset_dst: object = None
12937
        Starting offset in dst.
12938
12939
Copy count bytes from one file descriptor to another.
12940
12941
If offset_src is None, then src is read from the current position;
12942
respectively for offset_dst.
12943
[clinic start generated code]*/
12944
12945
static PyObject *
12946
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12947
                        PyObject *offset_src, PyObject *offset_dst)
12948
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12949
0
{
12950
0
    off_t offset_src_val, offset_dst_val;
12951
0
    off_t *p_offset_src = NULL;
12952
0
    off_t *p_offset_dst = NULL;
12953
0
    Py_ssize_t ret;
12954
0
    int async_err = 0;
12955
    /* The flags argument is provided to allow
12956
     * for future extensions and currently must be to 0. */
12957
0
    int flags = 0;
12958
12959
12960
0
    if (offset_src != Py_None) {
12961
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12962
0
            return NULL;
12963
0
        }
12964
0
        p_offset_src = &offset_src_val;
12965
0
    }
12966
12967
0
    if (offset_dst != Py_None) {
12968
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12969
0
            return NULL;
12970
0
        }
12971
0
        p_offset_dst = &offset_dst_val;
12972
0
    }
12973
12974
0
    do {
12975
0
        Py_BEGIN_ALLOW_THREADS
12976
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
12977
0
        Py_END_ALLOW_THREADS
12978
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12979
12980
0
    if (ret < 0) {
12981
0
        return (!async_err) ? posix_error() : NULL;
12982
0
    }
12983
12984
0
    return PyLong_FromSsize_t(ret);
12985
0
}
12986
#endif /* HAVE_COPY_FILE_RANGE*/
12987
12988
#if (defined(HAVE_SPLICE) && !defined(_AIX))
12989
/*[clinic input]
12990
12991
os.splice
12992
    src: int
12993
        Source file descriptor.
12994
    dst: int
12995
        Destination file descriptor.
12996
    count: Py_ssize_t(allow_negative=False)
12997
        Number of bytes to copy.
12998
    offset_src: object = None
12999
        Starting offset in src.
13000
    offset_dst: object = None
13001
        Starting offset in dst.
13002
    flags: unsigned_int = 0
13003
        Flags to modify the semantics of the call.
13004
13005
Transfer count bytes from one pipe to a descriptor or vice versa.
13006
13007
If offset_src is None, then src is read from the current position;
13008
respectively for offset_dst. The offset associated to the file
13009
descriptor that refers to a pipe must be None.
13010
[clinic start generated code]*/
13011
13012
static PyObject *
13013
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13014
               PyObject *offset_src, PyObject *offset_dst,
13015
               unsigned int flags)
13016
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13017
0
{
13018
0
    off_t offset_src_val, offset_dst_val;
13019
0
    off_t *p_offset_src = NULL;
13020
0
    off_t *p_offset_dst = NULL;
13021
0
    Py_ssize_t ret;
13022
0
    int async_err = 0;
13023
13024
13025
0
    if (offset_src != Py_None) {
13026
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13027
0
            return NULL;
13028
0
        }
13029
0
        p_offset_src = &offset_src_val;
13030
0
    }
13031
13032
0
    if (offset_dst != Py_None) {
13033
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13034
0
            return NULL;
13035
0
        }
13036
0
        p_offset_dst = &offset_dst_val;
13037
0
    }
13038
13039
0
    do {
13040
0
        Py_BEGIN_ALLOW_THREADS
13041
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13042
0
        Py_END_ALLOW_THREADS
13043
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13044
13045
0
    if (ret < 0) {
13046
0
        return (!async_err) ? posix_error() : NULL;
13047
0
    }
13048
13049
0
    return PyLong_FromSsize_t(ret);
13050
0
}
13051
#endif /* HAVE_SPLICE*/
13052
13053
#ifdef HAVE_MKFIFO
13054
/*[clinic input]
13055
os.mkfifo
13056
13057
    path: path_t
13058
    mode: int=0o666
13059
    *
13060
    dir_fd: dir_fd(requires='mkfifoat')=None
13061
13062
Create a "fifo" (a POSIX named pipe).
13063
13064
If dir_fd is not None, it should be a file descriptor open to a directory,
13065
  and path should be relative; path will then be relative to that directory.
13066
dir_fd may not be implemented on your platform.
13067
  If it is unavailable, using it will raise a NotImplementedError.
13068
[clinic start generated code]*/
13069
13070
static PyObject *
13071
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13072
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
13073
0
{
13074
0
    int result;
13075
0
    int async_err = 0;
13076
0
#ifdef HAVE_MKFIFOAT
13077
0
    int mkfifoat_unavailable = 0;
13078
0
#endif
13079
13080
0
    do {
13081
0
        Py_BEGIN_ALLOW_THREADS
13082
0
#ifdef HAVE_MKFIFOAT
13083
0
        if (dir_fd != DEFAULT_DIR_FD) {
13084
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13085
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13086
13087
0
            } else {
13088
0
                mkfifoat_unavailable = 1;
13089
0
                result = 0;
13090
0
            }
13091
0
        } else
13092
0
#endif
13093
0
            result = mkfifo(path->narrow, mode);
13094
0
        Py_END_ALLOW_THREADS
13095
0
    } while (result != 0 && errno == EINTR &&
13096
0
             !(async_err = PyErr_CheckSignals()));
13097
13098
0
#ifdef HAVE_MKFIFOAT
13099
0
    if (mkfifoat_unavailable) {
13100
0
        argument_unavailable_error(NULL, "dir_fd");
13101
0
        return NULL;
13102
0
    }
13103
0
#endif
13104
13105
0
    if (result != 0)
13106
0
        return (!async_err) ? posix_error() : NULL;
13107
13108
0
    Py_RETURN_NONE;
13109
0
}
13110
#endif /* HAVE_MKFIFO */
13111
13112
13113
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13114
/*[clinic input]
13115
@permit_long_docstring_body
13116
os.mknod
13117
13118
    path: path_t
13119
    mode: int=0o600
13120
    device: dev_t=0
13121
    *
13122
    dir_fd: dir_fd(requires='mknodat')=None
13123
13124
Create a node in the file system.
13125
13126
Create a node in the file system (file, device special file or named pipe)
13127
at path.  mode specifies both the permissions to use and the
13128
type of node to be created, being combined (bitwise OR) with one of
13129
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
13130
device defines the newly created device special file (probably using
13131
os.makedev()).  Otherwise device is ignored.
13132
13133
If dir_fd is not None, it should be a file descriptor open to a directory,
13134
  and path should be relative; path will then be relative to that directory.
13135
dir_fd may not be implemented on your platform.
13136
  If it is unavailable, using it will raise a NotImplementedError.
13137
[clinic start generated code]*/
13138
13139
static PyObject *
13140
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13141
              int dir_fd)
13142
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
13143
0
{
13144
0
    int result;
13145
0
    int async_err = 0;
13146
0
#ifdef HAVE_MKNODAT
13147
0
    int mknodat_unavailable = 0;
13148
0
#endif
13149
13150
0
    do {
13151
0
        Py_BEGIN_ALLOW_THREADS
13152
0
#ifdef HAVE_MKNODAT
13153
0
        if (dir_fd != DEFAULT_DIR_FD) {
13154
0
            if (HAVE_MKNODAT_RUNTIME) {
13155
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13156
13157
0
            } else {
13158
0
                mknodat_unavailable = 1;
13159
0
                result = 0;
13160
0
            }
13161
0
        } else
13162
0
#endif
13163
0
            result = mknod(path->narrow, mode, device);
13164
0
        Py_END_ALLOW_THREADS
13165
0
    } while (result != 0 && errno == EINTR &&
13166
0
             !(async_err = PyErr_CheckSignals()));
13167
0
#ifdef HAVE_MKNODAT
13168
0
    if (mknodat_unavailable) {
13169
0
        argument_unavailable_error(NULL, "dir_fd");
13170
0
        return NULL;
13171
0
    }
13172
0
#endif
13173
0
    if (result != 0)
13174
0
        return (!async_err) ? posix_error() : NULL;
13175
13176
0
    Py_RETURN_NONE;
13177
0
}
13178
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13179
13180
13181
#ifdef HAVE_DEVICE_MACROS
13182
static PyObject *
13183
major_minor_conv(unsigned int value)
13184
0
{
13185
0
#ifdef NODEV
13186
0
    if (value == (unsigned int)NODEV) {
13187
0
        return PyLong_FromLong((int)NODEV);
13188
0
    }
13189
0
#endif
13190
0
    return PyLong_FromUnsignedLong(value);
13191
0
}
13192
13193
static int
13194
major_minor_check(dev_t value)
13195
0
{
13196
0
#ifdef NODEV
13197
0
    if (value == NODEV) {
13198
0
        return 1;
13199
0
    }
13200
0
#endif
13201
0
    return (dev_t)(unsigned int)value == value;
13202
0
}
13203
13204
/*[clinic input]
13205
os.major
13206
13207
    device: dev_t
13208
    /
13209
13210
Extracts a device major number from a raw device number.
13211
[clinic start generated code]*/
13212
13213
static PyObject *
13214
os_major_impl(PyObject *module, dev_t device)
13215
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13216
0
{
13217
0
    return major_minor_conv(major(device));
13218
0
}
13219
13220
13221
/*[clinic input]
13222
os.minor
13223
13224
    device: dev_t
13225
    /
13226
13227
Extracts a device minor number from a raw device number.
13228
[clinic start generated code]*/
13229
13230
static PyObject *
13231
os_minor_impl(PyObject *module, dev_t device)
13232
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13233
0
{
13234
0
    return major_minor_conv(minor(device));
13235
0
}
13236
13237
13238
/*[clinic input]
13239
os.makedev -> dev_t
13240
13241
    major: dev_t
13242
    minor: dev_t
13243
    /
13244
13245
Composes a raw device number from the major and minor device numbers.
13246
[clinic start generated code]*/
13247
13248
static dev_t
13249
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13250
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13251
0
{
13252
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13253
0
        PyErr_SetString(PyExc_OverflowError,
13254
0
                        "Python int too large to convert to C unsigned int");
13255
0
        return (dev_t)-1;
13256
0
    }
13257
0
    return makedev(major, minor);
13258
0
}
13259
#endif /* HAVE_DEVICE_MACROS */
13260
13261
13262
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13263
/*[clinic input]
13264
os.ftruncate
13265
13266
    fd: int
13267
    length: Py_off_t
13268
    /
13269
13270
Truncate a file, specified by file descriptor, to a specific length.
13271
[clinic start generated code]*/
13272
13273
static PyObject *
13274
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13275
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13276
0
{
13277
0
    int result;
13278
0
    int async_err = 0;
13279
13280
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13281
0
        return NULL;
13282
0
    }
13283
13284
0
    do {
13285
0
        Py_BEGIN_ALLOW_THREADS
13286
0
        _Py_BEGIN_SUPPRESS_IPH
13287
#ifdef MS_WINDOWS
13288
        result = _chsize_s(fd, length);
13289
#else
13290
0
        result = ftruncate(fd, length);
13291
0
#endif
13292
0
        _Py_END_SUPPRESS_IPH
13293
0
        Py_END_ALLOW_THREADS
13294
0
    } while (result != 0 && errno == EINTR &&
13295
0
             !(async_err = PyErr_CheckSignals()));
13296
0
    if (result != 0)
13297
0
        return (!async_err) ? posix_error() : NULL;
13298
0
    Py_RETURN_NONE;
13299
0
}
13300
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13301
13302
13303
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13304
/*[clinic input]
13305
os.truncate
13306
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13307
    length: Py_off_t
13308
13309
Truncate a file, specified by path, to a specific length.
13310
13311
On some platforms, path may also be specified as an open file descriptor.
13312
  If this functionality is unavailable, using it raises an exception.
13313
[clinic start generated code]*/
13314
13315
static PyObject *
13316
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13317
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
13318
0
{
13319
0
    int result;
13320
#ifdef MS_WINDOWS
13321
    int fd;
13322
#endif
13323
13324
0
    if (path->fd != -1)
13325
0
        return os_ftruncate_impl(module, path->fd, length);
13326
13327
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13328
0
        return NULL;
13329
0
    }
13330
13331
0
    Py_BEGIN_ALLOW_THREADS
13332
0
    _Py_BEGIN_SUPPRESS_IPH
13333
#ifdef MS_WINDOWS
13334
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13335
    if (fd < 0)
13336
        result = -1;
13337
    else {
13338
        result = _chsize_s(fd, length);
13339
        close(fd);
13340
        if (result < 0)
13341
            errno = result;
13342
    }
13343
#else
13344
0
    result = truncate(path->narrow, length);
13345
0
#endif
13346
0
    _Py_END_SUPPRESS_IPH
13347
0
    Py_END_ALLOW_THREADS
13348
0
    if (result < 0)
13349
0
        return posix_path_error(path);
13350
13351
0
    Py_RETURN_NONE;
13352
0
}
13353
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13354
13355
13356
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
13357
   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
13358
   defined, which is the case in Python on AIX. AIX bug report:
13359
   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
13360
#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
13361
#  define POSIX_FADVISE_AIX_BUG
13362
#endif
13363
13364
13365
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13366
   OSs, support was dropped in WASI preview2. */
13367
#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \
13368
    !defined(__wasi__)
13369
/*[clinic input]
13370
os.posix_fallocate
13371
13372
    fd: int
13373
    offset: Py_off_t
13374
    length: Py_off_t
13375
    /
13376
13377
Ensure a file has allocated at least a particular number of bytes on disk.
13378
13379
Ensure that the file specified by fd encompasses a range of bytes
13380
starting at offset bytes from the beginning and continuing for length bytes.
13381
[clinic start generated code]*/
13382
13383
static PyObject *
13384
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13385
                        Py_off_t length)
13386
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
13387
0
{
13388
0
    int result;
13389
0
    int async_err = 0;
13390
13391
0
    do {
13392
0
        Py_BEGIN_ALLOW_THREADS
13393
0
        result = posix_fallocate(fd, offset, length);
13394
0
        Py_END_ALLOW_THREADS
13395
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13396
13397
0
    if (result == 0)
13398
0
        Py_RETURN_NONE;
13399
13400
0
    if (async_err)
13401
0
        return NULL;
13402
13403
0
    errno = result;
13404
0
    return posix_error();
13405
0
}
13406
#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */
13407
13408
13409
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
13410
/*[clinic input]
13411
os.posix_fadvise
13412
13413
    fd: int
13414
    offset: Py_off_t
13415
    length: Py_off_t
13416
    advice: int
13417
    /
13418
13419
Announce an intention to access data in a specific pattern.
13420
13421
Announce an intention to access data in a specific pattern, thus allowing
13422
the kernel to make optimizations.
13423
The advice applies to the region of the file specified by fd starting at
13424
offset and continuing for length bytes.
13425
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13426
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13427
POSIX_FADV_DONTNEED.
13428
[clinic start generated code]*/
13429
13430
static PyObject *
13431
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13432
                      Py_off_t length, int advice)
13433
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13434
0
{
13435
0
    int result;
13436
0
    int async_err = 0;
13437
13438
0
    do {
13439
0
        Py_BEGIN_ALLOW_THREADS
13440
0
        result = posix_fadvise(fd, offset, length, advice);
13441
0
        Py_END_ALLOW_THREADS
13442
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13443
13444
0
    if (result == 0)
13445
0
        Py_RETURN_NONE;
13446
13447
0
    if (async_err)
13448
0
        return NULL;
13449
13450
0
    errno = result;
13451
0
    return posix_error();
13452
0
}
13453
#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
13454
13455
13456
#ifdef MS_WINDOWS
13457
static PyObject*
13458
win32_putenv(PyObject *name, PyObject *value)
13459
{
13460
    /* Search from index 1 because on Windows starting '=' is allowed for
13461
       defining hidden environment variables. */
13462
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13463
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13464
    {
13465
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13466
        return NULL;
13467
    }
13468
    PyObject *unicode;
13469
    if (value != NULL) {
13470
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13471
    }
13472
    else {
13473
        unicode = PyUnicode_FromFormat("%U=", name);
13474
    }
13475
    if (unicode == NULL) {
13476
        return NULL;
13477
    }
13478
13479
    Py_ssize_t size;
13480
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13481
    Py_DECREF(unicode);
13482
13483
    if (env == NULL) {
13484
        return NULL;
13485
    }
13486
    if (size > _MAX_ENV) {
13487
        PyErr_Format(PyExc_ValueError,
13488
                     "the environment variable is longer than %u characters",
13489
                     _MAX_ENV);
13490
        PyMem_Free(env);
13491
        return NULL;
13492
    }
13493
    if (wcslen(env) != (size_t)size) {
13494
        PyErr_SetString(PyExc_ValueError,
13495
                        "embedded null character");
13496
        PyMem_Free(env);
13497
        return NULL;
13498
    }
13499
13500
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13501
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13502
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13503
13504
       Prefer _wputenv() to be compatible with C libraries using CRT
13505
       variables and CRT functions using these variables (ex: getenv()). */
13506
    int err = _wputenv(env);
13507
13508
    if (err) {
13509
        posix_error();
13510
        PyMem_Free(env);
13511
        return NULL;
13512
    }
13513
    PyMem_Free(env);
13514
13515
    Py_RETURN_NONE;
13516
}
13517
#endif
13518
13519
13520
#ifdef MS_WINDOWS
13521
/*[clinic input]
13522
os.putenv
13523
13524
    name: unicode
13525
    value: unicode
13526
    /
13527
13528
Change or add an environment variable.
13529
[clinic start generated code]*/
13530
13531
static PyObject *
13532
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13533
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13534
{
13535
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13536
        return NULL;
13537
    }
13538
    return win32_putenv(name, value);
13539
}
13540
#else
13541
/*[clinic input]
13542
os.putenv
13543
13544
    name: unicode_fs_encoded
13545
    value: unicode_fs_encoded
13546
    /
13547
13548
Change or add an environment variable.
13549
[clinic start generated code]*/
13550
13551
static PyObject *
13552
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13553
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13554
0
{
13555
0
    const char *name_string = PyBytes_AS_STRING(name);
13556
0
    const char *value_string = PyBytes_AS_STRING(value);
13557
13558
0
    if (strchr(name_string, '=') != NULL) {
13559
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13560
0
        return NULL;
13561
0
    }
13562
13563
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13564
0
        return NULL;
13565
0
    }
13566
13567
0
    if (setenv(name_string, value_string, 1)) {
13568
0
        return posix_error();
13569
0
    }
13570
0
    Py_RETURN_NONE;
13571
0
}
13572
#endif  /* !defined(MS_WINDOWS) */
13573
13574
13575
#ifdef MS_WINDOWS
13576
/*[clinic input]
13577
os.unsetenv
13578
    name: unicode
13579
    /
13580
13581
Delete an environment variable.
13582
[clinic start generated code]*/
13583
13584
static PyObject *
13585
os_unsetenv_impl(PyObject *module, PyObject *name)
13586
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13587
{
13588
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13589
        return NULL;
13590
    }
13591
    return win32_putenv(name, NULL);
13592
}
13593
#else
13594
/*[clinic input]
13595
os.unsetenv
13596
    name: unicode_fs_encoded
13597
    /
13598
13599
Delete an environment variable.
13600
[clinic start generated code]*/
13601
13602
static PyObject *
13603
os_unsetenv_impl(PyObject *module, PyObject *name)
13604
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13605
0
{
13606
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13607
0
        return NULL;
13608
0
    }
13609
#ifdef HAVE_BROKEN_UNSETENV
13610
    unsetenv(PyBytes_AS_STRING(name));
13611
#else
13612
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13613
0
    if (err) {
13614
0
        return posix_error();
13615
0
    }
13616
0
#endif
13617
13618
0
    Py_RETURN_NONE;
13619
0
}
13620
#endif /* !MS_WINDOWS */
13621
13622
13623
#ifdef HAVE_CLEARENV
13624
/*[clinic input]
13625
os._clearenv
13626
[clinic start generated code]*/
13627
13628
static PyObject *
13629
os__clearenv_impl(PyObject *module)
13630
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13631
0
{
13632
0
    errno = 0;
13633
0
    int err = clearenv();
13634
0
    if (err) {
13635
0
        return posix_error();
13636
0
    }
13637
0
    Py_RETURN_NONE;
13638
0
}
13639
#endif
13640
13641
13642
/*[clinic input]
13643
os.strerror
13644
13645
    code: int
13646
    /
13647
13648
Translate an error code to a message string.
13649
[clinic start generated code]*/
13650
13651
static PyObject *
13652
os_strerror_impl(PyObject *module, int code)
13653
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13654
0
{
13655
0
    char *message = strerror(code);
13656
0
    if (message == NULL) {
13657
0
        PyErr_SetString(PyExc_ValueError,
13658
0
                        "strerror() argument out of range");
13659
0
        return NULL;
13660
0
    }
13661
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13662
0
}
13663
13664
13665
#ifdef HAVE_SYS_WAIT_H
13666
#ifdef WCOREDUMP
13667
/*[clinic input]
13668
os.WCOREDUMP -> bool
13669
13670
    status: int
13671
    /
13672
13673
Return True if the process returning status was dumped to a core file.
13674
[clinic start generated code]*/
13675
13676
static int
13677
os_WCOREDUMP_impl(PyObject *module, int status)
13678
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13679
0
{
13680
0
    WAIT_TYPE wait_status;
13681
0
    WAIT_STATUS_INT(wait_status) = status;
13682
0
    return WCOREDUMP(wait_status);
13683
0
}
13684
#endif /* WCOREDUMP */
13685
13686
13687
#ifdef WIFCONTINUED
13688
/*[clinic input]
13689
os.WIFCONTINUED -> bool
13690
13691
    status: int
13692
13693
Return True if a particular process was continued from a job control stop.
13694
13695
Return True if the process returning status was continued from a
13696
job control stop.
13697
[clinic start generated code]*/
13698
13699
static int
13700
os_WIFCONTINUED_impl(PyObject *module, int status)
13701
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13702
0
{
13703
0
    WAIT_TYPE wait_status;
13704
0
    WAIT_STATUS_INT(wait_status) = status;
13705
0
    return WIFCONTINUED(wait_status);
13706
0
}
13707
#endif /* WIFCONTINUED */
13708
13709
13710
#ifdef WIFSTOPPED
13711
/*[clinic input]
13712
os.WIFSTOPPED -> bool
13713
13714
    status: int
13715
13716
Return True if the process returning status was stopped.
13717
[clinic start generated code]*/
13718
13719
static int
13720
os_WIFSTOPPED_impl(PyObject *module, int status)
13721
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13722
0
{
13723
0
    WAIT_TYPE wait_status;
13724
0
    WAIT_STATUS_INT(wait_status) = status;
13725
0
    return WIFSTOPPED(wait_status);
13726
0
}
13727
#endif /* WIFSTOPPED */
13728
13729
13730
#ifdef WIFSIGNALED
13731
/*[clinic input]
13732
os.WIFSIGNALED -> bool
13733
13734
    status: int
13735
13736
Return True if the process returning status was terminated by a signal.
13737
[clinic start generated code]*/
13738
13739
static int
13740
os_WIFSIGNALED_impl(PyObject *module, int status)
13741
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13742
0
{
13743
0
    WAIT_TYPE wait_status;
13744
0
    WAIT_STATUS_INT(wait_status) = status;
13745
0
    return WIFSIGNALED(wait_status);
13746
0
}
13747
#endif /* WIFSIGNALED */
13748
13749
13750
#ifdef WIFEXITED
13751
/*[clinic input]
13752
@permit_long_summary
13753
os.WIFEXITED -> bool
13754
13755
    status: int
13756
13757
Return True if the process returning status exited via the exit() system call.
13758
[clinic start generated code]*/
13759
13760
static int
13761
os_WIFEXITED_impl(PyObject *module, int status)
13762
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13763
0
{
13764
0
    WAIT_TYPE wait_status;
13765
0
    WAIT_STATUS_INT(wait_status) = status;
13766
0
    return WIFEXITED(wait_status);
13767
0
}
13768
#endif /* WIFEXITED */
13769
13770
13771
#ifdef WEXITSTATUS
13772
/*[clinic input]
13773
os.WEXITSTATUS -> int
13774
13775
    status: int
13776
13777
Return the process return code from status.
13778
[clinic start generated code]*/
13779
13780
static int
13781
os_WEXITSTATUS_impl(PyObject *module, int status)
13782
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13783
0
{
13784
0
    WAIT_TYPE wait_status;
13785
0
    WAIT_STATUS_INT(wait_status) = status;
13786
0
    return WEXITSTATUS(wait_status);
13787
0
}
13788
#endif /* WEXITSTATUS */
13789
13790
13791
#ifdef WTERMSIG
13792
/*[clinic input]
13793
@permit_long_summary
13794
os.WTERMSIG -> int
13795
13796
    status: int
13797
13798
Return the signal that terminated the process that provided the status value.
13799
[clinic start generated code]*/
13800
13801
static int
13802
os_WTERMSIG_impl(PyObject *module, int status)
13803
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13804
0
{
13805
0
    WAIT_TYPE wait_status;
13806
0
    WAIT_STATUS_INT(wait_status) = status;
13807
0
    return WTERMSIG(wait_status);
13808
0
}
13809
#endif /* WTERMSIG */
13810
13811
13812
#ifdef WSTOPSIG
13813
/*[clinic input]
13814
os.WSTOPSIG -> int
13815
13816
    status: int
13817
13818
Return the signal that stopped the process that provided the status value.
13819
[clinic start generated code]*/
13820
13821
static int
13822
os_WSTOPSIG_impl(PyObject *module, int status)
13823
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13824
0
{
13825
0
    WAIT_TYPE wait_status;
13826
0
    WAIT_STATUS_INT(wait_status) = status;
13827
0
    return WSTOPSIG(wait_status);
13828
0
}
13829
#endif /* WSTOPSIG */
13830
#endif /* HAVE_SYS_WAIT_H */
13831
13832
13833
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13834
#ifdef _SCO_DS
13835
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13836
   needed definitions in sys/statvfs.h */
13837
#define _SVID3
13838
#endif
13839
#include <sys/statvfs.h>
13840
13841
#ifdef __APPLE__
13842
/* On macOS struct statvfs uses 32-bit integers for block counts,
13843
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13844
 * os.statvfs is implemented in terms of statfs(2).
13845
 */
13846
13847
static PyObject*
13848
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13849
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13850
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13851
    if (v == NULL) {
13852
        return NULL;
13853
    }
13854
13855
    long flags = 0;
13856
    if (st.f_flags & MNT_RDONLY) {
13857
        flags |= ST_RDONLY;
13858
    }
13859
    if (st.f_flags & MNT_NOSUID) {
13860
        flags |= ST_NOSUID;
13861
    }
13862
13863
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13864
13865
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13866
    do {                                                 \
13867
        PyObject *obj = (EXPR);                          \
13868
        if (obj == NULL) {                               \
13869
            Py_DECREF((SEQ));                            \
13870
            return NULL;                                 \
13871
        }                                                \
13872
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13873
    } while (0)
13874
13875
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13876
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13877
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13878
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13879
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13880
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13881
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13882
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13883
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13884
13885
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13886
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13887
13888
#undef SET_ITEM
13889
13890
    return v;
13891
}
13892
13893
#else
13894
13895
13896
13897
static PyObject*
13898
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13899
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13900
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13901
0
    if (v == NULL)
13902
0
        return NULL;
13903
13904
0
    int pos = 0;
13905
13906
0
#define SET_RESULT(CALL)                                     \
13907
0
    do {                                                     \
13908
0
        PyObject *item = (CALL);                             \
13909
0
        if (item == NULL) {                                  \
13910
0
            Py_DECREF(v);                                    \
13911
0
            return NULL;                                     \
13912
0
        }                                                    \
13913
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13914
0
    } while(0)
13915
13916
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13917
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13918
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13919
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13920
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13921
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13922
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13923
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13924
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13925
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13926
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13927
#else
13928
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13929
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13930
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13931
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13932
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13933
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13934
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13935
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13936
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13937
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13938
#endif
13939
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13940
 * (issue #32390). */
13941
#if defined(_AIX) && defined(_ALL_SOURCE)
13942
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13943
#else
13944
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13945
0
#endif
13946
13947
0
#undef SET_RESULT
13948
13949
0
    return v;
13950
0
}
13951
13952
#endif
13953
13954
13955
/*[clinic input]
13956
os.fstatvfs
13957
    fd: int
13958
    /
13959
13960
Perform an fstatvfs system call on the given fd.
13961
13962
Equivalent to statvfs(fd).
13963
[clinic start generated code]*/
13964
13965
static PyObject *
13966
os_fstatvfs_impl(PyObject *module, int fd)
13967
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13968
0
{
13969
0
    int result;
13970
0
    int async_err = 0;
13971
#ifdef __APPLE__
13972
    struct statfs st;
13973
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13974
     * the former uses 32-bit values for block counts.
13975
     */
13976
    do {
13977
        Py_BEGIN_ALLOW_THREADS
13978
        result = fstatfs(fd, &st);
13979
        Py_END_ALLOW_THREADS
13980
    } while (result != 0 && errno == EINTR &&
13981
             !(async_err = PyErr_CheckSignals()));
13982
    if (result != 0)
13983
        return (!async_err) ? posix_error() : NULL;
13984
13985
    return _pystatvfs_fromstructstatfs(module, st);
13986
#else
13987
0
    struct statvfs st;
13988
13989
0
    do {
13990
0
        Py_BEGIN_ALLOW_THREADS
13991
0
        result = fstatvfs(fd, &st);
13992
0
        Py_END_ALLOW_THREADS
13993
0
    } while (result != 0 && errno == EINTR &&
13994
0
             !(async_err = PyErr_CheckSignals()));
13995
0
    if (result != 0)
13996
0
        return (!async_err) ? posix_error() : NULL;
13997
13998
0
    return _pystatvfs_fromstructstatvfs(module, st);
13999
0
#endif
14000
0
}
14001
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14002
14003
14004
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14005
#include <sys/statvfs.h>
14006
/*[clinic input]
14007
os.statvfs
14008
14009
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14010
14011
Perform a statvfs system call on the given path.
14012
14013
path may always be specified as a string.
14014
On some platforms, path may also be specified as an open file descriptor.
14015
  If this functionality is unavailable, using it raises an exception.
14016
[clinic start generated code]*/
14017
14018
static PyObject *
14019
os_statvfs_impl(PyObject *module, path_t *path)
14020
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
14021
0
{
14022
0
    int result;
14023
14024
#ifdef __APPLE__
14025
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14026
     * the former uses 32-bit values for block counts.
14027
     */
14028
    struct statfs st;
14029
14030
    Py_BEGIN_ALLOW_THREADS
14031
    if (path->fd != -1) {
14032
        result = fstatfs(path->fd, &st);
14033
    }
14034
    else
14035
        result = statfs(path->narrow, &st);
14036
    Py_END_ALLOW_THREADS
14037
14038
    if (result) {
14039
        return path_error(path);
14040
    }
14041
14042
    return _pystatvfs_fromstructstatfs(module, st);
14043
14044
#else
14045
0
    struct statvfs st;
14046
14047
0
    Py_BEGIN_ALLOW_THREADS
14048
0
#ifdef HAVE_FSTATVFS
14049
0
    if (path->fd != -1) {
14050
0
        result = fstatvfs(path->fd, &st);
14051
0
    }
14052
0
    else
14053
0
#endif
14054
0
        result = statvfs(path->narrow, &st);
14055
0
    Py_END_ALLOW_THREADS
14056
14057
0
    if (result) {
14058
0
        return path_error(path);
14059
0
    }
14060
14061
0
    return _pystatvfs_fromstructstatvfs(module, st);
14062
0
#endif
14063
0
}
14064
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14065
14066
14067
#ifdef MS_WINDOWS
14068
/*[clinic input]
14069
os._getdiskusage
14070
14071
    path: path_t
14072
14073
Return disk usage statistics about the given path as a (total, free) tuple.
14074
[clinic start generated code]*/
14075
14076
static PyObject *
14077
os__getdiskusage_impl(PyObject *module, path_t *path)
14078
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
14079
{
14080
    BOOL retval;
14081
    ULARGE_INTEGER _, total, free;
14082
    DWORD err = 0;
14083
14084
    Py_BEGIN_ALLOW_THREADS
14085
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14086
    Py_END_ALLOW_THREADS
14087
    if (retval == 0) {
14088
        if (GetLastError() == ERROR_DIRECTORY) {
14089
            wchar_t *dir_path = NULL;
14090
14091
            dir_path = PyMem_New(wchar_t, path->length + 1);
14092
            if (dir_path == NULL) {
14093
                return PyErr_NoMemory();
14094
            }
14095
14096
            wcscpy_s(dir_path, path->length + 1, path->wide);
14097
14098
            if (_dirnameW(dir_path) != -1) {
14099
                Py_BEGIN_ALLOW_THREADS
14100
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14101
                Py_END_ALLOW_THREADS
14102
            }
14103
            /* Record the last error in case it's modified by PyMem_Free. */
14104
            err = GetLastError();
14105
            PyMem_Free(dir_path);
14106
            if (retval) {
14107
                goto success;
14108
            }
14109
        }
14110
        return PyErr_SetFromWindowsErr(err);
14111
    }
14112
14113
success:
14114
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14115
}
14116
#endif /* MS_WINDOWS */
14117
14118
14119
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14120
 * It maps strings representing configuration variable names to
14121
 * integer values, allowing those functions to be called with the
14122
 * magic names instead of polluting the module's namespace with tons of
14123
 * rarely-used constants.  There are three separate tables that use
14124
 * these definitions.
14125
 *
14126
 * This code is always included, even if none of the interfaces that
14127
 * need it are included.  The #if hackery needed to avoid it would be
14128
 * sufficiently pervasive that it's not worth the loss of readability.
14129
 */
14130
struct constdef {
14131
    const char *name;
14132
    int value;
14133
};
14134
14135
static int
14136
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14137
0
{
14138
0
    if (PyUnicode_Check(arg)) {
14139
0
        PyObject *table = PyObject_GetAttrString(module, tablename);
14140
0
        if (table == NULL) {
14141
0
            return 0;
14142
0
        }
14143
14144
0
        arg = PyObject_GetItem(table, arg);
14145
0
        Py_DECREF(table);
14146
0
        if (arg == NULL) {
14147
0
            PyErr_SetString(
14148
0
                PyExc_ValueError, "unrecognized configuration name");
14149
0
            return 0;
14150
0
        }
14151
0
    } else {
14152
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14153
0
    }
14154
14155
0
    int success = 0;
14156
0
    if (!PyIndex_Check(arg)) {
14157
0
        PyErr_SetString(PyExc_TypeError,
14158
0
            "configuration names must be strings or integers");
14159
0
    } else {
14160
0
        int value = PyLong_AsInt(arg);
14161
0
        if (!(value == -1 && PyErr_Occurred())) {
14162
0
            *valuep = value;
14163
0
            success = 1;
14164
0
        }
14165
0
    }
14166
0
    Py_DECREF(arg);
14167
0
    return success;
14168
0
}
14169
14170
14171
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14172
static struct constdef  posix_constants_pathconf[] = {
14173
#ifdef _PC_ABI_AIO_XFER_MAX
14174
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14175
#endif
14176
#ifdef _PC_ABI_ASYNC_IO
14177
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14178
#endif
14179
#ifdef _PC_ASYNC_IO
14180
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14181
#endif
14182
#ifdef _PC_CHOWN_RESTRICTED
14183
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14184
#endif
14185
#ifdef _PC_FILESIZEBITS
14186
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14187
#endif
14188
#ifdef _PC_LAST
14189
    {"PC_LAST", _PC_LAST},
14190
#endif
14191
#ifdef _PC_LINK_MAX
14192
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14193
#endif
14194
#ifdef _PC_MAX_CANON
14195
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14196
#endif
14197
#ifdef _PC_MAX_INPUT
14198
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14199
#endif
14200
#ifdef _PC_NAME_MAX
14201
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14202
#endif
14203
#ifdef _PC_NO_TRUNC
14204
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14205
#endif
14206
#ifdef _PC_PATH_MAX
14207
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14208
#endif
14209
#ifdef _PC_PIPE_BUF
14210
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14211
#endif
14212
#ifdef _PC_PRIO_IO
14213
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14214
#endif
14215
#ifdef _PC_SOCK_MAXBUF
14216
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14217
#endif
14218
#ifdef _PC_SYNC_IO
14219
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14220
#endif
14221
#ifdef _PC_VDISABLE
14222
    {"PC_VDISABLE",     _PC_VDISABLE},
14223
#endif
14224
#ifdef _PC_ACL_ENABLED
14225
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14226
#endif
14227
#ifdef _PC_MIN_HOLE_SIZE
14228
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14229
#endif
14230
#ifdef _PC_ALLOC_SIZE_MIN
14231
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14232
#endif
14233
#ifdef _PC_REC_INCR_XFER_SIZE
14234
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14235
#endif
14236
#ifdef _PC_REC_MAX_XFER_SIZE
14237
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14238
#endif
14239
#ifdef _PC_REC_MIN_XFER_SIZE
14240
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14241
#endif
14242
#ifdef _PC_REC_XFER_ALIGN
14243
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14244
#endif
14245
#ifdef _PC_SYMLINK_MAX
14246
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14247
#endif
14248
#ifdef _PC_XATTR_ENABLED
14249
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14250
#endif
14251
#ifdef _PC_XATTR_EXISTS
14252
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14253
#endif
14254
#ifdef _PC_TIMESTAMP_RESOLUTION
14255
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14256
#endif
14257
};
14258
#endif
14259
14260
14261
#ifdef HAVE_FPATHCONF
14262
/*[clinic input]
14263
os.fpathconf -> long
14264
14265
    fd: fildes
14266
    name: confname(table="pathconf_names")
14267
    /
14268
14269
Return the configuration limit name for the file descriptor fd.
14270
14271
If there is no limit, return -1.
14272
[clinic start generated code]*/
14273
14274
static long
14275
os_fpathconf_impl(PyObject *module, int fd, int name)
14276
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14277
0
{
14278
0
    long limit;
14279
14280
0
    errno = 0;
14281
0
    limit = fpathconf(fd, name);
14282
0
    if (limit == -1 && errno != 0)
14283
0
        posix_error();
14284
14285
0
    return limit;
14286
0
}
14287
#endif /* HAVE_FPATHCONF */
14288
14289
14290
#ifdef HAVE_PATHCONF
14291
/*[clinic input]
14292
os.pathconf -> long
14293
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14294
    name: confname(table="pathconf_names")
14295
14296
Return the configuration limit name for the file or directory path.
14297
14298
If there is no limit, return -1.
14299
On some platforms, path may also be specified as an open file descriptor.
14300
  If this functionality is unavailable, using it raises an exception.
14301
[clinic start generated code]*/
14302
14303
static long
14304
os_pathconf_impl(PyObject *module, path_t *path, int name)
14305
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
14306
0
{
14307
0
    long limit;
14308
14309
0
    errno = 0;
14310
0
#ifdef HAVE_FPATHCONF
14311
0
    if (path->fd != -1)
14312
0
        limit = fpathconf(path->fd, name);
14313
0
    else
14314
0
#endif
14315
0
        limit = pathconf(path->narrow, name);
14316
0
    if (limit == -1 && errno != 0) {
14317
0
        if (errno == EINVAL)
14318
            /* could be a path or name problem */
14319
0
            posix_error();
14320
0
        else
14321
0
            path_error(path);
14322
0
    }
14323
14324
0
    return limit;
14325
0
}
14326
#endif /* HAVE_PATHCONF */
14327
14328
#ifdef HAVE_CONFSTR
14329
static struct constdef posix_constants_confstr[] = {
14330
#ifdef _CS_ARCHITECTURE
14331
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14332
#endif
14333
#ifdef _CS_GNU_LIBC_VERSION
14334
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14335
#endif
14336
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14337
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14338
#endif
14339
#ifdef _CS_HOSTNAME
14340
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14341
#endif
14342
#ifdef _CS_HW_PROVIDER
14343
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14344
#endif
14345
#ifdef _CS_HW_SERIAL
14346
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14347
#endif
14348
#ifdef _CS_INITTAB_NAME
14349
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14350
#endif
14351
#ifdef _CS_LFS64_CFLAGS
14352
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14353
#endif
14354
#ifdef _CS_LFS64_LDFLAGS
14355
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14356
#endif
14357
#ifdef _CS_LFS64_LIBS
14358
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14359
#endif
14360
#ifdef _CS_LFS64_LINTFLAGS
14361
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14362
#endif
14363
#ifdef _CS_LFS_CFLAGS
14364
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14365
#endif
14366
#ifdef _CS_LFS_LDFLAGS
14367
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14368
#endif
14369
#ifdef _CS_LFS_LIBS
14370
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14371
#endif
14372
#ifdef _CS_LFS_LINTFLAGS
14373
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14374
#endif
14375
#ifdef _CS_MACHINE
14376
    {"CS_MACHINE",      _CS_MACHINE},
14377
#endif
14378
#ifdef _CS_PATH
14379
    {"CS_PATH", _CS_PATH},
14380
#endif
14381
#ifdef _CS_RELEASE
14382
    {"CS_RELEASE",      _CS_RELEASE},
14383
#endif
14384
#ifdef _CS_SRPC_DOMAIN
14385
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14386
#endif
14387
#ifdef _CS_SYSNAME
14388
    {"CS_SYSNAME",      _CS_SYSNAME},
14389
#endif
14390
#ifdef _CS_VERSION
14391
    {"CS_VERSION",      _CS_VERSION},
14392
#endif
14393
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14394
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14395
#endif
14396
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14397
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14398
#endif
14399
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14400
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14401
#endif
14402
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14403
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14404
#endif
14405
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14406
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14407
#endif
14408
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14409
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14410
#endif
14411
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14412
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14413
#endif
14414
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14415
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14416
#endif
14417
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14418
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14419
#endif
14420
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14421
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14422
#endif
14423
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14424
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14425
#endif
14426
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14427
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14428
#endif
14429
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14430
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14431
#endif
14432
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14433
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14434
#endif
14435
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14436
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14437
#endif
14438
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14439
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14440
#endif
14441
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14442
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14443
#endif
14444
#ifdef _MIPS_CS_BASE
14445
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14446
#endif
14447
#ifdef _MIPS_CS_HOSTID
14448
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14449
#endif
14450
#ifdef _MIPS_CS_HW_NAME
14451
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14452
#endif
14453
#ifdef _MIPS_CS_NUM_PROCESSORS
14454
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14455
#endif
14456
#ifdef _MIPS_CS_OSREL_MAJ
14457
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14458
#endif
14459
#ifdef _MIPS_CS_OSREL_MIN
14460
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14461
#endif
14462
#ifdef _MIPS_CS_OSREL_PATCH
14463
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14464
#endif
14465
#ifdef _MIPS_CS_OS_NAME
14466
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14467
#endif
14468
#ifdef _MIPS_CS_OS_PROVIDER
14469
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14470
#endif
14471
#ifdef _MIPS_CS_PROCESSORS
14472
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14473
#endif
14474
#ifdef _MIPS_CS_SERIAL
14475
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14476
#endif
14477
#ifdef _MIPS_CS_VENDOR
14478
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14479
#endif
14480
};
14481
14482
14483
/*[clinic input]
14484
os.confstr
14485
14486
    name: confname(table="confstr_names")
14487
    /
14488
14489
Return a string-valued system configuration variable.
14490
[clinic start generated code]*/
14491
14492
static PyObject *
14493
os_confstr_impl(PyObject *module, int name)
14494
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14495
0
{
14496
0
    PyObject *result = NULL;
14497
0
    char buffer[255];
14498
0
    size_t len;
14499
14500
0
    errno = 0;
14501
0
    len = confstr(name, buffer, sizeof(buffer));
14502
0
    if (len == 0) {
14503
0
        if (errno) {
14504
0
            posix_error();
14505
0
            return NULL;
14506
0
        }
14507
0
        else {
14508
0
            Py_RETURN_NONE;
14509
0
        }
14510
0
    }
14511
14512
0
    if (len >= sizeof(buffer)) {
14513
0
        size_t len2;
14514
0
        char *buf = PyMem_Malloc(len);
14515
0
        if (buf == NULL)
14516
0
            return PyErr_NoMemory();
14517
0
        len2 = confstr(name, buf, len);
14518
0
        assert(len == len2);
14519
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14520
0
        PyMem_Free(buf);
14521
0
    }
14522
0
    else
14523
0
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14524
0
    return result;
14525
0
}
14526
#endif /* HAVE_CONFSTR */
14527
14528
14529
#ifdef HAVE_SYSCONF
14530
static struct constdef posix_constants_sysconf[] = {
14531
#ifdef _SC_2_CHAR_TERM
14532
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14533
#endif
14534
#ifdef _SC_2_C_BIND
14535
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14536
#endif
14537
#ifdef _SC_2_C_DEV
14538
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14539
#endif
14540
#ifdef _SC_2_C_VERSION
14541
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14542
#endif
14543
#ifdef _SC_2_FORT_DEV
14544
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14545
#endif
14546
#ifdef _SC_2_FORT_RUN
14547
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14548
#endif
14549
#ifdef _SC_2_LOCALEDEF
14550
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14551
#endif
14552
#ifdef _SC_2_SW_DEV
14553
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14554
#endif
14555
#ifdef _SC_2_UPE
14556
    {"SC_2_UPE",        _SC_2_UPE},
14557
#endif
14558
#ifdef _SC_2_VERSION
14559
    {"SC_2_VERSION",    _SC_2_VERSION},
14560
#endif
14561
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14562
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14563
#endif
14564
#ifdef _SC_ACL
14565
    {"SC_ACL",  _SC_ACL},
14566
#endif
14567
#ifdef _SC_AIO_LISTIO_MAX
14568
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14569
#endif
14570
#ifdef _SC_AIO_MAX
14571
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14572
#endif
14573
#ifdef _SC_AIO_PRIO_DELTA_MAX
14574
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14575
#endif
14576
#ifdef _SC_ARG_MAX
14577
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14578
#endif
14579
#ifdef _SC_ASYNCHRONOUS_IO
14580
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14581
#endif
14582
#ifdef _SC_ATEXIT_MAX
14583
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14584
#endif
14585
#ifdef _SC_AUDIT
14586
    {"SC_AUDIT",        _SC_AUDIT},
14587
#endif
14588
#ifdef _SC_AVPHYS_PAGES
14589
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14590
#endif
14591
#ifdef _SC_BC_BASE_MAX
14592
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14593
#endif
14594
#ifdef _SC_BC_DIM_MAX
14595
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14596
#endif
14597
#ifdef _SC_BC_SCALE_MAX
14598
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14599
#endif
14600
#ifdef _SC_BC_STRING_MAX
14601
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14602
#endif
14603
#ifdef _SC_CAP
14604
    {"SC_CAP",  _SC_CAP},
14605
#endif
14606
#ifdef _SC_CHARCLASS_NAME_MAX
14607
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14608
#endif
14609
#ifdef _SC_CHAR_BIT
14610
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14611
#endif
14612
#ifdef _SC_CHAR_MAX
14613
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14614
#endif
14615
#ifdef _SC_CHAR_MIN
14616
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14617
#endif
14618
#ifdef _SC_CHILD_MAX
14619
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14620
#endif
14621
#ifdef _SC_CLK_TCK
14622
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14623
#endif
14624
#ifdef _SC_COHER_BLKSZ
14625
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14626
#endif
14627
#ifdef _SC_COLL_WEIGHTS_MAX
14628
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14629
#endif
14630
#ifdef _SC_DCACHE_ASSOC
14631
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14632
#endif
14633
#ifdef _SC_DCACHE_BLKSZ
14634
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14635
#endif
14636
#ifdef _SC_DCACHE_LINESZ
14637
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14638
#endif
14639
#ifdef _SC_DCACHE_SZ
14640
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14641
#endif
14642
#ifdef _SC_DCACHE_TBLKSZ
14643
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14644
#endif
14645
#ifdef _SC_DELAYTIMER_MAX
14646
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14647
#endif
14648
#ifdef _SC_EQUIV_CLASS_MAX
14649
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14650
#endif
14651
#ifdef _SC_EXPR_NEST_MAX
14652
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14653
#endif
14654
#ifdef _SC_FSYNC
14655
    {"SC_FSYNC",        _SC_FSYNC},
14656
#endif
14657
#ifdef _SC_GETGR_R_SIZE_MAX
14658
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14659
#endif
14660
#ifdef _SC_GETPW_R_SIZE_MAX
14661
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14662
#endif
14663
#ifdef _SC_ICACHE_ASSOC
14664
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14665
#endif
14666
#ifdef _SC_ICACHE_BLKSZ
14667
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14668
#endif
14669
#ifdef _SC_ICACHE_LINESZ
14670
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14671
#endif
14672
#ifdef _SC_ICACHE_SZ
14673
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14674
#endif
14675
#ifdef _SC_INF
14676
    {"SC_INF",  _SC_INF},
14677
#endif
14678
#ifdef _SC_INT_MAX
14679
    {"SC_INT_MAX",      _SC_INT_MAX},
14680
#endif
14681
#ifdef _SC_INT_MIN
14682
    {"SC_INT_MIN",      _SC_INT_MIN},
14683
#endif
14684
#ifdef _SC_IOV_MAX
14685
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14686
#endif
14687
#ifdef _SC_IP_SECOPTS
14688
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14689
#endif
14690
#ifdef _SC_JOB_CONTROL
14691
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14692
#endif
14693
#ifdef _SC_KERN_POINTERS
14694
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14695
#endif
14696
#ifdef _SC_KERN_SIM
14697
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14698
#endif
14699
#ifdef _SC_LINE_MAX
14700
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14701
#endif
14702
#ifdef _SC_LOGIN_NAME_MAX
14703
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14704
#endif
14705
#ifdef _SC_LOGNAME_MAX
14706
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14707
#endif
14708
#ifdef _SC_LONG_BIT
14709
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14710
#endif
14711
#ifdef _SC_MAC
14712
    {"SC_MAC",  _SC_MAC},
14713
#endif
14714
#ifdef _SC_MAPPED_FILES
14715
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14716
#endif
14717
#ifdef _SC_MAXPID
14718
    {"SC_MAXPID",       _SC_MAXPID},
14719
#endif
14720
#ifdef _SC_MB_LEN_MAX
14721
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14722
#endif
14723
#ifdef _SC_MEMLOCK
14724
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14725
#endif
14726
#ifdef _SC_MEMLOCK_RANGE
14727
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14728
#endif
14729
#ifdef _SC_MEMORY_PROTECTION
14730
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14731
#endif
14732
#ifdef _SC_MESSAGE_PASSING
14733
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14734
#endif
14735
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14736
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14737
#endif
14738
#ifdef _SC_MQ_OPEN_MAX
14739
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14740
#endif
14741
#ifdef _SC_MQ_PRIO_MAX
14742
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14743
#endif
14744
#ifdef _SC_NACLS_MAX
14745
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14746
#endif
14747
#ifdef _SC_NGROUPS_MAX
14748
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14749
#endif
14750
#ifdef _SC_NL_ARGMAX
14751
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14752
#endif
14753
#ifdef _SC_NL_LANGMAX
14754
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14755
#endif
14756
#ifdef _SC_NL_MSGMAX
14757
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14758
#endif
14759
#ifdef _SC_NL_NMAX
14760
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14761
#endif
14762
#ifdef _SC_NL_SETMAX
14763
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14764
#endif
14765
#ifdef _SC_NL_TEXTMAX
14766
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14767
#endif
14768
#ifdef _SC_NPROCESSORS_CONF
14769
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14770
#endif
14771
#ifdef _SC_NPROCESSORS_ONLN
14772
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14773
#endif
14774
#ifdef _SC_NPROC_CONF
14775
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14776
#endif
14777
#ifdef _SC_NPROC_ONLN
14778
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14779
#endif
14780
#ifdef _SC_NZERO
14781
    {"SC_NZERO",        _SC_NZERO},
14782
#endif
14783
#ifdef _SC_OPEN_MAX
14784
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14785
#endif
14786
#ifdef _SC_PAGESIZE
14787
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14788
#endif
14789
#ifdef _SC_PAGE_SIZE
14790
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14791
#endif
14792
#ifdef _SC_AIX_REALMEM
14793
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14794
#endif
14795
#ifdef _SC_PASS_MAX
14796
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14797
#endif
14798
#ifdef _SC_PHYS_PAGES
14799
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14800
#endif
14801
#ifdef _SC_PII
14802
    {"SC_PII",  _SC_PII},
14803
#endif
14804
#ifdef _SC_PII_INTERNET
14805
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14806
#endif
14807
#ifdef _SC_PII_INTERNET_DGRAM
14808
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14809
#endif
14810
#ifdef _SC_PII_INTERNET_STREAM
14811
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14812
#endif
14813
#ifdef _SC_PII_OSI
14814
    {"SC_PII_OSI",      _SC_PII_OSI},
14815
#endif
14816
#ifdef _SC_PII_OSI_CLTS
14817
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14818
#endif
14819
#ifdef _SC_PII_OSI_COTS
14820
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14821
#endif
14822
#ifdef _SC_PII_OSI_M
14823
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14824
#endif
14825
#ifdef _SC_PII_SOCKET
14826
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14827
#endif
14828
#ifdef _SC_PII_XTI
14829
    {"SC_PII_XTI",      _SC_PII_XTI},
14830
#endif
14831
#ifdef _SC_POLL
14832
    {"SC_POLL", _SC_POLL},
14833
#endif
14834
#ifdef _SC_PRIORITIZED_IO
14835
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14836
#endif
14837
#ifdef _SC_PRIORITY_SCHEDULING
14838
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14839
#endif
14840
#ifdef _SC_REALTIME_SIGNALS
14841
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14842
#endif
14843
#ifdef _SC_RE_DUP_MAX
14844
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14845
#endif
14846
#ifdef _SC_RTSIG_MAX
14847
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14848
#endif
14849
#ifdef _SC_SAVED_IDS
14850
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14851
#endif
14852
#ifdef _SC_SCHAR_MAX
14853
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14854
#endif
14855
#ifdef _SC_SCHAR_MIN
14856
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14857
#endif
14858
#ifdef _SC_SELECT
14859
    {"SC_SELECT",       _SC_SELECT},
14860
#endif
14861
#ifdef _SC_SEMAPHORES
14862
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14863
#endif
14864
#ifdef _SC_SEM_NSEMS_MAX
14865
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14866
#endif
14867
#ifdef _SC_SEM_VALUE_MAX
14868
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14869
#endif
14870
#ifdef _SC_SHARED_MEMORY_OBJECTS
14871
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14872
#endif
14873
#ifdef _SC_SHRT_MAX
14874
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14875
#endif
14876
#ifdef _SC_SHRT_MIN
14877
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14878
#endif
14879
#ifdef _SC_SIGQUEUE_MAX
14880
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14881
#endif
14882
#ifdef _SC_SIGRT_MAX
14883
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14884
#endif
14885
#ifdef _SC_SIGRT_MIN
14886
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14887
#endif
14888
#ifdef _SC_SOFTPOWER
14889
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14890
#endif
14891
#ifdef _SC_SPLIT_CACHE
14892
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14893
#endif
14894
#ifdef _SC_SSIZE_MAX
14895
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14896
#endif
14897
#ifdef _SC_STACK_PROT
14898
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14899
#endif
14900
#ifdef _SC_STREAM_MAX
14901
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14902
#endif
14903
#ifdef _SC_SYNCHRONIZED_IO
14904
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14905
#endif
14906
#ifdef _SC_THREADS
14907
    {"SC_THREADS",      _SC_THREADS},
14908
#endif
14909
#ifdef _SC_THREAD_ATTR_STACKADDR
14910
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14911
#endif
14912
#ifdef _SC_THREAD_ATTR_STACKSIZE
14913
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14914
#endif
14915
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14916
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14917
#endif
14918
#ifdef _SC_THREAD_KEYS_MAX
14919
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14920
#endif
14921
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14922
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14923
#endif
14924
#ifdef _SC_THREAD_PRIO_INHERIT
14925
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14926
#endif
14927
#ifdef _SC_THREAD_PRIO_PROTECT
14928
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14929
#endif
14930
#ifdef _SC_THREAD_PROCESS_SHARED
14931
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14932
#endif
14933
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14934
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14935
#endif
14936
#ifdef _SC_THREAD_STACK_MIN
14937
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14938
#endif
14939
#ifdef _SC_THREAD_THREADS_MAX
14940
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14941
#endif
14942
#ifdef _SC_TIMERS
14943
    {"SC_TIMERS",       _SC_TIMERS},
14944
#endif
14945
#ifdef _SC_TIMER_MAX
14946
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14947
#endif
14948
#ifdef _SC_TTY_NAME_MAX
14949
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14950
#endif
14951
#ifdef _SC_TZNAME_MAX
14952
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14953
#endif
14954
#ifdef _SC_T_IOV_MAX
14955
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14956
#endif
14957
#ifdef _SC_UCHAR_MAX
14958
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14959
#endif
14960
#ifdef _SC_UINT_MAX
14961
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14962
#endif
14963
#ifdef _SC_UIO_MAXIOV
14964
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14965
#endif
14966
#ifdef _SC_ULONG_MAX
14967
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14968
#endif
14969
#ifdef _SC_USHRT_MAX
14970
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14971
#endif
14972
#ifdef _SC_VERSION
14973
    {"SC_VERSION",      _SC_VERSION},
14974
#endif
14975
#ifdef _SC_WORD_BIT
14976
    {"SC_WORD_BIT",     _SC_WORD_BIT},
14977
#endif
14978
#ifdef _SC_XBS5_ILP32_OFF32
14979
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
14980
#endif
14981
#ifdef _SC_XBS5_ILP32_OFFBIG
14982
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
14983
#endif
14984
#ifdef _SC_XBS5_LP64_OFF64
14985
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
14986
#endif
14987
#ifdef _SC_XBS5_LPBIG_OFFBIG
14988
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
14989
#endif
14990
#ifdef _SC_XOPEN_CRYPT
14991
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
14992
#endif
14993
#ifdef _SC_XOPEN_ENH_I18N
14994
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
14995
#endif
14996
#ifdef _SC_XOPEN_LEGACY
14997
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
14998
#endif
14999
#ifdef _SC_XOPEN_REALTIME
15000
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15001
#endif
15002
#ifdef _SC_XOPEN_REALTIME_THREADS
15003
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15004
#endif
15005
#ifdef _SC_XOPEN_SHM
15006
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15007
#endif
15008
#ifdef _SC_XOPEN_UNIX
15009
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15010
#endif
15011
#ifdef _SC_XOPEN_VERSION
15012
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15013
#endif
15014
#ifdef _SC_XOPEN_XCU_VERSION
15015
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15016
#endif
15017
#ifdef _SC_XOPEN_XPG2
15018
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15019
#endif
15020
#ifdef _SC_XOPEN_XPG3
15021
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15022
#endif
15023
#ifdef _SC_XOPEN_XPG4
15024
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15025
#endif
15026
#ifdef _SC_MINSIGSTKSZ
15027
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15028
#endif
15029
};
15030
15031
15032
/*[clinic input]
15033
os.sysconf -> long
15034
    name: confname(table="sysconf_names")
15035
    /
15036
15037
Return an integer-valued system configuration variable.
15038
[clinic start generated code]*/
15039
15040
static long
15041
os_sysconf_impl(PyObject *module, int name)
15042
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15043
0
{
15044
0
    long value;
15045
15046
0
    errno = 0;
15047
0
    value = sysconf(name);
15048
0
    if (value == -1 && errno != 0)
15049
0
        posix_error();
15050
0
    return value;
15051
0
}
15052
#endif /* HAVE_SYSCONF */
15053
15054
15055
static int
15056
setup_confname_table(struct constdef *table, size_t tablesize,
15057
                     const char *tablename, PyObject *module)
15058
66
{
15059
66
    PyObject *d = PyDict_New();
15060
66
    if (d == NULL)
15061
0
        return -1;
15062
15063
4.04k
    for (size_t i=0; i < tablesize; ++i) {
15064
3.98k
        PyObject *o = PyLong_FromLong(table[i].value);
15065
3.98k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15066
0
            Py_XDECREF(o);
15067
0
            Py_DECREF(d);
15068
0
            return -1;
15069
0
        }
15070
3.98k
        Py_DECREF(o);
15071
3.98k
    }
15072
66
    return PyModule_Add(module, tablename, d);
15073
66
}
15074
15075
/* Return -1 on failure, 0 on success. */
15076
static int
15077
setup_confname_tables(PyObject *module)
15078
22
{
15079
22
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15080
22
    if (setup_confname_table(posix_constants_pathconf,
15081
22
                             sizeof(posix_constants_pathconf)
15082
22
                               / sizeof(struct constdef),
15083
22
                             "pathconf_names", module))
15084
0
        return -1;
15085
22
#endif
15086
22
#ifdef HAVE_CONFSTR
15087
22
    if (setup_confname_table(posix_constants_confstr,
15088
22
                             sizeof(posix_constants_confstr)
15089
22
                               / sizeof(struct constdef),
15090
22
                             "confstr_names", module))
15091
0
        return -1;
15092
22
#endif
15093
22
#ifdef HAVE_SYSCONF
15094
22
    if (setup_confname_table(posix_constants_sysconf,
15095
22
                             sizeof(posix_constants_sysconf)
15096
22
                               / sizeof(struct constdef),
15097
22
                             "sysconf_names", module))
15098
0
        return -1;
15099
22
#endif
15100
22
    return 0;
15101
22
}
15102
15103
15104
/*[clinic input]
15105
os.abort
15106
15107
Abort the interpreter immediately.
15108
15109
This function 'dumps core' or otherwise fails in the hardest way possible
15110
on the hosting operating system.  This function never returns.
15111
[clinic start generated code]*/
15112
15113
static PyObject *
15114
os_abort_impl(PyObject *module)
15115
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
15116
0
{
15117
0
    abort();
15118
    /*NOTREACHED*/
15119
#ifndef __clang__
15120
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15121
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15122
       is smarter and emits a warning on the return. */
15123
    Py_FatalError("abort() called from Python code didn't abort!");
15124
    return NULL;
15125
#endif
15126
0
}
15127
15128
#ifdef MS_WINDOWS
15129
/* Grab ShellExecute dynamically from shell32 */
15130
static int has_ShellExecute = -1;
15131
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15132
                                              LPCWSTR, INT);
15133
static int
15134
check_ShellExecute(void)
15135
{
15136
    HINSTANCE hShell32;
15137
15138
    /* only recheck */
15139
    if (-1 == has_ShellExecute) {
15140
        Py_BEGIN_ALLOW_THREADS
15141
        /* Security note: this call is not vulnerable to "DLL hijacking".
15142
           SHELL32 is part of "KnownDLLs" and so Windows always load
15143
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15144
           in the DLL search path. */
15145
        hShell32 = LoadLibraryW(L"SHELL32");
15146
        if (hShell32) {
15147
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15148
                                            "ShellExecuteW");
15149
            has_ShellExecute = Py_ShellExecuteW != NULL;
15150
        } else {
15151
            has_ShellExecute = 0;
15152
        }
15153
        Py_END_ALLOW_THREADS
15154
    }
15155
    return has_ShellExecute;
15156
}
15157
15158
15159
/*[clinic input]
15160
os.startfile
15161
    filepath: path_t
15162
    operation: Py_UNICODE = NULL
15163
    arguments: Py_UNICODE = NULL
15164
    cwd: path_t(nullable=True) = None
15165
    show_cmd: int = 1
15166
15167
Start a file with its associated application.
15168
15169
When "operation" is not specified or "open", this acts like
15170
double-clicking the file in Explorer, or giving the file name as an
15171
argument to the DOS "start" command: the file is opened with whatever
15172
application (if any) its extension is associated.
15173
When another "operation" is given, it specifies what should be done with
15174
the file.  A typical operation is "print".
15175
15176
"arguments" is passed to the application, but should be omitted if the
15177
file is a document.
15178
15179
"cwd" is the working directory for the operation. If "filepath" is
15180
relative, it will be resolved against this directory. This argument
15181
should usually be an absolute path.
15182
15183
"show_cmd" can be used to override the recommended visibility option.
15184
See the Windows ShellExecute documentation for values.
15185
15186
startfile returns as soon as the associated application is launched.
15187
There is no option to wait for the application to close, and no way
15188
to retrieve the application's exit status.
15189
15190
The filepath is relative to the current directory.  If you want to use
15191
an absolute path, make sure the first character is not a slash ("/");
15192
the underlying Win32 ShellExecute function doesn't work if it is.
15193
[clinic start generated code]*/
15194
15195
static PyObject *
15196
os_startfile_impl(PyObject *module, path_t *filepath,
15197
                  const wchar_t *operation, const wchar_t *arguments,
15198
                  path_t *cwd, int show_cmd)
15199
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15200
{
15201
    HINSTANCE rc;
15202
15203
    if(!check_ShellExecute()) {
15204
        /* If the OS doesn't have ShellExecute, return a
15205
           NotImplementedError. */
15206
        return PyErr_Format(PyExc_NotImplementedError,
15207
            "startfile not available on this platform");
15208
    }
15209
15210
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15211
        return NULL;
15212
    }
15213
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15214
                    arguments, cwd->object ? cwd->object : Py_None,
15215
                    show_cmd) < 0) {
15216
        return NULL;
15217
    }
15218
15219
    Py_BEGIN_ALLOW_THREADS
15220
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15221
                          arguments, cwd->wide, show_cmd);
15222
    Py_END_ALLOW_THREADS
15223
15224
    if (rc <= (HINSTANCE)32) {
15225
        win32_error_object("startfile", filepath->object);
15226
        return NULL;
15227
    }
15228
    Py_RETURN_NONE;
15229
}
15230
#endif /* MS_WINDOWS */
15231
15232
15233
#ifdef HAVE_GETLOADAVG
15234
/*[clinic input]
15235
os.getloadavg
15236
15237
Return average recent system load information.
15238
15239
Return the number of processes in the system run queue averaged over
15240
the last 1, 5, and 15 minutes as a tuple of three floats.
15241
Raises OSError if the load average was unobtainable.
15242
[clinic start generated code]*/
15243
15244
static PyObject *
15245
os_getloadavg_impl(PyObject *module)
15246
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15247
0
{
15248
0
    double loadavg[3];
15249
0
    if (getloadavg(loadavg, 3)!=3) {
15250
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15251
0
        return NULL;
15252
0
    } else
15253
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15254
0
}
15255
#endif /* HAVE_GETLOADAVG */
15256
15257
15258
/*[clinic input]
15259
os.device_encoding
15260
    fd: int
15261
15262
Return a string describing the encoding of a terminal's file descriptor.
15263
15264
The file descriptor must be attached to a terminal.
15265
If the device is not a terminal, return None.
15266
[clinic start generated code]*/
15267
15268
static PyObject *
15269
os_device_encoding_impl(PyObject *module, int fd)
15270
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15271
0
{
15272
0
    return _Py_device_encoding(fd);
15273
0
}
15274
15275
15276
#ifdef HAVE_SETRESUID
15277
/*[clinic input]
15278
os.setresuid
15279
15280
    ruid: uid_t
15281
    euid: uid_t
15282
    suid: uid_t
15283
    /
15284
15285
Set the current process's real, effective, and saved user ids.
15286
[clinic start generated code]*/
15287
15288
static PyObject *
15289
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15290
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15291
0
{
15292
0
    if (setresuid(ruid, euid, suid) < 0)
15293
0
        return posix_error();
15294
0
    Py_RETURN_NONE;
15295
0
}
15296
#endif /* HAVE_SETRESUID */
15297
15298
15299
#ifdef HAVE_SETRESGID
15300
/*[clinic input]
15301
os.setresgid
15302
15303
    rgid: gid_t
15304
    egid: gid_t
15305
    sgid: gid_t
15306
    /
15307
15308
Set the current process's real, effective, and saved group ids.
15309
[clinic start generated code]*/
15310
15311
static PyObject *
15312
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15313
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15314
0
{
15315
0
    if (setresgid(rgid, egid, sgid) < 0)
15316
0
        return posix_error();
15317
0
    Py_RETURN_NONE;
15318
0
}
15319
#endif /* HAVE_SETRESGID */
15320
15321
15322
#ifdef HAVE_GETRESUID
15323
/*[clinic input]
15324
os.getresuid
15325
15326
Return a tuple of the current process's real, effective, and saved user ids.
15327
[clinic start generated code]*/
15328
15329
static PyObject *
15330
os_getresuid_impl(PyObject *module)
15331
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
15332
0
{
15333
0
    uid_t ruid, euid, suid;
15334
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15335
0
        return posix_error();
15336
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15337
0
                                  _PyLong_FromUid(euid),
15338
0
                                  _PyLong_FromUid(suid));
15339
0
}
15340
#endif /* HAVE_GETRESUID */
15341
15342
15343
#ifdef HAVE_GETRESGID
15344
/*[clinic input]
15345
@permit_long_summary
15346
os.getresgid
15347
15348
Return a tuple of the current process's real, effective, and saved group ids.
15349
[clinic start generated code]*/
15350
15351
static PyObject *
15352
os_getresgid_impl(PyObject *module)
15353
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15354
0
{
15355
0
    gid_t rgid, egid, sgid;
15356
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15357
0
        return posix_error();
15358
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15359
0
                                  _PyLong_FromGid(egid),
15360
0
                                  _PyLong_FromGid(sgid));
15361
0
}
15362
#endif /* HAVE_GETRESGID */
15363
15364
15365
#ifdef USE_XATTRS
15366
/*[clinic input]
15367
os.getxattr
15368
15369
    path: path_t(allow_fd=True)
15370
    attribute: path_t
15371
    *
15372
    follow_symlinks: bool = True
15373
15374
Return the value of extended attribute attribute on path.
15375
15376
path may be either a string, a path-like object, or an open file descriptor.
15377
If follow_symlinks is False, and the last element of the path is a symbolic
15378
  link, getxattr will examine the symbolic link itself instead of the file
15379
  the link points to.
15380
15381
[clinic start generated code]*/
15382
15383
static PyObject *
15384
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15385
                 int follow_symlinks)
15386
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
15387
0
{
15388
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
15389
0
        return NULL;
15390
15391
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15392
0
        return NULL;
15393
0
    }
15394
15395
0
    for (Py_ssize_t i = 0; ; i++) {
15396
0
        ssize_t result;
15397
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15398
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15399
0
        if (!buffer_size) {
15400
0
            path_error(path);
15401
0
            return NULL;
15402
0
        }
15403
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15404
0
        if (writer == NULL) {
15405
0
            return NULL;
15406
0
        }
15407
0
        void *ptr = PyBytesWriter_GetData(writer);
15408
15409
0
        Py_BEGIN_ALLOW_THREADS;
15410
0
        if (path->fd >= 0)
15411
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15412
0
        else if (follow_symlinks)
15413
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15414
0
        else
15415
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15416
0
        Py_END_ALLOW_THREADS;
15417
15418
0
        if (result < 0) {
15419
0
            PyBytesWriter_Discard(writer);
15420
0
            if (errno == ERANGE) {
15421
0
                continue;
15422
0
            }
15423
0
            path_error(path);
15424
0
            return NULL;
15425
0
        }
15426
15427
0
        return PyBytesWriter_FinishWithSize(writer, result);
15428
0
    }
15429
0
}
15430
15431
15432
/*[clinic input]
15433
@permit_long_docstring_body
15434
os.setxattr
15435
15436
    path: path_t(allow_fd=True)
15437
    attribute: path_t
15438
    value: Py_buffer
15439
    flags: int = 0
15440
    *
15441
    follow_symlinks: bool = True
15442
15443
Set extended attribute attribute on path to value.
15444
15445
path may be either a string, a path-like object,  or an open file descriptor.
15446
If follow_symlinks is False, and the last element of the path is a symbolic
15447
  link, setxattr will modify the symbolic link itself instead of the file
15448
  the link points to.
15449
15450
[clinic start generated code]*/
15451
15452
static PyObject *
15453
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15454
                 Py_buffer *value, int flags, int follow_symlinks)
15455
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15456
0
{
15457
0
    ssize_t result;
15458
15459
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
15460
0
        return NULL;
15461
15462
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15463
0
                    value->buf, value->len, flags) < 0) {
15464
0
        return NULL;
15465
0
    }
15466
15467
0
    Py_BEGIN_ALLOW_THREADS;
15468
0
    if (path->fd > -1)
15469
0
        result = fsetxattr(path->fd, attribute->narrow,
15470
0
                           value->buf, value->len, flags);
15471
0
    else if (follow_symlinks)
15472
0
        result = setxattr(path->narrow, attribute->narrow,
15473
0
                           value->buf, value->len, flags);
15474
0
    else
15475
0
        result = lsetxattr(path->narrow, attribute->narrow,
15476
0
                           value->buf, value->len, flags);
15477
0
    Py_END_ALLOW_THREADS;
15478
15479
0
    if (result) {
15480
0
        path_error(path);
15481
0
        return NULL;
15482
0
    }
15483
15484
0
    Py_RETURN_NONE;
15485
0
}
15486
15487
15488
/*[clinic input]
15489
os.removexattr
15490
15491
    path: path_t(allow_fd=True)
15492
    attribute: path_t
15493
    *
15494
    follow_symlinks: bool = True
15495
15496
Remove extended attribute attribute on path.
15497
15498
path may be either a string, a path-like object, or an open file descriptor.
15499
If follow_symlinks is False, and the last element of the path is a symbolic
15500
  link, removexattr will modify the symbolic link itself instead of the file
15501
  the link points to.
15502
15503
[clinic start generated code]*/
15504
15505
static PyObject *
15506
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15507
                    int follow_symlinks)
15508
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15509
0
{
15510
0
    ssize_t result;
15511
15512
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
15513
0
        return NULL;
15514
15515
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15516
0
        return NULL;
15517
0
    }
15518
15519
0
    Py_BEGIN_ALLOW_THREADS;
15520
0
    if (path->fd > -1)
15521
0
        result = fremovexattr(path->fd, attribute->narrow);
15522
0
    else if (follow_symlinks)
15523
0
        result = removexattr(path->narrow, attribute->narrow);
15524
0
    else
15525
0
        result = lremovexattr(path->narrow, attribute->narrow);
15526
0
    Py_END_ALLOW_THREADS;
15527
15528
0
    if (result) {
15529
0
        return path_error(path);
15530
0
    }
15531
15532
0
    Py_RETURN_NONE;
15533
0
}
15534
15535
15536
/*[clinic input]
15537
@permit_long_docstring_body
15538
os.listxattr
15539
15540
    path: path_t(allow_fd=True, nullable=True) = None
15541
    *
15542
    follow_symlinks: bool = True
15543
15544
Return a list of extended attributes on path.
15545
15546
path may be either None, a string, a path-like object, or an open file descriptor.
15547
if path is None, listxattr will examine the current directory.
15548
If follow_symlinks is False, and the last element of the path is a symbolic
15549
  link, listxattr will examine the symbolic link itself instead of the file
15550
  the link points to.
15551
[clinic start generated code]*/
15552
15553
static PyObject *
15554
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15555
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15556
0
{
15557
0
    Py_ssize_t i;
15558
0
    PyObject *result = NULL;
15559
0
    const char *name;
15560
0
    char *buffer = NULL;
15561
15562
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
15563
0
        goto exit;
15564
15565
0
    if (PySys_Audit("os.listxattr", "(O)",
15566
0
                    path->object ? path->object : Py_None) < 0) {
15567
0
        return NULL;
15568
0
    }
15569
15570
0
    name = path->narrow ? path->narrow : ".";
15571
15572
0
    for (i = 0; ; i++) {
15573
0
        const char *start, *trace, *end;
15574
0
        ssize_t length;
15575
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15576
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15577
0
        if (!buffer_size) {
15578
            /* ERANGE */
15579
0
            path_error(path);
15580
0
            break;
15581
0
        }
15582
0
        buffer = PyMem_Malloc(buffer_size);
15583
0
        if (!buffer) {
15584
0
            PyErr_NoMemory();
15585
0
            break;
15586
0
        }
15587
15588
0
        Py_BEGIN_ALLOW_THREADS;
15589
0
        if (path->fd > -1)
15590
0
            length = flistxattr(path->fd, buffer, buffer_size);
15591
0
        else if (follow_symlinks)
15592
0
            length = listxattr(name, buffer, buffer_size);
15593
0
        else
15594
0
            length = llistxattr(name, buffer, buffer_size);
15595
0
        Py_END_ALLOW_THREADS;
15596
15597
0
        if (length < 0) {
15598
0
            if (errno == ERANGE) {
15599
0
                PyMem_Free(buffer);
15600
0
                buffer = NULL;
15601
0
                continue;
15602
0
            }
15603
0
            path_error(path);
15604
0
            break;
15605
0
        }
15606
15607
0
        result = PyList_New(0);
15608
0
        if (!result) {
15609
0
            goto exit;
15610
0
        }
15611
15612
0
        end = buffer + length;
15613
0
        for (trace = start = buffer; trace != end; trace++) {
15614
0
            if (!*trace) {
15615
0
                int error;
15616
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15617
0
                                                                 trace - start);
15618
0
                if (!attribute) {
15619
0
                    Py_SETREF(result, NULL);
15620
0
                    goto exit;
15621
0
                }
15622
0
                error = PyList_Append(result, attribute);
15623
0
                Py_DECREF(attribute);
15624
0
                if (error) {
15625
0
                    Py_SETREF(result, NULL);
15626
0
                    goto exit;
15627
0
                }
15628
0
                start = trace + 1;
15629
0
            }
15630
0
        }
15631
0
    break;
15632
0
    }
15633
0
exit:
15634
0
    if (buffer)
15635
0
        PyMem_Free(buffer);
15636
0
    return result;
15637
0
}
15638
#endif /* USE_XATTRS */
15639
15640
15641
/*[clinic input]
15642
@permit_long_summary
15643
os.urandom
15644
15645
    size: Py_ssize_t(allow_negative=False)
15646
    /
15647
15648
Return a bytes object containing random bytes suitable for cryptographic use.
15649
[clinic start generated code]*/
15650
15651
static PyObject *
15652
os_urandom_impl(PyObject *module, Py_ssize_t size)
15653
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15654
0
{
15655
0
    if (size < 0) {
15656
0
        return PyErr_Format(PyExc_ValueError,
15657
0
                            "negative argument not allowed");
15658
0
    }
15659
15660
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15661
0
    if (writer == NULL) {
15662
0
        return NULL;
15663
0
    }
15664
15665
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15666
0
    if (result == -1) {
15667
0
        PyBytesWriter_Discard(writer);
15668
0
        return NULL;
15669
0
    }
15670
0
    return PyBytesWriter_Finish(writer);
15671
0
}
15672
15673
#ifdef HAVE_MEMFD_CREATE
15674
/*[clinic input]
15675
os.memfd_create
15676
15677
    name: unicode_fs_encoded
15678
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15679
15680
[clinic start generated code]*/
15681
15682
static PyObject *
15683
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15684
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15685
0
{
15686
0
    int fd;
15687
0
    const char *bytes = PyBytes_AS_STRING(name);
15688
0
    Py_BEGIN_ALLOW_THREADS
15689
0
    fd = memfd_create(bytes, flags);
15690
0
    Py_END_ALLOW_THREADS
15691
0
    if (fd == -1) {
15692
0
        return PyErr_SetFromErrno(PyExc_OSError);
15693
0
    }
15694
0
    return PyLong_FromLong(fd);
15695
0
}
15696
#endif
15697
15698
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15699
/*[clinic input]
15700
os.eventfd
15701
15702
    initval: unsigned_int
15703
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15704
15705
Creates and returns an event notification file descriptor.
15706
[clinic start generated code]*/
15707
15708
static PyObject *
15709
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15710
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15711
15712
0
{
15713
    /* initval is limited to uint32_t, internal counter is uint64_t */
15714
0
    int fd;
15715
0
    Py_BEGIN_ALLOW_THREADS
15716
0
    fd = eventfd(initval, flags);
15717
0
    Py_END_ALLOW_THREADS
15718
0
    if (fd == -1) {
15719
0
        return PyErr_SetFromErrno(PyExc_OSError);
15720
0
    }
15721
0
    return PyLong_FromLong(fd);
15722
0
}
15723
15724
/*[clinic input]
15725
os.eventfd_read
15726
15727
    fd: fildes
15728
15729
Read eventfd value
15730
[clinic start generated code]*/
15731
15732
static PyObject *
15733
os_eventfd_read_impl(PyObject *module, int fd)
15734
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15735
0
{
15736
0
    eventfd_t value;
15737
0
    int result;
15738
0
    Py_BEGIN_ALLOW_THREADS
15739
0
    result = eventfd_read(fd, &value);
15740
0
    Py_END_ALLOW_THREADS
15741
0
    if (result == -1) {
15742
0
        return PyErr_SetFromErrno(PyExc_OSError);
15743
0
    }
15744
0
    return PyLong_FromUnsignedLongLong(value);
15745
0
}
15746
15747
/*[clinic input]
15748
os.eventfd_write
15749
15750
    fd: fildes
15751
    value: unsigned_long_long
15752
15753
Write eventfd value.
15754
[clinic start generated code]*/
15755
15756
static PyObject *
15757
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15758
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15759
0
{
15760
0
    int result;
15761
0
    Py_BEGIN_ALLOW_THREADS
15762
0
    result = eventfd_write(fd, value);
15763
0
    Py_END_ALLOW_THREADS
15764
0
    if (result == -1) {
15765
0
        return PyErr_SetFromErrno(PyExc_OSError);
15766
0
    }
15767
0
    Py_RETURN_NONE;
15768
0
}
15769
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15770
15771
/* Terminal size querying */
15772
15773
PyDoc_STRVAR(TerminalSize_docstring,
15774
    "A tuple of (columns, lines) for holding terminal window size");
15775
15776
static PyStructSequence_Field TerminalSize_fields[] = {
15777
    {"columns", "width of the terminal window in characters"},
15778
    {"lines", "height of the terminal window in characters"},
15779
    {NULL, NULL}
15780
};
15781
15782
static PyStructSequence_Desc TerminalSize_desc = {
15783
    "os.terminal_size",
15784
    TerminalSize_docstring,
15785
    TerminalSize_fields,
15786
    2,
15787
};
15788
15789
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15790
/*[clinic input]
15791
os.get_terminal_size
15792
15793
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15794
    /
15795
15796
Return the size of the terminal window as (columns, lines).
15797
15798
The optional argument fd (default standard output) specifies
15799
which file descriptor should be queried.
15800
15801
If the file descriptor is not connected to a terminal, an OSError
15802
is thrown.
15803
15804
This function will only be defined if an implementation is
15805
available for this system.
15806
15807
shutil.get_terminal_size is the high-level function which should
15808
normally be used, os.get_terminal_size is the low-level implementation.
15809
[clinic start generated code]*/
15810
15811
static PyObject *
15812
os_get_terminal_size_impl(PyObject *module, int fd)
15813
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15814
0
{
15815
0
    int columns, lines;
15816
0
    PyObject *termsize;
15817
15818
    /* Under some conditions stdout may not be connected and
15819
     * fileno(stdout) may point to an invalid file descriptor. For example
15820
     * GUI apps don't have valid standard streams by default.
15821
     *
15822
     * If this happens, and the optional fd argument is not present,
15823
     * the ioctl below will fail returning EBADF. This is what we want.
15824
     */
15825
15826
0
#ifdef TERMSIZE_USE_IOCTL
15827
0
    {
15828
0
        struct winsize w;
15829
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15830
0
            return PyErr_SetFromErrno(PyExc_OSError);
15831
0
        columns = w.ws_col;
15832
0
        lines = w.ws_row;
15833
0
    }
15834
0
#endif /* TERMSIZE_USE_IOCTL */
15835
15836
#ifdef TERMSIZE_USE_CONIO
15837
    {
15838
        HANDLE handle;
15839
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15840
        handle = _Py_get_osfhandle(fd);
15841
        if (handle == INVALID_HANDLE_VALUE)
15842
            return NULL;
15843
15844
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15845
            return PyErr_SetFromWindowsErr(0);
15846
15847
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15848
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15849
    }
15850
#endif /* TERMSIZE_USE_CONIO */
15851
15852
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15853
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15854
0
    if (termsize == NULL)
15855
0
        return NULL;
15856
15857
0
    int pos = 0;
15858
15859
0
#define SET_TERMSIZE(CALL)                                   \
15860
0
    do {                                                     \
15861
0
        PyObject *item = (CALL);                             \
15862
0
        if (item == NULL) {                                  \
15863
0
            Py_DECREF(termsize);                             \
15864
0
            return NULL;                                     \
15865
0
        }                                                    \
15866
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15867
0
    } while(0)
15868
15869
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15870
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15871
0
#undef SET_TERMSIZE
15872
15873
0
    return termsize;
15874
0
}
15875
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15876
15877
/*[clinic input]
15878
os.cpu_count
15879
15880
Return the number of logical CPUs in the system.
15881
15882
Return None if indeterminable.
15883
[clinic start generated code]*/
15884
15885
static PyObject *
15886
os_cpu_count_impl(PyObject *module)
15887
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15888
0
{
15889
0
    const PyConfig *config = _Py_GetConfig();
15890
0
    if (config->cpu_count > 0) {
15891
0
        return PyLong_FromLong(config->cpu_count);
15892
0
    }
15893
15894
0
    int ncpu = 0;
15895
#ifdef MS_WINDOWS
15896
# ifdef MS_WINDOWS_DESKTOP
15897
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15898
# else
15899
    ncpu = 0;
15900
# endif
15901
15902
#elif defined(__hpux)
15903
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15904
15905
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15906
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15907
15908
#elif defined(__VXWORKS__)
15909
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15910
15911
#elif defined(__DragonFly__) || \
15912
      defined(__OpenBSD__)   || \
15913
      defined(__FreeBSD__)   || \
15914
      defined(__NetBSD__)    || \
15915
      defined(__APPLE__)
15916
    ncpu = 0;
15917
    size_t len = sizeof(ncpu);
15918
    int mib[2] = {CTL_HW, HW_NCPU};
15919
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15920
        ncpu = 0;
15921
    }
15922
#endif
15923
15924
0
    if (ncpu < 1) {
15925
0
        Py_RETURN_NONE;
15926
0
    }
15927
0
    return PyLong_FromLong(ncpu);
15928
0
}
15929
15930
15931
/*[clinic input]
15932
os.get_inheritable -> bool
15933
15934
    fd: int
15935
    /
15936
15937
Get the close-on-exe flag of the specified file descriptor.
15938
[clinic start generated code]*/
15939
15940
static int
15941
os_get_inheritable_impl(PyObject *module, int fd)
15942
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15943
0
{
15944
0
    int return_value;
15945
0
    _Py_BEGIN_SUPPRESS_IPH
15946
0
    return_value = _Py_get_inheritable(fd);
15947
0
    _Py_END_SUPPRESS_IPH
15948
0
    return return_value;
15949
0
}
15950
15951
15952
/*[clinic input]
15953
os.set_inheritable
15954
    fd: int
15955
    inheritable: int
15956
    /
15957
15958
Set the inheritable flag of the specified file descriptor.
15959
[clinic start generated code]*/
15960
15961
static PyObject *
15962
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15963
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15964
0
{
15965
0
    int result;
15966
15967
0
    _Py_BEGIN_SUPPRESS_IPH
15968
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15969
0
    _Py_END_SUPPRESS_IPH
15970
0
    if (result < 0)
15971
0
        return NULL;
15972
0
    Py_RETURN_NONE;
15973
0
}
15974
15975
15976
#ifdef MS_WINDOWS
15977
#ifndef HANDLE_FLAG_INHERIT
15978
#define HANDLE_FLAG_INHERIT 0x00000001
15979
#endif
15980
15981
/*[clinic input]
15982
os.get_handle_inheritable -> bool
15983
    handle: intptr_t
15984
    /
15985
15986
Get the close-on-exe flag of the specified file descriptor.
15987
[clinic start generated code]*/
15988
15989
static int
15990
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
15991
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
15992
{
15993
    DWORD flags;
15994
15995
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
15996
        PyErr_SetFromWindowsErr(0);
15997
        return -1;
15998
    }
15999
16000
    return flags & HANDLE_FLAG_INHERIT;
16001
}
16002
16003
16004
/*[clinic input]
16005
os.set_handle_inheritable
16006
    handle: intptr_t
16007
    inheritable: bool
16008
    /
16009
16010
Set the inheritable flag of the specified handle.
16011
[clinic start generated code]*/
16012
16013
static PyObject *
16014
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16015
                               int inheritable)
16016
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16017
{
16018
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16019
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16020
        PyErr_SetFromWindowsErr(0);
16021
        return NULL;
16022
    }
16023
    Py_RETURN_NONE;
16024
}
16025
#endif /* MS_WINDOWS */
16026
16027
/*[clinic input]
16028
os.get_blocking -> bool
16029
    fd: int
16030
    /
16031
16032
Get the blocking mode of the file descriptor.
16033
16034
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16035
[clinic start generated code]*/
16036
16037
static int
16038
os_get_blocking_impl(PyObject *module, int fd)
16039
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16040
0
{
16041
0
    int blocking;
16042
16043
0
    _Py_BEGIN_SUPPRESS_IPH
16044
0
    blocking = _Py_get_blocking(fd);
16045
0
    _Py_END_SUPPRESS_IPH
16046
0
    return blocking;
16047
0
}
16048
16049
/*[clinic input]
16050
os.set_blocking
16051
    fd: int
16052
    blocking: bool
16053
    /
16054
16055
Set the blocking mode of the specified file descriptor.
16056
16057
Set the O_NONBLOCK flag if blocking is False,
16058
clear the O_NONBLOCK flag otherwise.
16059
[clinic start generated code]*/
16060
16061
static PyObject *
16062
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16063
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16064
0
{
16065
0
    int result;
16066
16067
0
    _Py_BEGIN_SUPPRESS_IPH
16068
0
    result = _Py_set_blocking(fd, blocking);
16069
0
    _Py_END_SUPPRESS_IPH
16070
0
    if (result < 0)
16071
0
        return NULL;
16072
0
    Py_RETURN_NONE;
16073
0
}
16074
16075
16076
/*[clinic input]
16077
class os.DirEntry "DirEntry *" "DirEntryType"
16078
[clinic start generated code]*/
16079
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16080
16081
typedef struct {
16082
    PyObject_HEAD
16083
    PyObject *name;
16084
    PyObject *path;
16085
    PyObject *stat;
16086
    PyObject *lstat;
16087
#ifdef MS_WINDOWS
16088
    struct _Py_stat_struct win32_lstat;
16089
    uint64_t win32_file_index;
16090
    uint64_t win32_file_index_high;
16091
    int got_file_index;
16092
#else /* POSIX */
16093
#ifdef HAVE_DIRENT_D_TYPE
16094
    unsigned char d_type;
16095
#endif
16096
    ino_t d_ino;
16097
    int dir_fd;
16098
#endif
16099
} DirEntry;
16100
16101
0
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16102
16103
static void
16104
DirEntry_dealloc(PyObject *op)
16105
0
{
16106
0
    DirEntry *entry = DirEntry_CAST(op);
16107
0
    PyTypeObject *tp = Py_TYPE(entry);
16108
0
    Py_XDECREF(entry->name);
16109
0
    Py_XDECREF(entry->path);
16110
0
    Py_XDECREF(entry->stat);
16111
0
    Py_XDECREF(entry->lstat);
16112
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16113
0
    free_func(entry);
16114
0
    Py_DECREF(tp);
16115
0
}
16116
16117
/* Forward reference */
16118
static int
16119
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16120
                   int follow_symlinks, unsigned short mode_bits);
16121
16122
/*[clinic input]
16123
os.DirEntry.is_symlink -> bool
16124
    defining_class: defining_class
16125
    /
16126
16127
Return True if the entry is a symbolic link; cached per entry.
16128
[clinic start generated code]*/
16129
16130
static int
16131
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16132
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16133
0
{
16134
#ifdef MS_WINDOWS
16135
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16136
#elif defined(HAVE_DIRENT_D_TYPE)
16137
    /* POSIX */
16138
0
    if (self->d_type != DT_UNKNOWN)
16139
0
        return self->d_type == DT_LNK;
16140
0
    else
16141
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16142
#else
16143
    /* POSIX without d_type */
16144
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16145
#endif
16146
0
}
16147
16148
/*[clinic input]
16149
os.DirEntry.is_junction -> bool
16150
16151
Return True if the entry is a junction; cached per entry.
16152
[clinic start generated code]*/
16153
16154
static int
16155
os_DirEntry_is_junction_impl(DirEntry *self)
16156
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16157
0
{
16158
#ifdef MS_WINDOWS
16159
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16160
#else
16161
0
    return 0;
16162
0
#endif
16163
0
}
16164
16165
static PyObject *
16166
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16167
0
{
16168
0
    int result;
16169
0
    STRUCT_STAT st;
16170
0
    PyObject *ub;
16171
16172
#ifdef MS_WINDOWS
16173
    if (!PyUnicode_FSDecoder(self->path, &ub))
16174
        return NULL;
16175
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16176
    Py_DECREF(ub);
16177
#else /* POSIX */
16178
0
    if (!PyUnicode_FSConverter(self->path, &ub))
16179
0
        return NULL;
16180
0
    const char *path = PyBytes_AS_STRING(ub);
16181
0
    if (self->dir_fd != DEFAULT_DIR_FD) {
16182
0
#ifdef HAVE_FSTATAT
16183
0
      if (HAVE_FSTATAT_RUNTIME) {
16184
0
        Py_BEGIN_ALLOW_THREADS
16185
0
        result = fstatat(self->dir_fd, path, &st,
16186
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16187
0
        Py_END_ALLOW_THREADS
16188
0
      } else
16189
16190
0
#endif /* HAVE_FSTATAT */
16191
0
      {
16192
0
        Py_DECREF(ub);
16193
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16194
0
        return NULL;
16195
0
      }
16196
0
    }
16197
0
    else
16198
0
#endif
16199
0
    {
16200
0
        Py_BEGIN_ALLOW_THREADS
16201
0
        if (follow_symlinks) {
16202
0
            result = STAT(path, &st);
16203
0
        }
16204
0
        else {
16205
0
            result = LSTAT(path, &st);
16206
0
        }
16207
0
        Py_END_ALLOW_THREADS
16208
0
    }
16209
16210
0
    int saved_errno = errno;
16211
#if defined(MS_WINDOWS)
16212
    PyMem_Free(path);
16213
#else
16214
0
    Py_DECREF(ub);
16215
0
#endif
16216
16217
0
    if (result != 0) {
16218
0
        errno = saved_errno;
16219
0
        path_object_error(self->path);
16220
0
        return NULL;
16221
0
    }
16222
16223
0
    return _pystat_fromstructstat(module, &st);
16224
0
}
16225
16226
static PyObject *
16227
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16228
0
{
16229
0
    if (!self->lstat) {
16230
0
        PyObject *module = PyType_GetModule(defining_class);
16231
#ifdef MS_WINDOWS
16232
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16233
#else /* POSIX */
16234
0
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16235
0
#endif
16236
0
    }
16237
0
    return Py_XNewRef(self->lstat);
16238
0
}
16239
16240
/*[clinic input]
16241
os.DirEntry.stat
16242
    defining_class: defining_class
16243
    /
16244
    *
16245
    follow_symlinks: bool = True
16246
16247
Return stat_result object for the entry; cached per entry.
16248
[clinic start generated code]*/
16249
16250
static PyObject *
16251
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16252
                      int follow_symlinks)
16253
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16254
0
{
16255
0
    if (!follow_symlinks) {
16256
0
        return DirEntry_get_lstat(defining_class, self);
16257
0
    }
16258
16259
0
    if (!self->stat) {
16260
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16261
0
        if (result == -1) {
16262
0
            return NULL;
16263
0
        }
16264
0
        if (result) {
16265
0
            PyObject *module = PyType_GetModule(defining_class);
16266
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16267
0
        }
16268
0
        else {
16269
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16270
0
        }
16271
0
    }
16272
16273
0
    return Py_XNewRef(self->stat);
16274
0
}
16275
16276
/* Set exception and return -1 on error, 0 for False, 1 for True */
16277
static int
16278
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16279
                   int follow_symlinks, unsigned short mode_bits)
16280
0
{
16281
0
    PyObject *stat = NULL;
16282
0
    PyObject *st_mode = NULL;
16283
0
    long mode;
16284
0
    int result;
16285
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16286
0
    int is_symlink;
16287
0
    int need_stat;
16288
0
#endif
16289
#ifdef MS_WINDOWS
16290
    unsigned long dir_bits;
16291
#endif
16292
16293
#ifdef MS_WINDOWS
16294
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16295
    need_stat = follow_symlinks && is_symlink;
16296
#elif defined(HAVE_DIRENT_D_TYPE)
16297
0
    is_symlink = self->d_type == DT_LNK;
16298
0
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16299
0
#endif
16300
16301
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16302
0
    if (need_stat) {
16303
0
#endif
16304
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16305
0
        if (!stat) {
16306
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16307
                /* If file doesn't exist (anymore), then return False
16308
                   (i.e., say it's not a file/directory) */
16309
0
                PyErr_Clear();
16310
0
                return 0;
16311
0
            }
16312
0
            goto error;
16313
0
        }
16314
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16315
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16316
0
        if (!st_mode)
16317
0
            goto error;
16318
16319
0
        mode = PyLong_AsLong(st_mode);
16320
0
        if (mode == -1 && PyErr_Occurred())
16321
0
            goto error;
16322
0
        Py_CLEAR(st_mode);
16323
0
        Py_CLEAR(stat);
16324
0
        result = (mode & S_IFMT) == mode_bits;
16325
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16326
0
    }
16327
0
    else if (is_symlink) {
16328
0
        assert(mode_bits != S_IFLNK);
16329
0
        result = 0;
16330
0
    }
16331
0
    else {
16332
0
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16333
#ifdef MS_WINDOWS
16334
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16335
        if (mode_bits == S_IFDIR)
16336
            result = dir_bits != 0;
16337
        else
16338
            result = dir_bits == 0;
16339
#else /* POSIX */
16340
0
        if (mode_bits == S_IFDIR)
16341
0
            result = self->d_type == DT_DIR;
16342
0
        else
16343
0
            result = self->d_type == DT_REG;
16344
0
#endif
16345
0
    }
16346
0
#endif
16347
16348
0
    return result;
16349
16350
0
error:
16351
0
    Py_XDECREF(st_mode);
16352
0
    Py_XDECREF(stat);
16353
0
    return -1;
16354
0
}
16355
16356
/*[clinic input]
16357
os.DirEntry.is_dir -> bool
16358
    defining_class: defining_class
16359
    /
16360
    *
16361
    follow_symlinks: bool = True
16362
16363
Return True if the entry is a directory; cached per entry.
16364
[clinic start generated code]*/
16365
16366
static int
16367
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16368
                        int follow_symlinks)
16369
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16370
0
{
16371
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16372
0
}
16373
16374
/*[clinic input]
16375
os.DirEntry.is_file -> bool
16376
    defining_class: defining_class
16377
    /
16378
    *
16379
    follow_symlinks: bool = True
16380
16381
Return True if the entry is a file; cached per entry.
16382
[clinic start generated code]*/
16383
16384
static int
16385
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16386
                         int follow_symlinks)
16387
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16388
0
{
16389
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16390
0
}
16391
16392
/*[clinic input]
16393
os.DirEntry.inode
16394
16395
Return inode of the entry; cached per entry.
16396
[clinic start generated code]*/
16397
16398
static PyObject *
16399
os_DirEntry_inode_impl(DirEntry *self)
16400
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16401
0
{
16402
#ifdef MS_WINDOWS
16403
    if (!self->got_file_index) {
16404
        PyObject *unicode;
16405
        STRUCT_STAT stat;
16406
        int result;
16407
16408
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16409
            return NULL;
16410
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16411
        Py_DECREF(unicode);
16412
        result = LSTAT(path, &stat);
16413
16414
        int saved_errno = errno;
16415
        PyMem_Free(path);
16416
16417
        if (result != 0) {
16418
            errno = saved_errno;
16419
            return path_object_error(self->path);
16420
        }
16421
16422
        self->win32_file_index = stat.st_ino;
16423
        self->win32_file_index_high = stat.st_ino_high;
16424
        self->got_file_index = 1;
16425
    }
16426
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16427
#else /* POSIX */
16428
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16429
0
                  "DirEntry.d_ino is larger than unsigned long long");
16430
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16431
0
#endif
16432
0
}
16433
16434
static PyObject *
16435
DirEntry_repr(PyObject *op)
16436
0
{
16437
0
    DirEntry *self = DirEntry_CAST(op);
16438
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16439
0
}
16440
16441
/*[clinic input]
16442
os.DirEntry.__fspath__
16443
16444
Returns the path for the entry.
16445
[clinic start generated code]*/
16446
16447
static PyObject *
16448
os_DirEntry___fspath___impl(DirEntry *self)
16449
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16450
0
{
16451
0
    return Py_NewRef(self->path);
16452
0
}
16453
16454
static PyMemberDef DirEntry_members[] = {
16455
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16456
     "the entry's base filename, relative to scandir() \"path\" argument"},
16457
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16458
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16459
    {NULL}
16460
};
16461
16462
#include "clinic/posixmodule.c.h"
16463
16464
static PyMethodDef DirEntry_methods[] = {
16465
    OS_DIRENTRY_IS_DIR_METHODDEF
16466
    OS_DIRENTRY_IS_FILE_METHODDEF
16467
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16468
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16469
    OS_DIRENTRY_STAT_METHODDEF
16470
    OS_DIRENTRY_INODE_METHODDEF
16471
    OS_DIRENTRY___FSPATH___METHODDEF
16472
    {"__class_getitem__",       Py_GenericAlias,
16473
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16474
    {NULL}
16475
};
16476
16477
static PyType_Slot DirEntryType_slots[] = {
16478
    {Py_tp_dealloc, DirEntry_dealloc},
16479
    {Py_tp_repr, DirEntry_repr},
16480
    {Py_tp_methods, DirEntry_methods},
16481
    {Py_tp_members, DirEntry_members},
16482
    {0, 0},
16483
};
16484
16485
static PyType_Spec DirEntryType_spec = {
16486
    .name = MODNAME ".DirEntry",
16487
    .basicsize = sizeof(DirEntry),
16488
    .flags = (
16489
        Py_TPFLAGS_DEFAULT
16490
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16491
        | Py_TPFLAGS_IMMUTABLETYPE
16492
    ),
16493
    .slots = DirEntryType_slots
16494
};
16495
16496
16497
#ifdef MS_WINDOWS
16498
16499
static wchar_t *
16500
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16501
{
16502
    Py_ssize_t path_len;
16503
    Py_ssize_t size;
16504
    wchar_t *result;
16505
    wchar_t ch;
16506
16507
    if (!path_wide) { /* Default arg: "." */
16508
        path_wide = L".";
16509
        path_len = 1;
16510
    }
16511
    else {
16512
        path_len = wcslen(path_wide);
16513
    }
16514
16515
    /* The +1's are for the path separator and the NUL */
16516
    size = path_len + 1 + wcslen(filename) + 1;
16517
    result = PyMem_New(wchar_t, size);
16518
    if (!result) {
16519
        PyErr_NoMemory();
16520
        return NULL;
16521
    }
16522
    wcscpy(result, path_wide);
16523
    if (path_len > 0) {
16524
        ch = result[path_len - 1];
16525
        if (ch != SEP && ch != ALTSEP && ch != L':')
16526
            result[path_len++] = SEP;
16527
        wcscpy(result + path_len, filename);
16528
    }
16529
    return result;
16530
}
16531
16532
static PyObject *
16533
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16534
{
16535
    DirEntry *entry;
16536
    BY_HANDLE_FILE_INFORMATION file_info;
16537
    ULONG reparse_tag;
16538
    wchar_t *joined_path;
16539
16540
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16541
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16542
    if (!entry)
16543
        return NULL;
16544
    entry->name = NULL;
16545
    entry->path = NULL;
16546
    entry->stat = NULL;
16547
    entry->lstat = NULL;
16548
    entry->got_file_index = 0;
16549
16550
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16551
    if (!entry->name)
16552
        goto error;
16553
    int return_bytes = path->wide && PyBytes_Check(path->object);
16554
    if (return_bytes) {
16555
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16556
        if (!entry->name)
16557
            goto error;
16558
    }
16559
16560
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16561
    if (!joined_path)
16562
        goto error;
16563
16564
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16565
    PyMem_Free(joined_path);
16566
    if (!entry->path)
16567
        goto error;
16568
    if (return_bytes) {
16569
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16570
        if (!entry->path)
16571
            goto error;
16572
    }
16573
16574
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16575
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16576
16577
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16578
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16579
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16580
16581
    return (PyObject *)entry;
16582
16583
error:
16584
    Py_DECREF(entry);
16585
    return NULL;
16586
}
16587
16588
#else /* POSIX */
16589
16590
static char *
16591
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16592
0
{
16593
0
    Py_ssize_t path_len;
16594
0
    Py_ssize_t size;
16595
0
    char *result;
16596
16597
0
    if (!path_narrow) { /* Default arg: "." */
16598
0
        path_narrow = ".";
16599
0
        path_len = 1;
16600
0
    }
16601
0
    else {
16602
0
        path_len = strlen(path_narrow);
16603
0
    }
16604
16605
0
    if (filename_len == -1)
16606
0
        filename_len = strlen(filename);
16607
16608
    /* The +1's are for the path separator and the NUL */
16609
0
    size = path_len + 1 + filename_len + 1;
16610
0
    result = PyMem_New(char, size);
16611
0
    if (!result) {
16612
0
        PyErr_NoMemory();
16613
0
        return NULL;
16614
0
    }
16615
0
    strcpy(result, path_narrow);
16616
0
    if (path_len > 0 && result[path_len - 1] != '/')
16617
0
        result[path_len++] = '/';
16618
0
    strcpy(result + path_len, filename);
16619
0
    return result;
16620
0
}
16621
16622
static PyObject *
16623
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16624
                         Py_ssize_t name_len, ino_t d_ino
16625
#ifdef HAVE_DIRENT_D_TYPE
16626
                         , unsigned char d_type
16627
#endif
16628
                         )
16629
0
{
16630
0
    DirEntry *entry;
16631
0
    char *joined_path;
16632
16633
0
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16634
0
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16635
0
    if (!entry)
16636
0
        return NULL;
16637
0
    entry->name = NULL;
16638
0
    entry->path = NULL;
16639
0
    entry->stat = NULL;
16640
0
    entry->lstat = NULL;
16641
16642
0
    if (path->fd != -1) {
16643
0
        entry->dir_fd = path->fd;
16644
0
        joined_path = NULL;
16645
0
    }
16646
0
    else {
16647
0
        entry->dir_fd = DEFAULT_DIR_FD;
16648
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16649
0
        if (!joined_path)
16650
0
            goto error;
16651
0
    }
16652
16653
0
    if (!path->narrow || !PyBytes_Check(path->object)) {
16654
0
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16655
0
        if (joined_path)
16656
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16657
0
    }
16658
0
    else {
16659
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16660
0
        if (joined_path)
16661
0
            entry->path = PyBytes_FromString(joined_path);
16662
0
    }
16663
0
    PyMem_Free(joined_path);
16664
0
    if (!entry->name)
16665
0
        goto error;
16666
16667
0
    if (path->fd != -1) {
16668
0
        entry->path = Py_NewRef(entry->name);
16669
0
    }
16670
0
    else if (!entry->path)
16671
0
        goto error;
16672
16673
0
#ifdef HAVE_DIRENT_D_TYPE
16674
0
    entry->d_type = d_type;
16675
0
#endif
16676
0
    entry->d_ino = d_ino;
16677
16678
0
    return (PyObject *)entry;
16679
16680
0
error:
16681
0
    Py_XDECREF(entry);
16682
0
    return NULL;
16683
0
}
16684
16685
#endif
16686
16687
16688
typedef struct {
16689
    PyObject_HEAD
16690
    path_t path;
16691
#ifdef MS_WINDOWS
16692
    HANDLE handle;
16693
    WIN32_FIND_DATAW file_data;
16694
    int first_time;
16695
#else /* POSIX */
16696
    DIR *dirp;
16697
#endif
16698
#ifdef HAVE_FDOPENDIR
16699
    int fd;
16700
#endif
16701
} ScandirIterator;
16702
16703
0
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16704
16705
#ifdef MS_WINDOWS
16706
16707
static int
16708
ScandirIterator_is_closed(ScandirIterator *iterator)
16709
{
16710
    return iterator->handle == INVALID_HANDLE_VALUE;
16711
}
16712
16713
static void
16714
ScandirIterator_closedir(ScandirIterator *iterator)
16715
{
16716
    HANDLE handle = iterator->handle;
16717
16718
    if (handle == INVALID_HANDLE_VALUE)
16719
        return;
16720
16721
    iterator->handle = INVALID_HANDLE_VALUE;
16722
    Py_BEGIN_ALLOW_THREADS
16723
    FindClose(handle);
16724
    Py_END_ALLOW_THREADS
16725
}
16726
16727
static PyObject *
16728
ScandirIterator_iternext(PyObject *op)
16729
{
16730
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16731
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16732
    BOOL success;
16733
    PyObject *entry;
16734
16735
    /* Happens if the iterator is iterated twice, or closed explicitly */
16736
    if (iterator->handle == INVALID_HANDLE_VALUE)
16737
        return NULL;
16738
16739
    while (1) {
16740
        if (!iterator->first_time) {
16741
            Py_BEGIN_ALLOW_THREADS
16742
            success = FindNextFileW(iterator->handle, file_data);
16743
            Py_END_ALLOW_THREADS
16744
            if (!success) {
16745
                /* Error or no more files */
16746
                if (GetLastError() != ERROR_NO_MORE_FILES)
16747
                    path_error(&iterator->path);
16748
                break;
16749
            }
16750
        }
16751
        iterator->first_time = 0;
16752
16753
        /* Skip over . and .. */
16754
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16755
            wcscmp(file_data->cFileName, L"..") != 0)
16756
        {
16757
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16758
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16759
            if (!entry)
16760
                break;
16761
            return entry;
16762
        }
16763
16764
        /* Loop till we get a non-dot directory or finish iterating */
16765
    }
16766
16767
    /* Error or no more files */
16768
    ScandirIterator_closedir(iterator);
16769
    return NULL;
16770
}
16771
16772
#else /* POSIX */
16773
16774
static int
16775
ScandirIterator_is_closed(ScandirIterator *iterator)
16776
0
{
16777
0
    return !iterator->dirp;
16778
0
}
16779
16780
static void
16781
ScandirIterator_closedir(ScandirIterator *iterator)
16782
0
{
16783
0
    DIR *dirp = iterator->dirp;
16784
16785
0
    if (!dirp)
16786
0
        return;
16787
16788
0
    iterator->dirp = NULL;
16789
0
    Py_BEGIN_ALLOW_THREADS
16790
0
#ifdef HAVE_FDOPENDIR
16791
0
    if (iterator->path.fd != -1)
16792
0
        rewinddir(dirp);
16793
0
#endif
16794
0
    closedir(dirp);
16795
0
    Py_END_ALLOW_THREADS
16796
0
    return;
16797
0
}
16798
16799
static PyObject *
16800
ScandirIterator_iternext(PyObject *op)
16801
0
{
16802
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16803
0
    struct dirent *direntp;
16804
0
    Py_ssize_t name_len;
16805
0
    int is_dot;
16806
0
    PyObject *entry;
16807
16808
    /* Happens if the iterator is iterated twice, or closed explicitly */
16809
0
    if (!iterator->dirp)
16810
0
        return NULL;
16811
16812
0
    while (1) {
16813
0
        errno = 0;
16814
0
        Py_BEGIN_ALLOW_THREADS
16815
0
        direntp = readdir(iterator->dirp);
16816
0
        Py_END_ALLOW_THREADS
16817
16818
0
        if (!direntp) {
16819
            /* Error or no more files */
16820
0
            if (errno != 0)
16821
0
                path_error(&iterator->path);
16822
0
            break;
16823
0
        }
16824
16825
        /* Skip over . and .. */
16826
0
        name_len = NAMLEN(direntp);
16827
0
        is_dot = direntp->d_name[0] == '.' &&
16828
0
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16829
0
        if (!is_dot) {
16830
0
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16831
0
            entry = DirEntry_from_posix_info(module,
16832
0
                                             &iterator->path, direntp->d_name,
16833
0
                                             name_len, direntp->d_ino
16834
0
#ifdef HAVE_DIRENT_D_TYPE
16835
0
                                             , direntp->d_type
16836
0
#endif
16837
0
                                            );
16838
0
            if (!entry)
16839
0
                break;
16840
0
            return entry;
16841
0
        }
16842
16843
        /* Loop till we get a non-dot directory or finish iterating */
16844
0
    }
16845
16846
    /* Error or no more files */
16847
0
    ScandirIterator_closedir(iterator);
16848
0
    return NULL;
16849
0
}
16850
16851
#endif
16852
16853
static PyObject *
16854
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16855
0
{
16856
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16857
0
    ScandirIterator_closedir(self);
16858
0
    Py_RETURN_NONE;
16859
0
}
16860
16861
static PyObject *
16862
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16863
0
{
16864
0
    return Py_NewRef(self);
16865
0
}
16866
16867
static PyObject *
16868
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16869
0
{
16870
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16871
0
    ScandirIterator_closedir(self);
16872
0
    Py_RETURN_NONE;
16873
0
}
16874
16875
static void
16876
ScandirIterator_finalize(PyObject *op)
16877
0
{
16878
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16879
    /* Save the current exception, if any. */
16880
0
    PyObject *exc = PyErr_GetRaisedException();
16881
16882
0
    if (!ScandirIterator_is_closed(iterator)) {
16883
0
        ScandirIterator_closedir(iterator);
16884
16885
0
        if (PyErr_ResourceWarning(op, 1,
16886
0
                                  "unclosed scandir iterator %R", iterator))
16887
0
        {
16888
            /* Spurious errors can appear at shutdown */
16889
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16890
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16891
0
                                       "scandir iterator %R", iterator);
16892
0
            }
16893
0
        }
16894
0
    }
16895
16896
0
    path_cleanup(&iterator->path);
16897
16898
    /* Restore the saved exception. */
16899
0
    PyErr_SetRaisedException(exc);
16900
0
}
16901
16902
static void
16903
ScandirIterator_dealloc(PyObject *op)
16904
0
{
16905
0
    PyTypeObject *tp = Py_TYPE(op);
16906
0
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16907
0
        return;
16908
16909
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16910
0
    free_func(op);
16911
0
    Py_DECREF(tp);
16912
0
}
16913
16914
static PyMethodDef ScandirIterator_methods[] = {
16915
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16916
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16917
    {"close", ScandirIterator_close, METH_NOARGS},
16918
    {NULL}
16919
};
16920
16921
static PyType_Slot ScandirIteratorType_slots[] = {
16922
    {Py_tp_dealloc, ScandirIterator_dealloc},
16923
    {Py_tp_finalize, ScandirIterator_finalize},
16924
    {Py_tp_iter, PyObject_SelfIter},
16925
    {Py_tp_iternext, ScandirIterator_iternext},
16926
    {Py_tp_methods, ScandirIterator_methods},
16927
    {0, 0},
16928
};
16929
16930
static PyType_Spec ScandirIteratorType_spec = {
16931
    .name = MODNAME ".ScandirIterator",
16932
    .basicsize = sizeof(ScandirIterator),
16933
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16934
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16935
    .flags = (
16936
        Py_TPFLAGS_DEFAULT
16937
        | Py_TPFLAGS_HAVE_FINALIZE
16938
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16939
        | Py_TPFLAGS_IMMUTABLETYPE
16940
    ),
16941
    .slots = ScandirIteratorType_slots
16942
};
16943
16944
/*[clinic input]
16945
os.scandir
16946
16947
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16948
16949
Return an iterator of DirEntry objects for given path.
16950
16951
path can be specified as either str, bytes, or a path-like object.  If path
16952
is bytes, the names of yielded DirEntry objects will also be bytes; in
16953
all other circumstances they will be str.
16954
16955
If path is None, uses the path='.'.
16956
[clinic start generated code]*/
16957
16958
static PyObject *
16959
os_scandir_impl(PyObject *module, path_t *path)
16960
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16961
0
{
16962
0
    ScandirIterator *iterator;
16963
#ifdef MS_WINDOWS
16964
    wchar_t *path_strW;
16965
#else
16966
0
    const char *path_str;
16967
0
#ifdef HAVE_FDOPENDIR
16968
0
    int fd = -1;
16969
0
#endif
16970
0
#endif
16971
16972
0
    if (PySys_Audit("os.scandir", "O",
16973
0
                    path->object ? path->object : Py_None) < 0) {
16974
0
        return NULL;
16975
0
    }
16976
16977
0
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
16978
0
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
16979
0
    if (!iterator)
16980
0
        return NULL;
16981
16982
#ifdef MS_WINDOWS
16983
    iterator->handle = INVALID_HANDLE_VALUE;
16984
#else
16985
0
    iterator->dirp = NULL;
16986
0
#endif
16987
16988
    /* Move the ownership to iterator->path */
16989
0
    memcpy(&iterator->path, path, sizeof(path_t));
16990
0
    memset(path, 0, sizeof(path_t));
16991
16992
#ifdef MS_WINDOWS
16993
    iterator->first_time = 1;
16994
16995
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
16996
    if (!path_strW)
16997
        goto error;
16998
16999
    Py_BEGIN_ALLOW_THREADS
17000
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17001
    Py_END_ALLOW_THREADS
17002
17003
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17004
        path_error(&iterator->path);
17005
        PyMem_Free(path_strW);
17006
        goto error;
17007
    }
17008
    PyMem_Free(path_strW);
17009
#else /* POSIX */
17010
0
    errno = 0;
17011
0
#ifdef HAVE_FDOPENDIR
17012
0
    if (iterator->path.fd != -1) {
17013
0
      if (HAVE_FDOPENDIR_RUNTIME) {
17014
        /* closedir() closes the FD, so we duplicate it */
17015
0
        fd = _Py_dup(iterator->path.fd);
17016
0
        if (fd == -1)
17017
0
            goto error;
17018
17019
0
        Py_BEGIN_ALLOW_THREADS
17020
0
        iterator->dirp = fdopendir(fd);
17021
0
        Py_END_ALLOW_THREADS
17022
0
      } else {
17023
0
        PyErr_SetString(PyExc_TypeError,
17024
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17025
0
        return NULL;
17026
0
      }
17027
0
    }
17028
0
    else
17029
0
#endif
17030
0
    {
17031
0
        if (iterator->path.narrow)
17032
0
            path_str = iterator->path.narrow;
17033
0
        else
17034
0
            path_str = ".";
17035
17036
0
        Py_BEGIN_ALLOW_THREADS
17037
0
        iterator->dirp = opendir(path_str);
17038
0
        Py_END_ALLOW_THREADS
17039
0
    }
17040
17041
0
    if (!iterator->dirp) {
17042
0
        path_error(&iterator->path);
17043
0
#ifdef HAVE_FDOPENDIR
17044
0
        if (fd != -1) {
17045
0
            Py_BEGIN_ALLOW_THREADS
17046
0
            close(fd);
17047
0
            Py_END_ALLOW_THREADS
17048
0
        }
17049
0
#endif
17050
0
        goto error;
17051
0
    }
17052
0
#endif
17053
17054
0
    return (PyObject *)iterator;
17055
17056
0
error:
17057
0
    Py_DECREF(iterator);
17058
0
    return NULL;
17059
0
}
17060
17061
/*
17062
    Return the file system path representation of the object.
17063
17064
    If the object is str or bytes, then allow it to pass through with
17065
    an incremented refcount. If the object defines __fspath__(), then
17066
    return the result of that method. All other types raise a TypeError.
17067
*/
17068
PyObject *
17069
PyOS_FSPath(PyObject *path)
17070
37.9k
{
17071
    /* For error message reasons, this function is manually inlined in
17072
       path_converter(). */
17073
37.9k
    PyObject *func = NULL;
17074
37.9k
    PyObject *path_repr = NULL;
17075
17076
37.9k
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17077
37.9k
        return Py_NewRef(path);
17078
37.9k
    }
17079
17080
0
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17081
0
    if ((NULL == func) || (func == Py_None)) {
17082
0
        return PyErr_Format(PyExc_TypeError,
17083
0
                            "expected str, bytes or os.PathLike object, "
17084
0
                            "not %.200s",
17085
0
                            _PyType_Name(Py_TYPE(path)));
17086
0
    }
17087
17088
0
    path_repr = _PyObject_CallNoArgs(func);
17089
0
    Py_DECREF(func);
17090
0
    if (NULL == path_repr) {
17091
0
        return NULL;
17092
0
    }
17093
17094
0
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17095
0
        PyErr_Format(PyExc_TypeError,
17096
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17097
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17098
0
                     _PyType_Name(Py_TYPE(path_repr)));
17099
0
        Py_DECREF(path_repr);
17100
0
        return NULL;
17101
0
    }
17102
17103
0
    return path_repr;
17104
0
}
17105
17106
/*[clinic input]
17107
@permit_long_docstring_body
17108
os.fspath
17109
17110
    path: object
17111
17112
Return the file system path representation of the object.
17113
17114
If the object is str or bytes, then allow it to pass through as-is. If the
17115
object defines __fspath__(), then return the result of that method. All other
17116
types raise a TypeError.
17117
[clinic start generated code]*/
17118
17119
static PyObject *
17120
os_fspath_impl(PyObject *module, PyObject *path)
17121
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
17122
3.80k
{
17123
3.80k
    return PyOS_FSPath(path);
17124
3.80k
}
17125
17126
#ifdef HAVE_GETRANDOM_SYSCALL
17127
/*[clinic input]
17128
os.getrandom
17129
17130
    size: Py_ssize_t
17131
    flags: int=0
17132
17133
Obtain a series of random bytes.
17134
[clinic start generated code]*/
17135
17136
static PyObject *
17137
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17138
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17139
0
{
17140
0
    if (size < 0) {
17141
0
        errno = EINVAL;
17142
0
        return posix_error();
17143
0
    }
17144
17145
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17146
0
    if (writer == NULL) {
17147
0
        return NULL;
17148
0
    }
17149
0
    void *data = PyBytesWriter_GetData(writer);
17150
17151
0
    Py_ssize_t n;
17152
0
    while (1) {
17153
0
        n = syscall(SYS_getrandom, data, size, flags);
17154
0
        if (n < 0 && errno == EINTR) {
17155
0
            if (PyErr_CheckSignals() < 0) {
17156
0
                goto error;
17157
0
            }
17158
17159
            /* getrandom() was interrupted by a signal: retry */
17160
0
            continue;
17161
0
        }
17162
0
        break;
17163
0
    }
17164
17165
0
    if (n < 0) {
17166
0
        PyErr_SetFromErrno(PyExc_OSError);
17167
0
        goto error;
17168
0
    }
17169
17170
0
    return PyBytesWriter_FinishWithSize(writer, n);
17171
17172
0
error:
17173
0
    PyBytesWriter_Discard(writer);
17174
0
    return NULL;
17175
0
}
17176
#endif   /* HAVE_GETRANDOM_SYSCALL */
17177
17178
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17179
17180
/* bpo-36085: Helper functions for managing DLL search directories
17181
 * on win32
17182
 */
17183
17184
/*[clinic input]
17185
os._add_dll_directory
17186
17187
    path: path_t
17188
17189
Add a path to the DLL search path.
17190
17191
This search path is used when resolving dependencies for imported
17192
extension modules (the module itself is resolved through sys.path),
17193
and also by ctypes.
17194
17195
Returns an opaque value that may be passed to os.remove_dll_directory
17196
to remove this directory from the search path.
17197
[clinic start generated code]*/
17198
17199
static PyObject *
17200
os__add_dll_directory_impl(PyObject *module, path_t *path)
17201
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17202
{
17203
    DLL_DIRECTORY_COOKIE cookie = 0;
17204
    DWORD err = 0;
17205
17206
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17207
        return NULL;
17208
    }
17209
17210
    Py_BEGIN_ALLOW_THREADS
17211
    if (!(cookie = AddDllDirectory(path->wide))) {
17212
        err = GetLastError();
17213
    }
17214
    Py_END_ALLOW_THREADS
17215
17216
    if (err) {
17217
        return win32_error_object_err("add_dll_directory",
17218
                                      path->object, err);
17219
    }
17220
17221
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17222
}
17223
17224
/*[clinic input]
17225
os._remove_dll_directory
17226
17227
    cookie: object
17228
17229
Removes a path from the DLL search path.
17230
17231
The parameter is an opaque value that was returned from
17232
os.add_dll_directory. You can only remove directories that you added
17233
yourself.
17234
[clinic start generated code]*/
17235
17236
static PyObject *
17237
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17238
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17239
{
17240
    DLL_DIRECTORY_COOKIE cookieValue;
17241
    DWORD err = 0;
17242
17243
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17244
        PyErr_SetString(PyExc_TypeError,
17245
            "Provided cookie was not returned from os.add_dll_directory");
17246
        return NULL;
17247
    }
17248
17249
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17250
        cookie, "DLL directory cookie");
17251
17252
    Py_BEGIN_ALLOW_THREADS
17253
    if (!RemoveDllDirectory(cookieValue)) {
17254
        err = GetLastError();
17255
    }
17256
    Py_END_ALLOW_THREADS
17257
17258
    if (err) {
17259
        return win32_error_object_err("remove_dll_directory",
17260
                                      NULL, err);
17261
    }
17262
17263
    if (PyCapsule_SetName(cookie, NULL)) {
17264
        return NULL;
17265
    }
17266
17267
    Py_RETURN_NONE;
17268
}
17269
17270
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17271
17272
17273
/* Only check if WIFEXITED is available: expect that it comes
17274
   with WEXITSTATUS, WIFSIGNALED, etc.
17275
17276
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17277
   subprocess can safely call it during late Python finalization without
17278
   risking that used os attributes were set to None by finalize_modules(). */
17279
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17280
/*[clinic input]
17281
os.waitstatus_to_exitcode
17282
17283
    status as status_obj: object
17284
17285
Convert a wait status to an exit code.
17286
17287
On Unix:
17288
17289
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17290
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17291
* Otherwise, raise a ValueError.
17292
17293
On Windows, return status shifted right by 8 bits.
17294
17295
On Unix, if the process is being traced or if waitpid() was called with
17296
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
17297
This function must not be called if WIFSTOPPED(status) is true.
17298
[clinic start generated code]*/
17299
17300
static PyObject *
17301
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17302
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
17303
0
{
17304
0
#ifndef MS_WINDOWS
17305
0
    int status = PyLong_AsInt(status_obj);
17306
0
    if (status == -1 && PyErr_Occurred()) {
17307
0
        return NULL;
17308
0
    }
17309
17310
0
    WAIT_TYPE wait_status;
17311
0
    WAIT_STATUS_INT(wait_status) = status;
17312
0
    int exitcode;
17313
0
    if (WIFEXITED(wait_status)) {
17314
0
        exitcode = WEXITSTATUS(wait_status);
17315
        /* Sanity check to provide warranty on the function behavior.
17316
           It should not occur in practice */
17317
0
        if (exitcode < 0) {
17318
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17319
0
            return NULL;
17320
0
        }
17321
0
    }
17322
0
    else if (WIFSIGNALED(wait_status)) {
17323
0
        int signum = WTERMSIG(wait_status);
17324
        /* Sanity check to provide warranty on the function behavior.
17325
           It should not occurs in practice */
17326
0
        if (signum <= 0) {
17327
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17328
0
            return NULL;
17329
0
        }
17330
0
        exitcode = -signum;
17331
0
    } else if (WIFSTOPPED(wait_status)) {
17332
        /* Status only received if the process is being traced
17333
           or if waitpid() was called with WUNTRACED option. */
17334
0
        int signum = WSTOPSIG(wait_status);
17335
0
        PyErr_Format(PyExc_ValueError,
17336
0
                     "process stopped by delivery of signal %i",
17337
0
                     signum);
17338
0
        return NULL;
17339
0
    }
17340
0
    else {
17341
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17342
0
        return NULL;
17343
0
    }
17344
0
    return PyLong_FromLong(exitcode);
17345
#else
17346
    /* Windows implementation: see os.waitpid() implementation
17347
       which uses _cwait(). */
17348
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17349
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17350
        return NULL;
17351
    }
17352
17353
    unsigned long long exitcode = (status >> 8);
17354
    /* ExitProcess() accepts an UINT type:
17355
       reject exit code which doesn't fit in an UINT */
17356
    if (exitcode > UINT_MAX) {
17357
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17358
        return NULL;
17359
    }
17360
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17361
#endif
17362
0
}
17363
#endif
17364
17365
#if defined(MS_WINDOWS)
17366
/*[clinic input]
17367
os._supports_virtual_terminal
17368
17369
Checks if virtual terminal is supported in windows
17370
[clinic start generated code]*/
17371
17372
static PyObject *
17373
os__supports_virtual_terminal_impl(PyObject *module)
17374
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17375
{
17376
#ifdef HAVE_WINDOWS_CONSOLE_IO
17377
    DWORD mode = 0;
17378
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17379
    if (!GetConsoleMode(handle, &mode)) {
17380
        Py_RETURN_FALSE;
17381
    }
17382
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17383
#else
17384
    Py_RETURN_FALSE;
17385
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17386
}
17387
#endif
17388
17389
/*[clinic input]
17390
os._inputhook
17391
17392
Calls PyOS_InputHook dropping the GIL first
17393
[clinic start generated code]*/
17394
17395
static PyObject *
17396
os__inputhook_impl(PyObject *module)
17397
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17398
0
{
17399
0
     int result = 0;
17400
0
     if (PyOS_InputHook) {
17401
0
         Py_BEGIN_ALLOW_THREADS;
17402
0
         result = PyOS_InputHook();
17403
0
         Py_END_ALLOW_THREADS;
17404
0
     }
17405
0
     return PyLong_FromLong(result);
17406
0
}
17407
17408
/*[clinic input]
17409
os._is_inputhook_installed
17410
17411
Checks if PyOS_InputHook is set
17412
[clinic start generated code]*/
17413
17414
static PyObject *
17415
os__is_inputhook_installed_impl(PyObject *module)
17416
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17417
0
{
17418
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17419
0
}
17420
17421
/*[clinic input]
17422
os._create_environ
17423
17424
Create the environment dictionary.
17425
[clinic start generated code]*/
17426
17427
static PyObject *
17428
os__create_environ_impl(PyObject *module)
17429
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17430
0
{
17431
0
    return convertenviron();
17432
0
}
17433
17434
17435
#ifdef __EMSCRIPTEN__
17436
/*[clinic input]
17437
os._emscripten_debugger
17438
17439
Create a breakpoint for the JavaScript debugger. Emscripten only.
17440
[clinic start generated code]*/
17441
17442
static PyObject *
17443
os__emscripten_debugger_impl(PyObject *module)
17444
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17445
{
17446
    emscripten_debugger();
17447
    Py_RETURN_NONE;
17448
}
17449
17450
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17451
    console.warn(UTF8ToString(arg));
17452
});
17453
17454
/*[clinic input]
17455
os._emscripten_log
17456
   arg: str
17457
17458
Log something to the JS console. Emscripten only.
17459
[clinic start generated code]*/
17460
17461
static PyObject *
17462
os__emscripten_log_impl(PyObject *module, const char *arg)
17463
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17464
{
17465
    emscripten_log_impl_js(arg);
17466
    Py_RETURN_NONE;
17467
}
17468
#endif /* __EMSCRIPTEN__ */
17469
17470
17471
static PyMethodDef posix_methods[] = {
17472
    OS_STAT_METHODDEF
17473
    OS_STATX_METHODDEF
17474
    OS_ACCESS_METHODDEF
17475
    OS_TTYNAME_METHODDEF
17476
    OS_CHDIR_METHODDEF
17477
    OS_CHFLAGS_METHODDEF
17478
    OS_CHMOD_METHODDEF
17479
    OS_FCHMOD_METHODDEF
17480
    OS_LCHMOD_METHODDEF
17481
    OS_CHOWN_METHODDEF
17482
    OS_FCHOWN_METHODDEF
17483
    OS_LCHOWN_METHODDEF
17484
    OS_LCHFLAGS_METHODDEF
17485
    OS_CHROOT_METHODDEF
17486
    OS_CTERMID_METHODDEF
17487
    OS_GETCWD_METHODDEF
17488
    OS_GETCWDB_METHODDEF
17489
    OS_LINK_METHODDEF
17490
    OS_LISTDIR_METHODDEF
17491
    OS_LISTDRIVES_METHODDEF
17492
    OS_LISTMOUNTS_METHODDEF
17493
    OS_LISTVOLUMES_METHODDEF
17494
    OS_LSTAT_METHODDEF
17495
    OS_MKDIR_METHODDEF
17496
    OS_NICE_METHODDEF
17497
    OS_GETPRIORITY_METHODDEF
17498
    OS_SETPRIORITY_METHODDEF
17499
    OS_POSIX_SPAWN_METHODDEF
17500
    OS_POSIX_SPAWNP_METHODDEF
17501
    OS_READLINK_METHODDEF
17502
    OS_COPY_FILE_RANGE_METHODDEF
17503
    OS_SPLICE_METHODDEF
17504
    OS_RENAME_METHODDEF
17505
    OS_REPLACE_METHODDEF
17506
    OS_RMDIR_METHODDEF
17507
    OS_SYMLINK_METHODDEF
17508
    OS_SYSTEM_METHODDEF
17509
    OS_UMASK_METHODDEF
17510
    OS_UNAME_METHODDEF
17511
    OS_UNLINK_METHODDEF
17512
    OS_REMOVE_METHODDEF
17513
    OS_UTIME_METHODDEF
17514
    OS_TIMES_METHODDEF
17515
    OS__EXIT_METHODDEF
17516
    OS__FCOPYFILE_METHODDEF
17517
    OS_EXECV_METHODDEF
17518
    OS_EXECVE_METHODDEF
17519
    OS_SPAWNV_METHODDEF
17520
    OS_SPAWNVE_METHODDEF
17521
    OS_FORK1_METHODDEF
17522
    OS_FORK_METHODDEF
17523
    OS_REGISTER_AT_FORK_METHODDEF
17524
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17525
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17526
    OS_SCHED_GETPARAM_METHODDEF
17527
    OS_SCHED_GETSCHEDULER_METHODDEF
17528
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17529
    OS_SCHED_SETPARAM_METHODDEF
17530
    OS_SCHED_SETSCHEDULER_METHODDEF
17531
    OS_SCHED_YIELD_METHODDEF
17532
    OS_SCHED_SETAFFINITY_METHODDEF
17533
    OS_SCHED_GETAFFINITY_METHODDEF
17534
    OS_POSIX_OPENPT_METHODDEF
17535
    OS_GRANTPT_METHODDEF
17536
    OS_UNLOCKPT_METHODDEF
17537
    OS_PTSNAME_METHODDEF
17538
    OS_OPENPTY_METHODDEF
17539
    OS_LOGIN_TTY_METHODDEF
17540
    OS_FORKPTY_METHODDEF
17541
    OS_GETEGID_METHODDEF
17542
    OS_GETEUID_METHODDEF
17543
    OS_GETGID_METHODDEF
17544
    OS_GETGROUPLIST_METHODDEF
17545
    OS_GETGROUPS_METHODDEF
17546
    OS_GETPID_METHODDEF
17547
    OS_GETPGRP_METHODDEF
17548
    OS_GETPPID_METHODDEF
17549
    OS_GETUID_METHODDEF
17550
    OS_GETLOGIN_METHODDEF
17551
    OS_KILL_METHODDEF
17552
    OS_KILLPG_METHODDEF
17553
    OS_PLOCK_METHODDEF
17554
    OS_STARTFILE_METHODDEF
17555
    OS_SETUID_METHODDEF
17556
    OS_SETEUID_METHODDEF
17557
    OS_SETREUID_METHODDEF
17558
    OS_SETGID_METHODDEF
17559
    OS_SETEGID_METHODDEF
17560
    OS_SETREGID_METHODDEF
17561
    OS_SETGROUPS_METHODDEF
17562
    OS_INITGROUPS_METHODDEF
17563
    OS_GETPGID_METHODDEF
17564
    OS_SETPGRP_METHODDEF
17565
    OS_WAIT_METHODDEF
17566
    OS_WAIT3_METHODDEF
17567
    OS_WAIT4_METHODDEF
17568
    OS_WAITID_METHODDEF
17569
    OS_WAITPID_METHODDEF
17570
    OS_PIDFD_OPEN_METHODDEF
17571
    OS_GETSID_METHODDEF
17572
    OS_SETSID_METHODDEF
17573
    OS_SETPGID_METHODDEF
17574
    OS_TCGETPGRP_METHODDEF
17575
    OS_TCSETPGRP_METHODDEF
17576
    OS_OPEN_METHODDEF
17577
    OS_CLOSE_METHODDEF
17578
    OS_CLOSERANGE_METHODDEF
17579
    OS_DEVICE_ENCODING_METHODDEF
17580
    OS_DUP_METHODDEF
17581
    OS_DUP2_METHODDEF
17582
    OS_LOCKF_METHODDEF
17583
    OS_LSEEK_METHODDEF
17584
    OS_READ_METHODDEF
17585
    OS_READINTO_METHODDEF
17586
    OS_READV_METHODDEF
17587
    OS_PREAD_METHODDEF
17588
    OS_PREADV_METHODDEF
17589
    OS_WRITE_METHODDEF
17590
    OS_WRITEV_METHODDEF
17591
    OS_PWRITE_METHODDEF
17592
    OS_PWRITEV_METHODDEF
17593
    OS_SENDFILE_METHODDEF
17594
    OS_FSTAT_METHODDEF
17595
    OS_ISATTY_METHODDEF
17596
    OS_PIPE_METHODDEF
17597
    OS_PIPE2_METHODDEF
17598
    OS_MKFIFO_METHODDEF
17599
    OS_MKNOD_METHODDEF
17600
    OS_MAJOR_METHODDEF
17601
    OS_MINOR_METHODDEF
17602
    OS_MAKEDEV_METHODDEF
17603
    OS_FTRUNCATE_METHODDEF
17604
    OS_TRUNCATE_METHODDEF
17605
    OS_POSIX_FALLOCATE_METHODDEF
17606
    OS_POSIX_FADVISE_METHODDEF
17607
    OS_PUTENV_METHODDEF
17608
    OS_UNSETENV_METHODDEF
17609
    OS__CLEARENV_METHODDEF
17610
    OS_STRERROR_METHODDEF
17611
    OS_FCHDIR_METHODDEF
17612
    OS_FSYNC_METHODDEF
17613
    OS_SYNC_METHODDEF
17614
    OS_FDATASYNC_METHODDEF
17615
    OS_WCOREDUMP_METHODDEF
17616
    OS_WIFCONTINUED_METHODDEF
17617
    OS_WIFSTOPPED_METHODDEF
17618
    OS_WIFSIGNALED_METHODDEF
17619
    OS_WIFEXITED_METHODDEF
17620
    OS_WEXITSTATUS_METHODDEF
17621
    OS_WTERMSIG_METHODDEF
17622
    OS_WSTOPSIG_METHODDEF
17623
    OS_FSTATVFS_METHODDEF
17624
    OS_STATVFS_METHODDEF
17625
    OS_CONFSTR_METHODDEF
17626
    OS_SYSCONF_METHODDEF
17627
    OS_FPATHCONF_METHODDEF
17628
    OS_PATHCONF_METHODDEF
17629
    OS_ABORT_METHODDEF
17630
    OS__GETFULLPATHNAME_METHODDEF
17631
    OS__GETDISKUSAGE_METHODDEF
17632
    OS__GETFINALPATHNAME_METHODDEF
17633
    OS__FINDFIRSTFILE_METHODDEF
17634
    OS__GETVOLUMEPATHNAME_METHODDEF
17635
    OS__PATH_SPLITROOT_METHODDEF
17636
    OS__PATH_SPLITROOT_EX_METHODDEF
17637
    OS__PATH_NORMPATH_METHODDEF
17638
    OS_GETLOADAVG_METHODDEF
17639
    OS_URANDOM_METHODDEF
17640
    OS_SETRESUID_METHODDEF
17641
    OS_SETRESGID_METHODDEF
17642
    OS_GETRESUID_METHODDEF
17643
    OS_GETRESGID_METHODDEF
17644
17645
    OS_GETXATTR_METHODDEF
17646
    OS_SETXATTR_METHODDEF
17647
    OS_REMOVEXATTR_METHODDEF
17648
    OS_LISTXATTR_METHODDEF
17649
17650
    OS_GET_TERMINAL_SIZE_METHODDEF
17651
    OS_CPU_COUNT_METHODDEF
17652
    OS_GET_INHERITABLE_METHODDEF
17653
    OS_SET_INHERITABLE_METHODDEF
17654
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17655
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17656
    OS_GET_BLOCKING_METHODDEF
17657
    OS_SET_BLOCKING_METHODDEF
17658
    OS_SCANDIR_METHODDEF
17659
    OS_FSPATH_METHODDEF
17660
    OS_GETRANDOM_METHODDEF
17661
    OS_MEMFD_CREATE_METHODDEF
17662
    OS_EVENTFD_METHODDEF
17663
    OS_EVENTFD_READ_METHODDEF
17664
    OS_EVENTFD_WRITE_METHODDEF
17665
    OS__ADD_DLL_DIRECTORY_METHODDEF
17666
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17667
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17668
    OS_SETNS_METHODDEF
17669
    OS_UNSHARE_METHODDEF
17670
    OS_TIMERFD_CREATE_METHODDEF
17671
    OS_TIMERFD_SETTIME_METHODDEF
17672
    OS_TIMERFD_SETTIME_NS_METHODDEF
17673
    OS_TIMERFD_GETTIME_METHODDEF
17674
    OS_TIMERFD_GETTIME_NS_METHODDEF
17675
17676
    OS__PATH_ISDEVDRIVE_METHODDEF
17677
    OS__PATH_ISDIR_METHODDEF
17678
    OS__PATH_ISFILE_METHODDEF
17679
    OS__PATH_ISLINK_METHODDEF
17680
    OS__PATH_ISJUNCTION_METHODDEF
17681
    OS__PATH_EXISTS_METHODDEF
17682
    OS__PATH_LEXISTS_METHODDEF
17683
17684
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17685
    OS__INPUTHOOK_METHODDEF
17686
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17687
    OS__CREATE_ENVIRON_METHODDEF
17688
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17689
    OS__EMSCRIPTEN_LOG_METHODDEF
17690
    {NULL,              NULL}            /* Sentinel */
17691
};
17692
17693
static int
17694
all_ins(PyObject *m)
17695
22
{
17696
22
#ifdef F_OK
17697
22
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17698
22
#endif
17699
22
#ifdef R_OK
17700
22
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17701
22
#endif
17702
22
#ifdef W_OK
17703
22
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17704
22
#endif
17705
22
#ifdef X_OK
17706
22
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17707
22
#endif
17708
22
#ifdef NGROUPS_MAX
17709
22
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17710
22
#endif
17711
22
#ifdef TMP_MAX
17712
22
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17713
22
#endif
17714
22
#ifdef WCONTINUED
17715
22
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17716
22
#endif
17717
22
#ifdef WNOHANG
17718
22
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17719
22
#endif
17720
22
#ifdef WUNTRACED
17721
22
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17722
22
#endif
17723
22
#ifdef O_RDONLY
17724
22
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17725
22
#endif
17726
22
#ifdef O_WRONLY
17727
22
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17728
22
#endif
17729
22
#ifdef O_RDWR
17730
22
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17731
22
#endif
17732
22
#ifdef O_NDELAY
17733
22
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17734
22
#endif
17735
22
#ifdef O_NONBLOCK
17736
22
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17737
22
#endif
17738
22
#ifdef O_APPEND
17739
22
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17740
22
#endif
17741
22
#ifdef O_DSYNC
17742
22
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17743
22
#endif
17744
22
#ifdef O_RSYNC
17745
22
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17746
22
#endif
17747
22
#ifdef O_SYNC
17748
22
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17749
22
#endif
17750
22
#ifdef O_NOCTTY
17751
22
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17752
22
#endif
17753
22
#ifdef O_CREAT
17754
22
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17755
22
#endif
17756
22
#ifdef O_EXCL
17757
22
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17758
22
#endif
17759
22
#ifdef O_TRUNC
17760
22
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17761
22
#endif
17762
#ifdef O_BINARY
17763
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17764
#endif
17765
#ifdef O_TEXT
17766
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17767
#endif
17768
#ifdef O_XATTR
17769
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17770
#endif
17771
22
#ifdef O_LARGEFILE
17772
22
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17773
22
#endif
17774
22
#ifndef __GNU__
17775
#ifdef O_SHLOCK
17776
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17777
#endif
17778
#ifdef O_EXLOCK
17779
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17780
#endif
17781
22
#endif
17782
#ifdef O_EXEC
17783
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17784
#endif
17785
#ifdef O_SEARCH
17786
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17787
#endif
17788
22
#ifdef O_PATH
17789
22
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17790
22
#endif
17791
#ifdef O_TTY_INIT
17792
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17793
#endif
17794
22
#ifdef O_TMPFILE
17795
22
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17796
22
#endif
17797
22
#ifdef PRIO_PROCESS
17798
22
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17799
22
#endif
17800
22
#ifdef PRIO_PGRP
17801
22
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17802
22
#endif
17803
22
#ifdef PRIO_USER
17804
22
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17805
22
#endif
17806
#ifdef PRIO_DARWIN_THREAD
17807
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17808
#endif
17809
#ifdef PRIO_DARWIN_PROCESS
17810
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17811
#endif
17812
#ifdef PRIO_DARWIN_BG
17813
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17814
#endif
17815
#ifdef PRIO_DARWIN_NONUI
17816
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17817
#endif
17818
22
#ifdef O_CLOEXEC
17819
22
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17820
22
#endif
17821
22
#ifdef O_ACCMODE
17822
22
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17823
22
#endif
17824
#ifdef O_EVTONLY
17825
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17826
#endif
17827
22
#ifdef O_FSYNC
17828
22
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17829
22
#endif
17830
#ifdef O_SYMLINK
17831
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17832
#endif
17833
17834
22
#ifdef SEEK_HOLE
17835
22
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17836
22
#endif
17837
22
#ifdef SEEK_DATA
17838
22
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17839
22
#endif
17840
17841
/* MS Windows */
17842
#ifdef O_NOINHERIT
17843
    /* Don't inherit in child processes. */
17844
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17845
#endif
17846
#ifdef _O_SHORT_LIVED
17847
    /* Optimize for short life (keep in memory). */
17848
    /* MS forgot to define this one with a non-underscore form too. */
17849
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17850
#endif
17851
#ifdef O_TEMPORARY
17852
    /* Automatically delete when last handle is closed. */
17853
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17854
#endif
17855
#ifdef O_RANDOM
17856
    /* Optimize for random access. */
17857
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17858
#endif
17859
#ifdef O_SEQUENTIAL
17860
    /* Optimize for sequential access. */
17861
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17862
#endif
17863
17864
/* GNU extensions. */
17865
22
#ifdef O_ASYNC
17866
    /* Send a SIGIO signal whenever input or output
17867
       becomes available on file descriptor */
17868
22
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17869
22
#endif
17870
22
#ifdef O_DIRECT
17871
    /* Direct disk access. */
17872
22
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17873
22
#endif
17874
22
#ifdef O_DIRECTORY
17875
    /* Must be a directory.      */
17876
22
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17877
22
#endif
17878
22
#ifdef O_NOFOLLOW
17879
    /* Do not follow links.      */
17880
22
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17881
22
#endif
17882
#ifdef O_NOFOLLOW_ANY
17883
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17884
#endif
17885
#ifdef O_NOLINKS
17886
    /* Fails if link count of the named file is greater than 1 */
17887
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17888
#endif
17889
22
#ifdef O_NOATIME
17890
    /* Do not update the access time. */
17891
22
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17892
22
#endif
17893
17894
    /* These come from sysexits.h */
17895
22
#ifdef EX_OK
17896
22
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17897
22
#endif /* EX_OK */
17898
22
#ifdef EX_USAGE
17899
22
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17900
22
#endif /* EX_USAGE */
17901
22
#ifdef EX_DATAERR
17902
22
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17903
22
#endif /* EX_DATAERR */
17904
22
#ifdef EX_NOINPUT
17905
22
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17906
22
#endif /* EX_NOINPUT */
17907
22
#ifdef EX_NOUSER
17908
22
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17909
22
#endif /* EX_NOUSER */
17910
22
#ifdef EX_NOHOST
17911
22
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17912
22
#endif /* EX_NOHOST */
17913
22
#ifdef EX_UNAVAILABLE
17914
22
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17915
22
#endif /* EX_UNAVAILABLE */
17916
22
#ifdef EX_SOFTWARE
17917
22
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17918
22
#endif /* EX_SOFTWARE */
17919
22
#ifdef EX_OSERR
17920
22
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17921
22
#endif /* EX_OSERR */
17922
22
#ifdef EX_OSFILE
17923
22
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17924
22
#endif /* EX_OSFILE */
17925
22
#ifdef EX_CANTCREAT
17926
22
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17927
22
#endif /* EX_CANTCREAT */
17928
22
#ifdef EX_IOERR
17929
22
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17930
22
#endif /* EX_IOERR */
17931
22
#ifdef EX_TEMPFAIL
17932
22
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17933
22
#endif /* EX_TEMPFAIL */
17934
22
#ifdef EX_PROTOCOL
17935
22
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17936
22
#endif /* EX_PROTOCOL */
17937
22
#ifdef EX_NOPERM
17938
22
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17939
22
#endif /* EX_NOPERM */
17940
22
#ifdef EX_CONFIG
17941
22
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17942
22
#endif /* EX_CONFIG */
17943
#ifdef EX_NOTFOUND
17944
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17945
#endif /* EX_NOTFOUND */
17946
17947
    /* statvfs */
17948
22
#ifdef ST_RDONLY
17949
22
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17950
22
#endif /* ST_RDONLY */
17951
22
#ifdef ST_NOSUID
17952
22
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17953
22
#endif /* ST_NOSUID */
17954
17955
       /* GNU extensions */
17956
22
#ifdef ST_NODEV
17957
22
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17958
22
#endif /* ST_NODEV */
17959
22
#ifdef ST_NOEXEC
17960
22
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17961
22
#endif /* ST_NOEXEC */
17962
22
#ifdef ST_SYNCHRONOUS
17963
22
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17964
22
#endif /* ST_SYNCHRONOUS */
17965
22
#ifdef ST_MANDLOCK
17966
22
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17967
22
#endif /* ST_MANDLOCK */
17968
22
#ifdef ST_WRITE
17969
22
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17970
22
#endif /* ST_WRITE */
17971
22
#ifdef ST_APPEND
17972
22
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
17973
22
#endif /* ST_APPEND */
17974
22
#ifdef ST_NOATIME
17975
22
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
17976
22
#endif /* ST_NOATIME */
17977
22
#ifdef ST_NODIRATIME
17978
22
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
17979
22
#endif /* ST_NODIRATIME */
17980
22
#ifdef ST_RELATIME
17981
22
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
17982
22
#endif /* ST_RELATIME */
17983
17984
    /* FreeBSD sendfile() constants */
17985
#ifdef SF_NODISKIO
17986
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
17987
#endif
17988
    /* is obsolete since the 11.x release */
17989
#ifdef SF_MNOWAIT
17990
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
17991
#endif
17992
#ifdef SF_SYNC
17993
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
17994
#endif
17995
#ifdef SF_NOCACHE
17996
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
17997
#endif
17998
17999
22
#ifdef TFD_NONBLOCK
18000
22
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18001
22
#endif
18002
22
#ifdef TFD_CLOEXEC
18003
22
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18004
22
#endif
18005
22
#ifdef TFD_TIMER_ABSTIME
18006
22
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18007
22
#endif
18008
22
#ifdef TFD_TIMER_CANCEL_ON_SET
18009
22
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18010
22
#endif
18011
18012
    /* constants for posix_fadvise */
18013
22
#ifdef POSIX_FADV_NORMAL
18014
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18015
22
#endif
18016
22
#ifdef POSIX_FADV_SEQUENTIAL
18017
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18018
22
#endif
18019
22
#ifdef POSIX_FADV_RANDOM
18020
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18021
22
#endif
18022
22
#ifdef POSIX_FADV_NOREUSE
18023
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18024
22
#endif
18025
22
#ifdef POSIX_FADV_WILLNEED
18026
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18027
22
#endif
18028
22
#ifdef POSIX_FADV_DONTNEED
18029
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18030
22
#endif
18031
18032
    /* constants for waitid */
18033
22
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18034
22
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18035
22
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18036
22
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18037
22
#ifdef P_PIDFD
18038
22
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18039
22
#endif
18040
#ifdef PIDFD_NONBLOCK
18041
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18042
#endif
18043
22
#endif
18044
22
#ifdef WEXITED
18045
22
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18046
22
#endif
18047
22
#ifdef WNOWAIT
18048
22
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18049
22
#endif
18050
22
#ifdef WSTOPPED
18051
22
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18052
22
#endif
18053
22
#ifdef CLD_EXITED
18054
22
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18055
22
#endif
18056
22
#ifdef CLD_KILLED
18057
22
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18058
22
#endif
18059
22
#ifdef CLD_DUMPED
18060
22
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18061
22
#endif
18062
22
#ifdef CLD_TRAPPED
18063
22
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18064
22
#endif
18065
22
#ifdef CLD_STOPPED
18066
22
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18067
22
#endif
18068
22
#ifdef CLD_CONTINUED
18069
22
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18070
22
#endif
18071
18072
    /* constants for lockf */
18073
22
#ifdef F_LOCK
18074
22
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18075
22
#endif
18076
22
#ifdef F_TLOCK
18077
22
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18078
22
#endif
18079
22
#ifdef F_ULOCK
18080
22
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18081
22
#endif
18082
22
#ifdef F_TEST
18083
22
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18084
22
#endif
18085
18086
22
#ifdef RWF_DSYNC
18087
22
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18088
22
#endif
18089
22
#ifdef RWF_HIPRI
18090
22
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18091
22
#endif
18092
22
#ifdef RWF_SYNC
18093
22
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18094
22
#endif
18095
22
#ifdef RWF_NOWAIT
18096
22
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18097
22
#endif
18098
#ifdef RWF_DONTCACHE
18099
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18100
#endif
18101
22
#ifdef RWF_APPEND
18102
22
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18103
22
#endif
18104
18105
/* constants for splice */
18106
22
#if defined(HAVE_SPLICE) && defined(__linux__)
18107
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18108
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18109
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18110
22
#endif
18111
18112
/* constants for posix_spawn */
18113
22
#ifdef HAVE_POSIX_SPAWN
18114
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18115
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18116
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18117
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18118
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18119
#endif
18120
22
#endif
18121
18122
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18123
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18124
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18125
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18126
#endif
18127
#ifdef HAVE_SPAWNV
18128
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18129
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18130
#endif
18131
18132
22
#ifdef HAVE_SCHED_H
18133
22
#ifdef SCHED_OTHER
18134
22
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18135
22
#endif
18136
22
#ifdef SCHED_DEADLINE
18137
22
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18138
22
#endif
18139
22
#ifdef SCHED_FIFO
18140
22
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18141
22
#endif
18142
22
#ifdef SCHED_NORMAL
18143
22
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18144
22
#endif
18145
22
#ifdef SCHED_RR
18146
22
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18147
22
#endif
18148
#ifdef SCHED_SPORADIC
18149
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18150
#endif
18151
22
#ifdef SCHED_BATCH
18152
22
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18153
22
#endif
18154
22
#ifdef SCHED_IDLE
18155
22
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18156
22
#endif
18157
22
#ifdef SCHED_RESET_ON_FORK
18158
22
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18159
22
#endif
18160
#ifdef SCHED_SYS
18161
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18162
#endif
18163
#ifdef SCHED_IA
18164
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18165
#endif
18166
#ifdef SCHED_FSS
18167
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18168
#endif
18169
#ifdef SCHED_FX
18170
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18171
#endif
18172
18173
/* constants for namespaces */
18174
22
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18175
22
#ifdef CLONE_FS
18176
22
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18177
22
#endif
18178
22
#ifdef CLONE_FILES
18179
22
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18180
22
#endif
18181
22
#ifdef CLONE_NEWNS
18182
22
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18183
22
#endif
18184
22
#ifdef CLONE_NEWCGROUP
18185
22
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18186
22
#endif
18187
22
#ifdef CLONE_NEWUTS
18188
22
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18189
22
#endif
18190
22
#ifdef CLONE_NEWIPC
18191
22
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18192
22
#endif
18193
22
#ifdef CLONE_NEWUSER
18194
22
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18195
22
#endif
18196
22
#ifdef CLONE_NEWPID
18197
22
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18198
22
#endif
18199
22
#ifdef CLONE_NEWNET
18200
22
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18201
22
#endif
18202
#ifdef CLONE_NEWTIME
18203
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18204
#endif
18205
22
#ifdef CLONE_SYSVSEM
18206
22
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18207
22
#endif
18208
22
#ifdef CLONE_THREAD
18209
22
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18210
22
#endif
18211
22
#ifdef CLONE_SIGHAND
18212
22
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18213
22
#endif
18214
22
#ifdef CLONE_VM
18215
22
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18216
22
#endif
18217
22
#endif
18218
18219
22
#endif
18220
18221
22
#ifdef USE_XATTRS
18222
22
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18223
22
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18224
22
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18225
22
#endif
18226
18227
22
#if HAVE_DECL_RTLD_LAZY
18228
22
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18229
22
#endif
18230
22
#if HAVE_DECL_RTLD_NOW
18231
22
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18232
22
#endif
18233
22
#if HAVE_DECL_RTLD_GLOBAL
18234
22
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18235
22
#endif
18236
22
#if HAVE_DECL_RTLD_LOCAL
18237
22
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18238
22
#endif
18239
22
#if HAVE_DECL_RTLD_NODELETE
18240
22
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18241
22
#endif
18242
22
#if HAVE_DECL_RTLD_NOLOAD
18243
22
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18244
22
#endif
18245
22
#if HAVE_DECL_RTLD_DEEPBIND
18246
22
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18247
22
#endif
18248
#if HAVE_DECL_RTLD_MEMBER
18249
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18250
#endif
18251
18252
22
#ifdef HAVE_GETRANDOM_SYSCALL
18253
22
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18254
22
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18255
22
#endif
18256
22
#ifdef HAVE_MEMFD_CREATE
18257
22
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18258
22
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18259
22
#ifdef MFD_HUGETLB
18260
22
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18261
22
#endif
18262
22
#ifdef MFD_HUGE_SHIFT
18263
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18264
22
#endif
18265
22
#ifdef MFD_HUGE_MASK
18266
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18267
22
#endif
18268
22
#ifdef MFD_HUGE_64KB
18269
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18270
22
#endif
18271
22
#ifdef MFD_HUGE_512KB
18272
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18273
22
#endif
18274
22
#ifdef MFD_HUGE_1MB
18275
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18276
22
#endif
18277
22
#ifdef MFD_HUGE_2MB
18278
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18279
22
#endif
18280
22
#ifdef MFD_HUGE_8MB
18281
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18282
22
#endif
18283
22
#ifdef MFD_HUGE_16MB
18284
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18285
22
#endif
18286
22
#ifdef MFD_HUGE_32MB
18287
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18288
22
#endif
18289
22
#ifdef MFD_HUGE_256MB
18290
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18291
22
#endif
18292
22
#ifdef MFD_HUGE_512MB
18293
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18294
22
#endif
18295
22
#ifdef MFD_HUGE_1GB
18296
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18297
22
#endif
18298
22
#ifdef MFD_HUGE_2GB
18299
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18300
22
#endif
18301
22
#ifdef MFD_HUGE_16GB
18302
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18303
22
#endif
18304
22
#endif /* HAVE_MEMFD_CREATE */
18305
18306
22
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18307
22
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18308
22
#ifdef EFD_NONBLOCK
18309
22
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18310
22
#endif
18311
22
#ifdef EFD_SEMAPHORE
18312
22
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18313
22
#endif
18314
22
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18315
18316
22
#ifdef NODEV
18317
22
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18318
22
#endif
18319
18320
22
#ifdef AT_NO_AUTOMOUNT
18321
22
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18322
22
#endif
18323
18324
22
#ifdef HAVE_STATX
18325
22
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18326
22
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18327
22
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18328
22
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18329
22
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18330
22
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18331
22
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18332
22
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18333
22
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18334
22
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18335
22
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18336
22
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18337
22
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18338
#ifdef STATX_MNT_ID
18339
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18340
#endif
18341
#ifdef STATX_DIOALIGN
18342
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18343
#endif
18344
#ifdef STATX_MNT_ID_UNIQUE
18345
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18346
#endif
18347
#ifdef STATX_SUBVOL
18348
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18349
#endif
18350
#ifdef STATX_WRITE_ATOMIC
18351
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18352
#endif
18353
#ifdef STATX_DIO_READ_ALIGN
18354
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18355
#endif
18356
    /* STATX_ALL intentionally omitted because it is deprecated */
18357
22
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18358
22
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18359
22
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18360
    /* STATX_ATTR_* constants are in the stat module */
18361
22
#endif /* HAVE_STATX */
18362
18363
#if defined(__APPLE__)
18364
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18365
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18366
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18367
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18368
#endif
18369
18370
#ifdef MS_WINDOWS
18371
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18372
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18373
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18374
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18375
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18376
#endif
18377
18378
22
    return 0;
18379
22
}
18380
18381
18382
18383
#define PROBE(name, test) \
18384
   static int name(void)  \
18385
374
   {                      \
18386
374
      if (test) {        \
18387
374
          return 1;       \
18388
374
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
374
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_futimens
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_linkat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_openat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_renameat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18385
22
   {                      \
18386
22
      if (test) {        \
18387
22
          return 1;       \
18388
22
      } else {            \
18389
0
          return 0;       \
18390
0
      }                   \
18391
22
   }
18392
18393
#ifdef HAVE_FSTATAT
18394
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18395
#endif
18396
18397
#ifdef HAVE_FACCESSAT
18398
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18399
#endif
18400
18401
#ifdef HAVE_FCHMODAT
18402
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18403
#endif
18404
18405
#ifdef HAVE_FCHOWNAT
18406
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18407
#endif
18408
18409
#ifdef HAVE_LINKAT
18410
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18411
#endif
18412
18413
#ifdef HAVE_FDOPENDIR
18414
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18415
#endif
18416
18417
#ifdef HAVE_MKDIRAT
18418
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18419
#endif
18420
18421
#ifdef HAVE_MKFIFOAT
18422
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18423
#endif
18424
18425
#ifdef HAVE_MKNODAT
18426
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18427
#endif
18428
18429
#ifdef HAVE_RENAMEAT
18430
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18431
#endif
18432
18433
#ifdef HAVE_UNLINKAT
18434
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18435
#endif
18436
18437
#ifdef HAVE_OPENAT
18438
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18439
#endif
18440
18441
#ifdef HAVE_READLINKAT
18442
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18443
#endif
18444
18445
#ifdef HAVE_SYMLINKAT
18446
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18447
#endif
18448
18449
#ifdef HAVE_FUTIMENS
18450
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18451
#endif
18452
18453
#ifdef HAVE_UTIMENSAT
18454
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18455
#endif
18456
18457
#ifdef HAVE_PTSNAME_R
18458
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18459
#endif
18460
18461
18462
18463
static const struct have_function {
18464
    const char * const label;
18465
    int (*probe)(void);
18466
} have_functions[] = {
18467
18468
#ifdef HAVE_EVENTFD
18469
    {"HAVE_EVENTFD", NULL},
18470
#endif
18471
18472
#ifdef HAVE_TIMERFD_CREATE
18473
    {"HAVE_TIMERFD_CREATE", NULL},
18474
#endif
18475
18476
#ifdef HAVE_FACCESSAT
18477
    { "HAVE_FACCESSAT", probe_faccessat },
18478
#endif
18479
18480
#ifdef HAVE_FCHDIR
18481
    { "HAVE_FCHDIR", NULL },
18482
#endif
18483
18484
#ifdef HAVE_FCHMOD
18485
    { "HAVE_FCHMOD", NULL },
18486
#endif
18487
18488
#ifdef HAVE_FCHMODAT
18489
    { "HAVE_FCHMODAT", probe_fchmodat },
18490
#endif
18491
18492
#ifdef HAVE_FCHOWN
18493
    { "HAVE_FCHOWN", NULL },
18494
#endif
18495
18496
#ifdef HAVE_FCHOWNAT
18497
    { "HAVE_FCHOWNAT", probe_fchownat },
18498
#endif
18499
18500
#ifdef HAVE_FEXECVE
18501
    { "HAVE_FEXECVE", NULL },
18502
#endif
18503
18504
#ifdef HAVE_FDOPENDIR
18505
    { "HAVE_FDOPENDIR", probe_fdopendir },
18506
#endif
18507
18508
#ifdef HAVE_FPATHCONF
18509
    { "HAVE_FPATHCONF", NULL },
18510
#endif
18511
18512
#ifdef HAVE_FSTATAT
18513
    { "HAVE_FSTATAT", probe_fstatat },
18514
#endif
18515
18516
#ifdef HAVE_FSTATVFS
18517
    { "HAVE_FSTATVFS", NULL },
18518
#endif
18519
18520
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18521
    { "HAVE_FTRUNCATE", NULL },
18522
#endif
18523
18524
#ifdef HAVE_FUTIMENS
18525
    { "HAVE_FUTIMENS", probe_futimens },
18526
#endif
18527
18528
#ifdef HAVE_FUTIMES
18529
    { "HAVE_FUTIMES", NULL },
18530
#endif
18531
18532
#ifdef HAVE_FUTIMESAT
18533
    { "HAVE_FUTIMESAT", NULL },
18534
#endif
18535
18536
#ifdef HAVE_LINKAT
18537
    { "HAVE_LINKAT", probe_linkat },
18538
#endif
18539
18540
#ifdef HAVE_LCHFLAGS
18541
    { "HAVE_LCHFLAGS", NULL },
18542
#endif
18543
18544
#ifdef HAVE_LCHMOD
18545
    { "HAVE_LCHMOD", NULL },
18546
#endif
18547
18548
#ifdef HAVE_LCHOWN
18549
    { "HAVE_LCHOWN", NULL },
18550
#endif
18551
18552
#ifdef HAVE_LSTAT
18553
    { "HAVE_LSTAT", NULL },
18554
#endif
18555
18556
#ifdef HAVE_LUTIMES
18557
    { "HAVE_LUTIMES", NULL },
18558
#endif
18559
18560
#ifdef HAVE_MEMFD_CREATE
18561
    { "HAVE_MEMFD_CREATE", NULL },
18562
#endif
18563
18564
#ifdef HAVE_MKDIRAT
18565
    { "HAVE_MKDIRAT", probe_mkdirat },
18566
#endif
18567
18568
#ifdef HAVE_MKFIFOAT
18569
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18570
#endif
18571
18572
#ifdef HAVE_MKNODAT
18573
    { "HAVE_MKNODAT", probe_mknodat },
18574
#endif
18575
18576
#ifdef HAVE_OPENAT
18577
    { "HAVE_OPENAT", probe_openat },
18578
#endif
18579
18580
#ifdef HAVE_READLINKAT
18581
    { "HAVE_READLINKAT", probe_readlinkat },
18582
#endif
18583
18584
#ifdef HAVE_RENAMEAT
18585
    { "HAVE_RENAMEAT", probe_renameat },
18586
#endif
18587
18588
#ifdef HAVE_SYMLINKAT
18589
    { "HAVE_SYMLINKAT", probe_symlinkat },
18590
#endif
18591
18592
#ifdef HAVE_UNLINKAT
18593
    { "HAVE_UNLINKAT", probe_unlinkat },
18594
#endif
18595
18596
#ifdef HAVE_UTIMENSAT
18597
    { "HAVE_UTIMENSAT", probe_utimensat },
18598
#endif
18599
18600
#ifdef HAVE_PTSNAME_R
18601
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18602
#endif
18603
18604
#ifdef MS_WINDOWS
18605
    { "MS_WINDOWS", NULL },
18606
#endif
18607
18608
    { NULL, NULL }
18609
};
18610
18611
18612
static int
18613
posixmodule_exec(PyObject *m)
18614
22
{
18615
22
    _posixstate *state = get_posix_state(m);
18616
18617
22
#if defined(HAVE_PWRITEV)
18618
22
    if (HAVE_PWRITEV_RUNTIME) {} else {
18619
0
        PyObject* dct = PyModule_GetDict(m);
18620
18621
0
        if (dct == NULL) {
18622
0
            return -1;
18623
0
        }
18624
18625
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18626
0
            return -1;
18627
0
        }
18628
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18629
0
            return -1;
18630
0
        }
18631
0
    }
18632
22
#endif
18633
18634
22
#ifdef HAVE_STATX
18635
22
    if (statx == NULL) {
18636
0
        PyObject* dct = PyModule_GetDict(m);
18637
0
        if (dct == NULL) {
18638
0
            return -1;
18639
0
        }
18640
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18641
0
            return -1;
18642
0
        }
18643
0
    }
18644
22
    else {
18645
22
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18646
22
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18647
0
            return -1;
18648
0
        }
18649
22
    }
18650
22
#endif
18651
18652
    /* Initialize environ dictionary */
18653
22
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18654
0
        return -1;
18655
0
    }
18656
18657
22
    if (all_ins(m))
18658
0
        return -1;
18659
18660
22
    if (setup_confname_tables(m))
18661
0
        return -1;
18662
18663
22
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18664
0
        return -1;
18665
0
    }
18666
18667
22
#if defined(HAVE_WAITID)
18668
22
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18669
22
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18670
0
        return -1;
18671
0
    }
18672
22
#endif
18673
18674
22
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18675
22
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18676
22
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18677
22
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18678
22
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18679
0
        return -1;
18680
0
    }
18681
22
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18682
22
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18683
18684
22
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18685
22
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18686
0
        return -1;
18687
0
    }
18688
18689
22
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18690
22
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18691
22
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18692
0
        return -1;
18693
0
    }
18694
22
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18695
22
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18696
22
                          &os_sched_param_reduce_method) < 0)
18697
0
    {
18698
0
        return -1;
18699
0
    }
18700
22
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18701
22
#endif
18702
18703
    /* initialize TerminalSize_info */
18704
22
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18705
22
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18706
0
        return -1;
18707
0
    }
18708
18709
    /* initialize scandir types */
18710
22
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18711
22
    if (ScandirIteratorType == NULL) {
18712
0
        return -1;
18713
0
    }
18714
22
    state->ScandirIteratorType = ScandirIteratorType;
18715
18716
22
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18717
22
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18718
0
        return -1;
18719
0
    }
18720
18721
22
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18722
22
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18723
0
        return -1;
18724
0
    }
18725
18726
22
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18727
22
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18728
0
        return -1;
18729
0
    }
18730
18731
22
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18732
0
        return -1;
18733
22
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18734
22
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18735
22
    if (state->struct_rusage == NULL)
18736
0
        return -1;
18737
22
#endif
18738
22
    state->st_mode = PyUnicode_InternFromString("st_mode");
18739
22
    if (state->st_mode == NULL)
18740
0
        return -1;
18741
18742
    /* suppress "function not used" warnings */
18743
22
    {
18744
22
    int ignored;
18745
22
    fd_specified("", -1);
18746
22
    follow_symlinks_specified("", 1);
18747
22
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18748
22
    dir_fd_converter(Py_None, &ignored);
18749
22
    dir_fd_unavailable(Py_None, &ignored);
18750
22
    }
18751
18752
    /*
18753
     * provide list of locally available functions
18754
     * so os.py can populate support_* lists
18755
     */
18756
22
    PyObject *list = PyList_New(0);
18757
22
    if (!list) {
18758
0
        return -1;
18759
0
    }
18760
726
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18761
704
        PyObject *unicode;
18762
704
        if (trace->probe && !trace->probe()) continue;
18763
704
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18764
704
        if (!unicode)
18765
0
            return -1;
18766
704
        if (PyList_Append(list, unicode))
18767
0
            return -1;
18768
704
        Py_DECREF(unicode);
18769
704
    }
18770
18771
22
#ifndef MS_WINDOWS
18772
22
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18773
0
        PyErr_SetString(PyExc_RuntimeError,
18774
0
                        "cannot read ticks_per_second");
18775
0
        return -1;
18776
0
    }
18777
22
    assert(state->ticks_per_second >= 1);
18778
22
#endif
18779
18780
22
    return PyModule_Add(m, "_have_functions", list);
18781
22
}
18782
18783
18784
static PyModuleDef_Slot posixmodile_slots[] = {
18785
    {Py_mod_exec, posixmodule_exec},
18786
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18787
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18788
    {0, NULL}
18789
};
18790
18791
static struct PyModuleDef posixmodule = {
18792
    PyModuleDef_HEAD_INIT,
18793
    .m_name = MODNAME,
18794
    .m_doc = posix__doc__,
18795
    .m_size = sizeof(_posixstate),
18796
    .m_methods = posix_methods,
18797
    .m_slots = posixmodile_slots,
18798
    .m_traverse = _posix_traverse,
18799
    .m_clear = _posix_clear,
18800
    .m_free = _posix_free,
18801
};
18802
18803
PyMODINIT_FUNC
18804
INITFUNC(void)
18805
22
{
18806
22
    return PyModuleDef_Init(&posixmodule);
18807
22
}