Coverage Report

Created: 2026-04-12 06:54

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_tuple.h"         // _PyTuple_FromPairSteal
31
#include "pycore_typeobject.h"    // _PyType_AddMethod()
32
33
#ifndef MS_WINDOWS
34
#  include "posixmodule.h"        // _PyLong_FromUid()
35
#else
36
#  include "pycore_fileutils_windows.h" // _Py_GetFileInformationByName()
37
#  include "osdefs.h"             // SEP
38
#  include "winreparse.h"         // _Py_REPARSE_DATA_BUFFER
39
#endif
40
41
42
// --- System includes ------------------------------------------------------
43
44
#include <stddef.h>               // offsetof()
45
#include <stdio.h>                // ctermid()
46
#include <stdlib.h>               // system()
47
48
#ifdef HAVE_UNISTD_H
49
#  include <unistd.h>             // symlink()
50
#endif
51
52
#ifdef __APPLE__
53
   /* Needed for the implementation of os.statvfs */
54
#  include <sys/param.h>
55
#  include <sys/mount.h>
56
#endif
57
58
#ifdef HAVE_SYS_TIME_H
59
#  include <sys/time.h>           // futimes()
60
#endif
61
62
#ifdef HAVE_SYS_PIDFD_H
63
#  include <sys/pidfd.h>          // PIDFD_NONBLOCK
64
#endif
65
66
#ifdef __EMSCRIPTEN__
67
#  include "emscripten.h"         // emscripten_debugger()
68
#endif
69
70
#ifdef HAVE_SYS_UIO_H
71
#  include <sys/uio.h>
72
#endif
73
74
#ifdef HAVE_SYS_TYPES_H
75
   /* Should be included before <sys/sysmacros.h> on HP-UX v3 */
76
#  include <sys/types.h>
77
#endif
78
#ifdef HAVE_SYS_SYSMACROS_H
79
   /* GNU C Library: major(), minor(), makedev() */
80
#  include <sys/sysmacros.h>
81
#endif
82
83
#ifdef HAVE_SYS_STAT_H
84
#  include <sys/stat.h>
85
#endif
86
87
#ifdef HAVE_SYS_WAIT_H
88
#  include <sys/wait.h>           // WNOHANG
89
#endif
90
91
#ifdef HAVE_LINUX_WAIT_H
92
#  include <linux/wait.h>         // P_PIDFD
93
#endif
94
95
#ifdef HAVE_SIGNAL_H
96
#  include <signal.h>
97
#endif
98
99
#ifdef HAVE_FCNTL_H
100
#  include <fcntl.h>              // fcntl()
101
#endif
102
103
#ifdef HAVE_GRP_H
104
#  include <grp.h>                // setgroups()
105
#endif
106
107
#ifdef HAVE_SYSEXITS_H
108
#  include <sysexits.h>           // EX_OK
109
#endif
110
111
#ifdef HAVE_SYS_LOADAVG_H
112
#  include <sys/loadavg.h>        // getloadavg()
113
#endif
114
115
#ifdef HAVE_SYS_SENDFILE_H
116
#  include <sys/sendfile.h>       // sendfile()
117
#endif
118
119
#if defined(__APPLE__)
120
#  include <copyfile.h>           // fcopyfile()
121
#endif
122
123
#ifdef HAVE_SCHED_H
124
#  include <sched.h>              // sched_setscheduler()
125
#endif
126
#ifdef HAVE_LINUX_SCHED_H
127
#  include <linux/sched.h>        // SCHED_IDLE, SCHED_RR
128
#endif
129
130
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
131
#  ifdef HAVE_SYS_SOCKET_H
132
#    include <sys/socket.h>
133
#  endif
134
#endif
135
136
#ifdef HAVE_DLFCN_H
137
#  include <dlfcn.h>
138
#endif
139
140
#ifdef __hpux
141
#  include <sys/mpctl.h>
142
#endif
143
144
#if defined(__DragonFly__) || \
145
    defined(__OpenBSD__)   || \
146
    defined(__FreeBSD__)   || \
147
    defined(__NetBSD__)    || \
148
    defined(__APPLE__)
149
#  include <sys/sysctl.h>
150
#endif
151
152
#ifdef HAVE_LINUX_RANDOM_H
153
#  include <linux/random.h>       // GRND_RANDOM
154
#endif
155
#ifdef HAVE_GETRANDOM_SYSCALL
156
#  include <sys/syscall.h>        // syscall()
157
#endif
158
159
#ifdef HAVE_POSIX_SPAWN
160
#  include <spawn.h>              // posix_spawn()
161
#endif
162
163
#ifdef HAVE_UTIME_H
164
#  include <utime.h>              // utime()
165
#endif
166
167
#ifdef HAVE_SYS_UTIME_H
168
#  include <sys/utime.h>
169
#  define HAVE_UTIME_H /* pretend we do for the rest of this file */
170
#endif
171
172
#ifdef HAVE_SYS_TIMES_H
173
#  include <sys/times.h>          // times()
174
#endif
175
176
#ifdef HAVE_SYS_PARAM_H
177
#  include <sys/param.h>
178
#endif
179
180
#ifdef HAVE_SYS_UTSNAME_H
181
#  include <sys/utsname.h>        // uname()
182
#endif
183
184
/* memfd_create is either defined in sys/mman.h or sys/memfd.h
185
 * linux/memfd.h defines additional flags
186
 */
187
#ifdef HAVE_SYS_MMAN_H
188
#  include <sys/mman.h>           // memfd_create()
189
#endif
190
#ifdef HAVE_SYS_MEMFD_H
191
#  include <sys/memfd.h>          // memfd_create()
192
#endif
193
#ifdef HAVE_LINUX_MEMFD_H
194
#  include <linux/memfd.h>        // memfd_create(), MFD_CLOEXEC
195
#endif
196
197
#ifdef HAVE_SYS_EVENTFD_H
198
#  include <sys/eventfd.h>        // eventfd()
199
#endif
200
201
#ifdef HAVE_SYS_TIMERFD_H
202
#  include <sys/timerfd.h>        // timerfd_create()
203
#endif
204
205
#ifdef _Py_MEMORY_SANITIZER
206
#  include <sanitizer/msan_interface.h> // __msan_unpoison()
207
#endif
208
209
210
// --- More complex system includes -----------------------------------------
211
212
#ifdef MS_WINDOWS
213
#  include <windows.h>
214
#  if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP)
215
#    include <pathcch.h>          // PathCchSkipRoot()
216
#  endif
217
#  include <aclapi.h>             // SetEntriesInAcl
218
#  include <lmcons.h>             // UNLEN
219
#  include <sddl.h>               // SDDL_REVISION_1
220
#  include <winioctl.h>           // FSCTL_GET_REPARSE_POINT
221
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
222
#    define HAVE_SYMLINK
223
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
224
#endif
225
226
227
#ifdef _MSC_VER
228
#  ifdef HAVE_DIRECT_H
229
#    include <direct.h>
230
#  endif
231
#  ifdef HAVE_IO_H
232
#    include <io.h>
233
#  endif
234
#  ifdef HAVE_PROCESS_H
235
#    include <process.h>          // getpid(), _cwait()
236
#  endif
237
#  include <malloc.h>
238
#endif /* _MSC_VER */
239
240
241
#ifdef HAVE__GETPTY
242
#  include <sys/types.h>          // mode_t
243
   // SGI apparently needs this forward declaration
244
   extern char * _getpty(int *, int, mode_t, int);
245
#endif
246
247
248
#if defined(HAVE_SYS_XATTR_H)
249
#  if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
250
#    define USE_XATTRS
251
#    include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
252
#  endif
253
#  if defined(__CYGWIN__)
254
#    define USE_XATTRS
255
#    include <cygwin/limits.h>  // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX.
256
#  endif
257
#endif
258
#ifdef USE_XATTRS
259
#  include <sys/xattr.h>          // fgetxattr()
260
#endif
261
262
263
#ifdef HAVE_WINDOWS_CONSOLE_IO
264
#  define TERMSIZE_USE_CONIO
265
#elif defined(HAVE_SYS_IOCTL_H)
266
#  include <sys/ioctl.h>          // ioctl(), TIOCGWINSZ
267
#  if defined(HAVE_TERMIOS_H)
268
#    include <termios.h>
269
#  endif
270
#  if defined(TIOCGWINSZ)
271
#    define TERMSIZE_USE_IOCTL
272
#  endif
273
#endif
274
275
276
/* Various compilers have only certain posix functions */
277
/* XXX Gosh I wish these were all moved into pyconfig.h */
278
#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
279
#  define HAVE_OPENDIR    1
280
#  define HAVE_SYSTEM     1
281
#  include <process.h>
282
#elif defined( _MSC_VER)
283
  /* Microsoft compiler */
284
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
285
#    define HAVE_GETPPID    1
286
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */
287
#  if defined(MS_WINDOWS_DESKTOP)
288
#    define HAVE_GETLOGIN   1
289
#  endif /* MS_WINDOWS_DESKTOP */
290
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
291
#    define HAVE_SPAWNV     1
292
#    define HAVE_EXECV      1
293
#    define HAVE_WSPAWNV    1
294
#    define HAVE_WEXECV     1
295
#    define HAVE_SYSTEM     1
296
#    define HAVE_CWAIT      1
297
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
298
#  define HAVE_PIPE       1
299
#  define HAVE_FSYNC      1
300
#  define fsync _commit
301
#endif
302
303
304
#if !defined(_MSC_VER) && defined(__sgi) && _COMPILER_VERSION>=700
305
/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
306
   (default) */
307
extern char *ctermid_r(char *);
308
#endif
309
310
311
#if defined(__VXWORKS__)
312
#  include <vxCpuLib.h>
313
#  include <rtpLib.h>
314
#  include <wait.h>
315
#  include <taskLib.h>
316
#  ifndef _P_WAIT
317
#    define _P_WAIT          0
318
#    define _P_NOWAIT        1
319
#    define _P_NOWAITO       1
320
#  endif
321
#endif /* __VXWORKS__ */
322
323
324
#ifdef HAVE_DIRENT_H
325
#  include <dirent.h>             // opendir()
326
682k
#  define NAMLEN(dirent) strlen((dirent)->d_name)
327
#else
328
#  if defined(__WATCOMC__) && !defined(__QNX__)
329
#    include <direct.h>
330
#    define NAMLEN(dirent) strlen((dirent)->d_name)
331
#  else
332
#    define dirent direct
333
#    define NAMLEN(dirent) (dirent)->d_namlen
334
#  endif
335
#  ifdef HAVE_SYS_NDIR_H
336
#    include <sys/ndir.h>
337
#  endif
338
#  ifdef HAVE_SYS_DIR_H
339
#    include <sys/dir.h>
340
#  endif
341
#  ifdef HAVE_NDIR_H
342
#    include <ndir.h>
343
#  endif
344
#endif
345
346
347
#if defined(MAJOR_IN_MKDEV)
348
#  include <sys/mkdev.h>
349
#else
350
#  if defined(MAJOR_IN_SYSMACROS)
351
#    include <sys/sysmacros.h>
352
#  endif
353
#  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
354
#    include <sys/mkdev.h>
355
#  endif
356
#endif
357
358
359
// --- Macros ---------------------------------------------------------------
360
361
#ifndef MAXPATHLEN
362
#  if defined(PATH_MAX) && PATH_MAX > 1024
363
#    define MAXPATHLEN PATH_MAX
364
#  else
365
#    define MAXPATHLEN 1024
366
#  endif
367
#endif /* MAXPATHLEN */
368
369
370
#ifdef UNION_WAIT
371
   /* Emulate some macros on systems that have a union instead of macros */
372
#  ifndef WIFEXITED
373
#    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
374
#  endif
375
#  ifndef WEXITSTATUS
376
#    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
377
#  endif
378
#  ifndef WTERMSIG
379
#    define WTERMSIG(u_wait) ((u_wait).w_termsig)
380
#  endif
381
#  define WAIT_TYPE union wait
382
#  define WAIT_STATUS_INT(s) (s.w_status)
383
#else
384
   /* !UNION_WAIT */
385
0
#  define WAIT_TYPE int
386
0
#  define WAIT_STATUS_INT(s) (s)
387
#endif /* UNION_WAIT */
388
389
390
/* Don't use the "_r" form if we don't need it (also, won't have a
391
   prototype for it, at least on Solaris -- maybe others as well?). */
392
#if defined(HAVE_CTERMID_R)
393
#  define USE_CTERMID_R
394
#endif
395
396
397
/* choose the appropriate stat and fstat functions and return structs */
398
#undef STAT
399
#undef FSTAT
400
#undef STRUCT_STAT
401
#ifdef MS_WINDOWS
402
#  define STAT win32_stat
403
#  define LSTAT win32_lstat
404
#  define FSTAT _Py_fstat_noraise
405
#  define STRUCT_STAT struct _Py_stat_struct
406
#else
407
373k
#  define STAT stat
408
9.18k
#  define LSTAT lstat
409
213k
#  define FSTAT fstat
410
806k
#  define STRUCT_STAT struct stat
411
#endif
412
413
#ifdef HAVE_STATX
414
/* until we can assume glibc 2.28 at runtime, we must weakly link */
415
#  pragma weak statx
416
static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
417
#ifdef STATX_MNT_ID
418
                                             | STATX_MNT_ID
419
#endif
420
#ifdef STATX_DIOALIGN
421
                                             | STATX_DIOALIGN
422
#endif
423
#ifdef STATX_MNT_ID_UNIQUE
424
                                             | STATX_MNT_ID_UNIQUE
425
#endif
426
#ifdef STATX_SUBVOL
427
                                             | STATX_SUBVOL
428
#endif
429
#ifdef STATX_WRITE_ATOMIC
430
                                             | STATX_WRITE_ATOMIC
431
#endif
432
#ifdef STATX_DIO_READ_ALIGN
433
                                             | STATX_DIO_READ_ALIGN
434
#endif
435
                                            );
436
#endif /* HAVE_STATX */
437
438
439
#if !defined(EX_OK) && defined(EXIT_SUCCESS)
440
#  define EX_OK EXIT_SUCCESS
441
#endif
442
443
#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
444
#  undef HAVE_SCHED_SETAFFINITY
445
#endif
446
447
/* On android API level 21, 'AT_EACCESS' is not declared although
448
 * HAVE_FACCESSAT is defined. */
449
#ifdef __ANDROID__
450
#  undef HAVE_FACCESSAT
451
#endif
452
453
#if defined(__sun)
454
/* Something to implement in autoconf, not present in autoconf 2.69 */
455
#  define HAVE_STRUCT_STAT_ST_FSTYPE 1
456
#endif
457
458
459
// --- Apple __builtin_available() macros -----------------------------------
460
461
/*
462
 * A number of APIs are available on macOS from a certain macOS version.
463
 * To support building with a new SDK while deploying to older versions
464
 * the availability test is split into two:
465
 *   - HAVE_<FUNCTION>:  The configure check for compile time availability
466
 *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
467
 *
468
 * The latter is always true when not on macOS, or when using a compiler
469
 * that does not support __has_builtin (older versions of Xcode).
470
 *
471
 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
472
 *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
473
 *
474
 * In mixing the test with other tests or using negations will result in compile
475
 * errors.
476
 */
477
#if defined(__APPLE__)
478
479
#include <mach/mach.h>
480
481
#if defined(__has_builtin)
482
#if __has_builtin(__builtin_available)
483
#define HAVE_BUILTIN_AVAILABLE 1
484
#endif
485
#endif
486
487
#ifdef HAVE_BUILTIN_AVAILABLE
488
#  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
489
#  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
490
#  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
491
#  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
492
#  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
493
#  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
494
#  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
495
#  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
496
#  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
497
#  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
498
#  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
499
#  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
500
#  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
501
#  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
502
#  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
503
#  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
504
#  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
505
#  define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
506
507
#  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
508
509
#else /* Xcode 8 or earlier */
510
511
   /* __builtin_available is not present in these compilers, but
512
    * some of the symbols might be weak linked (10.10 SDK or later
513
    * deploying on 10.9.
514
    *
515
    * Fall back to the older style of availability checking for
516
    * symbols introduced in macOS 10.10.
517
    */
518
519
#  ifdef HAVE_FSTATAT
520
#    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
521
#  endif
522
523
#  ifdef HAVE_FACCESSAT
524
#    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
525
#  endif
526
527
#  ifdef HAVE_FCHMODAT
528
#    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
529
#  endif
530
531
#  ifdef HAVE_FCHOWNAT
532
#    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
533
#  endif
534
535
#  ifdef HAVE_LINKAT
536
#    define HAVE_LINKAT_RUNTIME (linkat != NULL)
537
#  endif
538
539
#  ifdef HAVE_FDOPENDIR
540
#    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
541
#  endif
542
543
#  ifdef HAVE_MKDIRAT
544
#    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
545
#  endif
546
547
#  ifdef HAVE_RENAMEAT
548
#    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
549
#  endif
550
551
#  ifdef HAVE_UNLINKAT
552
#    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
553
#  endif
554
555
#  ifdef HAVE_OPENAT
556
#    define HAVE_OPENAT_RUNTIME (openat != NULL)
557
#  endif
558
559
#  ifdef HAVE_READLINKAT
560
#    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
561
#  endif
562
563
#  ifdef HAVE_SYMLINKAT
564
#    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
565
#  endif
566
567
#  ifdef HAVE_UTIMENSAT
568
#    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
569
#  endif
570
571
#  ifdef HAVE_FUTIMENS
572
#    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
573
#  endif
574
575
#  ifdef HAVE_PWRITEV
576
#    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
577
#  endif
578
579
#  ifdef HAVE_MKFIFOAT
580
#    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
581
#  endif
582
583
#  ifdef HAVE_MKNODAT
584
#    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
585
#  endif
586
587
#  ifdef HAVE_PTSNAME_R
588
#    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
589
#  endif
590
591
#endif
592
593
#ifdef HAVE_FUTIMESAT
594
/* Some of the logic for weak linking depends on this assertion */
595
# error "HAVE_FUTIMESAT unexpectedly defined"
596
#endif
597
598
#else
599
209k
#  define HAVE_FSTATAT_RUNTIME 1
600
0
#  define HAVE_FACCESSAT_RUNTIME 1
601
0
#  define HAVE_FCHMODAT_RUNTIME 1
602
0
#  define HAVE_FCHOWNAT_RUNTIME 1
603
#ifdef __wasi__
604
#  define HAVE_LINKAT_RUNTIME 0
605
# else
606
0
#  define HAVE_LINKAT_RUNTIME 1
607
# endif
608
213k
#  define HAVE_FDOPENDIR_RUNTIME 1
609
0
#  define HAVE_MKDIRAT_RUNTIME 1
610
0
#  define HAVE_RENAMEAT_RUNTIME 1
611
234k
#  define HAVE_UNLINKAT_RUNTIME 1
612
209k
#  define HAVE_OPENAT_RUNTIME 1
613
0
#  define HAVE_READLINKAT_RUNTIME 1
614
0
#  define HAVE_SYMLINKAT_RUNTIME 1
615
0
#  define HAVE_FUTIMENS_RUNTIME 1
616
0
#  define HAVE_UTIMENSAT_RUNTIME 1
617
36
#  define HAVE_PWRITEV_RUNTIME 1
618
0
#  define HAVE_MKFIFOAT_RUNTIME 1
619
0
#  define HAVE_MKNODAT_RUNTIME 1
620
0
#  define HAVE_PTSNAME_R_RUNTIME 1
621
#endif
622
623
624
// --- os module ------------------------------------------------------------
625
626
#ifdef MS_WINDOWS
627
#  define INITFUNC PyInit_nt
628
#  define MODNAME "nt"
629
#  define MODNAME_OBJ &_Py_ID(nt)
630
#else
631
#  define INITFUNC PyInit_posix
632
#  define MODNAME "posix"
633
0
#  define MODNAME_OBJ &_Py_ID(posix)
634
#endif
635
636
/*[clinic input]
637
# one of the few times we lie about this name!
638
module os
639
[clinic start generated code]*/
640
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
641
642
PyDoc_STRVAR(posix__doc__,
643
"This module provides access to operating system functionality that is\n\
644
standardized by the C Standard and the POSIX standard (a thinly\n\
645
disguised Unix interface).  Refer to the library manual and\n\
646
corresponding Unix manual entries for more information on calls.");
647
648
649
// --- Functions ------------------------------------------------------------
650
651
#ifdef HAVE_FORK
652
static void
653
run_at_forkers(PyObject *lst, int reverse)
654
0
{
655
0
    Py_ssize_t i;
656
0
    PyObject *cpy;
657
658
0
    if (lst != NULL) {
659
0
        assert(PyList_CheckExact(lst));
660
661
        /* Use a list copy in case register_at_fork() is called from
662
         * one of the callbacks.
663
         */
664
0
        cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
665
0
        if (cpy == NULL) {
666
0
            PyErr_FormatUnraisable("Exception ignored in atfork callback "
667
0
                                   "while copying list %R", lst);
668
0
        }
669
0
        else {
670
0
            if (reverse)
671
0
                PyList_Reverse(cpy);
672
0
            for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
673
0
                PyObject *func, *res;
674
0
                func = PyList_GET_ITEM(cpy, i);
675
0
                res = _PyObject_CallNoArgs(func);
676
0
                if (res == NULL) {
677
0
                    PyErr_FormatUnraisable("Exception ignored "
678
0
                                           "in atfork callback %R", func);
679
0
                }
680
0
                else {
681
0
                    Py_DECREF(res);
682
0
                }
683
0
            }
684
0
            Py_DECREF(cpy);
685
0
        }
686
0
    }
687
0
}
688
689
void
690
PyOS_BeforeFork(void)
691
0
{
692
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
693
0
    run_at_forkers(interp->before_forkers, 1);
694
695
0
    _PyImport_AcquireLock(interp);
696
0
    _PyEval_StopTheWorldAll(&_PyRuntime);
697
0
    HEAD_LOCK(&_PyRuntime);
698
0
}
699
700
void
701
PyOS_AfterFork_Parent(void)
702
0
{
703
0
    HEAD_UNLOCK(&_PyRuntime);
704
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
705
706
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
707
0
    _PyImport_ReleaseLock(interp);
708
0
    run_at_forkers(interp->after_forkers_parent, 0);
709
0
}
710
711
static void
712
reset_remotedebug_data(PyThreadState *tstate)
713
0
{
714
0
    tstate->remote_debugger_support.debugger_pending_call = 0;
715
0
    memset(tstate->remote_debugger_support.debugger_script_path, 0,
716
0
           _Py_MAX_SCRIPT_PATH_SIZE);
717
0
}
718
719
static void
720
reset_asyncio_state(_PyThreadStateImpl *tstate)
721
0
{
722
0
    llist_init(&tstate->asyncio_tasks_head);
723
0
    tstate->asyncio_running_loop = NULL;
724
0
    tstate->asyncio_running_task = NULL;
725
0
}
726
727
728
void
729
PyOS_AfterFork_Child(void)
730
0
{
731
0
    PyStatus status;
732
0
    _PyRuntimeState *runtime = &_PyRuntime;
733
734
    // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
735
0
    status = _PyRuntimeState_ReInitThreads(runtime);
736
0
    if (_PyStatus_EXCEPTION(status)) {
737
0
        goto fatal_error;
738
0
    }
739
740
0
    PyThreadState *tstate = _PyThreadState_GET();
741
0
    _Py_EnsureTstateNotNULL(tstate);
742
743
0
    assert(tstate->thread_id == PyThread_get_thread_ident());
744
0
#ifdef PY_HAVE_THREAD_NATIVE_ID
745
0
    tstate->native_thread_id = PyThread_get_thread_native_id();
746
0
#endif
747
748
#ifdef Py_GIL_DISABLED
749
    _Py_brc_after_fork(tstate->interp);
750
    _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
751
#endif
752
753
    // Ideally we could guarantee tstate is running main.
754
0
    _PyInterpreterState_ReinitRunningMain(tstate);
755
756
0
    status = _PyEval_ReInitThreads(tstate);
757
0
    if (_PyStatus_EXCEPTION(status)) {
758
0
        goto fatal_error;
759
0
    }
760
761
0
    reset_remotedebug_data(tstate);
762
763
0
    reset_asyncio_state((_PyThreadStateImpl *)tstate);
764
765
    // Remove the dead thread states. We "start the world" once we are the only
766
    // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
767
    // That needs to happen before `_PyThreadState_DeleteList`, because that
768
    // may call destructors.
769
0
    PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
770
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
771
0
    _PyThreadState_DeleteList(list, /*is_after_fork=*/1);
772
773
0
    _PyImport_ReInitLock(tstate->interp);
774
0
    _PyImport_ReleaseLock(tstate->interp);
775
776
0
    _PySignal_AfterFork();
777
778
0
    status = _PyInterpreterState_DeleteExceptMain(runtime);
779
0
    if (_PyStatus_EXCEPTION(status)) {
780
0
        goto fatal_error;
781
0
    }
782
0
    assert(_PyThreadState_GET() == tstate);
783
784
0
    status = _PyPerfTrampoline_AfterFork_Child();
785
0
    if (_PyStatus_EXCEPTION(status)) {
786
0
        goto fatal_error;
787
0
    }
788
789
0
    run_at_forkers(tstate->interp->after_forkers_child, 0);
790
0
    return;
791
792
0
fatal_error:
793
0
    Py_ExitStatusException(status);
794
0
}
795
796
static int
797
register_at_forker(PyObject **lst, PyObject *func)
798
84
{
799
84
    if (func == NULL)  /* nothing to register? do nothing. */
800
48
        return 0;
801
36
    if (*lst == NULL) {
802
18
        *lst = PyList_New(0);
803
18
        if (*lst == NULL)
804
0
            return -1;
805
18
    }
806
36
    return PyList_Append(*lst, func);
807
36
}
808
#endif  /* HAVE_FORK */
809
810
811
/* Legacy wrapper */
812
void
813
PyOS_AfterFork(void)
814
0
{
815
0
#ifdef HAVE_FORK
816
0
    PyOS_AfterFork_Child();
817
0
#endif
818
0
}
819
820
821
#ifdef MS_WINDOWS
822
/* defined in fileutils.c */
823
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
824
void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
825
                                FILE_BASIC_INFO *, FILE_ID_INFO *,
826
                                struct _Py_stat_struct *);
827
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
828
                                 struct _Py_stat_struct *);
829
#endif
830
831
832
#ifndef MS_WINDOWS
833
PyObject *
834
_PyLong_FromUid(uid_t uid)
835
491k
{
836
491k
    if (uid == (uid_t)-1)
837
0
        return PyLong_FromLong(-1);
838
491k
    return PyLong_FromUnsignedLong(uid);
839
491k
}
840
841
PyObject *
842
_PyLong_FromGid(gid_t gid)
843
491k
{
844
491k
    if (gid == (gid_t)-1)
845
0
        return PyLong_FromLong(-1);
846
491k
    return PyLong_FromUnsignedLong(gid);
847
491k
}
848
849
int
850
_Py_Uid_Converter(PyObject *obj, uid_t *p)
851
0
{
852
0
    uid_t uid;
853
0
    PyObject *index;
854
0
    int overflow;
855
0
    long result;
856
0
    unsigned long uresult;
857
858
0
    index = _PyNumber_Index(obj);
859
0
    if (index == NULL) {
860
0
        PyErr_Format(PyExc_TypeError,
861
0
                     "uid should be integer, not %.200s",
862
0
                     _PyType_Name(Py_TYPE(obj)));
863
0
        return 0;
864
0
    }
865
866
    /*
867
     * Handling uid_t is complicated for two reasons:
868
     *  * Although uid_t is (always?) unsigned, it still
869
     *    accepts -1.
870
     *  * We don't know its size in advance--it may be
871
     *    bigger than an int, or it may be smaller than
872
     *    a long.
873
     *
874
     * So a bit of defensive programming is in order.
875
     * Start with interpreting the value passed
876
     * in as a signed long and see if it works.
877
     */
878
879
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
880
881
0
    if (!overflow) {
882
0
        uid = (uid_t)result;
883
884
0
        if (result == -1) {
885
0
            if (PyErr_Occurred())
886
0
                goto fail;
887
            /* It's a legitimate -1, we're done. */
888
0
            goto success;
889
0
        }
890
891
        /* Any other negative number is disallowed. */
892
0
        if (result < 0)
893
0
            goto underflow;
894
895
        /* Ensure the value wasn't truncated. */
896
0
        if (sizeof(uid_t) < sizeof(long) &&
897
0
            (long)uid != result)
898
0
            goto underflow;
899
0
        goto success;
900
0
    }
901
902
0
    if (overflow < 0)
903
0
        goto underflow;
904
905
    /*
906
     * Okay, the value overflowed a signed long.  If it
907
     * fits in an *unsigned* long, it may still be okay,
908
     * as uid_t may be unsigned long on this platform.
909
     */
910
0
    uresult = PyLong_AsUnsignedLong(index);
911
0
    if (PyErr_Occurred()) {
912
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
913
0
            goto overflow;
914
0
        goto fail;
915
0
    }
916
917
0
    uid = (uid_t)uresult;
918
919
    /*
920
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
921
     * but this value would get interpreted as (uid_t)-1  by chown
922
     * and its siblings.   That's not what the user meant!  So we
923
     * throw an overflow exception instead.   (We already
924
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
925
     */
926
0
    if (uid == (uid_t)-1)
927
0
        goto overflow;
928
929
    /* Ensure the value wasn't truncated. */
930
0
    if (sizeof(uid_t) < sizeof(long) &&
931
0
        (unsigned long)uid != uresult)
932
0
        goto overflow;
933
    /* fallthrough */
934
935
0
success:
936
0
    Py_DECREF(index);
937
0
    *p = uid;
938
0
    return 1;
939
940
0
underflow:
941
0
    PyErr_SetString(PyExc_OverflowError,
942
0
                    "uid is less than minimum");
943
0
    goto fail;
944
945
0
overflow:
946
0
    PyErr_SetString(PyExc_OverflowError,
947
0
                    "uid is greater than maximum");
948
    /* fallthrough */
949
950
0
fail:
951
0
    Py_DECREF(index);
952
0
    return 0;
953
0
}
954
955
int
956
_Py_Gid_Converter(PyObject *obj, gid_t *p)
957
0
{
958
0
    gid_t gid;
959
0
    PyObject *index;
960
0
    int overflow;
961
0
    long result;
962
0
    unsigned long uresult;
963
964
0
    index = _PyNumber_Index(obj);
965
0
    if (index == NULL) {
966
0
        PyErr_Format(PyExc_TypeError,
967
0
                     "gid should be integer, not %.200s",
968
0
                     _PyType_Name(Py_TYPE(obj)));
969
0
        return 0;
970
0
    }
971
972
    /*
973
     * Handling gid_t is complicated for two reasons:
974
     *  * Although gid_t is (always?) unsigned, it still
975
     *    accepts -1.
976
     *  * We don't know its size in advance--it may be
977
     *    bigger than an int, or it may be smaller than
978
     *    a long.
979
     *
980
     * So a bit of defensive programming is in order.
981
     * Start with interpreting the value passed
982
     * in as a signed long and see if it works.
983
     */
984
985
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
986
987
0
    if (!overflow) {
988
0
        gid = (gid_t)result;
989
990
0
        if (result == -1) {
991
0
            if (PyErr_Occurred())
992
0
                goto fail;
993
            /* It's a legitimate -1, we're done. */
994
0
            goto success;
995
0
        }
996
997
        /* Any other negative number is disallowed. */
998
0
        if (result < 0) {
999
0
            goto underflow;
1000
0
        }
1001
1002
        /* Ensure the value wasn't truncated. */
1003
0
        if (sizeof(gid_t) < sizeof(long) &&
1004
0
            (long)gid != result)
1005
0
            goto underflow;
1006
0
        goto success;
1007
0
    }
1008
1009
0
    if (overflow < 0)
1010
0
        goto underflow;
1011
1012
    /*
1013
     * Okay, the value overflowed a signed long.  If it
1014
     * fits in an *unsigned* long, it may still be okay,
1015
     * as gid_t may be unsigned long on this platform.
1016
     */
1017
0
    uresult = PyLong_AsUnsignedLong(index);
1018
0
    if (PyErr_Occurred()) {
1019
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1020
0
            goto overflow;
1021
0
        goto fail;
1022
0
    }
1023
1024
0
    gid = (gid_t)uresult;
1025
1026
    /*
1027
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
1028
     * but this value would get interpreted as (gid_t)-1  by chown
1029
     * and its siblings.   That's not what the user meant!  So we
1030
     * throw an overflow exception instead.   (We already
1031
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
1032
     */
1033
0
    if (gid == (gid_t)-1)
1034
0
        goto overflow;
1035
1036
    /* Ensure the value wasn't truncated. */
1037
0
    if (sizeof(gid_t) < sizeof(long) &&
1038
0
        (unsigned long)gid != uresult)
1039
0
        goto overflow;
1040
    /* fallthrough */
1041
1042
0
success:
1043
0
    Py_DECREF(index);
1044
0
    *p = gid;
1045
0
    return 1;
1046
1047
0
underflow:
1048
0
    PyErr_SetString(PyExc_OverflowError,
1049
0
                    "gid is less than minimum");
1050
0
    goto fail;
1051
1052
0
overflow:
1053
0
    PyErr_SetString(PyExc_OverflowError,
1054
0
                    "gid is greater than maximum");
1055
    /* fallthrough */
1056
1057
0
fail:
1058
0
    Py_DECREF(index);
1059
0
    return 0;
1060
0
}
1061
#endif /* MS_WINDOWS */
1062
1063
1064
static PyObject *
1065
_PyLong_FromDev(dev_t dev)
1066
983k
{
1067
983k
#ifdef NODEV
1068
983k
    if (dev == NODEV) {
1069
36
        return PyLong_FromLongLong((long long)dev);
1070
36
    }
1071
983k
#endif
1072
983k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1073
983k
}
1074
1075
1076
#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
1077
static int
1078
_Py_Dev_Converter(PyObject *obj, void *p)
1079
0
{
1080
0
    if (!PyLong_Check(obj)) {
1081
0
        obj = _PyNumber_Index(obj);
1082
0
        if (obj == NULL) {
1083
0
            return 0;
1084
0
        }
1085
0
    }
1086
0
    else {
1087
0
        Py_INCREF(obj);
1088
0
    }
1089
0
    assert(PyLong_Check(obj));
1090
0
#ifdef NODEV
1091
0
    if (_PyLong_IsNegative((PyLongObject *)obj)) {
1092
0
        int overflow;
1093
0
        long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
1094
0
        if (result == -1 && PyErr_Occurred()) {
1095
0
            Py_DECREF(obj);
1096
0
            return 0;
1097
0
        }
1098
0
        if (!overflow && result == (long long)NODEV) {
1099
0
            *((dev_t *)p) = NODEV;
1100
0
            Py_DECREF(obj);
1101
0
            return 1;
1102
0
        }
1103
0
    }
1104
0
#endif
1105
1106
0
    unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1107
0
    Py_DECREF(obj);
1108
0
    if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1109
0
        return 0;
1110
0
    }
1111
0
    if ((unsigned long long)(dev_t)result != result) {
1112
0
        PyErr_SetString(PyExc_OverflowError,
1113
0
                        "Python int too large to convert to C dev_t");
1114
0
        return 0;
1115
0
    }
1116
0
    *((dev_t *)p) = (dev_t)result;
1117
0
    return 1;
1118
0
}
1119
#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1120
1121
1122
#ifdef AT_FDCWD
1123
/*
1124
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1125
 * without the int cast, the value gets interpreted as uint (4291925331),
1126
 * which doesn't play nicely with all the initializer lines in this file that
1127
 * look like this:
1128
 *      int dir_fd = DEFAULT_DIR_FD;
1129
 */
1130
3.54M
#define DEFAULT_DIR_FD (int)AT_FDCWD
1131
#else
1132
#define DEFAULT_DIR_FD (-100)
1133
#endif
1134
1135
static int
1136
_fd_converter(PyObject *o, int *p)
1137
658k
{
1138
658k
    int overflow;
1139
658k
    long long_value;
1140
1141
658k
    if (PyBool_Check(o)) {
1142
0
        if (PyErr_WarnEx(PyExc_RuntimeWarning,
1143
0
                "bool is used as a file descriptor", 1))
1144
0
        {
1145
0
            return 0;
1146
0
        }
1147
0
    }
1148
658k
    PyObject *index = _PyNumber_Index(o);
1149
658k
    if (index == NULL) {
1150
0
        return 0;
1151
0
    }
1152
1153
658k
    assert(PyLong_Check(index));
1154
658k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1155
658k
    Py_DECREF(index);
1156
658k
    assert(!PyErr_Occurred());
1157
658k
    if (overflow > 0 || long_value > INT_MAX) {
1158
0
        PyErr_SetString(PyExc_OverflowError,
1159
0
                        "fd is greater than maximum");
1160
0
        return 0;
1161
0
    }
1162
658k
    if (overflow < 0 || long_value < INT_MIN) {
1163
0
        PyErr_SetString(PyExc_OverflowError,
1164
0
                        "fd is less than minimum");
1165
0
        return 0;
1166
0
    }
1167
1168
658k
    *p = (int)long_value;
1169
658k
    return 1;
1170
658k
}
1171
1172
static int
1173
dir_fd_converter(PyObject *o, void *p)
1174
462k
{
1175
462k
    if (o == Py_None) {
1176
17.9k
        *(int *)p = DEFAULT_DIR_FD;
1177
17.9k
        return 1;
1178
17.9k
    }
1179
444k
    else if (PyIndex_Check(o)) {
1180
444k
        return _fd_converter(o, (int *)p);
1181
444k
    }
1182
0
    else {
1183
0
        PyErr_Format(PyExc_TypeError,
1184
0
                     "argument should be integer or None, not %.200s",
1185
0
                     _PyType_Name(Py_TYPE(o)));
1186
0
        return 0;
1187
0
    }
1188
462k
}
1189
1190
typedef struct {
1191
    PyObject *billion;
1192
    PyObject *DirEntryType;
1193
    PyObject *ScandirIteratorType;
1194
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1195
    PyObject *SchedParamType;
1196
#endif
1197
    newfunc statresult_new_orig;
1198
    PyObject *StatResultType;
1199
#ifdef HAVE_STATX
1200
    PyObject *StatxResultType;
1201
#endif
1202
    PyObject *StatVFSResultType;
1203
    PyObject *TerminalSizeType;
1204
    PyObject *TimesResultType;
1205
    PyObject *UnameResultType;
1206
#if defined(HAVE_WAITID)
1207
    PyObject *WaitidResultType;
1208
#endif
1209
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1210
    PyObject *struct_rusage;
1211
#endif
1212
    PyObject *st_mode;
1213
#ifndef MS_WINDOWS
1214
    // times() clock frequency in hertz; used by os.times()
1215
    long ticks_per_second;
1216
#endif
1217
} _posixstate;
1218
1219
1220
static inline _posixstate*
1221
get_posix_state(PyObject *module)
1222
942k
{
1223
942k
    void *state = _PyModule_GetState(module);
1224
942k
    assert(state != NULL);
1225
942k
    return (_posixstate *)state;
1226
942k
}
1227
1228
/*
1229
 * A PyArg_ParseTuple "converter" function
1230
 * that handles filesystem paths in the manner
1231
 * preferred by the os module.
1232
 *
1233
 * path_converter accepts (Unicode) strings and their
1234
 * subclasses, and bytes and their subclasses.  What
1235
 * it does with the argument depends on path.make_wide:
1236
 *
1237
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1238
 *     string we extract the wchar_t * and return it; if we
1239
 *     get bytes we decode to wchar_t * and return that.
1240
 *
1241
 *   * If path.make_wide is zero, if we get bytes we extract
1242
 *     the char_t * and return it; if we get a (Unicode)
1243
 *     string we encode to char_t * and return that.
1244
 *
1245
 * path_converter also optionally accepts signed
1246
 * integers (representing open file descriptors) instead
1247
 * of path strings.
1248
 *
1249
 * Input fields:
1250
 *   path.nullable
1251
 *     If nonzero, the path is permitted to be None.
1252
 *   path.nonstrict
1253
 *     If nonzero, the path is permitted to contain
1254
 *     embedded null characters and have any length.
1255
 *   path.make_wide
1256
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1257
 *     it always uses narrow, encoding if necessary. The default value is
1258
 *     nonzero on Windows, else zero.
1259
 *   path.suppress_value_error
1260
 *     If nonzero, raising ValueError is suppressed.
1261
 *   path.allow_fd
1262
 *     If nonzero, the path is permitted to be a file handle
1263
 *     (a signed int) instead of a string.
1264
 *   path.function_name
1265
 *     If non-NULL, path_converter will use that as the name
1266
 *     of the function in error messages.
1267
 *     (If path.function_name is NULL it omits the function name.)
1268
 *   path.argument_name
1269
 *     If non-NULL, path_converter will use that as the name
1270
 *     of the parameter in error messages.
1271
 *     (If path.argument_name is NULL it uses "path".)
1272
 *
1273
 * Output fields:
1274
 *   path.wide
1275
 *     Points to the path if it was expressed as Unicode
1276
 *     or if it was bytes and decoded to Unicode.
1277
 *   path.narrow
1278
 *     Points to the path if it was expressed as bytes,
1279
 *     or if it was Unicode and encoded to bytes.
1280
 *   path.fd
1281
 *     Contains a file descriptor if path.accept_fd was true
1282
 *     and the caller provided a signed integer instead of any
1283
 *     sort of string.
1284
 *   path.is_fd
1285
 *     True if path was provided as a file descriptor.
1286
 *
1287
 *     WARNING: if your "path" parameter is optional, and is
1288
 *     unspecified, path_converter will never get called.
1289
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1290
 *     yourself!
1291
 *   path.value_error
1292
 *     If nonzero, then suppress_value_error was specified and a ValueError
1293
 *     occurred.
1294
 *   path.length
1295
 *     The length of the path in characters, if specified as
1296
 *     a string.
1297
 *   path.object
1298
 *     The original object passed in (if get a PathLike object,
1299
 *     the result of PyOS_FSPath() is treated as the original object).
1300
 *     Own a reference to the object.
1301
 *   path.cleanup
1302
 *     For internal use only.  May point to a temporary object.
1303
 *     (Pay no attention to the man behind the curtain.)
1304
 *
1305
 *   At most one of path.wide or path.narrow will be non-NULL.
1306
 *   If path was None and path.nullable was set,
1307
 *     or if path was an integer and path.allow_fd was set,
1308
 *     both path.wide and path.narrow will be NULL
1309
 *     and path.length will be 0.
1310
 *
1311
 *   path_converter takes care to not write to the path_t
1312
 *   unless it's successful.  However it must reset the
1313
 *   "cleanup" field each time it's called.
1314
 *
1315
 * Use as follows:
1316
 *      path_t path;
1317
 *      memset(&path, 0, sizeof(path));
1318
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1319
 *      // ... use values from path ...
1320
 *      path_cleanup(&path);
1321
 *
1322
 * (Note that if PyArg_Parse fails you don't need to call
1323
 * path_cleanup().  However it is safe to do so.)
1324
 */
1325
typedef struct {
1326
    // Input fields
1327
    const char *function_name;
1328
    const char *argument_name;
1329
    int nullable;
1330
    int nonstrict;
1331
    int make_wide;
1332
    int suppress_value_error;
1333
    int allow_fd;
1334
    // Output fields
1335
    const wchar_t *wide;
1336
    const char *narrow;
1337
    int fd;
1338
    bool is_fd;
1339
    int value_error;
1340
    Py_ssize_t length;
1341
    PyObject *object;
1342
    PyObject *cleanup;
1343
} path_t;
1344
1345
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1346
                          make_wide, suppress_value_error, allow_fd) \
1347
1.53M
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1348
1.53M
     suppress_value_error, allow_fd, NULL, NULL, -1, false, 0, 0, NULL, NULL}
1349
#ifdef MS_WINDOWS
1350
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1351
                            nonstrict, suppress_value_error, allow_fd) \
1352
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1353
                      suppress_value_error, allow_fd)
1354
#else
1355
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1356
                            nonstrict, suppress_value_error, allow_fd) \
1357
1.26M
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1358
1.26M
                      suppress_value_error, allow_fd)
1359
#endif
1360
1361
static void
1362
path_cleanup(path_t *path)
1363
1.75M
{
1364
1.75M
    wchar_t *wide = (wchar_t *)path->wide;
1365
1.75M
    path->wide = NULL;
1366
1.75M
    PyMem_Free(wide);
1367
1.75M
    Py_CLEAR(path->object);
1368
1.75M
    Py_CLEAR(path->cleanup);
1369
1.75M
}
1370
1371
static int
1372
path_converter(PyObject *o, void *p)
1373
1.53M
{
1374
1.53M
    path_t *path = (path_t *)p;
1375
1.53M
    PyObject *bytes = NULL;
1376
1.53M
    Py_ssize_t length = 0;
1377
1.53M
    int is_index, is_bytes, is_unicode;
1378
1.53M
    const char *narrow;
1379
1.53M
    PyObject *wo = NULL;
1380
1.53M
    wchar_t *wide = NULL;
1381
1382
1.53M
#define FORMAT_EXCEPTION(exc, fmt) \
1383
1.53M
    PyErr_Format(exc, "%s%s" fmt, \
1384
0
        path->function_name ? path->function_name : "", \
1385
0
        path->function_name ? ": "                : "", \
1386
0
        path->argument_name ? path->argument_name : "path")
1387
1388
    /* Py_CLEANUP_SUPPORTED support */
1389
1.53M
    if (o == NULL) {
1390
0
        path_cleanup(path);
1391
0
        return 1;
1392
0
    }
1393
1394
    /* Ensure it's always safe to call path_cleanup(). */
1395
1.53M
    path->object = path->cleanup = NULL;
1396
    /* path->object owns a reference to the original object */
1397
1.53M
    Py_INCREF(o);
1398
1399
1.53M
    if ((o == Py_None) && path->nullable) {
1400
0
        path->wide = NULL;
1401
0
        path->narrow = NULL;
1402
0
        path->fd = -1;
1403
0
        goto success_exit;
1404
0
    }
1405
1406
    /* Only call this here so that we don't treat the return value of
1407
       os.fspath() as an fd or buffer. */
1408
1.53M
    is_index = path->allow_fd && PyIndex_Check(o);
1409
1.53M
    is_bytes = PyBytes_Check(o);
1410
1.53M
    is_unicode = PyUnicode_Check(o);
1411
1412
1.53M
    if (!is_index && !is_unicode && !is_bytes) {
1413
        /* Inline PyOS_FSPath() for better error messages. */
1414
12
        PyObject *func, *res;
1415
1416
12
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1417
12
        if ((NULL == func) || (func == Py_None)) {
1418
0
            goto error_format;
1419
0
        }
1420
12
        res = _PyObject_CallNoArgs(func);
1421
12
        Py_DECREF(func);
1422
12
        if (NULL == res) {
1423
0
            goto error_exit;
1424
0
        }
1425
12
        else if (PyUnicode_Check(res)) {
1426
12
            is_unicode = 1;
1427
12
        }
1428
0
        else if (PyBytes_Check(res)) {
1429
0
            is_bytes = 1;
1430
0
        }
1431
0
        else {
1432
0
            PyErr_Format(PyExc_TypeError,
1433
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1434
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1435
0
                 _PyType_Name(Py_TYPE(res)));
1436
0
            Py_DECREF(res);
1437
0
            goto error_exit;
1438
0
        }
1439
1440
        /* still owns a reference to the original object */
1441
12
        Py_SETREF(o, res);
1442
12
    }
1443
1444
1.53M
    if (is_unicode) {
1445
1.32M
        if (path->make_wide) {
1446
273k
            wide = PyUnicode_AsWideCharString(o, &length);
1447
273k
            if (!wide) {
1448
0
                goto error_exit;
1449
0
            }
1450
#ifdef MS_WINDOWS
1451
            if (!path->nonstrict && length > 32767) {
1452
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1453
                goto error_exit;
1454
            }
1455
#endif
1456
273k
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1457
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1458
0
                                 "embedded null character in %s");
1459
0
                goto error_exit;
1460
0
            }
1461
1462
273k
            path->wide = wide;
1463
273k
            path->narrow = NULL;
1464
273k
            path->fd = -1;
1465
273k
            wide = NULL;
1466
273k
            goto success_exit;
1467
273k
        }
1468
1.05M
        bytes = PyUnicode_EncodeFSDefault(o);
1469
1.05M
        if (!bytes) {
1470
0
            goto error_exit;
1471
0
        }
1472
1.05M
    }
1473
213k
    else if (is_bytes) {
1474
0
        bytes = Py_NewRef(o);
1475
0
    }
1476
213k
    else if (is_index) {
1477
213k
        if (!_fd_converter(o, &path->fd)) {
1478
0
            goto error_exit;
1479
0
        }
1480
213k
        path->wide = NULL;
1481
213k
        path->narrow = NULL;
1482
213k
        path->is_fd = true;
1483
213k
        goto success_exit;
1484
213k
    }
1485
0
    else {
1486
0
 error_format:
1487
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1488
0
            path->function_name ? path->function_name : "",
1489
0
            path->function_name ? ": "                : "",
1490
0
            path->argument_name ? path->argument_name : "path",
1491
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1492
0
                                               "integer or None" :
1493
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1494
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1495
0
                             "string, bytes or os.PathLike",
1496
0
            _PyType_Name(Py_TYPE(o)));
1497
0
        goto error_exit;
1498
0
    }
1499
1500
1.05M
    length = PyBytes_GET_SIZE(bytes);
1501
1.05M
    narrow = PyBytes_AS_STRING(bytes);
1502
1.05M
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1503
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1504
0
        goto error_exit;
1505
0
    }
1506
1507
1.05M
    if (path->make_wide) {
1508
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1509
0
        if (!wo) {
1510
0
            goto error_exit;
1511
0
        }
1512
1513
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1514
0
        Py_DECREF(wo);
1515
0
        if (!wide) {
1516
0
            goto error_exit;
1517
0
        }
1518
#ifdef MS_WINDOWS
1519
        if (!path->nonstrict && length > 32767) {
1520
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1521
            goto error_exit;
1522
        }
1523
#endif
1524
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1525
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1526
0
                             "embedded null character in %s");
1527
0
            goto error_exit;
1528
0
        }
1529
0
        path->wide = wide;
1530
0
        path->narrow = NULL;
1531
0
        Py_DECREF(bytes);
1532
0
        wide = NULL;
1533
0
    }
1534
1.05M
    else {
1535
1.05M
        path->wide = NULL;
1536
1.05M
        path->narrow = narrow;
1537
1.05M
        if (bytes == o) {
1538
            /* Still a reference owned by path->object, don't have to
1539
            worry about path->narrow is used after free. */
1540
0
            Py_DECREF(bytes);
1541
0
        }
1542
1.05M
        else {
1543
1.05M
            path->cleanup = bytes;
1544
1.05M
        }
1545
1.05M
    }
1546
1.05M
    path->fd = -1;
1547
1548
1.53M
 success_exit:
1549
1.53M
    path->value_error = 0;
1550
1.53M
    path->length = length;
1551
1.53M
    path->object = o;
1552
1.53M
    return Py_CLEANUP_SUPPORTED;
1553
1554
0
 error_exit:
1555
0
    Py_XDECREF(o);
1556
0
    Py_XDECREF(bytes);
1557
0
    PyMem_Free(wide);
1558
0
    if (!path->suppress_value_error ||
1559
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1560
0
    {
1561
0
        return 0;
1562
0
    }
1563
0
    PyErr_Clear();
1564
0
    path->wide = NULL;
1565
0
    path->narrow = NULL;
1566
0
    path->fd = -1;
1567
0
    path->value_error = 1;
1568
0
    path->length = 0;
1569
0
    path->object = NULL;
1570
0
    return Py_CLEANUP_SUPPORTED;
1571
0
}
1572
1573
static void
1574
argument_unavailable_error(const char *function_name, const char *argument_name)
1575
0
{
1576
0
    PyErr_Format(PyExc_NotImplementedError,
1577
0
        "%s%s%s unavailable on this platform",
1578
0
        (function_name != NULL) ? function_name : "",
1579
0
        (function_name != NULL) ? ": ": "",
1580
0
        argument_name);
1581
0
}
1582
1583
static int
1584
dir_fd_unavailable(PyObject *o, void *p)
1585
36
{
1586
36
    int dir_fd;
1587
36
    if (!dir_fd_converter(o, &dir_fd))
1588
0
        return 0;
1589
36
    if (dir_fd != DEFAULT_DIR_FD) {
1590
0
        argument_unavailable_error(NULL, "dir_fd");
1591
0
        return 0;
1592
0
    }
1593
36
    *(int *)p = dir_fd;
1594
36
    return 1;
1595
36
}
1596
1597
static int
1598
fd_specified(const char *function_name, int fd)
1599
36
{
1600
36
    if (fd == -1)
1601
36
        return 0;
1602
1603
0
    argument_unavailable_error(function_name, "fd");
1604
0
    return 1;
1605
36
}
1606
1607
static int
1608
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1609
36
{
1610
36
    if (follow_symlinks)
1611
36
        return 0;
1612
1613
0
    argument_unavailable_error(function_name, "follow_symlinks");
1614
0
    return 1;
1615
36
}
1616
1617
static int
1618
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1619
382k
{
1620
382k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1621
0
        PyErr_Format(PyExc_ValueError,
1622
0
                     "%s: can't specify dir_fd without matching path",
1623
0
                     function_name);
1624
0
        return 1;
1625
0
    }
1626
382k
    return 0;
1627
382k
}
1628
1629
static int
1630
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1631
382k
{
1632
382k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1633
0
        PyErr_Format(PyExc_ValueError,
1634
0
                     "%s: can't specify both dir_fd and fd",
1635
0
                     function_name);
1636
0
        return 1;
1637
0
    }
1638
382k
    return 0;
1639
382k
}
1640
1641
static int
1642
fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
1643
                               int follow_symlinks)
1644
382k
{
1645
382k
    if (is_fd && (!follow_symlinks)) {
1646
0
        PyErr_Format(PyExc_ValueError,
1647
0
                     "%s: cannot use fd and follow_symlinks together",
1648
0
                     function_name);
1649
0
        return 1;
1650
0
    }
1651
382k
    return 0;
1652
382k
}
1653
1654
static int
1655
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1656
                                   int follow_symlinks)
1657
36
{
1658
36
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1659
0
        PyErr_Format(PyExc_ValueError,
1660
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1661
0
                     function_name);
1662
0
        return 1;
1663
0
    }
1664
36
    return 0;
1665
36
}
1666
1667
#if defined(HAVE_WAITID)
1668
static int
1669
idtype_t_converter(PyObject *arg, void *addr)
1670
0
{
1671
0
    int value = PyLong_AsInt(arg);
1672
0
    if (value == -1 && PyErr_Occurred()) {
1673
0
        return 0;
1674
0
    }
1675
0
    *((idtype_t *)addr) = (idtype_t)(value);
1676
0
    return 1;
1677
0
}
1678
#endif
1679
1680
#ifdef MS_WINDOWS
1681
    typedef long long Py_off_t;
1682
#else
1683
    typedef off_t Py_off_t;
1684
#endif
1685
1686
static int
1687
Py_off_t_converter(PyObject *arg, void *addr)
1688
0
{
1689
#ifdef HAVE_LARGEFILE_SUPPORT
1690
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1691
#else
1692
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1693
0
#endif
1694
0
    if (PyErr_Occurred())
1695
0
        return 0;
1696
0
    return 1;
1697
0
}
1698
1699
static PyObject *
1700
PyLong_FromPy_off_t(Py_off_t offset)
1701
0
{
1702
#ifdef HAVE_LARGEFILE_SUPPORT
1703
    return PyLong_FromLongLong(offset);
1704
#else
1705
0
    return PyLong_FromLong(offset);
1706
0
#endif
1707
0
}
1708
1709
#ifdef HAVE_SIGSET_T
1710
/* Convert an iterable of integers to a sigset.
1711
   Return 1 on success, return 0 and raise an exception on error. */
1712
int
1713
_Py_Sigset_Converter(PyObject *obj, void *addr)
1714
0
{
1715
0
    sigset_t *mask = (sigset_t *)addr;
1716
0
    PyObject *iterator, *item;
1717
0
    long signum;
1718
0
    int overflow;
1719
1720
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1721
0
    if (sigemptyset(mask) < (0)) {
1722
        /* Probably only if mask == NULL. */
1723
0
        PyErr_SetFromErrno(PyExc_OSError);
1724
0
        return 0;
1725
0
    }
1726
1727
0
    iterator = PyObject_GetIter(obj);
1728
0
    if (iterator == NULL) {
1729
0
        return 0;
1730
0
    }
1731
1732
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1733
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1734
0
        Py_DECREF(item);
1735
0
        if (signum <= 0 || signum >= Py_NSIG) {
1736
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1737
0
                PyErr_Format(PyExc_ValueError,
1738
0
                             "signal number %ld out of range [1; %i]",
1739
0
                             signum, Py_NSIG - 1);
1740
0
            }
1741
0
            goto error;
1742
0
        }
1743
0
        if (sigaddset(mask, (int)signum)) {
1744
0
            if (errno != EINVAL) {
1745
                /* Probably impossible */
1746
0
                PyErr_SetFromErrno(PyExc_OSError);
1747
0
                goto error;
1748
0
            }
1749
            /* For backwards compatibility, allow idioms such as
1750
             * `range(1, NSIG)` but warn about invalid signal numbers
1751
             */
1752
0
            const char msg[] =
1753
0
                "invalid signal number %ld, please use valid_signals()";
1754
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1755
0
                goto error;
1756
0
            }
1757
0
        }
1758
0
    }
1759
0
    if (!PyErr_Occurred()) {
1760
0
        Py_DECREF(iterator);
1761
0
        return 1;
1762
0
    }
1763
1764
0
error:
1765
0
    Py_DECREF(iterator);
1766
0
    return 0;
1767
0
}
1768
#endif /* HAVE_SIGSET_T */
1769
1770
/* Return a dictionary corresponding to the POSIX environment table */
1771
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1772
/* On Darwin/MacOSX a shared library or framework has no access to
1773
** environ directly, we must obtain it with _NSGetEnviron(). See also
1774
** man environ(7).
1775
*/
1776
#include <crt_externs.h>
1777
#define USE_DARWIN_NS_GET_ENVIRON 1
1778
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1779
extern char **environ;
1780
#endif /* !_MSC_VER */
1781
1782
static PyObject *
1783
convertenviron(void)
1784
36
{
1785
36
    PyObject *d;
1786
#ifdef MS_WINDOWS
1787
    wchar_t **e;
1788
#else
1789
36
    char **e;
1790
36
#endif
1791
1792
36
    d = PyDict_New();
1793
36
    if (d == NULL)
1794
0
        return NULL;
1795
#ifdef MS_WINDOWS
1796
    /* _wenviron must be initialized in this way if the program is started
1797
       through main() instead of wmain(). */
1798
    (void)_wgetenv(L"");
1799
    e = _wenviron;
1800
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1801
    /* environ is not accessible as an extern in a shared object on OSX; use
1802
       _NSGetEnviron to resolve it. The value changes if you add environment
1803
       variables between calls to Py_Initialize, so don't cache the value. */
1804
    e = *_NSGetEnviron();
1805
#else
1806
36
    e = environ;
1807
36
#endif
1808
36
    if (e == NULL)
1809
0
        return d;
1810
1.26k
    for (; *e != NULL; e++) {
1811
1.22k
        PyObject *k;
1812
1.22k
        PyObject *v;
1813
#ifdef MS_WINDOWS
1814
        const wchar_t *p = wcschr(*e, L'=');
1815
#else
1816
1.22k
        const char *p = strchr(*e, '=');
1817
1.22k
#endif
1818
1.22k
        if (p == NULL)
1819
0
            continue;
1820
#ifdef MS_WINDOWS
1821
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1822
#else
1823
1.22k
        k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
1824
1.22k
#endif
1825
1.22k
        if (k == NULL) {
1826
0
            Py_DECREF(d);
1827
0
            return NULL;
1828
0
        }
1829
#ifdef MS_WINDOWS
1830
        v = PyUnicode_FromWideChar(p+1, -1);
1831
#else
1832
1.22k
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1833
1.22k
#endif
1834
1.22k
        if (v == NULL) {
1835
0
            Py_DECREF(k);
1836
0
            Py_DECREF(d);
1837
0
            return NULL;
1838
0
        }
1839
1.22k
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1840
0
            Py_DECREF(v);
1841
0
            Py_DECREF(k);
1842
0
            Py_DECREF(d);
1843
0
            return NULL;
1844
0
        }
1845
1.22k
        Py_DECREF(k);
1846
1.22k
        Py_DECREF(v);
1847
1.22k
    }
1848
36
    return d;
1849
36
}
1850
1851
/* Set a POSIX-specific error from errno, and return NULL */
1852
1853
static PyObject *
1854
posix_error(void)
1855
0
{
1856
0
    return PyErr_SetFromErrno(PyExc_OSError);
1857
0
}
1858
1859
#ifdef MS_WINDOWS
1860
static PyObject *
1861
win32_error(const char* function, const char* filename)
1862
{
1863
    /* XXX We should pass the function name along in the future.
1864
       (winreg.c also wants to pass the function name.)
1865
       This would however require an additional param to the
1866
       Windows error object, which is non-trivial.
1867
    */
1868
    errno = GetLastError();
1869
    if (filename)
1870
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1871
    else
1872
        return PyErr_SetFromWindowsErr(errno);
1873
}
1874
1875
static PyObject *
1876
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1877
{
1878
    /* XXX - see win32_error for comments on 'function' */
1879
    if (filename)
1880
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1881
                    PyExc_OSError,
1882
                    err,
1883
                    filename);
1884
    else
1885
        return PyErr_SetFromWindowsErr(err);
1886
}
1887
1888
static PyObject *
1889
win32_error_object(const char* function, PyObject* filename)
1890
{
1891
    errno = GetLastError();
1892
    return win32_error_object_err(function, filename, errno);
1893
}
1894
1895
#endif /* MS_WINDOWS */
1896
1897
static PyObject *
1898
posix_path_object_error(PyObject *path)
1899
315k
{
1900
315k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1901
315k
}
1902
1903
static PyObject *
1904
path_object_error(PyObject *path)
1905
315k
{
1906
#ifdef MS_WINDOWS
1907
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1908
                PyExc_OSError, 0, path);
1909
#else
1910
315k
    return posix_path_object_error(path);
1911
315k
#endif
1912
315k
}
1913
1914
static PyObject *
1915
path_object_error2(PyObject *path, PyObject *path2)
1916
0
{
1917
#ifdef MS_WINDOWS
1918
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1919
                PyExc_OSError, 0, path, path2);
1920
#else
1921
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1922
0
#endif
1923
0
}
1924
1925
static PyObject *
1926
path_error(path_t *path)
1927
315k
{
1928
315k
    return path_object_error(path->object);
1929
315k
}
1930
1931
static PyObject *
1932
posix_path_error(path_t *path)
1933
0
{
1934
0
    return posix_path_object_error(path->object);
1935
0
}
1936
1937
static PyObject *
1938
path_error2(path_t *path, path_t *path2)
1939
0
{
1940
0
    return path_object_error2(path->object, path2->object);
1941
0
}
1942
1943
1944
/* POSIX generic methods */
1945
1946
static PyObject *
1947
posix_fildes_fd(int fd, int (*func)(int))
1948
0
{
1949
0
    int res;
1950
0
    int async_err = 0;
1951
1952
0
    do {
1953
0
        Py_BEGIN_ALLOW_THREADS
1954
0
        _Py_BEGIN_SUPPRESS_IPH
1955
0
        res = (*func)(fd);
1956
0
        _Py_END_SUPPRESS_IPH
1957
0
        Py_END_ALLOW_THREADS
1958
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1959
0
    if (res != 0)
1960
0
        return (!async_err) ? posix_error() : NULL;
1961
0
    Py_RETURN_NONE;
1962
0
}
1963
1964
1965
#ifdef MS_WINDOWS
1966
/* This is a reimplementation of the C library's chdir function,
1967
   but one that produces Win32 errors instead of DOS error codes.
1968
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1969
   it also needs to set "magic" environment variables indicating
1970
   the per-drive current directory, which are of the form =<drive>: */
1971
static BOOL __stdcall
1972
win32_wchdir(LPCWSTR path)
1973
{
1974
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1975
    int result;
1976
    wchar_t env[4] = L"=x:";
1977
1978
    if(!SetCurrentDirectoryW(path))
1979
        return FALSE;
1980
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1981
    if (!result)
1982
        return FALSE;
1983
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1984
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1985
        if (!new_path) {
1986
            SetLastError(ERROR_OUTOFMEMORY);
1987
            return FALSE;
1988
        }
1989
        result = GetCurrentDirectoryW(result, new_path);
1990
        if (!result) {
1991
            PyMem_RawFree(new_path);
1992
            return FALSE;
1993
        }
1994
    }
1995
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1996
                            wcsncmp(new_path, L"//", 2) == 0);
1997
    if (!is_unc_like_path) {
1998
        env[1] = new_path[0];
1999
        result = SetEnvironmentVariableW(env, new_path);
2000
    }
2001
    if (new_path != path_buf)
2002
        PyMem_RawFree(new_path);
2003
    return result ? TRUE : FALSE;
2004
}
2005
#endif
2006
2007
#ifdef MS_WINDOWS
2008
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2009
   - time stamps are restricted to second resolution
2010
   - file modification times suffer from forth-and-back conversions between
2011
     UTC and local time
2012
   Therefore, we implement our own stat, based on the Win32 API directly.
2013
*/
2014
#define HAVE_STAT_NSEC 1
2015
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2016
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2017
2018
static void
2019
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2020
                       BY_HANDLE_FILE_INFORMATION *info,
2021
                       ULONG *reparse_tag)
2022
{
2023
    memset(info, 0, sizeof(*info));
2024
    info->dwFileAttributes = pFileData->dwFileAttributes;
2025
    info->ftCreationTime   = pFileData->ftCreationTime;
2026
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
2027
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
2028
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
2029
    info->nFileSizeLow     = pFileData->nFileSizeLow;
2030
/*  info->nNumberOfLinks   = 1; */
2031
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2032
        *reparse_tag = pFileData->dwReserved0;
2033
    else
2034
        *reparse_tag = 0;
2035
}
2036
2037
static BOOL
2038
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
2039
{
2040
    HANDLE hFindFile;
2041
    WIN32_FIND_DATAW FileData;
2042
    LPCWSTR filename = pszFile;
2043
    size_t n = wcslen(pszFile);
2044
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2045
        // cannot use PyMem_Malloc here because we do not hold the GIL
2046
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2047
        if(!filename) {
2048
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2049
            return FALSE;
2050
        }
2051
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2052
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2053
            ((LPWSTR)filename)[n] = L'\0';
2054
        }
2055
        if (!n || (n == 1 && filename[1] == L':')) {
2056
            // Nothing left to query
2057
            free((void *)filename);
2058
            return FALSE;
2059
        }
2060
    }
2061
    hFindFile = FindFirstFileW(filename, &FileData);
2062
    if (pszFile != filename) {
2063
        free((void *)filename);
2064
    }
2065
    if (hFindFile == INVALID_HANDLE_VALUE) {
2066
        return FALSE;
2067
    }
2068
    FindClose(hFindFile);
2069
    find_data_to_file_info(&FileData, info, reparse_tag);
2070
    return TRUE;
2071
}
2072
2073
2074
static void
2075
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2076
                         struct _Py_stat_struct *result)
2077
{
2078
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2079
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2080
           the filename has an extension that is commonly used by files
2081
           that CreateProcessW can execute. A real implementation calls
2082
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2083
           AccessCheck to check for generic read, write, and execute
2084
           access. */
2085
        const wchar_t *fileExtension = wcsrchr(path, '.');
2086
        if (fileExtension) {
2087
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2088
                _wcsicmp(fileExtension, L".bat") == 0 ||
2089
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2090
                _wcsicmp(fileExtension, L".com") == 0) {
2091
                result->st_mode |= 0111;
2092
            }
2093
        }
2094
    }
2095
}
2096
2097
2098
static int
2099
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2100
                      BOOL traverse)
2101
{
2102
    HANDLE hFile;
2103
    BY_HANDLE_FILE_INFORMATION fileInfo;
2104
    FILE_BASIC_INFO basicInfo;
2105
    FILE_BASIC_INFO *pBasicInfo = NULL;
2106
    FILE_ID_INFO idInfo;
2107
    FILE_ID_INFO *pIdInfo = NULL;
2108
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2109
    DWORD fileType, error;
2110
    BOOL isUnhandledTag = FALSE;
2111
    int retval = 0;
2112
2113
    DWORD access = FILE_READ_ATTRIBUTES;
2114
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2115
    if (!traverse) {
2116
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2117
    }
2118
2119
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2120
    if (hFile == INVALID_HANDLE_VALUE) {
2121
        /* Either the path doesn't exist, or the caller lacks access. */
2122
        error = GetLastError();
2123
        switch (error) {
2124
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2125
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2126
            /* Try reading the parent directory. */
2127
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2128
                /* Cannot read the parent directory. */
2129
                switch (GetLastError()) {
2130
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2131
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2132
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2133
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2134
                    break;
2135
                /* Restore the error from CreateFileW(). */
2136
                default:
2137
                    SetLastError(error);
2138
                }
2139
2140
                return -1;
2141
            }
2142
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2143
                if (traverse ||
2144
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2145
                    /* The stat call has to traverse but cannot, so fail. */
2146
                    SetLastError(error);
2147
                    return -1;
2148
                }
2149
            }
2150
            break;
2151
2152
        case ERROR_INVALID_PARAMETER:
2153
            /* \\.\con requires read or write access. */
2154
            hFile = CreateFileW(path, access | GENERIC_READ,
2155
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2156
                        OPEN_EXISTING, flags, NULL);
2157
            if (hFile == INVALID_HANDLE_VALUE) {
2158
                SetLastError(error);
2159
                return -1;
2160
            }
2161
            break;
2162
2163
        case ERROR_CANT_ACCESS_FILE:
2164
            /* bpo37834: open unhandled reparse points if traverse fails. */
2165
            if (traverse) {
2166
                traverse = FALSE;
2167
                isUnhandledTag = TRUE;
2168
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2169
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2170
            }
2171
            if (hFile == INVALID_HANDLE_VALUE) {
2172
                SetLastError(error);
2173
                return -1;
2174
            }
2175
            break;
2176
2177
        default:
2178
            return -1;
2179
        }
2180
    }
2181
2182
    if (hFile != INVALID_HANDLE_VALUE) {
2183
        /* Handle types other than files on disk. */
2184
        fileType = GetFileType(hFile);
2185
        if (fileType != FILE_TYPE_DISK) {
2186
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2187
                retval = -1;
2188
                goto cleanup;
2189
            }
2190
            DWORD fileAttributes = GetFileAttributesW(path);
2191
            memset(result, 0, sizeof(*result));
2192
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2193
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2194
                /* \\.\pipe\ or \\.\mailslot\ */
2195
                result->st_mode = _S_IFDIR;
2196
            } else if (fileType == FILE_TYPE_CHAR) {
2197
                /* \\.\nul */
2198
                result->st_mode = _S_IFCHR;
2199
            } else if (fileType == FILE_TYPE_PIPE) {
2200
                /* \\.\pipe\spam */
2201
                result->st_mode = _S_IFIFO;
2202
            }
2203
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2204
            goto cleanup;
2205
        }
2206
2207
        /* Query the reparse tag, and traverse a non-link. */
2208
        if (!traverse) {
2209
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2210
                    &tagInfo, sizeof(tagInfo))) {
2211
                /* Allow devices that do not support FileAttributeTagInfo. */
2212
                switch (GetLastError()) {
2213
                case ERROR_INVALID_PARAMETER:
2214
                case ERROR_INVALID_FUNCTION:
2215
                case ERROR_NOT_SUPPORTED:
2216
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2217
                    tagInfo.ReparseTag = 0;
2218
                    break;
2219
                default:
2220
                    retval = -1;
2221
                    goto cleanup;
2222
                }
2223
            } else if (tagInfo.FileAttributes &
2224
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2225
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2226
                    if (isUnhandledTag) {
2227
                        /* Traversing previously failed for either this link
2228
                           or its target. */
2229
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2230
                        retval = -1;
2231
                        goto cleanup;
2232
                    }
2233
                /* Traverse a non-link, but not if traversing already failed
2234
                   for an unhandled tag. */
2235
                } else if (!isUnhandledTag) {
2236
                    CloseHandle(hFile);
2237
                    return win32_xstat_slow_impl(path, result, TRUE);
2238
                }
2239
            }
2240
        }
2241
2242
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2243
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2244
                                          &basicInfo, sizeof(basicInfo))) {
2245
            switch (GetLastError()) {
2246
            case ERROR_INVALID_PARAMETER:
2247
            case ERROR_INVALID_FUNCTION:
2248
            case ERROR_NOT_SUPPORTED:
2249
                /* Volumes and physical disks are block devices, e.g.
2250
                   \\.\C: and \\.\PhysicalDrive0. */
2251
                memset(result, 0, sizeof(*result));
2252
                result->st_mode = 0x6000; /* S_IFBLK */
2253
                goto cleanup;
2254
            }
2255
            retval = -1;
2256
            goto cleanup;
2257
        }
2258
2259
        /* Successfully got FileBasicInfo, so we'll pass it along */
2260
        pBasicInfo = &basicInfo;
2261
2262
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2263
            /* Successfully got FileIdInfo, so pass it along */
2264
            pIdInfo = &idInfo;
2265
        }
2266
    }
2267
2268
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2269
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2270
2271
cleanup:
2272
    if (hFile != INVALID_HANDLE_VALUE) {
2273
        /* Preserve last error if we are failing */
2274
        error = retval ? GetLastError() : 0;
2275
        if (!CloseHandle(hFile)) {
2276
            retval = -1;
2277
        } else if (retval) {
2278
            /* Restore last error */
2279
            SetLastError(error);
2280
        }
2281
    }
2282
2283
    return retval;
2284
}
2285
2286
static int
2287
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2288
                 BOOL traverse)
2289
{
2290
    FILE_STAT_BASIC_INFORMATION statInfo;
2291
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2292
                                     &statInfo, sizeof(statInfo))) {
2293
        if (// Cannot use fast path for reparse points ...
2294
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2295
            // ... unless it's a name surrogate (symlink) and we're not following
2296
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2297
        ) {
2298
            _Py_stat_basic_info_to_stat(&statInfo, result);
2299
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2300
            return 0;
2301
        }
2302
    } else {
2303
        switch(GetLastError()) {
2304
        case ERROR_FILE_NOT_FOUND:
2305
        case ERROR_PATH_NOT_FOUND:
2306
        case ERROR_NOT_READY:
2307
        case ERROR_BAD_NET_NAME:
2308
            /* These errors aren't worth retrying with the slow path */
2309
            return -1;
2310
        case ERROR_NOT_SUPPORTED:
2311
            /* indicates the API couldn't be loaded */
2312
            break;
2313
        }
2314
    }
2315
2316
    return win32_xstat_slow_impl(path, result, traverse);
2317
}
2318
2319
static int
2320
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2321
{
2322
    /* Protocol violation: we explicitly clear errno, instead of
2323
       setting it to a POSIX error. Callers should use GetLastError. */
2324
    int code = win32_xstat_impl(path, result, traverse);
2325
    errno = 0;
2326
2327
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2328
    result->st_ctime = result->st_birthtime;
2329
    result->st_ctime_nsec = result->st_birthtime_nsec;
2330
    return code;
2331
}
2332
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2333
2334
   In Posix, stat automatically traverses symlinks and returns the stat
2335
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2336
   default does not traverse symlinks and instead returns attributes for
2337
   the symlink.
2338
2339
   Instead, we will open the file (which *does* traverse symlinks by default)
2340
   and GetFileInformationByHandle(). */
2341
2342
static int
2343
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2344
{
2345
    return win32_xstat(path, result, FALSE);
2346
}
2347
2348
static int
2349
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2350
{
2351
    return win32_xstat(path, result, TRUE);
2352
}
2353
2354
#endif /* MS_WINDOWS */
2355
2356
PyDoc_STRVAR(stat_result__doc__,
2357
"stat_result: Result from stat, fstat, or lstat.\n\n\
2358
This object may be accessed either as a tuple of\n\
2359
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2360
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2361
\n\
2362
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2363
or st_flags, they are available as attributes only.\n\
2364
\n\
2365
See os.stat for more information.");
2366
2367
static PyStructSequence_Field stat_result_fields[] = {
2368
    {"st_mode",    "protection bits"},
2369
    {"st_ino",     "inode"},
2370
    {"st_dev",     "device"},
2371
    {"st_nlink",   "number of hard links"},
2372
    {"st_uid",     "user ID of owner"},
2373
    {"st_gid",     "group ID of owner"},
2374
    {"st_size",    "total size, in bytes"},
2375
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2376
    {NULL,   "integer time of last access"},
2377
    {NULL,   "integer time of last modification"},
2378
    {NULL,   "integer time of last change"},
2379
    {"st_atime",   "time of last access"},
2380
    {"st_mtime",   "time of last modification"},
2381
    {"st_ctime",   "time of last change"},
2382
    {"st_atime_ns",   "time of last access in nanoseconds"},
2383
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2384
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2385
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2386
    {"st_blksize", "blocksize for filesystem I/O"},
2387
#endif
2388
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2389
    {"st_blocks",  "number of blocks allocated"},
2390
#endif
2391
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2392
    {"st_rdev",    "device type (if inode device)"},
2393
#endif
2394
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2395
    {"st_flags",   "user defined flags for file"},
2396
#endif
2397
#ifdef HAVE_STRUCT_STAT_ST_GEN
2398
    {"st_gen",    "generation number"},
2399
#endif
2400
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2401
    {"st_birthtime",   "time of creation"},
2402
#endif
2403
#ifdef MS_WINDOWS
2404
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2405
#endif
2406
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2407
    {"st_file_attributes", "Windows file attribute bits"},
2408
#endif
2409
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2410
    {"st_fstype",  "Type of filesystem"},
2411
#endif
2412
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2413
    {"st_reparse_tag", "Windows reparse tag"},
2414
#endif
2415
    {0}
2416
};
2417
2418
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2419
#define ST_BLKSIZE_IDX 16
2420
#else
2421
#define ST_BLKSIZE_IDX 15
2422
#endif
2423
2424
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2425
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2426
#else
2427
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2428
#endif
2429
2430
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2431
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2432
#else
2433
#define ST_RDEV_IDX ST_BLOCKS_IDX
2434
#endif
2435
2436
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2437
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2438
#else
2439
#define ST_FLAGS_IDX ST_RDEV_IDX
2440
#endif
2441
2442
#ifdef HAVE_STRUCT_STAT_ST_GEN
2443
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2444
#else
2445
#define ST_GEN_IDX ST_FLAGS_IDX
2446
#endif
2447
2448
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2449
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2450
#else
2451
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2452
#endif
2453
2454
#ifdef MS_WINDOWS
2455
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2456
#else
2457
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2458
#endif
2459
2460
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2461
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2462
#else
2463
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2464
#endif
2465
2466
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2467
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2468
#else
2469
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2470
#endif
2471
2472
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2473
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2474
#else
2475
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2476
#endif
2477
2478
static PyStructSequence_Desc stat_result_desc = {
2479
    "os.stat_result", /* name; see issue gh-63408 */
2480
    stat_result__doc__, /* doc */
2481
    stat_result_fields,
2482
    10
2483
};
2484
2485
PyDoc_STRVAR(statvfs_result__doc__,
2486
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2487
This object may be accessed either as a tuple of\n\
2488
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2489
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2490
\n\
2491
See os.statvfs for more information.");
2492
2493
static PyStructSequence_Field statvfs_result_fields[] = {
2494
    {"f_bsize",  },
2495
    {"f_frsize", },
2496
    {"f_blocks", },
2497
    {"f_bfree",  },
2498
    {"f_bavail", },
2499
    {"f_files",  },
2500
    {"f_ffree",  },
2501
    {"f_favail", },
2502
    {"f_flag",   },
2503
    {"f_namemax",},
2504
    {"f_fsid",   },
2505
    {0}
2506
};
2507
2508
static PyStructSequence_Desc statvfs_result_desc = {
2509
    "os.statvfs_result", /* name; see issue gh-63408 */
2510
    statvfs_result__doc__, /* doc */
2511
    statvfs_result_fields,
2512
    10
2513
};
2514
2515
#if defined(HAVE_WAITID)
2516
PyDoc_STRVAR(waitid_result__doc__,
2517
"waitid_result: Result from waitid.\n\n\
2518
This object may be accessed either as a tuple of\n\
2519
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2520
or via the attributes si_pid, si_uid, and so on.\n\
2521
\n\
2522
See os.waitid for more information.");
2523
2524
static PyStructSequence_Field waitid_result_fields[] = {
2525
    {"si_pid",  },
2526
    {"si_uid", },
2527
    {"si_signo", },
2528
    {"si_status",  },
2529
    {"si_code", },
2530
    {0}
2531
};
2532
2533
static PyStructSequence_Desc waitid_result_desc = {
2534
    MODNAME ".waitid_result", /* name */
2535
    waitid_result__doc__, /* doc */
2536
    waitid_result_fields,
2537
    5
2538
};
2539
#endif
2540
2541
static PyObject *
2542
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2543
0
{
2544
0
    PyStructSequence *result;
2545
0
    int i;
2546
2547
    // ht_module doesn't get set in PyStructSequence_NewType(),
2548
    // so we can't use PyType_GetModule().
2549
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2550
0
    if (mod == NULL) {
2551
0
        return NULL;
2552
0
    }
2553
0
    _posixstate *state = get_posix_state(mod);
2554
0
    Py_DECREF(mod);
2555
0
    if (state == NULL) {
2556
0
        return NULL;
2557
0
    }
2558
0
#define structseq_new state->statresult_new_orig
2559
2560
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2561
0
    if (!result)
2562
0
        return NULL;
2563
    /* If we have been initialized from a tuple,
2564
       st_?time might be set to None. Initialize it
2565
       from the int slots.  */
2566
0
    for (i = 7; i <= 9; i++) {
2567
0
        if (result->ob_item[i+3] == Py_None) {
2568
0
            Py_DECREF(Py_None);
2569
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2570
0
        }
2571
0
    }
2572
0
    return (PyObject*)result;
2573
0
}
2574
2575
static int
2576
_posix_clear(PyObject *module)
2577
0
{
2578
0
    _posixstate *state = get_posix_state(module);
2579
0
    Py_CLEAR(state->billion);
2580
0
    Py_CLEAR(state->DirEntryType);
2581
0
    Py_CLEAR(state->ScandirIteratorType);
2582
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2583
0
    Py_CLEAR(state->SchedParamType);
2584
0
#endif
2585
0
    Py_CLEAR(state->StatResultType);
2586
0
#ifdef HAVE_STATX
2587
0
    Py_CLEAR(state->StatxResultType);
2588
0
#endif
2589
0
    Py_CLEAR(state->StatVFSResultType);
2590
0
    Py_CLEAR(state->TerminalSizeType);
2591
0
    Py_CLEAR(state->TimesResultType);
2592
0
    Py_CLEAR(state->UnameResultType);
2593
0
#if defined(HAVE_WAITID)
2594
0
    Py_CLEAR(state->WaitidResultType);
2595
0
#endif
2596
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2597
0
    Py_CLEAR(state->struct_rusage);
2598
0
#endif
2599
0
    Py_CLEAR(state->st_mode);
2600
0
    return 0;
2601
0
}
2602
2603
static int
2604
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2605
1.79k
{
2606
1.79k
    _posixstate *state = get_posix_state(module);
2607
1.79k
    Py_VISIT(state->billion);
2608
1.79k
    Py_VISIT(state->DirEntryType);
2609
1.79k
    Py_VISIT(state->ScandirIteratorType);
2610
1.79k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2611
1.79k
    Py_VISIT(state->SchedParamType);
2612
1.79k
#endif
2613
1.79k
    Py_VISIT(state->StatResultType);
2614
1.79k
#ifdef HAVE_STATX
2615
1.79k
    Py_VISIT(state->StatxResultType);
2616
1.79k
#endif
2617
1.79k
    Py_VISIT(state->StatVFSResultType);
2618
1.79k
    Py_VISIT(state->TerminalSizeType);
2619
1.79k
    Py_VISIT(state->TimesResultType);
2620
1.79k
    Py_VISIT(state->UnameResultType);
2621
1.79k
#if defined(HAVE_WAITID)
2622
1.79k
    Py_VISIT(state->WaitidResultType);
2623
1.79k
#endif
2624
1.79k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2625
1.79k
    Py_VISIT(state->struct_rusage);
2626
1.79k
#endif
2627
1.79k
    Py_VISIT(state->st_mode);
2628
1.79k
    return 0;
2629
1.79k
}
2630
2631
static void
2632
_posix_free(void *module)
2633
0
{
2634
0
   _posix_clear((PyObject *)module);
2635
0
}
2636
2637
2638
4.42M
#define SEC_TO_NS (1000000000LL)
2639
static PyObject *
2640
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2641
1.47M
{
2642
#if SIZEOF_TIME_T == 4
2643
    return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2644
#else
2645
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2646
1.47M
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2647
1.47M
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2648
1.47M
    }
2649
0
    else
2650
0
    {
2651
0
        PyObject *ns_total = NULL;
2652
0
        PyObject *s_in_ns = NULL;
2653
0
        PyObject *s = _PyLong_FromTime_t(sec);
2654
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2655
0
        if (s == NULL || ns_fractional == NULL) {
2656
0
            goto exit;
2657
0
        }
2658
2659
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2660
0
        if (s_in_ns == NULL) {
2661
0
            goto exit;
2662
0
        }
2663
2664
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2665
2666
0
    exit:
2667
0
        Py_XDECREF(s);
2668
0
        Py_XDECREF(ns_fractional);
2669
0
        Py_XDECREF(s_in_ns);
2670
0
        return ns_total;
2671
0
    }
2672
1.47M
#endif
2673
1.47M
}
2674
2675
static int
2676
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2677
          int ns_index, time_t sec, unsigned long nsec)
2678
1.47M
{
2679
1.47M
    assert(!PyErr_Occurred());
2680
1.47M
    assert(nsec < SEC_TO_NS);
2681
2682
1.47M
    if (s_index >= 0) {
2683
1.47M
        PyObject *s = _PyLong_FromTime_t(sec);
2684
1.47M
        if (s == NULL) {
2685
0
            return -1;
2686
0
        }
2687
1.47M
        PyStructSequence_SET_ITEM(v, s_index, s);
2688
1.47M
    }
2689
2690
1.47M
    if (f_index >= 0) {
2691
1.47M
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2692
1.47M
        if (float_s == NULL) {
2693
0
            return -1;
2694
0
        }
2695
1.47M
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2696
1.47M
    }
2697
2698
1.47M
    if (ns_index >= 0) {
2699
1.47M
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2700
1.47M
        if (ns_total == NULL) {
2701
0
            return -1;
2702
0
        }
2703
1.47M
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2704
1.47M
    }
2705
2706
1.47M
    assert(!PyErr_Occurred());
2707
1.47M
    return 0;
2708
1.47M
}
2709
#undef SEC_TO_NS
2710
2711
#ifdef MS_WINDOWS
2712
static PyObject*
2713
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2714
{
2715
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2716
    if (!o_low || !high) {
2717
        return o_low;
2718
    }
2719
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2720
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2721
    if (!l64) {
2722
        Py_XDECREF(o_high);
2723
        Py_DECREF(o_low);
2724
        return NULL;
2725
    }
2726
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2727
    Py_DECREF(l64);
2728
    if (!o_high) {
2729
        Py_DECREF(o_low);
2730
        return NULL;
2731
    }
2732
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2733
    Py_DECREF(o_high);
2734
    return o_low;
2735
}
2736
#endif
2737
2738
/* pack a system stat C structure into the Python stat tuple
2739
   (used by posix_stat() and posix_fstat()) */
2740
static PyObject*
2741
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2742
491k
{
2743
491k
    assert(!PyErr_Occurred());
2744
2745
491k
    _posixstate *state = get_posix_state(module);
2746
491k
    PyObject *StatResultType = state->StatResultType;
2747
491k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2748
491k
    if (v == NULL) {
2749
0
        return NULL;
2750
0
    }
2751
2752
491k
#define SET_ITEM(pos, expr) \
2753
4.91M
    do { \
2754
4.91M
        PyObject *obj = (expr); \
2755
4.91M
        if (obj == NULL) { \
2756
0
            goto error; \
2757
0
        } \
2758
4.91M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2759
4.91M
    } while (0)
2760
2761
491k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2762
#ifdef MS_WINDOWS
2763
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2764
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2765
#else
2766
491k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2767
491k
                  "stat.st_ino is larger than unsigned long long");
2768
491k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2769
491k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2770
491k
#endif
2771
491k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2772
#if defined(MS_WINDOWS)
2773
    SET_ITEM(4, PyLong_FromLong(0));
2774
    SET_ITEM(5, PyLong_FromLong(0));
2775
#else
2776
491k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2777
491k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2778
491k
#endif
2779
491k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2780
491k
                  "stat.st_size is larger than long long");
2781
491k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2782
2783
    // Set st_atime, st_mtime and st_ctime
2784
491k
    unsigned long ansec, mnsec, cnsec;
2785
491k
#if defined(HAVE_STAT_TV_NSEC)
2786
491k
    ansec = st->st_atim.tv_nsec;
2787
491k
    mnsec = st->st_mtim.tv_nsec;
2788
491k
    cnsec = st->st_ctim.tv_nsec;
2789
#elif defined(HAVE_STAT_TV_NSEC2)
2790
    ansec = st->st_atimespec.tv_nsec;
2791
    mnsec = st->st_mtimespec.tv_nsec;
2792
    cnsec = st->st_ctimespec.tv_nsec;
2793
#elif defined(HAVE_STAT_NSEC)
2794
    ansec = st->st_atime_nsec;
2795
    mnsec = st->st_mtime_nsec;
2796
    cnsec = st->st_ctime_nsec;
2797
#else
2798
    ansec = mnsec = cnsec = 0;
2799
#endif
2800
491k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2801
0
        goto error;
2802
0
    }
2803
491k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2804
0
        goto error;
2805
0
    }
2806
491k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2807
0
        goto error;
2808
0
    }
2809
2810
491k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2811
491k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2812
491k
#endif
2813
491k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2814
491k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2815
491k
#endif
2816
491k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2817
491k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2818
491k
#endif
2819
#ifdef HAVE_STRUCT_STAT_ST_GEN
2820
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2821
#endif
2822
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2823
    {
2824
      unsigned long bsec, bnsec;
2825
      bsec = (long)st->st_birthtime;
2826
#ifdef HAVE_STAT_TV_NSEC2
2827
      bnsec = st->st_birthtimespec.tv_nsec;
2828
#else
2829
      bnsec = 0;
2830
#endif
2831
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2832
    }
2833
#elif defined(MS_WINDOWS)
2834
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2835
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2836
        goto error;
2837
    }
2838
#endif
2839
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2840
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2841
#endif
2842
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2843
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2844
             PyLong_FromUnsignedLong(st->st_file_attributes));
2845
#endif
2846
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2847
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2848
#endif
2849
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2850
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2851
#endif
2852
2853
491k
    assert(!PyErr_Occurred());
2854
491k
    return v;
2855
2856
0
error:
2857
0
    Py_DECREF(v);
2858
0
    return NULL;
2859
2860
491k
#undef SET_ITEM
2861
491k
}
2862
2863
/* POSIX methods */
2864
2865
2866
static PyObject *
2867
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2868
              int dir_fd, int follow_symlinks)
2869
382k
{
2870
382k
    STRUCT_STAT st;
2871
382k
    int result;
2872
2873
382k
#ifdef HAVE_FSTATAT
2874
382k
    int fstatat_unavailable = 0;
2875
382k
#endif
2876
2877
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2878
    if (follow_symlinks_specified(function_name, follow_symlinks))
2879
        return NULL;
2880
#endif
2881
2882
382k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2883
382k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2884
382k
        fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
2885
0
        return NULL;
2886
2887
382k
    Py_BEGIN_ALLOW_THREADS
2888
382k
    if (path->is_fd) {
2889
0
        result = FSTAT(path->fd, &st);
2890
0
    }
2891
#ifdef MS_WINDOWS
2892
    else if (follow_symlinks)
2893
        result = win32_stat(path->wide, &st);
2894
    else
2895
        result = win32_lstat(path->wide, &st);
2896
#else
2897
382k
    else
2898
382k
#if defined(HAVE_LSTAT)
2899
382k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2900
9.18k
        result = LSTAT(path->narrow, &st);
2901
373k
    else
2902
373k
#endif /* HAVE_LSTAT */
2903
373k
#ifdef HAVE_FSTATAT
2904
373k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2905
0
        if (HAVE_FSTATAT_RUNTIME) {
2906
0
            result = fstatat(dir_fd, path->narrow, &st,
2907
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2908
2909
0
        } else {
2910
0
            fstatat_unavailable = 1;
2911
0
        }
2912
0
    } else
2913
373k
#endif /* HAVE_FSTATAT */
2914
373k
        result = STAT(path->narrow, &st);
2915
382k
#endif /* MS_WINDOWS */
2916
382k
    Py_END_ALLOW_THREADS
2917
2918
382k
#ifdef HAVE_FSTATAT
2919
382k
    if (fstatat_unavailable) {
2920
0
        argument_unavailable_error("stat", "dir_fd");
2921
0
        return NULL;
2922
0
    }
2923
382k
#endif
2924
2925
382k
    if (result != 0) {
2926
314k
        return path_error(path);
2927
314k
    }
2928
2929
68.0k
    return _pystat_fromstructstat(module, &st);
2930
382k
}
2931
2932
/*[python input]
2933
2934
for s in """
2935
2936
FACCESSAT
2937
FCHMODAT
2938
FCHOWNAT
2939
FSTATAT
2940
LINKAT
2941
MKDIRAT
2942
MKFIFOAT
2943
MKNODAT
2944
OPENAT
2945
READLINKAT
2946
SYMLINKAT
2947
UNLINKAT
2948
2949
""".strip().split():
2950
    s = s.strip()
2951
    print("""
2952
#ifdef HAVE_{s}
2953
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2954
#else
2955
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2956
#endif
2957
""".rstrip().format(s=s))
2958
2959
for s in """
2960
2961
FCHDIR
2962
FCHMOD
2963
FCHOWN
2964
FDOPENDIR
2965
FEXECVE
2966
FPATHCONF
2967
FSTATVFS
2968
FTRUNCATE
2969
2970
""".strip().split():
2971
    s = s.strip()
2972
    print("""
2973
#ifdef HAVE_{s}
2974
    #define PATH_HAVE_{s} 1
2975
#else
2976
    #define PATH_HAVE_{s} 0
2977
#endif
2978
2979
""".rstrip().format(s=s))
2980
[python start generated code]*/
2981
2982
#ifdef HAVE_FACCESSAT
2983
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2984
#else
2985
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2986
#endif
2987
2988
#ifdef HAVE_FCHMODAT
2989
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2990
#else
2991
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2992
#endif
2993
2994
#ifdef HAVE_FCHOWNAT
2995
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2996
#else
2997
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2998
#endif
2999
3000
#ifdef HAVE_FSTATAT
3001
8.95k
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
3002
#else
3003
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
3004
#endif
3005
3006
#ifdef HAVE_LINKAT
3007
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
3008
#else
3009
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3010
#endif
3011
3012
#ifdef HAVE_MKDIRAT
3013
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3014
#else
3015
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3016
#endif
3017
3018
#ifdef HAVE_MKFIFOAT
3019
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3020
#else
3021
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3022
#endif
3023
3024
#ifdef HAVE_MKNODAT
3025
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3026
#else
3027
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3028
#endif
3029
3030
#ifdef HAVE_OPENAT
3031
213k
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3032
#else
3033
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3034
#endif
3035
3036
#ifdef HAVE_READLINKAT
3037
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3038
#else
3039
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3040
#endif
3041
3042
#ifdef HAVE_SYMLINKAT
3043
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3044
#else
3045
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3046
#endif
3047
3048
#ifdef HAVE_UNLINKAT
3049
239k
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3050
#else
3051
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3052
#endif
3053
3054
#ifdef HAVE_FCHDIR
3055
    #define PATH_HAVE_FCHDIR 1
3056
#else
3057
    #define PATH_HAVE_FCHDIR 0
3058
#endif
3059
3060
#ifdef HAVE_FCHMOD
3061
    #define PATH_HAVE_FCHMOD 1
3062
#else
3063
    #define PATH_HAVE_FCHMOD 0
3064
#endif
3065
3066
#ifdef HAVE_FCHOWN
3067
    #define PATH_HAVE_FCHOWN 1
3068
#else
3069
    #define PATH_HAVE_FCHOWN 0
3070
#endif
3071
3072
#ifdef HAVE_FDOPENDIR
3073
    #define PATH_HAVE_FDOPENDIR 1
3074
#else
3075
    #define PATH_HAVE_FDOPENDIR 0
3076
#endif
3077
3078
#ifdef HAVE_FEXECVE
3079
    #define PATH_HAVE_FEXECVE 1
3080
#else
3081
    #define PATH_HAVE_FEXECVE 0
3082
#endif
3083
3084
#ifdef HAVE_FPATHCONF
3085
    #define PATH_HAVE_FPATHCONF 1
3086
#else
3087
    #define PATH_HAVE_FPATHCONF 0
3088
#endif
3089
3090
#ifdef HAVE_FSTATVFS
3091
    #define PATH_HAVE_FSTATVFS 1
3092
#else
3093
    #define PATH_HAVE_FSTATVFS 0
3094
#endif
3095
3096
#ifdef HAVE_FTRUNCATE
3097
    #define PATH_HAVE_FTRUNCATE 1
3098
#else
3099
    #define PATH_HAVE_FTRUNCATE 0
3100
#endif
3101
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3102
3103
#ifdef MS_WINDOWS
3104
    #undef PATH_HAVE_FTRUNCATE
3105
    #define PATH_HAVE_FTRUNCATE 1
3106
    #undef PATH_HAVE_FCHMOD
3107
    #define PATH_HAVE_FCHMOD 1
3108
#endif
3109
3110
/*[python input]
3111
3112
class path_t_converter(CConverter):
3113
3114
    type = "path_t"
3115
    impl_by_reference = True
3116
    parse_by_reference = True
3117
    default_type = ()
3118
    c_init_default = "<placeholder>"  # overridden in pre_render(()
3119
3120
    converter = 'path_converter'
3121
3122
    def converter_init(self, *, allow_fd=False, make_wide=None,
3123
                       nonstrict=False, nullable=False,
3124
                       suppress_value_error=False):
3125
3126
        self.nullable = nullable
3127
        self.nonstrict = nonstrict
3128
        self.make_wide = make_wide
3129
        self.suppress_value_error = suppress_value_error
3130
        self.allow_fd = allow_fd
3131
        if nullable:
3132
            self.default_type = NoneType
3133
3134
    def pre_render(self):
3135
        def strify(value):
3136
            if isinstance(value, str):
3137
                return value
3138
            return str(int(bool(value)))
3139
3140
        # add self.py_name here when merging with posixmodule conversion
3141
        if self.make_wide is None:
3142
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3143
                self.function.name,
3144
                self.name,
3145
                strify(self.nullable),
3146
                strify(self.nonstrict),
3147
                strify(self.suppress_value_error),
3148
                strify(self.allow_fd),
3149
            )
3150
        else:
3151
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3152
                self.function.name,
3153
                self.name,
3154
                strify(self.nullable),
3155
                strify(self.nonstrict),
3156
                strify(self.make_wide),
3157
                strify(self.suppress_value_error),
3158
                strify(self.allow_fd),
3159
            )
3160
3161
    def cleanup(self):
3162
        return "path_cleanup(&" + self.name + ");\n"
3163
3164
3165
class dir_fd_converter(CConverter):
3166
    type = 'int'
3167
    default_type = NoneType
3168
    c_init_default = 'DEFAULT_DIR_FD'
3169
3170
    def converter_init(self, requires=None):
3171
        if self.default in (unspecified, None):
3172
            self.c_default = 'DEFAULT_DIR_FD'
3173
        if isinstance(requires, str):
3174
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3175
        else:
3176
            self.converter = 'dir_fd_converter'
3177
3178
    def c_default_init(self):
3179
        self.c_default = 'DEFAULT_DIR_FD'
3180
3181
class uid_t_converter(CConverter):
3182
    type = "uid_t"
3183
    converter = '_Py_Uid_Converter'
3184
3185
class gid_t_converter(CConverter):
3186
    type = "gid_t"
3187
    converter = '_Py_Gid_Converter'
3188
3189
class dev_t_converter(CConverter):
3190
    type = 'dev_t'
3191
    converter = '_Py_Dev_Converter'
3192
3193
class dev_t_return_converter(unsigned_long_return_converter):
3194
    type = 'dev_t'
3195
    conversion_fn = '_PyLong_FromDev'
3196
    unsigned_cast = '(dev_t)'
3197
3198
class pid_t_converter(CConverter):
3199
    type = 'pid_t'
3200
    format_unit = '" _Py_PARSE_PID "'
3201
3202
    def parse_arg(self, argname, displayname, *, limited_capi):
3203
        return self.format_code("""
3204
            {paramname} = PyLong_AsPid({argname});
3205
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3206
                goto exit;
3207
            }}}}
3208
            """, argname=argname)
3209
3210
class idtype_t_converter(CConverter):
3211
    type = 'idtype_t'
3212
    converter = 'idtype_t_converter'
3213
3214
class id_t_converter(CConverter):
3215
    type = 'id_t'
3216
    format_unit = '" _Py_PARSE_PID "'
3217
3218
    def parse_arg(self, argname, displayname, *, limited_capi):
3219
        return self.format_code("""
3220
            {paramname} = (id_t)PyLong_AsPid({argname});
3221
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3222
                goto exit;
3223
            }}}}
3224
            """, argname=argname)
3225
3226
class intptr_t_converter(CConverter):
3227
    type = 'intptr_t'
3228
    format_unit = '" _Py_PARSE_INTPTR "'
3229
3230
    def parse_arg(self, argname, displayname, *, limited_capi):
3231
        return self.format_code("""
3232
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3233
            if (!{paramname} && PyErr_Occurred()) {{{{
3234
                goto exit;
3235
            }}}}
3236
            """, argname=argname)
3237
3238
class Py_off_t_converter(CConverter):
3239
    type = 'Py_off_t'
3240
    converter = 'Py_off_t_converter'
3241
3242
class Py_off_t_return_converter(long_return_converter):
3243
    type = 'Py_off_t'
3244
    conversion_fn = 'PyLong_FromPy_off_t'
3245
3246
class confname_converter(CConverter):
3247
    type="int"
3248
    converter="conv_confname"
3249
3250
    def converter_init(self, *, table):
3251
        self.table = table
3252
3253
    def parse_arg(self, argname, displayname, *, limited_capi):
3254
        return self.format_code("""
3255
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3256
                goto exit;
3257
            }}}}
3258
        """, argname=argname, converter=self.converter, table=self.table)
3259
3260
[python start generated code]*/
3261
/*[python end generated code: output=da39a3ee5e6b4b0d input=d58f18bdf3bd3565]*/
3262
3263
/*[clinic input]
3264
3265
os.stat
3266
3267
    path : path_t(allow_fd=True)
3268
        Path to be examined; can be string, bytes, a path-like object or
3269
        open-file-descriptor int.
3270
3271
    *
3272
3273
    dir_fd : dir_fd(requires='fstatat') = None
3274
        If not None, it should be a file descriptor open to a directory,
3275
        and path should be a relative string; path will then be relative to
3276
        that directory.
3277
3278
    follow_symlinks: bool = True
3279
        If False, and the last element of the path is a symbolic link,
3280
        stat will examine the symbolic link itself instead of the file
3281
        the link points to.
3282
3283
Perform a stat system call on the given path.
3284
3285
dir_fd and follow_symlinks may not be implemented
3286
  on your platform.  If they are unavailable, using them will raise a
3287
  NotImplementedError.
3288
3289
It's an error to use dir_fd or follow_symlinks when specifying path as
3290
  an open file descriptor.
3291
3292
[clinic start generated code]*/
3293
3294
static PyObject *
3295
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3296
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3297
373k
{
3298
373k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3299
373k
}
3300
3301
3302
/*[clinic input]
3303
@permit_long_summary
3304
os.lstat
3305
3306
    path : path_t
3307
3308
    *
3309
3310
    dir_fd : dir_fd(requires='fstatat') = None
3311
3312
Perform a stat system call on the given path, without following symbolic links.
3313
3314
Like stat(), but do not follow symbolic links.
3315
Equivalent to stat(path, follow_symlinks=False).
3316
[clinic start generated code]*/
3317
3318
static PyObject *
3319
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3320
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3321
9.18k
{
3322
9.18k
    int follow_symlinks = 0;
3323
9.18k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3324
9.18k
}
3325
3326
3327
#ifdef HAVE_STATX
3328
typedef struct {
3329
    PyObject_HEAD
3330
    dev_t rdev, dev;
3331
    struct statx stx;
3332
} Py_statx_result;
3333
3334
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3335
3336
#define M(attr, type, offset, doc) \
3337
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3338
#define MM(attr, type, member, doc) \
3339
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3340
#define MX(attr, type, member, doc) \
3341
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3342
3343
static PyMemberDef pystatx_result_members[] = {
3344
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3345
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3346
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3347
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3348
        "Mask of supported bits in stx_attributes"),
3349
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3350
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3351
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3352
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3353
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3354
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3355
    {NULL},
3356
};
3357
3358
#undef MX
3359
#undef MM
3360
#undef M
3361
3362
3363
#define STATX_GET_UINT(ATTR, MASK) \
3364
    static PyObject* \
3365
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3366
0
    { \
3367
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3368
0
        if (!(self->stx.stx_mask & MASK)) { \
3369
0
            Py_RETURN_NONE; \
3370
0
        } \
3371
0
        unsigned long value = self->stx.ATTR; \
3372
0
        return PyLong_FromUnsignedLong(value); \
3373
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
3374
3375
STATX_GET_UINT(stx_uid, STATX_UID)
3376
STATX_GET_UINT(stx_gid, STATX_GID)
3377
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3378
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3379
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3380
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3381
#endif
3382
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3383
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3384
#endif
3385
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3386
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3387
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3388
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3389
#endif
3390
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3391
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3392
#endif
3393
3394
3395
static PyObject*
3396
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3397
0
{
3398
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3399
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3400
0
        Py_RETURN_NONE;
3401
0
    }
3402
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3403
0
}
3404
3405
3406
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3407
    static PyObject* \
3408
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3409
0
    { \
3410
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3411
0
        if (!(self->stx.stx_mask & MASK)) { \
3412
0
            Py_RETURN_NONE; \
3413
0
        } \
3414
0
        unsigned long long value = self->stx.ATTR; \
3415
0
        return PyLong_FromUnsignedLongLong(value); \
3416
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
3417
3418
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3419
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3420
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3421
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3422
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3423
#endif
3424
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3425
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3426
#endif
3427
3428
3429
#define STATX_GET_DOUBLE(ATTR, MASK) \
3430
    static PyObject* \
3431
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3432
0
    { \
3433
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3434
0
        if (!(self->stx.stx_mask & MASK)) { \
3435
0
            Py_RETURN_NONE; \
3436
0
        } \
3437
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3438
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3439
0
        return PyFloat_FromDouble(sec); \
3440
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
3441
3442
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3443
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3444
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3445
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3446
3447
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3448
    static PyObject* \
3449
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3450
0
    { \
3451
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3452
0
        if (!(self->stx.stx_mask & MASK)) { \
3453
0
            Py_RETURN_NONE; \
3454
0
        } \
3455
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3456
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3457
0
        assert(state != NULL); \
3458
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3459
0
    }
3460
3461
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3462
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3463
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3464
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3465
3466
#define G(attr, doc) \
3467
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3468
3469
static PyGetSetDef pystatx_result_getset[] = {
3470
    G(stx_mode, "protection bits"),
3471
    G(stx_nlink, "number of hard links"),
3472
    G(stx_uid, "user ID of owner"),
3473
    G(stx_gid, "group ID of owner"),
3474
    G(stx_ino, "inode"),
3475
    G(stx_size, "total size, in bytes"),
3476
    G(stx_blocks, "number of blocks allocated"),
3477
    G(stx_atime, "time of last access"),
3478
    G(stx_atime_ns, "time of last access in nanoseconds"),
3479
    G(stx_btime, "time of creation"),
3480
    G(stx_btime_ns, "time of creation in nanoseconds"),
3481
    G(stx_ctime, "time of last change"),
3482
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3483
    G(stx_mtime, "time of last modification"),
3484
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3485
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3486
    G(stx_mnt_id, "mount ID"),
3487
#endif
3488
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3489
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3490
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3491
#endif
3492
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3493
    G(stx_subvol, "subvolume ID"),
3494
#endif
3495
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3496
    G(stx_atomic_write_unit_min,
3497
      "minimum size for direct I/O with torn-write protection"),
3498
    G(stx_atomic_write_unit_max,
3499
        "maximum size for direct I/O with torn-write protection"),
3500
    G(stx_atomic_write_segments_max,
3501
        "maximum iovecs for direct I/O with torn-write protection"),
3502
#endif
3503
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3504
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3505
#endif
3506
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3507
    G(stx_atomic_write_unit_max_opt,
3508
        "maximum optimized size for direct I/O with torn-write protection"),
3509
#endif
3510
    {NULL},
3511
};
3512
3513
#undef G
3514
3515
static PyObject *
3516
pystatx_result_repr(PyObject *op)
3517
0
{
3518
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3519
0
    if (writer == NULL) {
3520
0
        return NULL;
3521
0
    }
3522
0
#define WRITE_ASCII(s) \
3523
0
    do { \
3524
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3525
0
            goto error; \
3526
0
        } \
3527
0
    } while (0)
3528
3529
0
    WRITE_ASCII("os.statx_result(");
3530
3531
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3532
0
        if (i > 0) {
3533
0
            WRITE_ASCII(", ");
3534
0
        }
3535
3536
0
        PyMemberDef *d = &pystatx_result_members[i];
3537
0
        WRITE_ASCII(d->name);
3538
0
        WRITE_ASCII("=");
3539
3540
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3541
0
        if (o == NULL) {
3542
0
            goto error;
3543
0
        }
3544
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3545
0
            Py_DECREF(o);
3546
0
            goto error;
3547
0
        }
3548
0
        Py_DECREF(o);
3549
0
    }
3550
3551
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3552
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3553
0
        PyObject *o = d->get(op, d->closure);
3554
0
        if (o == NULL) {
3555
0
            goto error;
3556
0
        }
3557
0
        if (o == Py_None) {
3558
0
            continue;
3559
0
        }
3560
3561
0
        WRITE_ASCII(", ");
3562
0
        WRITE_ASCII(d->name);
3563
0
        WRITE_ASCII("=");
3564
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3565
0
            Py_DECREF(o);
3566
0
            goto error;
3567
0
        }
3568
0
        Py_DECREF(o);
3569
0
    }
3570
3571
0
    WRITE_ASCII(")");
3572
0
    return PyUnicodeWriter_Finish(writer);
3573
0
#undef WRITE_ASCII
3574
3575
0
error:
3576
0
    PyUnicodeWriter_Discard(writer);
3577
0
    return NULL;
3578
0
}
3579
3580
static int
3581
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3582
0
{
3583
0
    Py_VISIT(Py_TYPE(self));
3584
0
    return 0;
3585
0
}
3586
3587
static void
3588
pystatx_result_dealloc(PyObject *op)
3589
0
{
3590
0
    Py_statx_result *self = (Py_statx_result *) op;
3591
0
    PyTypeObject *tp = Py_TYPE(self);
3592
0
    PyObject_GC_UnTrack(self);
3593
0
    tp->tp_free(self);
3594
0
    Py_DECREF(tp);
3595
0
}
3596
3597
static PyType_Slot pystatx_result_slots[] = {
3598
    {Py_tp_repr, pystatx_result_repr},
3599
    {Py_tp_traverse, pystatx_result_traverse},
3600
    {Py_tp_dealloc, pystatx_result_dealloc},
3601
    {Py_tp_members, pystatx_result_members},
3602
    {Py_tp_getset, pystatx_result_getset},
3603
    {0, NULL},
3604
};
3605
3606
static PyType_Spec pystatx_result_spec = {
3607
    .name = "os.statx_result",
3608
    .basicsize = sizeof(Py_statx_result),
3609
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3610
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3611
    .slots = pystatx_result_slots,
3612
};
3613
3614
/*[clinic input]
3615
3616
os.statx
3617
3618
    path : path_t(allow_fd=True)
3619
        Path to be examined; can be string, bytes, a path-like object or
3620
        open-file-descriptor int.
3621
3622
    mask: unsigned_int(bitwise=True)
3623
        A bitmask of STATX_* constants defining the requested information.
3624
3625
    *
3626
3627
    flags: int = 0
3628
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3629
3630
    dir_fd : dir_fd = None
3631
        If not None, it should be a file descriptor open to a directory,
3632
        and path should be a relative string; path will then be relative to
3633
        that directory.
3634
3635
    follow_symlinks: bool = True
3636
        If False, and the last element of the path is a symbolic link,
3637
        statx will examine the symbolic link itself instead of the file
3638
        the link points to.
3639
3640
Perform a statx system call on the given path.
3641
3642
It's an error to use dir_fd or follow_symlinks when specifying path as
3643
  an open file descriptor.
3644
3645
[clinic start generated code]*/
3646
3647
static PyObject *
3648
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3649
              int dir_fd, int follow_symlinks)
3650
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3651
0
{
3652
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3653
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3654
0
        fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) {
3655
0
        return NULL;
3656
0
    }
3657
3658
    /* reject flags covered by kwargs, but allow unknown flags that may be
3659
       future AT_STATX_* extensions */
3660
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3661
0
        PyErr_Format(PyExc_ValueError,
3662
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3663
0
        return NULL;
3664
0
    }
3665
0
    if (flags & AT_EMPTY_PATH) {
3666
0
        PyErr_Format(PyExc_ValueError,
3667
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3668
0
        return NULL;
3669
0
    }
3670
3671
    /* Future bits may refer to members beyond the current size of struct
3672
       statx, so we need to mask them off to prevent memory corruption. */
3673
0
    mask &= _Py_STATX_KNOWN;
3674
3675
0
    _posixstate *state = get_posix_state(module);
3676
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3677
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3678
0
    if (v == NULL) {
3679
0
        return NULL;
3680
0
    }
3681
3682
0
    int result;
3683
0
    Py_BEGIN_ALLOW_THREADS
3684
0
    if (path->is_fd) {
3685
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3686
0
    }
3687
0
    else {
3688
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3689
0
    }
3690
0
    Py_END_ALLOW_THREADS
3691
3692
0
    if (result != 0) {
3693
0
        Py_DECREF(v);
3694
0
        return path_error(path);
3695
0
    }
3696
3697
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3698
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3699
3700
0
    assert(!PyErr_Occurred());
3701
0
    return (PyObject *)v;
3702
0
}
3703
#endif /* HAVE_STATX */
3704
3705
3706
/*[clinic input]
3707
os.access -> bool
3708
3709
    path: path_t
3710
        Path to be tested; can be string, bytes, or a path-like object.
3711
3712
    mode: int
3713
        Operating-system mode bitfield.  Can be F_OK to test existence,
3714
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3715
3716
    *
3717
3718
    dir_fd : dir_fd(requires='faccessat') = None
3719
        If not None, it should be a file descriptor open to a directory,
3720
        and path should be relative; path will then be relative to that
3721
        directory.
3722
3723
    effective_ids: bool = False
3724
        If True, access will use the effective uid/gid instead of
3725
        the real uid/gid.
3726
3727
    follow_symlinks: bool = True
3728
        If False, and the last element of the path is a symbolic link,
3729
        access will examine the symbolic link itself instead of the file
3730
        the link points to.
3731
3732
Use the real uid/gid to test for access to a path.
3733
3734
{parameters}
3735
dir_fd, effective_ids, and follow_symlinks may not be implemented
3736
  on your platform.  If they are unavailable, using them will raise a
3737
  NotImplementedError.
3738
3739
Note that most operations will use the effective uid/gid, therefore this
3740
  routine can be used in a suid/sgid environment to test if the invoking
3741
  user has the specified access to the path.
3742
3743
[clinic start generated code]*/
3744
3745
static int
3746
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3747
               int effective_ids, int follow_symlinks)
3748
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3749
0
{
3750
0
    int return_value;
3751
3752
#ifdef MS_WINDOWS
3753
    DWORD attr;
3754
#else
3755
0
    int result;
3756
0
#endif
3757
3758
0
#ifdef HAVE_FACCESSAT
3759
0
    int faccessat_unavailable = 0;
3760
0
#endif
3761
3762
#ifndef HAVE_FACCESSAT
3763
    if (follow_symlinks_specified("access", follow_symlinks))
3764
        return -1;
3765
3766
    if (effective_ids) {
3767
        argument_unavailable_error("access", "effective_ids");
3768
        return -1;
3769
    }
3770
#endif
3771
3772
#ifdef MS_WINDOWS
3773
    Py_BEGIN_ALLOW_THREADS
3774
    attr = GetFileAttributesW(path->wide);
3775
    Py_END_ALLOW_THREADS
3776
3777
    /*
3778
     * Access is possible if
3779
     *   * we didn't get a -1, and
3780
     *     * write access wasn't requested,
3781
     *     * or the file isn't read-only,
3782
     *     * or it's a directory.
3783
     * (Directories cannot be read-only on Windows.)
3784
    */
3785
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3786
            (!(mode & 2) ||
3787
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3788
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3789
#else
3790
3791
0
    Py_BEGIN_ALLOW_THREADS
3792
0
#ifdef HAVE_FACCESSAT
3793
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3794
0
        effective_ids ||
3795
0
        !follow_symlinks) {
3796
3797
0
        if (HAVE_FACCESSAT_RUNTIME) {
3798
0
            int flags = 0;
3799
0
            if (!follow_symlinks)
3800
0
                flags |= AT_SYMLINK_NOFOLLOW;
3801
0
            if (effective_ids)
3802
0
                flags |= AT_EACCESS;
3803
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3804
0
        } else {
3805
0
            faccessat_unavailable = 1;
3806
0
        }
3807
0
    }
3808
0
    else
3809
0
#endif
3810
0
        result = access(path->narrow, mode);
3811
0
    Py_END_ALLOW_THREADS
3812
3813
0
#ifdef HAVE_FACCESSAT
3814
0
    if (faccessat_unavailable) {
3815
0
        if (dir_fd != DEFAULT_DIR_FD) {
3816
0
            argument_unavailable_error("access", "dir_fd");
3817
0
            return -1;
3818
0
        }
3819
0
        if (follow_symlinks_specified("access", follow_symlinks))
3820
0
            return -1;
3821
3822
0
        if (effective_ids) {
3823
0
            argument_unavailable_error("access", "effective_ids");
3824
0
            return -1;
3825
0
        }
3826
        /* should be unreachable */
3827
0
        return -1;
3828
0
    }
3829
0
#endif
3830
0
    return_value = !result;
3831
0
#endif
3832
3833
0
    return return_value;
3834
0
}
3835
3836
#ifndef F_OK
3837
#define F_OK 0
3838
#endif
3839
#ifndef R_OK
3840
#define R_OK 4
3841
#endif
3842
#ifndef W_OK
3843
#define W_OK 2
3844
#endif
3845
#ifndef X_OK
3846
#define X_OK 1
3847
#endif
3848
3849
3850
#ifdef HAVE_TTYNAME_R
3851
/*[clinic input]
3852
os.ttyname
3853
3854
    fd: int
3855
        Integer file descriptor handle.
3856
3857
    /
3858
3859
Return the name of the terminal device connected to 'fd'.
3860
[clinic start generated code]*/
3861
3862
static PyObject *
3863
os_ttyname_impl(PyObject *module, int fd)
3864
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3865
0
{
3866
3867
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3868
0
    if (size == -1) {
3869
0
        return posix_error();
3870
0
    }
3871
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3872
0
    if (buffer == NULL) {
3873
0
        return PyErr_NoMemory();
3874
0
    }
3875
0
    int ret = ttyname_r(fd, buffer, size);
3876
0
    if (ret != 0) {
3877
0
        PyMem_RawFree(buffer);
3878
0
        errno = ret;
3879
0
        return posix_error();
3880
0
    }
3881
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3882
0
    PyMem_RawFree(buffer);
3883
0
    return res;
3884
0
}
3885
#endif
3886
3887
#ifdef HAVE_CTERMID
3888
/*[clinic input]
3889
os.ctermid
3890
3891
Return the name of the controlling terminal for this process.
3892
[clinic start generated code]*/
3893
3894
static PyObject *
3895
os_ctermid_impl(PyObject *module)
3896
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3897
0
{
3898
0
    char *ret;
3899
0
    char buffer[L_ctermid];
3900
3901
#ifdef USE_CTERMID_R
3902
    ret = ctermid_r(buffer);
3903
#else
3904
0
    ret = ctermid(buffer);
3905
0
#endif
3906
0
    if (ret == NULL)
3907
0
        return posix_error();
3908
0
    return PyUnicode_DecodeFSDefault(buffer);
3909
0
}
3910
#endif /* HAVE_CTERMID */
3911
3912
3913
/*[clinic input]
3914
os.chdir
3915
3916
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3917
3918
Change the current working directory to the specified path.
3919
3920
path may always be specified as a string.
3921
On some platforms, path may also be specified as an open file descriptor.
3922
If this functionality is unavailable, using it raises an exception.
3923
[clinic start generated code]*/
3924
3925
static PyObject *
3926
os_chdir_impl(PyObject *module, path_t *path)
3927
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3928
0
{
3929
0
    int result;
3930
3931
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3932
0
        return NULL;
3933
0
    }
3934
3935
0
    Py_BEGIN_ALLOW_THREADS
3936
#ifdef MS_WINDOWS
3937
    /* on unix, success = 0, on windows, success = !0 */
3938
    result = !win32_wchdir(path->wide);
3939
#else
3940
0
#ifdef HAVE_FCHDIR
3941
0
    if (path->is_fd)
3942
0
        result = fchdir(path->fd);
3943
0
    else
3944
0
#endif
3945
0
        result = chdir(path->narrow);
3946
0
#endif
3947
0
    Py_END_ALLOW_THREADS
3948
3949
0
    if (result) {
3950
0
        return path_error(path);
3951
0
    }
3952
3953
0
    Py_RETURN_NONE;
3954
0
}
3955
3956
3957
#ifdef HAVE_FCHDIR
3958
/*[clinic input]
3959
os.fchdir
3960
3961
    fd: fildes
3962
3963
Change to the directory of the given file descriptor.
3964
3965
fd must be opened on a directory, not a file.
3966
Equivalent to os.chdir(fd).
3967
3968
[clinic start generated code]*/
3969
3970
static PyObject *
3971
os_fchdir_impl(PyObject *module, int fd)
3972
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3973
0
{
3974
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3975
0
        return NULL;
3976
0
    }
3977
0
    return posix_fildes_fd(fd, fchdir);
3978
0
}
3979
#endif /* HAVE_FCHDIR */
3980
3981
#ifdef MS_WINDOWS
3982
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3983
#else
3984
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3985
#endif
3986
3987
#ifdef MS_WINDOWS
3988
static int
3989
win32_lchmod(LPCWSTR path, int mode)
3990
{
3991
    DWORD attr = GetFileAttributesW(path);
3992
    if (attr == INVALID_FILE_ATTRIBUTES) {
3993
        return 0;
3994
    }
3995
    if (mode & _S_IWRITE) {
3996
        attr &= ~FILE_ATTRIBUTE_READONLY;
3997
    }
3998
    else {
3999
        attr |= FILE_ATTRIBUTE_READONLY;
4000
    }
4001
    return SetFileAttributesW(path, attr);
4002
}
4003
4004
static int
4005
win32_hchmod(HANDLE hfile, int mode)
4006
{
4007
    FILE_BASIC_INFO info;
4008
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4009
                                      &info, sizeof(info)))
4010
    {
4011
        return 0;
4012
    }
4013
    if (mode & _S_IWRITE) {
4014
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4015
    }
4016
    else {
4017
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4018
    }
4019
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4020
                                      &info, sizeof(info));
4021
}
4022
4023
static int
4024
win32_fchmod(int fd, int mode)
4025
{
4026
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4027
    if (hfile == INVALID_HANDLE_VALUE) {
4028
        SetLastError(ERROR_INVALID_HANDLE);
4029
        return 0;
4030
    }
4031
    return win32_hchmod(hfile, mode);
4032
}
4033
4034
#endif /* MS_WINDOWS */
4035
4036
/*[clinic input]
4037
os.chmod
4038
4039
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4040
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
4041
        On some platforms, path may also be specified as an open file descriptor.
4042
        If this functionality is unavailable, using it raises an exception.
4043
4044
    mode: int
4045
        Operating-system mode bitfield.
4046
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4047
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4048
        Python.
4049
4050
    *
4051
4052
    dir_fd : dir_fd(requires='fchmodat') = None
4053
        If not None, it should be a file descriptor open to a directory,
4054
        and path should be relative; path will then be relative to that
4055
        directory.
4056
4057
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4058
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4059
        If False, and the last element of the path is a symbolic link,
4060
        chmod will modify the symbolic link itself instead of the file
4061
        the link points to.
4062
4063
Change the access permissions of a file.
4064
4065
It is an error to use dir_fd or follow_symlinks when specifying path as
4066
  an open file descriptor.
4067
dir_fd and follow_symlinks may not be implemented on your platform.
4068
  If they are unavailable, using them will raise a NotImplementedError.
4069
4070
[clinic start generated code]*/
4071
4072
static PyObject *
4073
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4074
              int follow_symlinks)
4075
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
4076
0
{
4077
0
    int result;
4078
4079
0
#ifdef HAVE_FCHMODAT
4080
0
    int fchmodat_nofollow_unsupported = 0;
4081
0
    int fchmodat_unsupported = 0;
4082
0
#endif
4083
4084
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4085
    if (follow_symlinks_specified("chmod", follow_symlinks))
4086
        return NULL;
4087
#endif
4088
4089
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4090
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4091
0
        return NULL;
4092
0
    }
4093
4094
#ifdef MS_WINDOWS
4095
    result = 0;
4096
    Py_BEGIN_ALLOW_THREADS
4097
    if (path->is_fd) {
4098
        result = win32_fchmod(path->fd, mode);
4099
    }
4100
    else if (follow_symlinks) {
4101
        HANDLE hfile = CreateFileW(path->wide,
4102
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4103
                                   0, NULL,
4104
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4105
        if (hfile != INVALID_HANDLE_VALUE) {
4106
            result = win32_hchmod(hfile, mode);
4107
            (void)CloseHandle(hfile);
4108
        }
4109
    }
4110
    else {
4111
        result = win32_lchmod(path->wide, mode);
4112
    }
4113
    Py_END_ALLOW_THREADS
4114
    if (!result) {
4115
        return path_error(path);
4116
    }
4117
#else /* MS_WINDOWS */
4118
0
    Py_BEGIN_ALLOW_THREADS
4119
0
#ifdef HAVE_FCHMOD
4120
0
    if (path->is_fd) {
4121
0
        result = fchmod(path->fd, mode);
4122
0
    }
4123
0
    else
4124
0
#endif /* HAVE_CHMOD */
4125
#ifdef HAVE_LCHMOD
4126
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4127
        result = lchmod(path->narrow, mode);
4128
    else
4129
#endif /* HAVE_LCHMOD */
4130
0
#ifdef HAVE_FCHMODAT
4131
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4132
0
        if (HAVE_FCHMODAT_RUNTIME) {
4133
            /*
4134
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4135
             * The documentation specifically shows how to use it,
4136
             * and then says it isn't implemented yet.
4137
             * (true on linux with glibc 2.15, and openindiana 3.x)
4138
             *
4139
             * Once it is supported, os.chmod will automatically
4140
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4141
             * Until then, we need to be careful what exception we raise.
4142
             */
4143
0
            result = fchmodat(dir_fd, path->narrow, mode,
4144
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4145
            /*
4146
             * But wait!  We can't throw the exception without allowing threads,
4147
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4148
             */
4149
0
            fchmodat_nofollow_unsupported =
4150
0
                             result &&
4151
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4152
0
                             !follow_symlinks;
4153
0
        } else {
4154
0
            fchmodat_unsupported = 1;
4155
0
            fchmodat_nofollow_unsupported = 1;
4156
4157
0
            result = -1;
4158
0
        }
4159
0
    }
4160
0
    else
4161
0
#endif /* HAVE_FHCMODAT */
4162
0
    {
4163
0
#ifdef HAVE_CHMOD
4164
0
        result = chmod(path->narrow, mode);
4165
#elif defined(__wasi__)
4166
        // WASI SDK 15.0 does not support chmod.
4167
        // Ignore missing syscall for now.
4168
        result = 0;
4169
#else
4170
        result = -1;
4171
        errno = ENOSYS;
4172
#endif
4173
0
    }
4174
0
    Py_END_ALLOW_THREADS
4175
4176
0
    if (result) {
4177
0
#ifdef HAVE_FCHMODAT
4178
0
        if (fchmodat_unsupported) {
4179
0
            if (dir_fd != DEFAULT_DIR_FD) {
4180
0
                argument_unavailable_error("chmod", "dir_fd");
4181
0
                return NULL;
4182
0
            }
4183
0
        }
4184
4185
0
        if (fchmodat_nofollow_unsupported) {
4186
0
            if (dir_fd != DEFAULT_DIR_FD)
4187
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4188
0
                                                   dir_fd, follow_symlinks);
4189
0
            else
4190
0
                follow_symlinks_specified("chmod", follow_symlinks);
4191
0
            return NULL;
4192
0
        }
4193
0
        else
4194
0
#endif /* HAVE_FCHMODAT */
4195
0
        return path_error(path);
4196
0
    }
4197
0
#endif /* MS_WINDOWS */
4198
4199
0
    Py_RETURN_NONE;
4200
0
}
4201
4202
4203
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4204
/*[clinic input]
4205
os.fchmod
4206
4207
    fd: int
4208
        The file descriptor of the file to be modified.
4209
    mode: int
4210
        Operating-system mode bitfield.
4211
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4212
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4213
        Python.
4214
4215
Change the access permissions of the file given by file descriptor fd.
4216
4217
Equivalent to os.chmod(fd, mode).
4218
[clinic start generated code]*/
4219
4220
static PyObject *
4221
os_fchmod_impl(PyObject *module, int fd, int mode)
4222
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
4223
0
{
4224
0
    int res;
4225
4226
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4227
0
        return NULL;
4228
0
    }
4229
4230
#ifdef MS_WINDOWS
4231
    res = 0;
4232
    Py_BEGIN_ALLOW_THREADS
4233
    res = win32_fchmod(fd, mode);
4234
    Py_END_ALLOW_THREADS
4235
    if (!res) {
4236
        return PyErr_SetFromWindowsErr(0);
4237
    }
4238
#else /* MS_WINDOWS */
4239
0
    int async_err = 0;
4240
0
    do {
4241
0
        Py_BEGIN_ALLOW_THREADS
4242
0
        res = fchmod(fd, mode);
4243
0
        Py_END_ALLOW_THREADS
4244
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4245
0
    if (res != 0)
4246
0
        return (!async_err) ? posix_error() : NULL;
4247
0
#endif /* MS_WINDOWS */
4248
4249
0
    Py_RETURN_NONE;
4250
0
}
4251
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4252
4253
4254
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4255
/*[clinic input]
4256
os.lchmod
4257
4258
    path: path_t
4259
    mode: int
4260
4261
Change the access permissions of a file, without following symbolic links.
4262
4263
If path is a symlink, this affects the link itself rather than the target.
4264
Equivalent to chmod(path, mode, follow_symlinks=False)."
4265
[clinic start generated code]*/
4266
4267
static PyObject *
4268
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4269
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
4270
{
4271
    int res;
4272
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4273
        return NULL;
4274
    }
4275
#ifdef MS_WINDOWS
4276
    Py_BEGIN_ALLOW_THREADS
4277
    res = win32_lchmod(path->wide, mode);
4278
    Py_END_ALLOW_THREADS
4279
    if (!res) {
4280
        path_error(path);
4281
        return NULL;
4282
    }
4283
#else /* MS_WINDOWS */
4284
    Py_BEGIN_ALLOW_THREADS
4285
    res = lchmod(path->narrow, mode);
4286
    Py_END_ALLOW_THREADS
4287
    if (res < 0) {
4288
        path_error(path);
4289
        return NULL;
4290
    }
4291
#endif /* MS_WINDOWS */
4292
    Py_RETURN_NONE;
4293
}
4294
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4295
4296
4297
#ifdef HAVE_CHFLAGS
4298
/*[clinic input]
4299
os.chflags
4300
4301
    path: path_t
4302
    flags: unsigned_long(bitwise=True)
4303
    follow_symlinks: bool=True
4304
4305
Set file flags.
4306
4307
If follow_symlinks is False, and the last element of the path is a symbolic
4308
  link, chflags will change flags on the symbolic link itself instead of the
4309
  file the link points to.
4310
follow_symlinks may not be implemented on your platform.  If it is
4311
unavailable, using it will raise a NotImplementedError.
4312
4313
[clinic start generated code]*/
4314
4315
static PyObject *
4316
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4317
                int follow_symlinks)
4318
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
4319
{
4320
    int result;
4321
4322
#ifndef HAVE_LCHFLAGS
4323
    if (follow_symlinks_specified("chflags", follow_symlinks))
4324
        return NULL;
4325
#endif
4326
4327
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4328
        return NULL;
4329
    }
4330
4331
    Py_BEGIN_ALLOW_THREADS
4332
#ifdef HAVE_LCHFLAGS
4333
    if (!follow_symlinks)
4334
        result = lchflags(path->narrow, flags);
4335
    else
4336
#endif
4337
        result = chflags(path->narrow, flags);
4338
    Py_END_ALLOW_THREADS
4339
4340
    if (result)
4341
        return path_error(path);
4342
4343
    Py_RETURN_NONE;
4344
}
4345
#endif /* HAVE_CHFLAGS */
4346
4347
4348
#ifdef HAVE_LCHFLAGS
4349
/*[clinic input]
4350
os.lchflags
4351
4352
    path: path_t
4353
    flags: unsigned_long(bitwise=True)
4354
4355
Set file flags.
4356
4357
This function will not follow symbolic links.
4358
Equivalent to chflags(path, flags, follow_symlinks=False).
4359
[clinic start generated code]*/
4360
4361
static PyObject *
4362
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4363
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4364
{
4365
    int res;
4366
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4367
        return NULL;
4368
    }
4369
    Py_BEGIN_ALLOW_THREADS
4370
    res = lchflags(path->narrow, flags);
4371
    Py_END_ALLOW_THREADS
4372
    if (res < 0) {
4373
        return path_error(path);
4374
    }
4375
    Py_RETURN_NONE;
4376
}
4377
#endif /* HAVE_LCHFLAGS */
4378
4379
4380
#ifdef HAVE_CHROOT
4381
/*[clinic input]
4382
os.chroot
4383
    path: path_t
4384
4385
Change root directory to path.
4386
4387
[clinic start generated code]*/
4388
4389
static PyObject *
4390
os_chroot_impl(PyObject *module, path_t *path)
4391
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4392
0
{
4393
0
    int res;
4394
0
    Py_BEGIN_ALLOW_THREADS
4395
0
    res = chroot(path->narrow);
4396
0
    Py_END_ALLOW_THREADS
4397
0
    if (res < 0)
4398
0
        return path_error(path);
4399
0
    Py_RETURN_NONE;
4400
0
}
4401
#endif /* HAVE_CHROOT */
4402
4403
4404
#ifdef HAVE_FSYNC
4405
/*[clinic input]
4406
os.fsync
4407
4408
    fd: fildes
4409
4410
Force write of fd to disk.
4411
[clinic start generated code]*/
4412
4413
static PyObject *
4414
os_fsync_impl(PyObject *module, int fd)
4415
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4416
0
{
4417
0
    return posix_fildes_fd(fd, fsync);
4418
0
}
4419
#endif /* HAVE_FSYNC */
4420
4421
4422
#ifdef HAVE_SYNC
4423
/*[clinic input]
4424
os.sync
4425
4426
Force write of everything to disk.
4427
[clinic start generated code]*/
4428
4429
static PyObject *
4430
os_sync_impl(PyObject *module)
4431
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4432
0
{
4433
0
    Py_BEGIN_ALLOW_THREADS
4434
0
    sync();
4435
0
    Py_END_ALLOW_THREADS
4436
0
    Py_RETURN_NONE;
4437
0
}
4438
#endif /* HAVE_SYNC */
4439
4440
4441
#ifdef HAVE_FDATASYNC
4442
#ifdef __hpux
4443
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4444
#endif
4445
4446
/*[clinic input]
4447
os.fdatasync
4448
4449
    fd: fildes
4450
4451
Force write of fd to disk without forcing update of metadata.
4452
[clinic start generated code]*/
4453
4454
static PyObject *
4455
os_fdatasync_impl(PyObject *module, int fd)
4456
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4457
0
{
4458
0
    return posix_fildes_fd(fd, fdatasync);
4459
0
}
4460
#endif /* HAVE_FDATASYNC */
4461
4462
4463
#ifdef HAVE_CHOWN
4464
/*[clinic input]
4465
os.chown
4466
4467
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4468
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4469
4470
    uid: uid_t
4471
4472
    gid: gid_t
4473
4474
    *
4475
4476
    dir_fd : dir_fd(requires='fchownat') = None
4477
        If not None, it should be a file descriptor open to a directory,
4478
        and path should be relative; path will then be relative to that
4479
        directory.
4480
4481
    follow_symlinks: bool = True
4482
        If False, and the last element of the path is a symbolic link,
4483
        stat will examine the symbolic link itself instead of the file
4484
        the link points to.
4485
4486
Change the owner and group id of path to the numeric uid and gid.\
4487
4488
path may always be specified as a string.
4489
On some platforms, path may also be specified as an open file descriptor.
4490
  If this functionality is unavailable, using it raises an exception.
4491
If dir_fd is not None, it should be a file descriptor open to a directory,
4492
  and path should be relative; path will then be relative to that directory.
4493
If follow_symlinks is False, and the last element of the path is a symbolic
4494
  link, chown will modify the symbolic link itself instead of the file the
4495
  link points to.
4496
It is an error to use dir_fd or follow_symlinks when specifying path as
4497
  an open file descriptor.
4498
dir_fd and follow_symlinks may not be implemented on your platform.
4499
  If they are unavailable, using them will raise a NotImplementedError.
4500
4501
[clinic start generated code]*/
4502
4503
static PyObject *
4504
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4505
              int dir_fd, int follow_symlinks)
4506
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4507
0
{
4508
0
    int result;
4509
4510
0
#if defined(HAVE_FCHOWNAT)
4511
0
    int fchownat_unsupported = 0;
4512
0
#endif
4513
4514
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4515
    if (follow_symlinks_specified("chown", follow_symlinks))
4516
        return NULL;
4517
#endif
4518
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4519
0
        fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
4520
0
        return NULL;
4521
4522
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4523
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4524
0
        return NULL;
4525
0
    }
4526
4527
0
    Py_BEGIN_ALLOW_THREADS
4528
0
#ifdef HAVE_FCHOWN
4529
0
    if (path->is_fd)
4530
0
        result = fchown(path->fd, uid, gid);
4531
0
    else
4532
0
#endif
4533
0
#ifdef HAVE_LCHOWN
4534
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4535
0
        result = lchown(path->narrow, uid, gid);
4536
0
    else
4537
0
#endif
4538
0
#ifdef HAVE_FCHOWNAT
4539
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4540
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4541
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4542
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4543
0
      } else {
4544
0
         fchownat_unsupported = 1;
4545
0
      }
4546
0
    } else
4547
0
#endif
4548
0
        result = chown(path->narrow, uid, gid);
4549
0
    Py_END_ALLOW_THREADS
4550
4551
0
#ifdef HAVE_FCHOWNAT
4552
0
    if (fchownat_unsupported) {
4553
        /* This would be incorrect if the current platform
4554
         * doesn't support lchown.
4555
         */
4556
0
        argument_unavailable_error(NULL, "dir_fd");
4557
0
        return NULL;
4558
0
    }
4559
0
#endif
4560
4561
0
    if (result)
4562
0
        return path_error(path);
4563
4564
0
    Py_RETURN_NONE;
4565
0
}
4566
#endif /* HAVE_CHOWN */
4567
4568
4569
#ifdef HAVE_FCHOWN
4570
/*[clinic input]
4571
os.fchown
4572
4573
    fd: int
4574
    uid: uid_t
4575
    gid: gid_t
4576
4577
Change the owner and group id of the file specified by file descriptor.
4578
4579
Equivalent to os.chown(fd, uid, gid).
4580
4581
[clinic start generated code]*/
4582
4583
static PyObject *
4584
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4585
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4586
0
{
4587
0
    int res;
4588
0
    int async_err = 0;
4589
4590
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4591
0
        return NULL;
4592
0
    }
4593
4594
0
    do {
4595
0
        Py_BEGIN_ALLOW_THREADS
4596
0
        res = fchown(fd, uid, gid);
4597
0
        Py_END_ALLOW_THREADS
4598
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4599
0
    if (res != 0)
4600
0
        return (!async_err) ? posix_error() : NULL;
4601
4602
0
    Py_RETURN_NONE;
4603
0
}
4604
#endif /* HAVE_FCHOWN */
4605
4606
4607
#ifdef HAVE_LCHOWN
4608
/*[clinic input]
4609
os.lchown
4610
4611
    path : path_t
4612
    uid: uid_t
4613
    gid: gid_t
4614
4615
Change the owner and group id of path to the numeric uid and gid.
4616
4617
This function will not follow symbolic links.
4618
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4619
[clinic start generated code]*/
4620
4621
static PyObject *
4622
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4623
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4624
0
{
4625
0
    int res;
4626
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4627
0
        return NULL;
4628
0
    }
4629
0
    Py_BEGIN_ALLOW_THREADS
4630
0
    res = lchown(path->narrow, uid, gid);
4631
0
    Py_END_ALLOW_THREADS
4632
0
    if (res < 0) {
4633
0
        return path_error(path);
4634
0
    }
4635
0
    Py_RETURN_NONE;
4636
0
}
4637
#endif /* HAVE_LCHOWN */
4638
4639
4640
static PyObject *
4641
posix_getcwd(int use_bytes)
4642
6
{
4643
#ifdef MS_WINDOWS
4644
    wchar_t wbuf[MAXPATHLEN];
4645
    wchar_t *wbuf2 = wbuf;
4646
    DWORD len;
4647
4648
    Py_BEGIN_ALLOW_THREADS
4649
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4650
    /* If the buffer is large enough, len does not include the
4651
       terminating \0. If the buffer is too small, len includes
4652
       the space needed for the terminator. */
4653
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4654
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4655
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4656
        }
4657
        else {
4658
            wbuf2 = NULL;
4659
        }
4660
        if (wbuf2) {
4661
            len = GetCurrentDirectoryW(len, wbuf2);
4662
        }
4663
    }
4664
    Py_END_ALLOW_THREADS
4665
4666
    if (!wbuf2) {
4667
        PyErr_NoMemory();
4668
        return NULL;
4669
    }
4670
    if (!len) {
4671
        PyErr_SetFromWindowsErr(0);
4672
        if (wbuf2 != wbuf)
4673
            PyMem_RawFree(wbuf2);
4674
        return NULL;
4675
    }
4676
4677
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4678
    if (wbuf2 != wbuf) {
4679
        PyMem_RawFree(wbuf2);
4680
    }
4681
4682
    if (use_bytes) {
4683
        if (resobj == NULL) {
4684
            return NULL;
4685
        }
4686
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4687
    }
4688
4689
    return resobj;
4690
#else
4691
6
    const size_t chunk = 1024;
4692
4693
6
    char *buf = NULL;
4694
6
    char *cwd = NULL;
4695
6
    size_t buflen = 0;
4696
4697
6
    Py_BEGIN_ALLOW_THREADS
4698
6
    do {
4699
6
        char *newbuf;
4700
6
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4701
6
            buflen += chunk;
4702
6
            newbuf = PyMem_RawRealloc(buf, buflen);
4703
6
        }
4704
0
        else {
4705
0
            newbuf = NULL;
4706
0
        }
4707
6
        if (newbuf == NULL) {
4708
0
            PyMem_RawFree(buf);
4709
0
            buf = NULL;
4710
0
            break;
4711
0
        }
4712
6
        buf = newbuf;
4713
4714
6
        cwd = getcwd(buf, buflen);
4715
6
    } while (cwd == NULL && errno == ERANGE);
4716
6
    Py_END_ALLOW_THREADS
4717
4718
6
    if (buf == NULL) {
4719
0
        return PyErr_NoMemory();
4720
0
    }
4721
6
    if (cwd == NULL) {
4722
0
        posix_error();
4723
0
        PyMem_RawFree(buf);
4724
0
        return NULL;
4725
0
    }
4726
4727
6
    PyObject *obj;
4728
6
    if (use_bytes) {
4729
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4730
0
    }
4731
6
    else {
4732
6
        obj = PyUnicode_DecodeFSDefault(buf);
4733
6
    }
4734
6
#ifdef __linux__
4735
6
    if (buf[0] != '/') {
4736
        /*
4737
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4738
         * relative pathname starting with '(unreachable)'. We detect this
4739
         * and fail with ENOENT, matching newer glibc behaviour.
4740
         */
4741
0
        errno = ENOENT;
4742
0
        path_object_error(obj);
4743
0
        PyMem_RawFree(buf);
4744
0
        return NULL;
4745
0
    }
4746
6
#endif
4747
6
    assert(buf[0] == '/');
4748
6
    PyMem_RawFree(buf);
4749
4750
6
    return obj;
4751
6
#endif   /* !MS_WINDOWS */
4752
6
}
4753
4754
4755
/*[clinic input]
4756
os.getcwd
4757
4758
Return a unicode string representing the current working directory.
4759
[clinic start generated code]*/
4760
4761
static PyObject *
4762
os_getcwd_impl(PyObject *module)
4763
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4764
6
{
4765
6
    return posix_getcwd(0);
4766
6
}
4767
4768
4769
/*[clinic input]
4770
os.getcwdb
4771
4772
Return a bytes string representing the current working directory.
4773
[clinic start generated code]*/
4774
4775
static PyObject *
4776
os_getcwdb_impl(PyObject *module)
4777
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4778
0
{
4779
0
    return posix_getcwd(1);
4780
0
}
4781
4782
4783
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4784
#define HAVE_LINK 1
4785
#endif
4786
4787
#ifdef HAVE_LINK
4788
/*[clinic input]
4789
4790
@permit_long_docstring_body
4791
os.link
4792
4793
    src : path_t
4794
    dst : path_t
4795
    *
4796
    src_dir_fd : dir_fd = None
4797
    dst_dir_fd : dir_fd = None
4798
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4799
4800
Create a hard link to a file.
4801
4802
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4803
  descriptor open to a directory, and the respective path string (src or dst)
4804
  should be relative; the path will then be relative to that directory.
4805
If follow_symlinks is False, and the last element of src is a symbolic
4806
  link, link will create a link to the symbolic link itself instead of the
4807
  file the link points to.
4808
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4809
  platform.  If they are unavailable, using them will raise a
4810
  NotImplementedError.
4811
[clinic start generated code]*/
4812
4813
static PyObject *
4814
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4815
             int dst_dir_fd, int follow_symlinks)
4816
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4817
0
{
4818
#ifdef MS_WINDOWS
4819
    BOOL result = FALSE;
4820
#else
4821
0
    int result;
4822
0
#endif
4823
4824
0
#ifdef HAVE_LINKAT
4825
0
    if (HAVE_LINKAT_RUNTIME) {
4826
0
        if (follow_symlinks < 0) {
4827
0
            follow_symlinks = 1;
4828
0
        }
4829
0
    }
4830
0
    else
4831
0
#endif
4832
0
    {
4833
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4834
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4835
0
            return NULL;
4836
0
        }
4837
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4838
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4839
0
#if defined(MS_WINDOWS) || defined(__linux__)
4840
0
        if (follow_symlinks == 1) {
4841
0
            argument_unavailable_error("link", "follow_symlinks=True");
4842
0
            return NULL;
4843
0
        }
4844
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4845
        if (follow_symlinks == 0) {
4846
            argument_unavailable_error("link", "follow_symlinks=False");
4847
            return NULL;
4848
        }
4849
#else
4850
        if (follow_symlinks >= 0) {
4851
            argument_unavailable_error("link", "follow_symlinks");
4852
            return NULL;
4853
        }
4854
#endif
4855
0
    }
4856
4857
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4858
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4859
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4860
0
        return NULL;
4861
0
    }
4862
4863
#ifdef MS_WINDOWS
4864
    Py_BEGIN_ALLOW_THREADS
4865
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4866
    Py_END_ALLOW_THREADS
4867
4868
    if (!result)
4869
        return path_error2(src, dst);
4870
#else
4871
0
    Py_BEGIN_ALLOW_THREADS
4872
0
#ifdef HAVE_LINKAT
4873
0
    if (HAVE_LINKAT_RUNTIME) {
4874
0
        result = linkat(src_dir_fd, src->narrow,
4875
0
            dst_dir_fd, dst->narrow,
4876
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4877
0
    }
4878
0
    else
4879
0
#endif
4880
0
    {
4881
        /* linkat not available */
4882
0
        result = link(src->narrow, dst->narrow);
4883
0
    }
4884
0
    Py_END_ALLOW_THREADS
4885
4886
0
    if (result)
4887
0
        return path_error2(src, dst);
4888
0
#endif /* MS_WINDOWS */
4889
4890
0
    Py_RETURN_NONE;
4891
0
}
4892
#endif
4893
4894
4895
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4896
static PyObject *
4897
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4898
{
4899
    PyObject *v;
4900
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4901
    BOOL result, return_bytes;
4902
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4903
    /* only claim to have space for MAX_PATH */
4904
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4905
    wchar_t *wnamebuf = NULL;
4906
4907
    WIN32_FIND_DATAW wFileData;
4908
    const wchar_t *po_wchars;
4909
4910
    if (!path->wide) { /* Default arg: "." */
4911
        po_wchars = L".";
4912
        len = 1;
4913
        return_bytes = 0;
4914
    } else {
4915
        po_wchars = path->wide;
4916
        len = wcslen(path->wide);
4917
        return_bytes = PyBytes_Check(path->object);
4918
    }
4919
    /* The +5 is so we can append "\\*.*\0" */
4920
    wnamebuf = PyMem_New(wchar_t, len + 5);
4921
    if (!wnamebuf) {
4922
        PyErr_NoMemory();
4923
        goto exit;
4924
    }
4925
    wcscpy(wnamebuf, po_wchars);
4926
    if (len > 0) {
4927
        wchar_t wch = wnamebuf[len-1];
4928
        if (wch != SEP && wch != ALTSEP && wch != L':')
4929
            wnamebuf[len++] = SEP;
4930
        wcscpy(wnamebuf + len, L"*.*");
4931
    }
4932
    if ((list = PyList_New(0)) == NULL) {
4933
        goto exit;
4934
    }
4935
    Py_BEGIN_ALLOW_THREADS
4936
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4937
    Py_END_ALLOW_THREADS
4938
    if (hFindFile == INVALID_HANDLE_VALUE) {
4939
        int error = GetLastError();
4940
        if (error == ERROR_FILE_NOT_FOUND)
4941
            goto exit;
4942
        path_error(path);
4943
        Py_CLEAR(list);
4944
        goto exit;
4945
    }
4946
    do {
4947
        /* Skip over . and .. */
4948
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4949
            wcscmp(wFileData.cFileName, L"..") != 0) {
4950
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4951
                                       wcslen(wFileData.cFileName));
4952
            if (return_bytes && v) {
4953
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4954
            }
4955
            if (v == NULL) {
4956
                Py_CLEAR(list);
4957
                break;
4958
            }
4959
            if (PyList_Append(list, v) != 0) {
4960
                Py_DECREF(v);
4961
                Py_CLEAR(list);
4962
                break;
4963
            }
4964
            Py_DECREF(v);
4965
        }
4966
        Py_BEGIN_ALLOW_THREADS
4967
        result = FindNextFileW(hFindFile, &wFileData);
4968
        Py_END_ALLOW_THREADS
4969
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4970
           it got to the end of the directory. */
4971
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4972
            path_error(path);
4973
            Py_CLEAR(list);
4974
            goto exit;
4975
        }
4976
    } while (result == TRUE);
4977
4978
exit:
4979
    if (hFindFile != INVALID_HANDLE_VALUE) {
4980
        if (FindClose(hFindFile) == FALSE) {
4981
            if (list != NULL) {
4982
                path_error(path);
4983
                Py_CLEAR(list);
4984
            }
4985
        }
4986
    }
4987
    PyMem_Free(wnamebuf);
4988
4989
    return list;
4990
}  /* end of _listdir_windows_no_opendir */
4991
4992
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4993
4994
static PyObject *
4995
_posix_listdir(path_t *path, PyObject *list)
4996
388
{
4997
388
    PyObject *v;
4998
388
    DIR *dirp = NULL;
4999
388
    struct dirent *ep;
5000
388
    int return_str; /* if false, return bytes */
5001
388
#ifdef HAVE_FDOPENDIR
5002
388
    int fd = -1;
5003
388
#endif
5004
5005
388
    errno = 0;
5006
388
#ifdef HAVE_FDOPENDIR
5007
388
    if (path->is_fd) {
5008
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5009
        /* closedir() closes the FD, so we duplicate it */
5010
0
        fd = _Py_dup(path->fd);
5011
0
        if (fd == -1)
5012
0
            return NULL;
5013
5014
0
        return_str = 1;
5015
5016
0
        Py_BEGIN_ALLOW_THREADS
5017
0
        dirp = fdopendir(fd);
5018
0
        Py_END_ALLOW_THREADS
5019
0
      } else {
5020
0
        PyErr_SetString(PyExc_TypeError,
5021
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5022
0
        return NULL;
5023
0
      }
5024
0
    }
5025
388
    else
5026
388
#endif
5027
388
    {
5028
388
        const char *name;
5029
388
        if (path->narrow) {
5030
388
            name = path->narrow;
5031
            /* only return bytes if they specified a bytes object */
5032
388
            return_str = !PyBytes_Check(path->object);
5033
388
        }
5034
0
        else {
5035
0
            name = ".";
5036
0
            return_str = 1;
5037
0
        }
5038
5039
388
        Py_BEGIN_ALLOW_THREADS
5040
388
        dirp = opendir(name);
5041
388
        Py_END_ALLOW_THREADS
5042
388
    }
5043
5044
388
    if (dirp == NULL) {
5045
8
        path_error(path);
5046
8
        list = NULL;
5047
8
#ifdef HAVE_FDOPENDIR
5048
8
        if (fd != -1) {
5049
0
            Py_BEGIN_ALLOW_THREADS
5050
0
            close(fd);
5051
0
            Py_END_ALLOW_THREADS
5052
0
        }
5053
8
#endif
5054
8
        goto exit;
5055
8
    }
5056
380
    if ((list = PyList_New(0)) == NULL) {
5057
0
        goto exit;
5058
0
    }
5059
19.8k
    for (;;) {
5060
19.8k
        errno = 0;
5061
19.8k
        Py_BEGIN_ALLOW_THREADS
5062
19.8k
        ep = readdir(dirp);
5063
19.8k
        Py_END_ALLOW_THREADS
5064
19.8k
        if (ep == NULL) {
5065
380
            if (errno == 0) {
5066
380
                break;
5067
380
            } else {
5068
0
                path_error(path);
5069
0
                Py_CLEAR(list);
5070
0
                goto exit;
5071
0
            }
5072
380
        }
5073
19.5k
        if (ep->d_name[0] == '.' &&
5074
760
            (NAMLEN(ep) == 1 ||
5075
380
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5076
760
            continue;
5077
18.7k
        if (return_str)
5078
18.7k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5079
0
        else
5080
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5081
18.7k
        if (v == NULL) {
5082
0
            Py_CLEAR(list);
5083
0
            break;
5084
0
        }
5085
18.7k
        if (PyList_Append(list, v) != 0) {
5086
0
            Py_DECREF(v);
5087
0
            Py_CLEAR(list);
5088
0
            break;
5089
0
        }
5090
18.7k
        Py_DECREF(v);
5091
18.7k
    }
5092
5093
388
exit:
5094
388
    if (dirp != NULL) {
5095
380
        Py_BEGIN_ALLOW_THREADS
5096
380
#ifdef HAVE_FDOPENDIR
5097
380
        if (fd > -1)
5098
0
            rewinddir(dirp);
5099
380
#endif
5100
380
        closedir(dirp);
5101
380
        Py_END_ALLOW_THREADS
5102
380
    }
5103
5104
388
    return list;
5105
380
}  /* end of _posix_listdir */
5106
#endif  /* which OS */
5107
5108
5109
/*[clinic input]
5110
@permit_long_docstring_body
5111
os.listdir
5112
5113
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5114
5115
Return a list containing the names of the files in the directory.
5116
5117
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
5118
  the filenames returned will also be bytes; in all other circumstances
5119
  the filenames returned will be str.
5120
If path is None, uses the path='.'.
5121
On some platforms, path may also be specified as an open file descriptor;\
5122
  the file descriptor must refer to a directory.
5123
  If this functionality is unavailable, using it raises NotImplementedError.
5124
5125
The list is in arbitrary order.  It does not include the special
5126
entries '.' and '..' even if they are present in the directory.
5127
5128
5129
[clinic start generated code]*/
5130
5131
static PyObject *
5132
os_listdir_impl(PyObject *module, path_t *path)
5133
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
5134
388
{
5135
388
    if (PySys_Audit("os.listdir", "O",
5136
388
                    path->object ? path->object : Py_None) < 0) {
5137
0
        return NULL;
5138
0
    }
5139
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5140
    return _listdir_windows_no_opendir(path, NULL);
5141
#else
5142
388
    return _posix_listdir(path, NULL);
5143
388
#endif
5144
388
}
5145
5146
5147
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5148
5149
/*[clinic input]
5150
os.listdrives
5151
5152
Return a list containing the names of drives in the system.
5153
5154
A drive name typically looks like 'C:\\'.
5155
5156
[clinic start generated code]*/
5157
5158
static PyObject *
5159
os_listdrives_impl(PyObject *module)
5160
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5161
{
5162
    /* Number of possible drives is limited, so 256 should always be enough.
5163
       On the day when it is not, listmounts() will have to be used. */
5164
    wchar_t buffer[256];
5165
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5166
    PyObject *result = NULL;
5167
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5168
        return NULL;
5169
    }
5170
5171
    Py_BEGIN_ALLOW_THREADS;
5172
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5173
    Py_END_ALLOW_THREADS;
5174
5175
    if (!buflen) {
5176
        PyErr_SetFromWindowsErr(0);
5177
        return NULL;
5178
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5179
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5180
        return NULL;
5181
    }
5182
5183
    /* buflen includes a null terminator, so remove it */
5184
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5185
    if (str) {
5186
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5187
        if (nullchar) {
5188
            result = PyUnicode_Split(str, nullchar, -1);
5189
            Py_DECREF(nullchar);
5190
        }
5191
        Py_DECREF(str);
5192
    }
5193
    return result;
5194
}
5195
5196
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5197
5198
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5199
5200
/*[clinic input]
5201
os.listvolumes
5202
5203
Return a list containing the volumes in the system.
5204
5205
Volumes are typically represented as a GUID path.
5206
5207
[clinic start generated code]*/
5208
5209
static PyObject *
5210
os_listvolumes_impl(PyObject *module)
5211
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5212
{
5213
    PyObject *result = PyList_New(0);
5214
    HANDLE find = INVALID_HANDLE_VALUE;
5215
    wchar_t buffer[MAX_PATH + 1];
5216
    if (!result) {
5217
        return NULL;
5218
    }
5219
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5220
        Py_DECREF(result);
5221
        return NULL;
5222
    }
5223
5224
    int err = 0;
5225
    Py_BEGIN_ALLOW_THREADS;
5226
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5227
    if (find == INVALID_HANDLE_VALUE) {
5228
        err = GetLastError();
5229
    }
5230
    Py_END_ALLOW_THREADS;
5231
5232
    while (!err) {
5233
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5234
        if (!s || PyList_Append(result, s) < 0) {
5235
            Py_XDECREF(s);
5236
            Py_CLEAR(result);
5237
            break;
5238
        }
5239
        Py_DECREF(s);
5240
5241
        Py_BEGIN_ALLOW_THREADS;
5242
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5243
            err = GetLastError();
5244
        }
5245
        Py_END_ALLOW_THREADS;
5246
    }
5247
5248
    if (find != INVALID_HANDLE_VALUE) {
5249
        Py_BEGIN_ALLOW_THREADS;
5250
        FindVolumeClose(find);
5251
        Py_END_ALLOW_THREADS;
5252
    }
5253
    if (err && err != ERROR_NO_MORE_FILES) {
5254
        PyErr_SetFromWindowsErr(err);
5255
        Py_XDECREF(result);
5256
        result = NULL;
5257
    }
5258
    return result;
5259
}
5260
5261
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5262
5263
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5264
5265
/*[clinic input]
5266
os.listmounts
5267
5268
    volume: path_t
5269
5270
Return a list containing mount points for a particular volume.
5271
5272
'volume' should be a GUID path as returned from os.listvolumes.
5273
5274
[clinic start generated code]*/
5275
5276
static PyObject *
5277
os_listmounts_impl(PyObject *module, path_t *volume)
5278
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5279
{
5280
    wchar_t default_buffer[MAX_PATH + 1];
5281
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5282
    LPWSTR buffer = default_buffer;
5283
    DWORD attributes;
5284
    PyObject *str = NULL;
5285
    PyObject *nullchar = NULL;
5286
    PyObject *result = NULL;
5287
5288
    /* Ensure we have a valid volume path before continuing */
5289
    Py_BEGIN_ALLOW_THREADS
5290
    attributes = GetFileAttributesW(volume->wide);
5291
    Py_END_ALLOW_THREADS
5292
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5293
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5294
    {
5295
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5296
    }
5297
5298
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5299
        return NULL;
5300
    }
5301
5302
    while (1) {
5303
        BOOL success;
5304
        Py_BEGIN_ALLOW_THREADS
5305
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5306
                                                   buflen, &buflen);
5307
        Py_END_ALLOW_THREADS
5308
        if (success) {
5309
            break;
5310
        }
5311
        if (GetLastError() != ERROR_MORE_DATA) {
5312
            PyErr_SetFromWindowsErr(0);
5313
            goto exit;
5314
        }
5315
        if (buffer != default_buffer) {
5316
            PyMem_Free((void *)buffer);
5317
        }
5318
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5319
        if (!buffer) {
5320
            PyErr_NoMemory();
5321
            goto exit;
5322
        }
5323
    }
5324
    if (buflen < 2) {
5325
        result = PyList_New(0);
5326
        goto exit;
5327
    }
5328
    // buflen includes two null terminators, one for the last string
5329
    // and one for the array of strings.
5330
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5331
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5332
    if (str && nullchar) {
5333
        result = PyUnicode_Split(str, nullchar, -1);
5334
    }
5335
exit:
5336
    if (buffer != default_buffer) {
5337
        PyMem_Free(buffer);
5338
    }
5339
    Py_XDECREF(nullchar);
5340
    Py_XDECREF(str);
5341
    return result;
5342
}
5343
5344
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5345
5346
#ifdef MS_WINDOWS
5347
5348
/*[clinic input]
5349
os._path_isdevdrive
5350
5351
    path: path_t
5352
5353
Determines whether the specified path is on a Windows Dev Drive.
5354
5355
[clinic start generated code]*/
5356
5357
static PyObject *
5358
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5359
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5360
{
5361
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5362
    /* This flag will be documented at
5363
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5364
       after release, and will be available in the latest WinSDK.
5365
       We include the flag to avoid a specific version dependency
5366
       on the latest WinSDK. */
5367
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5368
#endif
5369
    int err = 0;
5370
    PyObject *r = NULL;
5371
    wchar_t volume[MAX_PATH];
5372
5373
    Py_BEGIN_ALLOW_THREADS
5374
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5375
        /* invalid path of some kind */
5376
        /* Note that this also includes the case where a volume is mounted
5377
           in a path longer than 260 characters. This is likely to be rare
5378
           and problematic for other reasons, so a (soft) failure in this
5379
           check seems okay. */
5380
        err = GetLastError();
5381
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5382
        /* only care about local dev drives */
5383
        r = Py_False;
5384
    } else {
5385
        HANDLE hVolume = CreateFileW(
5386
            volume,
5387
            FILE_READ_ATTRIBUTES,
5388
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5389
            NULL,
5390
            OPEN_EXISTING,
5391
            FILE_FLAG_BACKUP_SEMANTICS,
5392
            NULL
5393
        );
5394
        if (hVolume == INVALID_HANDLE_VALUE) {
5395
            err = GetLastError();
5396
        } else {
5397
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5398
            volumeState.Version = 1;
5399
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5400
            if (!DeviceIoControl(
5401
                hVolume,
5402
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5403
                &volumeState,
5404
                sizeof(volumeState),
5405
                &volumeState,
5406
                sizeof(volumeState),
5407
                NULL,
5408
                NULL
5409
            )) {
5410
                err = GetLastError();
5411
            }
5412
            CloseHandle(hVolume);
5413
            if (err == ERROR_INVALID_PARAMETER) {
5414
                /* not supported on this platform */
5415
                r = Py_False;
5416
            } else if (!err) {
5417
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5418
                    ? Py_True : Py_False;
5419
            }
5420
        }
5421
    }
5422
    Py_END_ALLOW_THREADS
5423
5424
    if (err) {
5425
        PyErr_SetFromWindowsErr(err);
5426
        return NULL;
5427
    }
5428
5429
    if (r) {
5430
        return Py_NewRef(r);
5431
    }
5432
5433
    return NULL;
5434
}
5435
5436
5437
int
5438
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5439
{
5440
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5441
    DWORD result;
5442
5443
    result = GetFullPathNameW(path,
5444
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5445
                              NULL);
5446
    if (!result) {
5447
        return -1;
5448
    }
5449
5450
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5451
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5452
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5453
        }
5454
        else {
5455
            woutbufp = NULL;
5456
        }
5457
        if (!woutbufp) {
5458
            *abspath_p = NULL;
5459
            return 0;
5460
        }
5461
5462
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5463
        if (!result) {
5464
            PyMem_RawFree(woutbufp);
5465
            return -1;
5466
        }
5467
    }
5468
5469
    if (woutbufp != woutbuf) {
5470
        *abspath_p = woutbufp;
5471
        return 0;
5472
    }
5473
5474
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5475
    return 0;
5476
}
5477
5478
5479
/* A helper function for abspath on win32 */
5480
/*[clinic input]
5481
os._getfullpathname
5482
5483
    path: path_t
5484
    /
5485
5486
[clinic start generated code]*/
5487
5488
static PyObject *
5489
os__getfullpathname_impl(PyObject *module, path_t *path)
5490
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5491
{
5492
    wchar_t *abspath;
5493
5494
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5495
        return win32_error_object("GetFullPathNameW", path->object);
5496
    }
5497
    if (abspath == NULL) {
5498
        return PyErr_NoMemory();
5499
    }
5500
5501
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5502
    PyMem_RawFree(abspath);
5503
    if (str == NULL) {
5504
        return NULL;
5505
    }
5506
    if (PyBytes_Check(path->object)) {
5507
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5508
    }
5509
    return str;
5510
}
5511
5512
5513
/*[clinic input]
5514
os._getfinalpathname
5515
5516
    path: path_t
5517
    /
5518
5519
A helper function for samepath on windows.
5520
[clinic start generated code]*/
5521
5522
static PyObject *
5523
os__getfinalpathname_impl(PyObject *module, path_t *path)
5524
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5525
{
5526
    HANDLE hFile;
5527
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5528
    int buf_size = Py_ARRAY_LENGTH(buf);
5529
    int result_length;
5530
    PyObject *result;
5531
5532
    Py_BEGIN_ALLOW_THREADS
5533
    hFile = CreateFileW(
5534
        path->wide,
5535
        0, /* desired access */
5536
        0, /* share mode */
5537
        NULL, /* security attributes */
5538
        OPEN_EXISTING,
5539
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5540
        FILE_FLAG_BACKUP_SEMANTICS,
5541
        NULL);
5542
    Py_END_ALLOW_THREADS
5543
5544
    if (hFile == INVALID_HANDLE_VALUE) {
5545
        return win32_error_object("CreateFileW", path->object);
5546
    }
5547
5548
    /* We have a good handle to the target, use it to determine the
5549
       target path name. */
5550
    while (1) {
5551
        Py_BEGIN_ALLOW_THREADS
5552
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5553
                                                  buf_size, VOLUME_NAME_DOS);
5554
        Py_END_ALLOW_THREADS
5555
5556
        if (!result_length) {
5557
            result = win32_error_object("GetFinalPathNameByHandleW",
5558
                                         path->object);
5559
            goto cleanup;
5560
        }
5561
5562
        if (result_length < buf_size) {
5563
            break;
5564
        }
5565
5566
        wchar_t *tmp;
5567
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5568
                            result_length * sizeof(*tmp));
5569
        if (!tmp) {
5570
            result = PyErr_NoMemory();
5571
            goto cleanup;
5572
        }
5573
5574
        buf_size = result_length;
5575
        target_path = tmp;
5576
    }
5577
5578
    result = PyUnicode_FromWideChar(target_path, result_length);
5579
    if (result && PyBytes_Check(path->object)) {
5580
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5581
    }
5582
5583
cleanup:
5584
    if (target_path != buf) {
5585
        PyMem_Free(target_path);
5586
    }
5587
    CloseHandle(hFile);
5588
    return result;
5589
}
5590
5591
/*[clinic input]
5592
os._findfirstfile
5593
    path: path_t
5594
    /
5595
A function to get the real file name without accessing the file in Windows.
5596
[clinic start generated code]*/
5597
5598
static PyObject *
5599
os__findfirstfile_impl(PyObject *module, path_t *path)
5600
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5601
{
5602
    PyObject *result;
5603
    HANDLE hFindFile;
5604
    WIN32_FIND_DATAW wFileData;
5605
    WCHAR *wRealFileName;
5606
5607
    Py_BEGIN_ALLOW_THREADS
5608
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5609
    Py_END_ALLOW_THREADS
5610
5611
    if (hFindFile == INVALID_HANDLE_VALUE) {
5612
        path_error(path);
5613
        return NULL;
5614
    }
5615
5616
    wRealFileName = wFileData.cFileName;
5617
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5618
    FindClose(hFindFile);
5619
    return result;
5620
}
5621
5622
5623
/*[clinic input]
5624
os._getvolumepathname
5625
5626
    path: path_t
5627
5628
A helper function for ismount on Win32.
5629
[clinic start generated code]*/
5630
5631
static PyObject *
5632
os__getvolumepathname_impl(PyObject *module, path_t *path)
5633
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5634
{
5635
    PyObject *result;
5636
    wchar_t *mountpath=NULL;
5637
    size_t buflen;
5638
    BOOL ret;
5639
5640
    /* Volume path should be shorter than entire path */
5641
    buflen = Py_MAX(path->length, MAX_PATH);
5642
5643
    if (buflen > PY_DWORD_MAX) {
5644
        PyErr_SetString(PyExc_OverflowError, "path too long");
5645
        return NULL;
5646
    }
5647
5648
    mountpath = PyMem_New(wchar_t, buflen);
5649
    if (mountpath == NULL)
5650
        return PyErr_NoMemory();
5651
5652
    Py_BEGIN_ALLOW_THREADS
5653
    ret = GetVolumePathNameW(path->wide, mountpath,
5654
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5655
    Py_END_ALLOW_THREADS
5656
5657
    if (!ret) {
5658
        result = win32_error_object("_getvolumepathname", path->object);
5659
        goto exit;
5660
    }
5661
    result = PyUnicode_FromWideChar(mountpath, -1);
5662
    if (PyBytes_Check(path->object))
5663
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5664
5665
exit:
5666
    PyMem_Free(mountpath);
5667
    return result;
5668
}
5669
5670
5671
/*[clinic input]
5672
os._path_splitroot
5673
5674
    path: path_t
5675
    /
5676
5677
Removes everything after the root on Win32.
5678
[clinic start generated code]*/
5679
5680
static PyObject *
5681
os__path_splitroot_impl(PyObject *module, path_t *path)
5682
/*[clinic end generated code: output=ab7f1a88b654581c input=d356de1edb6050a2]*/
5683
{
5684
    wchar_t *buffer;
5685
    wchar_t *end;
5686
    PyObject *result = NULL;
5687
    HRESULT ret;
5688
5689
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5690
    if (!buffer) {
5691
        return NULL;
5692
    }
5693
    wcscpy(buffer, path->wide);
5694
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5695
        *p = L'\\';
5696
    }
5697
5698
    Py_BEGIN_ALLOW_THREADS
5699
    ret = PathCchSkipRoot(buffer, &end);
5700
    Py_END_ALLOW_THREADS
5701
    if (FAILED(ret)) {
5702
        result = Py_BuildValue("sO", "", path->object);
5703
    } else if (end != buffer) {
5704
        size_t rootLen = (size_t)(end - buffer);
5705
        result = Py_BuildValue("NN",
5706
            PyUnicode_FromWideChar(path->wide, rootLen),
5707
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5708
        );
5709
    } else {
5710
        result = Py_BuildValue("Os", path->object, "");
5711
    }
5712
    PyMem_Free(buffer);
5713
5714
    return result;
5715
}
5716
5717
5718
#define PY_IFREG  1 // Regular file
5719
#define PY_IFDIR  2 // Directory
5720
#define PY_IFLNK  4 // Symlink
5721
#define PY_IFMNT  8 // Mount Point (junction)
5722
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5723
#define PY_IFRRP 32 // Regular Reparse Point
5724
5725
static inline BOOL
5726
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5727
{
5728
    switch (testedType) {
5729
    case PY_IFREG:
5730
        return diskDevice && attributes &&
5731
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5732
    case PY_IFDIR:
5733
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5734
    case PY_IFLNK:
5735
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5736
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5737
    case PY_IFMNT:
5738
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5739
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5740
    case PY_IFLRP:
5741
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5742
               IsReparseTagNameSurrogate(reparseTag);
5743
    case PY_IFRRP:
5744
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5745
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5746
    }
5747
5748
    return FALSE;
5749
}
5750
5751
static BOOL
5752
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5753
{
5754
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5755
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5756
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5757
5758
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5759
    if (diskOnly && !diskDevice) {
5760
        return FALSE;
5761
    }
5762
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5763
        FILE_ATTRIBUTE_TAG_INFO info;
5764
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5765
                                            sizeof(info)) &&
5766
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5767
                         testedType);
5768
    }
5769
    FILE_BASIC_INFO info;
5770
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5771
                                        sizeof(info)) &&
5772
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5773
}
5774
5775
static BOOL
5776
_testFileTypeByName(LPCWSTR path, int testedType)
5777
{
5778
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5779
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5780
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5781
5782
    FILE_STAT_BASIC_INFORMATION info;
5783
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5784
                                     sizeof(info)))
5785
    {
5786
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5787
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5788
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5789
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5790
                                diskDevice, testedType);
5791
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5792
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5793
        {
5794
            return result;
5795
        }
5796
    }
5797
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5798
                GetLastError()))
5799
    {
5800
        return FALSE;
5801
    }
5802
5803
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5804
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5805
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5806
    }
5807
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5808
                               OPEN_EXISTING, flags, NULL);
5809
    if (hfile != INVALID_HANDLE_VALUE) {
5810
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5811
        CloseHandle(hfile);
5812
        return result;
5813
    }
5814
5815
    switch (GetLastError()) {
5816
    case ERROR_ACCESS_DENIED:
5817
    case ERROR_SHARING_VIOLATION:
5818
    case ERROR_CANT_ACCESS_FILE:
5819
    case ERROR_INVALID_PARAMETER:
5820
        int rc;
5821
        STRUCT_STAT st;
5822
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5823
            rc = STAT(path, &st);
5824
        }
5825
        else {
5826
            // PY_IFRRP is not generally supported in this case, except for
5827
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5828
            rc = LSTAT(path, &st);
5829
        }
5830
        if (!rc) {
5831
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5832
                             st.st_mode & S_IFREG, testedType);
5833
        }
5834
    }
5835
5836
    return FALSE;
5837
}
5838
5839
5840
static BOOL
5841
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5842
{
5843
    FILE_STAT_BASIC_INFORMATION info;
5844
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5845
                                     sizeof(info)))
5846
    {
5847
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5848
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5849
        {
5850
            return TRUE;
5851
        }
5852
    }
5853
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5854
                    GetLastError()))
5855
    {
5856
        return FALSE;
5857
    }
5858
5859
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5860
    if (!followLinks) {
5861
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5862
    }
5863
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5864
                               OPEN_EXISTING, flags, NULL);
5865
    if (hfile != INVALID_HANDLE_VALUE) {
5866
        if (followLinks) {
5867
            CloseHandle(hfile);
5868
            return TRUE;
5869
        }
5870
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5871
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5872
        CloseHandle(hfile);
5873
        if (!result) {
5874
            return TRUE;
5875
        }
5876
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5877
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5878
        if (hfile != INVALID_HANDLE_VALUE) {
5879
            CloseHandle(hfile);
5880
            return TRUE;
5881
        }
5882
    }
5883
5884
    switch (GetLastError()) {
5885
    case ERROR_ACCESS_DENIED:
5886
    case ERROR_SHARING_VIOLATION:
5887
    case ERROR_CANT_ACCESS_FILE:
5888
    case ERROR_INVALID_PARAMETER:
5889
        STRUCT_STAT _st;
5890
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5891
    }
5892
5893
    return FALSE;
5894
}
5895
5896
5897
static BOOL
5898
_testFileExists(path_t *path, BOOL followLinks)
5899
{
5900
    BOOL result = FALSE;
5901
    if (path->value_error) {
5902
        return FALSE;
5903
    }
5904
5905
    Py_BEGIN_ALLOW_THREADS
5906
    if (path->is_fd) {
5907
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5908
        if (hfile != INVALID_HANDLE_VALUE) {
5909
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5910
                result = TRUE;
5911
            }
5912
        }
5913
    }
5914
    else if (path->wide) {
5915
        result = _testFileExistsByName(path->wide, followLinks);
5916
    }
5917
    Py_END_ALLOW_THREADS
5918
5919
    return result;
5920
}
5921
5922
5923
static BOOL
5924
_testFileType(path_t *path, int testedType)
5925
{
5926
    BOOL result = FALSE;
5927
    if (path->value_error) {
5928
        return FALSE;
5929
    }
5930
5931
    Py_BEGIN_ALLOW_THREADS
5932
    if (path->is_fd) {
5933
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5934
        if (hfile != INVALID_HANDLE_VALUE) {
5935
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5936
        }
5937
    }
5938
    else if (path->wide) {
5939
        result = _testFileTypeByName(path->wide, testedType);
5940
    }
5941
    Py_END_ALLOW_THREADS
5942
5943
    return result;
5944
}
5945
5946
5947
/*[clinic input]
5948
os._path_exists -> bool
5949
5950
    path: path_t(allow_fd=True, suppress_value_error=True)
5951
5952
Test whether a path exists.  Returns False for broken symbolic links.
5953
5954
[clinic start generated code]*/
5955
5956
static int
5957
os__path_exists_impl(PyObject *module, path_t *path)
5958
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5959
{
5960
    return _testFileExists(path, TRUE);
5961
}
5962
5963
5964
/*[clinic input]
5965
os._path_lexists -> bool
5966
5967
    path: path_t(allow_fd=True, suppress_value_error=True)
5968
5969
Test whether a path exists.  Returns True for broken symbolic links.
5970
5971
[clinic start generated code]*/
5972
5973
static int
5974
os__path_lexists_impl(PyObject *module, path_t *path)
5975
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5976
{
5977
    return _testFileExists(path, FALSE);
5978
}
5979
5980
5981
/*[clinic input]
5982
os._path_isdir -> bool
5983
5984
    path: path_t(allow_fd=True, suppress_value_error=True)
5985
    /
5986
5987
Return true if the pathname refers to an existing directory.
5988
5989
[clinic start generated code]*/
5990
5991
static int
5992
os__path_isdir_impl(PyObject *module, path_t *path)
5993
/*[clinic end generated code: output=d5786196f9e2fa7a input=b15f9b697a7a759f]*/
5994
{
5995
    return _testFileType(path, PY_IFDIR);
5996
}
5997
5998
5999
/*[clinic input]
6000
os._path_isfile -> bool
6001
6002
    path: path_t(allow_fd=True, suppress_value_error=True)
6003
6004
Test whether a path is a regular file
6005
6006
[clinic start generated code]*/
6007
6008
static int
6009
os__path_isfile_impl(PyObject *module, path_t *path)
6010
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6011
{
6012
    return _testFileType(path, PY_IFREG);
6013
}
6014
6015
6016
/*[clinic input]
6017
os._path_islink -> bool
6018
6019
    path: path_t(allow_fd=True, suppress_value_error=True)
6020
6021
Test whether a path is a symbolic link
6022
6023
[clinic start generated code]*/
6024
6025
static int
6026
os__path_islink_impl(PyObject *module, path_t *path)
6027
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6028
{
6029
    return _testFileType(path, PY_IFLNK);
6030
}
6031
6032
6033
/*[clinic input]
6034
os._path_isjunction -> bool
6035
6036
    path: path_t(allow_fd=True, suppress_value_error=True)
6037
6038
Test whether a path is a junction
6039
6040
[clinic start generated code]*/
6041
6042
static int
6043
os__path_isjunction_impl(PyObject *module, path_t *path)
6044
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6045
{
6046
    return _testFileType(path, PY_IFMNT);
6047
}
6048
6049
#undef PY_IFREG
6050
#undef PY_IFDIR
6051
#undef PY_IFLNK
6052
#undef PY_IFMNT
6053
#undef PY_IFLRP
6054
#undef PY_IFRRP
6055
6056
#endif /* MS_WINDOWS */
6057
6058
6059
/*[clinic input]
6060
os._path_splitroot_ex
6061
6062
    path: path_t(make_wide=True, nonstrict=True)
6063
    /
6064
6065
Split a pathname into drive, root and tail.
6066
6067
The tail contains anything after the root.
6068
[clinic start generated code]*/
6069
6070
static PyObject *
6071
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6072
/*[clinic end generated code: output=4b0072b6cdf4b611 input=012fbfad14888b2b]*/
6073
239k
{
6074
239k
    Py_ssize_t drvsize, rootsize;
6075
239k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6076
6077
239k
    const wchar_t *buffer = path->wide;
6078
239k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6079
239k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6080
239k
    if (drv == NULL) {
6081
0
        goto exit;
6082
0
    }
6083
239k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6084
239k
    if (root == NULL) {
6085
0
        goto exit;
6086
0
    }
6087
239k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6088
239k
                                  path->length - drvsize - rootsize);
6089
239k
    if (tail == NULL) {
6090
0
        goto exit;
6091
0
    }
6092
239k
    if (PyBytes_Check(path->object)) {
6093
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6094
0
        if (drv == NULL) {
6095
0
            goto exit;
6096
0
        }
6097
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6098
0
        if (root == NULL) {
6099
0
            goto exit;
6100
0
        }
6101
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6102
0
        if (tail == NULL) {
6103
0
            goto exit;
6104
0
        }
6105
0
    }
6106
239k
    result = PyTuple_Pack(3, drv, root, tail);
6107
239k
exit:
6108
239k
    Py_XDECREF(drv);
6109
239k
    Py_XDECREF(root);
6110
239k
    Py_XDECREF(tail);
6111
239k
    return result;
6112
239k
}
6113
6114
6115
/*[clinic input]
6116
os._path_normpath
6117
6118
    path: path_t(make_wide=True, nonstrict=True)
6119
6120
Normalize path, eliminating double slashes, etc.
6121
[clinic start generated code]*/
6122
6123
static PyObject *
6124
os__path_normpath_impl(PyObject *module, path_t *path)
6125
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6126
34.1k
{
6127
34.1k
    PyObject *result;
6128
34.1k
    Py_ssize_t norm_len;
6129
34.1k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6130
34.1k
                                               path->length, &norm_len);
6131
34.1k
    if (!norm_len) {
6132
0
        result = PyUnicode_FromOrdinal('.');
6133
0
    }
6134
34.1k
    else {
6135
34.1k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6136
34.1k
    }
6137
34.1k
    if (PyBytes_Check(path->object)) {
6138
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6139
0
    }
6140
34.1k
    return result;
6141
34.1k
}
6142
6143
/*[clinic input]
6144
os.mkdir
6145
6146
    path : path_t
6147
6148
    mode: int = 0o777
6149
6150
    *
6151
6152
    dir_fd : dir_fd(requires='mkdirat') = None
6153
6154
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
6155
6156
Create a directory.
6157
6158
If dir_fd is not None, it should be a file descriptor open to a directory,
6159
  and path should be relative; path will then be relative to that directory.
6160
dir_fd may not be implemented on your platform.
6161
  If it is unavailable, using it will raise a NotImplementedError.
6162
6163
The mode argument is ignored on Windows. Where it is used, the current umask
6164
value is first masked out.
6165
[clinic start generated code]*/
6166
6167
static PyObject *
6168
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6169
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
6170
214k
{
6171
214k
    int result;
6172
#ifdef MS_WINDOWS
6173
    int error = 0;
6174
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6175
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6176
#endif
6177
214k
#ifdef HAVE_MKDIRAT
6178
214k
    int mkdirat_unavailable = 0;
6179
214k
#endif
6180
6181
214k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6182
214k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6183
0
        return NULL;
6184
0
    }
6185
6186
#ifdef MS_WINDOWS
6187
    Py_BEGIN_ALLOW_THREADS
6188
    // For API sets that don't support these APIs, we have no choice
6189
    // but to silently create a directory with default ACL.
6190
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6191
    if (mode == 0700 /* 0o700 */) {
6192
        ULONG sdSize;
6193
        pSecAttr = &secAttr;
6194
        // Set a discretionary ACL (D) that is protected (P) and includes
6195
        // inheritable (OICI) entries that allow (A) full control (FA) to
6196
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6197
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6198
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6199
            SDDL_REVISION_1,
6200
            &secAttr.lpSecurityDescriptor,
6201
            &sdSize
6202
        )) {
6203
            error = GetLastError();
6204
        }
6205
    }
6206
#endif
6207
    if (!error) {
6208
        result = CreateDirectoryW(path->wide, pSecAttr);
6209
        if (secAttr.lpSecurityDescriptor &&
6210
            // uncommonly, LocalFree returns non-zero on error, but still uses
6211
            // GetLastError() to see what the error code is
6212
            LocalFree(secAttr.lpSecurityDescriptor)) {
6213
            error = GetLastError();
6214
        }
6215
    }
6216
    Py_END_ALLOW_THREADS
6217
6218
    if (error) {
6219
        return PyErr_SetFromWindowsErr(error);
6220
    }
6221
    if (!result) {
6222
        return path_error(path);
6223
    }
6224
#else
6225
214k
    Py_BEGIN_ALLOW_THREADS
6226
214k
#if HAVE_MKDIRAT
6227
214k
    if (dir_fd != DEFAULT_DIR_FD) {
6228
0
      if (HAVE_MKDIRAT_RUNTIME) {
6229
0
        result = mkdirat(dir_fd, path->narrow, mode);
6230
6231
0
      } else {
6232
0
        mkdirat_unavailable = 1;
6233
0
      }
6234
0
    } else
6235
214k
#endif
6236
#if defined(__WATCOMC__) && !defined(__QNX__)
6237
        result = mkdir(path->narrow);
6238
#else
6239
214k
        result = mkdir(path->narrow, mode);
6240
214k
#endif
6241
214k
    Py_END_ALLOW_THREADS
6242
6243
214k
#if HAVE_MKDIRAT
6244
214k
    if (mkdirat_unavailable) {
6245
0
        argument_unavailable_error(NULL, "dir_fd");
6246
0
        return NULL;
6247
0
    }
6248
214k
#endif
6249
6250
214k
    if (result < 0)
6251
419
        return path_error(path);
6252
213k
#endif /* MS_WINDOWS */
6253
214k
    Py_RETURN_NONE;
6254
214k
}
6255
6256
6257
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6258
#if defined(HAVE_SYS_RESOURCE_H)
6259
#include <sys/resource.h>
6260
#endif
6261
6262
6263
#ifdef HAVE_NICE
6264
/*[clinic input]
6265
os.nice
6266
6267
    increment: int
6268
    /
6269
6270
Add increment to the priority of process and return the new priority.
6271
[clinic start generated code]*/
6272
6273
static PyObject *
6274
os_nice_impl(PyObject *module, int increment)
6275
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6276
0
{
6277
0
    int value;
6278
6279
    /* There are two flavours of 'nice': one that returns the new
6280
       priority (as required by almost all standards out there) and the
6281
       Linux/FreeBSD one, which returns '0' on success and advices
6282
       the use of getpriority() to get the new priority.
6283
6284
       If we are of the nice family that returns the new priority, we
6285
       need to clear errno before the call, and check if errno is filled
6286
       before calling posix_error() on a returnvalue of -1, because the
6287
       -1 may be the actual new priority! */
6288
6289
0
    errno = 0;
6290
0
    value = nice(increment);
6291
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6292
    if (value == 0)
6293
        value = getpriority(PRIO_PROCESS, 0);
6294
#endif
6295
0
    if (value == -1 && errno != 0)
6296
        /* either nice() or getpriority() returned an error */
6297
0
        return posix_error();
6298
0
    return PyLong_FromLong((long) value);
6299
0
}
6300
#endif /* HAVE_NICE */
6301
6302
6303
#ifdef HAVE_GETPRIORITY
6304
/*[clinic input]
6305
os.getpriority
6306
6307
    which: int
6308
    who: int
6309
6310
Return program scheduling priority.
6311
[clinic start generated code]*/
6312
6313
static PyObject *
6314
os_getpriority_impl(PyObject *module, int which, int who)
6315
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6316
0
{
6317
0
    int retval;
6318
6319
0
    errno = 0;
6320
0
    retval = getpriority(which, who);
6321
0
    if (errno != 0)
6322
0
        return posix_error();
6323
0
    return PyLong_FromLong((long)retval);
6324
0
}
6325
#endif /* HAVE_GETPRIORITY */
6326
6327
6328
#ifdef HAVE_SETPRIORITY
6329
/*[clinic input]
6330
os.setpriority
6331
6332
    which: int
6333
    who: int
6334
    priority: int
6335
6336
Set program scheduling priority.
6337
[clinic start generated code]*/
6338
6339
static PyObject *
6340
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6341
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6342
0
{
6343
0
    int retval;
6344
6345
0
    retval = setpriority(which, who, priority);
6346
0
    if (retval == -1)
6347
0
        return posix_error();
6348
0
    Py_RETURN_NONE;
6349
0
}
6350
#endif /* HAVE_SETPRIORITY */
6351
6352
6353
static PyObject *
6354
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6355
175
{
6356
175
    const char *function_name = is_replace ? "replace" : "rename";
6357
175
    int dir_fd_specified;
6358
6359
175
#ifdef HAVE_RENAMEAT
6360
175
    int renameat_unavailable = 0;
6361
175
#endif
6362
6363
#ifdef MS_WINDOWS
6364
    BOOL result;
6365
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6366
#else
6367
175
    int result;
6368
175
#endif
6369
6370
175
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6371
175
                       (dst_dir_fd != DEFAULT_DIR_FD);
6372
#ifndef HAVE_RENAMEAT
6373
    if (dir_fd_specified) {
6374
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6375
        return NULL;
6376
    }
6377
#endif
6378
6379
175
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6380
175
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6381
175
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6382
0
        return NULL;
6383
0
    }
6384
6385
#ifdef MS_WINDOWS
6386
    Py_BEGIN_ALLOW_THREADS
6387
    result = MoveFileExW(src->wide, dst->wide, flags);
6388
    Py_END_ALLOW_THREADS
6389
6390
    if (!result)
6391
        return path_error2(src, dst);
6392
6393
#else
6394
175
    Py_BEGIN_ALLOW_THREADS
6395
175
#ifdef HAVE_RENAMEAT
6396
175
    if (dir_fd_specified) {
6397
0
        if (HAVE_RENAMEAT_RUNTIME) {
6398
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6399
0
        } else {
6400
0
            renameat_unavailable = 1;
6401
0
        }
6402
0
    } else
6403
175
#endif
6404
175
    result = rename(src->narrow, dst->narrow);
6405
175
    Py_END_ALLOW_THREADS
6406
6407
6408
175
#ifdef HAVE_RENAMEAT
6409
175
    if (renameat_unavailable) {
6410
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6411
0
        return NULL;
6412
0
    }
6413
175
#endif
6414
6415
175
    if (result)
6416
0
        return path_error2(src, dst);
6417
175
#endif
6418
175
    Py_RETURN_NONE;
6419
175
}
6420
6421
6422
/*[clinic input]
6423
@permit_long_docstring_body
6424
os.rename
6425
6426
    src : path_t
6427
    dst : path_t
6428
    *
6429
    src_dir_fd : dir_fd = None
6430
    dst_dir_fd : dir_fd = None
6431
6432
Rename a file or directory.
6433
6434
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6435
  descriptor open to a directory, and the respective path string (src or dst)
6436
  should be relative; the path will then be relative to that directory.
6437
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6438
  If they are unavailable, using them will raise a NotImplementedError.
6439
[clinic start generated code]*/
6440
6441
static PyObject *
6442
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6443
               int dst_dir_fd)
6444
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6445
5
{
6446
5
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6447
5
}
6448
6449
6450
/*[clinic input]
6451
@permit_long_docstring_body
6452
os.replace = os.rename
6453
6454
Rename a file or directory, overwriting the destination.
6455
6456
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6457
  descriptor open to a directory, and the respective path string (src or dst)
6458
  should be relative; the path will then be relative to that directory.
6459
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6460
  If they are unavailable, using them will raise a NotImplementedError.
6461
[clinic start generated code]*/
6462
6463
static PyObject *
6464
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6465
                int dst_dir_fd)
6466
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6467
170
{
6468
170
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6469
170
}
6470
6471
6472
/*[clinic input]
6473
os.rmdir
6474
6475
    path: path_t
6476
    *
6477
    dir_fd: dir_fd(requires='unlinkat') = None
6478
6479
Remove a directory.
6480
6481
If dir_fd is not None, it should be a file descriptor open to a directory,
6482
  and path should be relative; path will then be relative to that directory.
6483
dir_fd may not be implemented on your platform.
6484
  If it is unavailable, using it will raise a NotImplementedError.
6485
[clinic start generated code]*/
6486
6487
static PyObject *
6488
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6489
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6490
213k
{
6491
213k
    int result;
6492
213k
#ifdef HAVE_UNLINKAT
6493
213k
    int unlinkat_unavailable = 0;
6494
213k
#endif
6495
6496
213k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6497
213k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6498
0
        return NULL;
6499
0
    }
6500
6501
213k
    Py_BEGIN_ALLOW_THREADS
6502
#ifdef MS_WINDOWS
6503
    /* Windows, success=1, UNIX, success=0 */
6504
    result = !RemoveDirectoryW(path->wide);
6505
#else
6506
213k
#ifdef HAVE_UNLINKAT
6507
213k
    if (dir_fd != DEFAULT_DIR_FD) {
6508
209k
      if (HAVE_UNLINKAT_RUNTIME) {
6509
209k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6510
209k
      } else {
6511
0
        unlinkat_unavailable = 1;
6512
0
        result = -1;
6513
0
      }
6514
209k
    } else
6515
4.48k
#endif
6516
4.48k
        result = rmdir(path->narrow);
6517
213k
#endif
6518
213k
    Py_END_ALLOW_THREADS
6519
6520
213k
#ifdef HAVE_UNLINKAT
6521
213k
    if (unlinkat_unavailable) {
6522
0
        argument_unavailable_error("rmdir", "dir_fd");
6523
0
        return NULL;
6524
0
    }
6525
213k
#endif
6526
6527
213k
    if (result)
6528
5
        return path_error(path);
6529
6530
213k
    Py_RETURN_NONE;
6531
213k
}
6532
6533
6534
#ifdef HAVE_SYSTEM
6535
#ifdef MS_WINDOWS
6536
/*[clinic input]
6537
os.system -> long
6538
6539
    command: Py_UNICODE
6540
6541
Execute the command in a subshell.
6542
[clinic start generated code]*/
6543
6544
static long
6545
os_system_impl(PyObject *module, const wchar_t *command)
6546
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6547
{
6548
    long result;
6549
6550
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6551
        return -1;
6552
    }
6553
6554
    Py_BEGIN_ALLOW_THREADS
6555
    _Py_BEGIN_SUPPRESS_IPH
6556
    result = _wsystem(command);
6557
    _Py_END_SUPPRESS_IPH
6558
    Py_END_ALLOW_THREADS
6559
    return result;
6560
}
6561
#else /* MS_WINDOWS */
6562
/*[clinic input]
6563
os.system -> long
6564
6565
    command: unicode_fs_encoded
6566
6567
Execute the command in a subshell.
6568
[clinic start generated code]*/
6569
6570
static long
6571
os_system_impl(PyObject *module, PyObject *command)
6572
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6573
0
{
6574
0
    long result;
6575
0
    const char *bytes = PyBytes_AsString(command);
6576
6577
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6578
0
        return -1;
6579
0
    }
6580
6581
0
    Py_BEGIN_ALLOW_THREADS
6582
0
    result = system(bytes);
6583
0
    Py_END_ALLOW_THREADS
6584
0
    return result;
6585
0
}
6586
#endif
6587
#endif /* HAVE_SYSTEM */
6588
6589
6590
#ifdef HAVE_UMASK
6591
/*[clinic input]
6592
os.umask
6593
6594
    mask: int
6595
    /
6596
6597
Set the current numeric umask and return the previous umask.
6598
[clinic start generated code]*/
6599
6600
static PyObject *
6601
os_umask_impl(PyObject *module, int mask)
6602
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6603
0
{
6604
0
    int i = (int)umask(mask);
6605
0
    if (i < 0)
6606
0
        return posix_error();
6607
0
    return PyLong_FromLong((long)i);
6608
0
}
6609
#endif
6610
6611
#ifdef MS_WINDOWS
6612
6613
/* override the default DeleteFileW behavior so that directory
6614
symlinks can be removed with this function, the same as with
6615
Unix symlinks */
6616
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6617
{
6618
    WIN32_FILE_ATTRIBUTE_DATA info;
6619
    WIN32_FIND_DATAW find_data;
6620
    HANDLE find_data_handle;
6621
    int is_directory = 0;
6622
    int is_link = 0;
6623
6624
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6625
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6626
6627
        /* Get WIN32_FIND_DATA structure for the path to determine if
6628
           it is a symlink */
6629
        if(is_directory &&
6630
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6631
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6632
6633
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6634
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6635
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6636
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6637
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6638
                FindClose(find_data_handle);
6639
            }
6640
        }
6641
    }
6642
6643
    if (is_directory && is_link)
6644
        return RemoveDirectoryW(lpFileName);
6645
6646
    return DeleteFileW(lpFileName);
6647
}
6648
#endif /* MS_WINDOWS */
6649
6650
6651
/*[clinic input]
6652
os.unlink
6653
6654
    path: path_t
6655
    *
6656
    dir_fd: dir_fd(requires='unlinkat')=None
6657
6658
Remove a file (same as remove()).
6659
6660
If dir_fd is not None, it should be a file descriptor open to a directory,
6661
  and path should be relative; path will then be relative to that directory.
6662
dir_fd may not be implemented on your platform.
6663
  If it is unavailable, using it will raise a NotImplementedError.
6664
6665
[clinic start generated code]*/
6666
6667
static PyObject *
6668
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6669
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6670
25.2k
{
6671
25.2k
    int result;
6672
25.2k
#ifdef HAVE_UNLINKAT
6673
25.2k
    int unlinkat_unavailable = 0;
6674
25.2k
#endif
6675
6676
25.2k
    if (PySys_Audit("os.remove", "Oi", path->object,
6677
25.2k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6678
0
        return NULL;
6679
0
    }
6680
6681
25.2k
    Py_BEGIN_ALLOW_THREADS
6682
25.2k
    _Py_BEGIN_SUPPRESS_IPH
6683
#ifdef MS_WINDOWS
6684
    /* Windows, success=1, UNIX, success=0 */
6685
    result = !Py_DeleteFileW(path->wide);
6686
#else
6687
25.2k
#ifdef HAVE_UNLINKAT
6688
25.2k
    if (dir_fd != DEFAULT_DIR_FD) {
6689
25.1k
      if (HAVE_UNLINKAT_RUNTIME) {
6690
6691
25.1k
        result = unlinkat(dir_fd, path->narrow, 0);
6692
25.1k
      } else {
6693
0
        unlinkat_unavailable = 1;
6694
0
      }
6695
25.1k
    } else
6696
2
#endif /* HAVE_UNLINKAT */
6697
2
        result = unlink(path->narrow);
6698
25.2k
#endif
6699
25.2k
    _Py_END_SUPPRESS_IPH
6700
25.2k
    Py_END_ALLOW_THREADS
6701
6702
25.2k
#ifdef HAVE_UNLINKAT
6703
25.2k
    if (unlinkat_unavailable) {
6704
0
        argument_unavailable_error(NULL, "dir_fd");
6705
0
        return NULL;
6706
0
    }
6707
25.2k
#endif
6708
6709
25.2k
    if (result)
6710
0
        return path_error(path);
6711
6712
25.2k
    Py_RETURN_NONE;
6713
25.2k
}
6714
6715
6716
/*[clinic input]
6717
os.remove = os.unlink
6718
6719
Remove a file (same as unlink()).
6720
6721
If dir_fd is not None, it should be a file descriptor open to a directory,
6722
  and path should be relative; path will then be relative to that directory.
6723
dir_fd may not be implemented on your platform.
6724
  If it is unavailable, using it will raise a NotImplementedError.
6725
[clinic start generated code]*/
6726
6727
static PyObject *
6728
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6729
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6730
0
{
6731
0
    return os_unlink_impl(module, path, dir_fd);
6732
0
}
6733
6734
6735
static PyStructSequence_Field uname_result_fields[] = {
6736
    {"sysname",    "operating system name"},
6737
    {"nodename",   "name of machine on network (implementation-defined)"},
6738
    {"release",    "operating system release"},
6739
    {"version",    "operating system version"},
6740
    {"machine",    "hardware identifier"},
6741
    {NULL}
6742
};
6743
6744
PyDoc_STRVAR(uname_result__doc__,
6745
"uname_result: Result from os.uname().\n\n\
6746
This object may be accessed either as a tuple of\n\
6747
  (sysname, nodename, release, version, machine),\n\
6748
or via the attributes sysname, nodename, release, version, and machine.\n\
6749
\n\
6750
See os.uname for more information.");
6751
6752
static PyStructSequence_Desc uname_result_desc = {
6753
    MODNAME ".uname_result", /* name */
6754
    uname_result__doc__, /* doc */
6755
    uname_result_fields,
6756
    5
6757
};
6758
6759
#ifdef HAVE_UNAME
6760
/*[clinic input]
6761
os.uname
6762
6763
Return an object identifying the current operating system.
6764
6765
The object behaves like a named tuple with the following fields:
6766
  (sysname, nodename, release, version, machine)
6767
6768
[clinic start generated code]*/
6769
6770
static PyObject *
6771
os_uname_impl(PyObject *module)
6772
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6773
4
{
6774
4
    struct utsname u;
6775
4
    int res;
6776
4
    PyObject *value;
6777
6778
4
    Py_BEGIN_ALLOW_THREADS
6779
4
    res = uname(&u);
6780
4
    Py_END_ALLOW_THREADS
6781
4
    if (res < 0)
6782
0
        return posix_error();
6783
6784
4
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6785
4
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6786
4
    if (value == NULL)
6787
0
        return NULL;
6788
6789
4
#define SET(i, field) \
6790
20
    { \
6791
20
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6792
20
    if (!o) { \
6793
0
        Py_DECREF(value); \
6794
0
        return NULL; \
6795
0
    } \
6796
20
    PyStructSequence_SET_ITEM(value, i, o); \
6797
20
    } \
6798
4
6799
8
    SET(0, u.sysname);
6800
8
    SET(1, u.nodename);
6801
4
    SET(2, u.release);
6802
4
    SET(3, u.version);
6803
4
    SET(4, u.machine);
6804
6805
4
#undef SET
6806
6807
4
    return value;
6808
4
}
6809
#endif /* HAVE_UNAME */
6810
6811
6812
6813
typedef struct {
6814
    int    now;
6815
    time_t atime_s;
6816
    long   atime_ns;
6817
    time_t mtime_s;
6818
    long   mtime_ns;
6819
} utime_t;
6820
6821
/*
6822
 * these macros assume that "ut" is a pointer to a utime_t
6823
 * they also intentionally leak the declaration of a pointer named "time"
6824
 */
6825
#define UTIME_TO_TIMESPEC \
6826
0
    struct timespec ts[2]; \
6827
0
    struct timespec *time; \
6828
0
    if (ut->now) \
6829
0
        time = NULL; \
6830
0
    else { \
6831
0
        ts[0].tv_sec = ut->atime_s; \
6832
0
        ts[0].tv_nsec = ut->atime_ns; \
6833
0
        ts[1].tv_sec = ut->mtime_s; \
6834
0
        ts[1].tv_nsec = ut->mtime_ns; \
6835
0
        time = ts; \
6836
0
    } \
6837
6838
#define UTIME_TO_TIMEVAL \
6839
0
    struct timeval tv[2]; \
6840
0
    struct timeval *time; \
6841
0
    if (ut->now) \
6842
0
        time = NULL; \
6843
0
    else { \
6844
0
        tv[0].tv_sec = ut->atime_s; \
6845
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6846
0
        tv[1].tv_sec = ut->mtime_s; \
6847
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6848
0
        time = tv; \
6849
0
    } \
6850
6851
#define UTIME_TO_UTIMBUF \
6852
    struct utimbuf u; \
6853
    struct utimbuf *time; \
6854
    if (ut->now) \
6855
        time = NULL; \
6856
    else { \
6857
        u.actime = ut->atime_s; \
6858
        u.modtime = ut->mtime_s; \
6859
        time = &u; \
6860
    }
6861
6862
#define UTIME_TO_TIME_T \
6863
    time_t timet[2]; \
6864
    time_t *time; \
6865
    if (ut->now) \
6866
        time = NULL; \
6867
    else { \
6868
        timet[0] = ut->atime_s; \
6869
        timet[1] = ut->mtime_s; \
6870
        time = timet; \
6871
    } \
6872
6873
6874
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6875
6876
static int
6877
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6878
0
{
6879
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6880
    if (HAVE_UTIMENSAT_RUNTIME) {
6881
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6882
        UTIME_TO_TIMESPEC;
6883
        return utimensat(dir_fd, path, time, flags);
6884
    }  else {
6885
        errno = ENOSYS;
6886
        return -1;
6887
    }
6888
#elif defined(HAVE_UTIMENSAT)
6889
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6890
0
    UTIME_TO_TIMESPEC;
6891
0
    return utimensat(dir_fd, path, time, flags);
6892
#elif defined(HAVE_FUTIMESAT)
6893
    UTIME_TO_TIMEVAL;
6894
    /*
6895
     * follow_symlinks will never be false here;
6896
     * we only allow !follow_symlinks and dir_fd together
6897
     * if we have utimensat()
6898
     */
6899
    assert(follow_symlinks);
6900
    return futimesat(dir_fd, path, time);
6901
#endif
6902
0
}
6903
6904
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6905
#else
6906
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6907
#endif
6908
6909
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6910
6911
static int
6912
utime_fd(utime_t *ut, int fd)
6913
0
{
6914
0
#ifdef HAVE_FUTIMENS
6915
6916
0
    if (HAVE_FUTIMENS_RUNTIME) {
6917
6918
0
    UTIME_TO_TIMESPEC;
6919
0
    return futimens(fd, time);
6920
6921
0
    } else
6922
#ifndef HAVE_FUTIMES
6923
    {
6924
        /* Not sure if this can happen */
6925
        PyErr_SetString(
6926
            PyExc_RuntimeError,
6927
            "neither futimens nor futimes are supported"
6928
            " on this system");
6929
        return -1;
6930
    }
6931
#endif
6932
6933
0
#endif
6934
0
#ifdef HAVE_FUTIMES
6935
0
    {
6936
0
    UTIME_TO_TIMEVAL;
6937
0
    return futimes(fd, time);
6938
0
    }
6939
0
#endif
6940
0
}
6941
6942
    #define PATH_UTIME_HAVE_FD 1
6943
#else
6944
    #define PATH_UTIME_HAVE_FD 0
6945
#endif
6946
6947
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6948
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6949
#endif
6950
6951
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6952
6953
static int
6954
utime_nofollow_symlinks(utime_t *ut, const char *path)
6955
0
{
6956
0
#ifdef HAVE_UTIMENSAT
6957
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6958
0
        UTIME_TO_TIMESPEC;
6959
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6960
0
    } else
6961
#ifndef HAVE_LUTIMES
6962
    {
6963
        /* Not sure if this can happen */
6964
        PyErr_SetString(
6965
            PyExc_RuntimeError,
6966
            "neither utimensat nor lutimes are supported"
6967
            " on this system");
6968
        return -1;
6969
    }
6970
#endif
6971
0
#endif
6972
6973
0
#ifdef HAVE_LUTIMES
6974
0
    {
6975
0
    UTIME_TO_TIMEVAL;
6976
0
    return lutimes(path, time);
6977
0
    }
6978
0
#endif
6979
0
}
6980
6981
#endif
6982
6983
#ifndef MS_WINDOWS
6984
6985
static int
6986
utime_default(utime_t *ut, const char *path)
6987
0
{
6988
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6989
    if (HAVE_UTIMENSAT_RUNTIME) {
6990
        UTIME_TO_TIMESPEC;
6991
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6992
    } else {
6993
        UTIME_TO_TIMEVAL;
6994
        return utimes(path, time);
6995
    }
6996
#elif defined(HAVE_UTIMENSAT)
6997
0
    UTIME_TO_TIMESPEC;
6998
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6999
#elif defined(HAVE_UTIMES)
7000
    UTIME_TO_TIMEVAL;
7001
    return utimes(path, time);
7002
#elif defined(HAVE_UTIME_H)
7003
    UTIME_TO_UTIMBUF;
7004
    return utime(path, time);
7005
#else
7006
    UTIME_TO_TIME_T;
7007
    return utime(path, time);
7008
#endif
7009
0
}
7010
7011
#endif
7012
7013
static int
7014
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7015
0
{
7016
0
    int result = 0;
7017
0
    PyObject *divmod;
7018
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7019
0
    if (!divmod)
7020
0
        goto exit;
7021
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7022
0
        PyErr_Format(PyExc_TypeError,
7023
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7024
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7025
0
        goto exit;
7026
0
    }
7027
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7028
0
    if ((*s == -1) && PyErr_Occurred())
7029
0
        goto exit;
7030
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7031
0
    if ((*ns == -1) && PyErr_Occurred())
7032
0
        goto exit;
7033
7034
0
    result = 1;
7035
0
exit:
7036
0
    Py_XDECREF(divmod);
7037
0
    return result;
7038
0
}
7039
7040
7041
/*[clinic input]
7042
os.utime
7043
7044
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7045
    times: object = None
7046
    *
7047
    ns: object = NULL
7048
    dir_fd: dir_fd(requires='futimensat') = None
7049
    follow_symlinks: bool=True
7050
7051
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
7052
7053
Set the access and modified time of path.
7054
7055
path may always be specified as a string.
7056
On some platforms, path may also be specified as an open file descriptor.
7057
  If this functionality is unavailable, using it raises an exception.
7058
7059
If times is not None, it must be a tuple (atime, mtime);
7060
    atime and mtime should be expressed as float seconds since the epoch.
7061
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7062
    atime_ns and mtime_ns should be expressed as integer nanoseconds
7063
    since the epoch.
7064
If times is None and ns is unspecified, utime uses the current time.
7065
Specifying tuples for both times and ns is an error.
7066
7067
If dir_fd is not None, it should be a file descriptor open to a directory,
7068
  and path should be relative; path will then be relative to that directory.
7069
If follow_symlinks is False, and the last element of the path is a symbolic
7070
  link, utime will modify the symbolic link itself instead of the file the
7071
  link points to.
7072
It is an error to use dir_fd or follow_symlinks when specifying path
7073
  as an open file descriptor.
7074
dir_fd and follow_symlinks may not be available on your platform.
7075
  If they are unavailable, using them will raise a NotImplementedError.
7076
7077
[clinic start generated code]*/
7078
7079
static PyObject *
7080
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7081
              int dir_fd, int follow_symlinks)
7082
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
7083
0
{
7084
#ifdef MS_WINDOWS
7085
    HANDLE hFile;
7086
    FILETIME atime, mtime;
7087
#else
7088
0
    int result;
7089
0
#endif
7090
7091
0
    utime_t utime;
7092
7093
0
    memset(&utime, 0, sizeof(utime_t));
7094
7095
0
    if (times != Py_None && ns) {
7096
0
        PyErr_SetString(PyExc_ValueError,
7097
0
                     "utime: you may specify either 'times'"
7098
0
                     " or 'ns' but not both");
7099
0
        return NULL;
7100
0
    }
7101
7102
0
    if (times != Py_None) {
7103
0
        time_t a_sec, m_sec;
7104
0
        long a_nsec, m_nsec;
7105
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7106
0
            PyErr_SetString(PyExc_TypeError,
7107
0
                         "utime: 'times' must be either"
7108
0
                         " a tuple of two numbers or None");
7109
0
            return NULL;
7110
0
        }
7111
0
        utime.now = 0;
7112
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7113
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7114
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7115
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7116
0
            return NULL;
7117
0
        }
7118
0
        utime.atime_s = a_sec;
7119
0
        utime.atime_ns = a_nsec;
7120
0
        utime.mtime_s = m_sec;
7121
0
        utime.mtime_ns = m_nsec;
7122
0
    }
7123
0
    else if (ns) {
7124
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7125
0
            PyErr_SetString(PyExc_TypeError,
7126
0
                         "utime: 'ns' must be a tuple of two ints");
7127
0
            return NULL;
7128
0
        }
7129
0
        utime.now = 0;
7130
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7131
0
                                      &utime.atime_s, &utime.atime_ns) ||
7132
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7133
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7134
0
            return NULL;
7135
0
        }
7136
0
    }
7137
0
    else {
7138
        /* times and ns are both None/unspecified. use "now". */
7139
0
        utime.now = 1;
7140
0
    }
7141
7142
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7143
    if (follow_symlinks_specified("utime", follow_symlinks))
7144
        return NULL;
7145
#endif
7146
7147
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7148
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7149
0
        fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
7150
0
        return NULL;
7151
7152
#if !defined(HAVE_UTIMENSAT)
7153
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7154
        PyErr_SetString(PyExc_ValueError,
7155
                     "utime: cannot use dir_fd and follow_symlinks "
7156
                     "together on this platform");
7157
        return NULL;
7158
    }
7159
#endif
7160
7161
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7162
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7163
0
        return NULL;
7164
0
    }
7165
7166
#ifdef MS_WINDOWS
7167
    Py_BEGIN_ALLOW_THREADS
7168
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7169
                        NULL, OPEN_EXISTING,
7170
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7171
    Py_END_ALLOW_THREADS
7172
    if (hFile == INVALID_HANDLE_VALUE) {
7173
        path_error(path);
7174
        return NULL;
7175
    }
7176
7177
    if (utime.now) {
7178
        GetSystemTimeAsFileTime(&mtime);
7179
        atime = mtime;
7180
    }
7181
    else {
7182
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7183
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7184
    }
7185
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7186
        path_error(path);
7187
        CloseHandle(hFile);
7188
        return NULL;
7189
    }
7190
    CloseHandle(hFile);
7191
#else /* MS_WINDOWS */
7192
0
    Py_BEGIN_ALLOW_THREADS
7193
7194
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7195
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7196
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7197
0
    else
7198
0
#endif
7199
7200
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7201
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7202
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7203
7204
0
    } else
7205
0
#endif
7206
7207
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7208
0
    if (path->is_fd)
7209
0
        result = utime_fd(&utime, path->fd);
7210
0
    else
7211
0
#endif
7212
7213
0
    result = utime_default(&utime, path->narrow);
7214
7215
0
    Py_END_ALLOW_THREADS
7216
7217
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7218
    /* See utime_dir_fd implementation */
7219
    if (result == -1 && errno == ENOSYS) {
7220
        argument_unavailable_error(NULL, "dir_fd");
7221
        return NULL;
7222
    }
7223
#endif
7224
7225
0
    if (result < 0) {
7226
0
        path_error(path);
7227
0
        return NULL;
7228
0
    }
7229
7230
0
#endif /* MS_WINDOWS */
7231
7232
0
    Py_RETURN_NONE;
7233
0
}
7234
7235
/* Process operations */
7236
7237
7238
/*[clinic input]
7239
os._exit
7240
7241
    status: int
7242
7243
Exit to the system with specified status, without normal exit processing.
7244
[clinic start generated code]*/
7245
7246
static PyObject *
7247
os__exit_impl(PyObject *module, int status)
7248
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
7249
0
{
7250
0
    _exit(status);
7251
0
    return NULL; /* Make gcc -Wall happy */
7252
0
}
7253
7254
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7255
#define EXECV_CHAR wchar_t
7256
#else
7257
0
#define EXECV_CHAR char
7258
#endif
7259
7260
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7261
static void
7262
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7263
0
{
7264
0
    Py_ssize_t i;
7265
0
    for (i = 0; i < count; i++)
7266
0
        PyMem_Free(array[i]);
7267
0
    PyMem_Free(array);
7268
0
}
7269
7270
static int
7271
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7272
0
{
7273
0
    Py_ssize_t size;
7274
0
    PyObject *ub;
7275
0
    int result = 0;
7276
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7277
    if (!PyUnicode_FSDecoder(o, &ub))
7278
        return 0;
7279
    *out = PyUnicode_AsWideCharString(ub, &size);
7280
    if (*out)
7281
        result = 1;
7282
#else
7283
0
    if (!PyUnicode_FSConverter(o, &ub))
7284
0
        return 0;
7285
0
    size = PyBytes_GET_SIZE(ub);
7286
0
    *out = PyMem_Malloc(size + 1);
7287
0
    if (*out) {
7288
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7289
0
        result = 1;
7290
0
    } else
7291
0
        PyErr_NoMemory();
7292
0
#endif
7293
0
    Py_DECREF(ub);
7294
0
    return result;
7295
0
}
7296
#endif
7297
7298
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7299
static EXECV_CHAR**
7300
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7301
0
{
7302
0
    Py_ssize_t i, pos, envc;
7303
0
    PyObject *keys = NULL, *vals = NULL;
7304
0
    PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
7305
0
    EXECV_CHAR **envlist;
7306
7307
0
    i = PyMapping_Size(env);
7308
0
    if (i < 0)
7309
0
        return NULL;
7310
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7311
0
    if (envlist == NULL) {
7312
0
        PyErr_NoMemory();
7313
0
        return NULL;
7314
0
    }
7315
0
    envc = 0;
7316
0
    keys = PyMapping_Keys(env);
7317
0
    if (!keys)
7318
0
        goto error;
7319
0
    vals = PyMapping_Values(env);
7320
0
    if (!vals)
7321
0
        goto error;
7322
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7323
0
        PyErr_Format(PyExc_TypeError,
7324
0
                     "env.keys() or env.values() is not a list");
7325
0
        goto error;
7326
0
    }
7327
7328
0
    for (pos = 0; pos < i; pos++) {
7329
        // The 'key' and 'val' must be strong references because of
7330
        // possible side-effects by PyUnicode_FS{Converter,Decoder}().
7331
0
        key = PyList_GetItemRef(keys, pos);
7332
0
        if (key == NULL) {
7333
0
            goto error;
7334
0
        }
7335
0
        val = PyList_GetItemRef(vals, pos);
7336
0
        if (val == NULL) {
7337
0
            goto error;
7338
0
        }
7339
7340
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7341
        if (!PyUnicode_FSDecoder(key, &key2)) {
7342
            goto error;
7343
        }
7344
        if (!PyUnicode_FSDecoder(val, &val2)) {
7345
            goto error;
7346
        }
7347
        /* Search from index 1 because on Windows starting '=' is allowed for
7348
           defining hidden environment variables. */
7349
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7350
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7351
        {
7352
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7353
            goto error;
7354
        }
7355
        PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7356
#else
7357
0
        if (!PyUnicode_FSConverter(key, &key2)) {
7358
0
            goto error;
7359
0
        }
7360
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7361
0
            goto error;
7362
0
        }
7363
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7364
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7365
0
        {
7366
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7367
0
            goto error;
7368
0
        }
7369
0
        PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7370
0
                                              PyBytes_AS_STRING(val2));
7371
0
#endif
7372
0
        if (!keyval) {
7373
0
            goto error;
7374
0
        }
7375
7376
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7377
0
            Py_DECREF(keyval);
7378
0
            goto error;
7379
0
        }
7380
7381
0
        Py_CLEAR(key);
7382
0
        Py_CLEAR(val);
7383
0
        Py_CLEAR(key2);
7384
0
        Py_CLEAR(val2);
7385
0
        Py_DECREF(keyval);
7386
0
    }
7387
0
    Py_DECREF(vals);
7388
0
    Py_DECREF(keys);
7389
7390
0
    envlist[envc] = 0;
7391
0
    *envc_ptr = envc;
7392
0
    return envlist;
7393
7394
0
error:
7395
0
    Py_XDECREF(key);
7396
0
    Py_XDECREF(val);
7397
0
    Py_XDECREF(key2);
7398
0
    Py_XDECREF(val2);
7399
0
    Py_XDECREF(keys);
7400
0
    Py_XDECREF(vals);
7401
0
    free_string_array(envlist, envc);
7402
0
    return NULL;
7403
0
}
7404
7405
static EXECV_CHAR**
7406
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7407
0
{
7408
0
    int i;
7409
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7410
0
    if (argvlist == NULL) {
7411
0
        PyErr_NoMemory();
7412
0
        return NULL;
7413
0
    }
7414
0
    for (i = 0; i < *argc; i++) {
7415
0
        PyObject* item = PySequence_ITEM(argv, i);
7416
0
        if (item == NULL)
7417
0
            goto fail;
7418
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7419
0
            Py_DECREF(item);
7420
0
            goto fail;
7421
0
        }
7422
0
        Py_DECREF(item);
7423
0
    }
7424
0
    argvlist[*argc] = NULL;
7425
0
    return argvlist;
7426
0
fail:
7427
0
    *argc = i;
7428
0
    free_string_array(argvlist, *argc);
7429
0
    return NULL;
7430
0
}
7431
7432
#endif
7433
7434
7435
#ifdef HAVE_EXECV
7436
/*[clinic input]
7437
os.execv
7438
7439
    path: path_t
7440
        Path of executable file.
7441
    argv: object
7442
        Tuple or list of strings.
7443
    /
7444
7445
Execute an executable path with arguments, replacing current process.
7446
[clinic start generated code]*/
7447
7448
static PyObject *
7449
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7450
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7451
0
{
7452
0
    EXECV_CHAR **argvlist;
7453
0
    Py_ssize_t argc;
7454
7455
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7456
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7457
0
        PyErr_SetString(PyExc_RuntimeError,
7458
0
                        "exec not supported for isolated subinterpreters");
7459
0
        return NULL;
7460
0
    }
7461
7462
    /* execv has two arguments: (path, argv), where
7463
       argv is a list or tuple of strings. */
7464
7465
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7466
0
        PyErr_SetString(PyExc_TypeError,
7467
0
                        "execv() arg 2 must be a tuple or list");
7468
0
        return NULL;
7469
0
    }
7470
0
    argc = PySequence_Size(argv);
7471
0
    if (argc < 1) {
7472
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7473
0
        return NULL;
7474
0
    }
7475
7476
0
    argvlist = parse_arglist(argv, &argc);
7477
0
    if (argvlist == NULL) {
7478
0
        return NULL;
7479
0
    }
7480
0
    if (!argvlist[0][0]) {
7481
0
        PyErr_SetString(PyExc_ValueError,
7482
0
            "execv() arg 2 first element cannot be empty");
7483
0
        free_string_array(argvlist, argc);
7484
0
        return NULL;
7485
0
    }
7486
7487
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7488
0
        free_string_array(argvlist, argc);
7489
0
        return NULL;
7490
0
    }
7491
7492
0
    _Py_BEGIN_SUPPRESS_IPH
7493
#ifdef HAVE_WEXECV
7494
    _wexecv(path->wide, argvlist);
7495
#else
7496
0
    execv(path->narrow, argvlist);
7497
0
#endif
7498
0
    _Py_END_SUPPRESS_IPH
7499
7500
    /* If we get here it's definitely an error */
7501
7502
0
    posix_error();
7503
0
    free_string_array(argvlist, argc);
7504
0
    return NULL;
7505
0
}
7506
7507
7508
/*[clinic input]
7509
os.execve
7510
7511
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7512
        Path of executable file.
7513
    argv: object
7514
        Tuple or list of strings.
7515
    env: object
7516
        Dictionary of strings mapping to strings.
7517
7518
Execute an executable path with arguments, replacing current process.
7519
[clinic start generated code]*/
7520
7521
static PyObject *
7522
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7523
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7524
0
{
7525
0
    EXECV_CHAR **argvlist = NULL;
7526
0
    EXECV_CHAR **envlist;
7527
0
    Py_ssize_t argc, envc;
7528
7529
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7530
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7531
0
        PyErr_SetString(PyExc_RuntimeError,
7532
0
                        "exec not supported for isolated subinterpreters");
7533
0
        return NULL;
7534
0
    }
7535
7536
    /* execve has three arguments: (path, argv, env), where
7537
       argv is a list or tuple of strings and env is a dictionary
7538
       like posix.environ. */
7539
7540
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7541
0
        PyErr_SetString(PyExc_TypeError,
7542
0
                        "execve: argv must be a tuple or list");
7543
0
        goto fail_0;
7544
0
    }
7545
0
    argc = PySequence_Size(argv);
7546
0
    if (argc < 1) {
7547
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7548
0
        return NULL;
7549
0
    }
7550
7551
0
    if (!PyMapping_Check(env)) {
7552
0
        PyErr_SetString(PyExc_TypeError,
7553
0
                        "execve: environment must be a mapping object");
7554
0
        goto fail_0;
7555
0
    }
7556
7557
0
    argvlist = parse_arglist(argv, &argc);
7558
0
    if (argvlist == NULL) {
7559
0
        goto fail_0;
7560
0
    }
7561
0
    if (!argvlist[0][0]) {
7562
0
        PyErr_SetString(PyExc_ValueError,
7563
0
            "execve: argv first element cannot be empty");
7564
0
        goto fail_0;
7565
0
    }
7566
7567
0
    envlist = parse_envlist(env, &envc);
7568
0
    if (envlist == NULL)
7569
0
        goto fail_0;
7570
7571
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7572
0
        goto fail_1;
7573
0
    }
7574
7575
0
    _Py_BEGIN_SUPPRESS_IPH
7576
0
#ifdef HAVE_FEXECVE
7577
0
    if (path->is_fd)
7578
0
        fexecve(path->fd, argvlist, envlist);
7579
0
    else
7580
0
#endif
7581
#ifdef HAVE_WEXECV
7582
        _wexecve(path->wide, argvlist, envlist);
7583
#else
7584
0
        execve(path->narrow, argvlist, envlist);
7585
0
#endif
7586
0
    _Py_END_SUPPRESS_IPH
7587
7588
    /* If we get here it's definitely an error */
7589
7590
0
    posix_path_error(path);
7591
0
  fail_1:
7592
0
    free_string_array(envlist, envc);
7593
0
  fail_0:
7594
0
    if (argvlist)
7595
0
        free_string_array(argvlist, argc);
7596
0
    return NULL;
7597
0
}
7598
7599
#endif /* HAVE_EXECV */
7600
7601
#ifdef HAVE_POSIX_SPAWN
7602
7603
enum posix_spawn_file_actions_identifier {
7604
    POSIX_SPAWN_OPEN,
7605
    POSIX_SPAWN_CLOSE,
7606
    POSIX_SPAWN_DUP2
7607
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7608
    ,POSIX_SPAWN_CLOSEFROM
7609
#endif
7610
};
7611
7612
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7613
static int
7614
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7615
#endif
7616
7617
static int
7618
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7619
                        int resetids, int setsid, PyObject *setsigmask,
7620
                        PyObject *setsigdef, PyObject *scheduler,
7621
                        posix_spawnattr_t *attrp)
7622
0
{
7623
0
    assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
7624
0
    long all_flags = 0;
7625
7626
0
    errno = posix_spawnattr_init(attrp);
7627
0
    if (errno) {
7628
0
        posix_error();
7629
0
        return -1;
7630
0
    }
7631
7632
0
    if (setpgroup && setpgroup != Py_None) {
7633
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7634
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7635
0
            goto fail;
7636
0
        }
7637
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7638
0
        if (errno) {
7639
0
            posix_error();
7640
0
            goto fail;
7641
0
        }
7642
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7643
0
    }
7644
7645
0
    if (resetids) {
7646
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7647
0
    }
7648
7649
0
    if (setsid) {
7650
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7651
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7652
#endif
7653
0
#ifdef POSIX_SPAWN_SETSID
7654
0
        all_flags |= POSIX_SPAWN_SETSID;
7655
#elif defined(POSIX_SPAWN_SETSID_NP)
7656
        all_flags |= POSIX_SPAWN_SETSID_NP;
7657
#else
7658
        argument_unavailable_error(func_name, "setsid");
7659
        return -1;
7660
#endif
7661
7662
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7663
        } else {
7664
            argument_unavailable_error(func_name, "setsid");
7665
            return -1;
7666
        }
7667
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7668
7669
0
    }
7670
7671
0
#ifdef HAVE_SIGSET_T
7672
0
   if (setsigmask) {
7673
0
        sigset_t set;
7674
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7675
0
            goto fail;
7676
0
        }
7677
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7678
0
        if (errno) {
7679
0
            posix_error();
7680
0
            goto fail;
7681
0
        }
7682
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7683
0
    }
7684
7685
0
    if (setsigdef) {
7686
0
        sigset_t set;
7687
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7688
0
            goto fail;
7689
0
        }
7690
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7691
0
        if (errno) {
7692
0
            posix_error();
7693
0
            goto fail;
7694
0
        }
7695
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7696
0
    }
7697
#else
7698
    if (setsigmask || setsigdef) {
7699
        PyErr_SetString(PyExc_NotImplementedError,
7700
                        "sigset is not supported on this platform");
7701
        goto fail;
7702
    }
7703
#endif
7704
7705
0
    if (scheduler && scheduler != Py_None) {
7706
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7707
0
        PyObject *py_schedpolicy;
7708
0
        PyObject *schedparam_obj;
7709
0
        struct sched_param schedparam;
7710
7711
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7712
0
                        ";A scheduler tuple must have two elements",
7713
0
                        &py_schedpolicy, &schedparam_obj)) {
7714
0
            goto fail;
7715
0
        }
7716
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7717
0
            goto fail;
7718
0
        }
7719
0
        if (py_schedpolicy != Py_None) {
7720
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7721
7722
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7723
0
                goto fail;
7724
0
            }
7725
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7726
0
            if (errno) {
7727
0
                posix_error();
7728
0
                goto fail;
7729
0
            }
7730
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7731
0
        }
7732
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7733
0
        if (errno) {
7734
0
            posix_error();
7735
0
            goto fail;
7736
0
        }
7737
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7738
#else
7739
        PyErr_SetString(PyExc_NotImplementedError,
7740
                "The scheduler option is not supported in this system.");
7741
        goto fail;
7742
#endif
7743
0
    }
7744
7745
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7746
0
    if (errno) {
7747
0
        posix_error();
7748
0
        goto fail;
7749
0
    }
7750
7751
0
    return 0;
7752
7753
0
fail:
7754
0
    (void)posix_spawnattr_destroy(attrp);
7755
0
    return -1;
7756
0
}
7757
7758
static int
7759
parse_file_actions(PyObject *file_actions,
7760
                   posix_spawn_file_actions_t *file_actionsp,
7761
                   PyObject *temp_buffer)
7762
0
{
7763
0
    PyObject *seq;
7764
0
    PyObject *file_action = NULL;
7765
0
    PyObject *tag_obj;
7766
7767
0
    seq = PySequence_Fast(file_actions,
7768
0
                          "file_actions must be a sequence or None");
7769
0
    if (seq == NULL) {
7770
0
        return -1;
7771
0
    }
7772
7773
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7774
0
    if (errno) {
7775
0
        posix_error();
7776
0
        Py_DECREF(seq);
7777
0
        return -1;
7778
0
    }
7779
7780
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7781
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7782
0
        Py_INCREF(file_action);
7783
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7784
0
            PyErr_SetString(PyExc_TypeError,
7785
0
                "Each file_actions element must be a non-empty tuple");
7786
0
            goto fail;
7787
0
        }
7788
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7789
0
        if (tag == -1 && PyErr_Occurred()) {
7790
0
            goto fail;
7791
0
        }
7792
7793
        /* Populate the file_actions object */
7794
0
        switch (tag) {
7795
0
            case POSIX_SPAWN_OPEN: {
7796
0
                int fd, oflag;
7797
0
                PyObject *path;
7798
0
                unsigned long mode;
7799
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7800
0
                        ";A open file_action tuple must have 5 elements",
7801
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7802
0
                        &oflag, &mode))
7803
0
                {
7804
0
                    goto fail;
7805
0
                }
7806
0
                if (PyList_Append(temp_buffer, path)) {
7807
0
                    Py_DECREF(path);
7808
0
                    goto fail;
7809
0
                }
7810
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7811
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7812
0
                if (errno) {
7813
0
                    posix_error();
7814
0
                    Py_DECREF(path);
7815
0
                    goto fail;
7816
0
                }
7817
0
                Py_DECREF(path);
7818
0
                break;
7819
0
            }
7820
0
            case POSIX_SPAWN_CLOSE: {
7821
0
                int fd;
7822
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7823
0
                        ";A close file_action tuple must have 2 elements",
7824
0
                        &tag_obj, &fd))
7825
0
                {
7826
0
                    goto fail;
7827
0
                }
7828
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7829
0
                if (errno) {
7830
0
                    posix_error();
7831
0
                    goto fail;
7832
0
                }
7833
0
                break;
7834
0
            }
7835
0
            case POSIX_SPAWN_DUP2: {
7836
0
                int fd1, fd2;
7837
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7838
0
                        ";A dup2 file_action tuple must have 3 elements",
7839
0
                        &tag_obj, &fd1, &fd2))
7840
0
                {
7841
0
                    goto fail;
7842
0
                }
7843
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7844
0
                                                         fd1, fd2);
7845
0
                if (errno) {
7846
0
                    posix_error();
7847
0
                    goto fail;
7848
0
                }
7849
0
                break;
7850
0
            }
7851
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7852
            case POSIX_SPAWN_CLOSEFROM: {
7853
                int fd;
7854
                if (!PyArg_ParseTuple(file_action, "Oi"
7855
                        ";A closefrom file_action tuple must have 2 elements",
7856
                        &tag_obj, &fd))
7857
                {
7858
                    goto fail;
7859
                }
7860
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7861
                                                                 fd);
7862
                if (errno) {
7863
                    posix_error();
7864
                    goto fail;
7865
                }
7866
                break;
7867
            }
7868
#endif
7869
0
            default: {
7870
0
                PyErr_SetString(PyExc_TypeError,
7871
0
                                "Unknown file_actions identifier");
7872
0
                goto fail;
7873
0
            }
7874
0
        }
7875
0
        Py_DECREF(file_action);
7876
0
    }
7877
7878
0
    Py_DECREF(seq);
7879
0
    return 0;
7880
7881
0
fail:
7882
0
    Py_DECREF(seq);
7883
0
    Py_DECREF(file_action);
7884
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7885
0
    return -1;
7886
0
}
7887
7888
7889
static PyObject *
7890
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7891
               PyObject *env, PyObject *file_actions,
7892
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7893
               PyObject *setsigdef, PyObject *scheduler)
7894
0
{
7895
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7896
0
    EXECV_CHAR **argvlist = NULL;
7897
0
    EXECV_CHAR **envlist = NULL;
7898
0
    posix_spawn_file_actions_t file_actions_buf;
7899
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7900
0
    posix_spawnattr_t attr;
7901
0
    posix_spawnattr_t *attrp = NULL;
7902
0
    Py_ssize_t argc, envc;
7903
0
    PyObject *result = NULL;
7904
0
    PyObject *temp_buffer = NULL;
7905
0
    pid_t pid;
7906
0
    int err_code;
7907
7908
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7909
       argv is a list or tuple of strings and env is a dictionary
7910
       like posix.environ. */
7911
7912
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7913
0
        PyErr_Format(PyExc_TypeError,
7914
0
                     "%s: argv must be a tuple or list", func_name);
7915
0
        goto exit;
7916
0
    }
7917
0
    argc = PySequence_Size(argv);
7918
0
    if (argc < 1) {
7919
0
        PyErr_Format(PyExc_ValueError,
7920
0
                     "%s: argv must not be empty", func_name);
7921
0
        goto exit;
7922
0
    }
7923
7924
0
    if (!PyMapping_Check(env) && env != Py_None) {
7925
0
        PyErr_Format(PyExc_TypeError,
7926
0
                     "%s: environment must be a mapping object or None", func_name);
7927
0
        goto exit;
7928
0
    }
7929
7930
0
    if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7931
0
        PyErr_Format(PyExc_TypeError,
7932
0
                     "%s: scheduler must be a tuple or None", func_name);
7933
0
        goto exit;
7934
0
    }
7935
7936
0
    argvlist = parse_arglist(argv, &argc);
7937
0
    if (argvlist == NULL) {
7938
0
        goto exit;
7939
0
    }
7940
0
    if (!argvlist[0][0]) {
7941
0
        PyErr_Format(PyExc_ValueError,
7942
0
                     "%s: argv first element cannot be empty", func_name);
7943
0
        goto exit;
7944
0
    }
7945
7946
#ifdef USE_DARWIN_NS_GET_ENVIRON
7947
    // There is no environ global in this situation.
7948
    char **environ = NULL;
7949
#endif
7950
7951
0
    if (env == Py_None) {
7952
#ifdef USE_DARWIN_NS_GET_ENVIRON
7953
        environ = *_NSGetEnviron();
7954
#endif
7955
0
        envlist = environ;
7956
0
    } else {
7957
0
        envlist = parse_envlist(env, &envc);
7958
0
        if (envlist == NULL) {
7959
0
            goto exit;
7960
0
        }
7961
0
    }
7962
7963
0
    if (file_actions != NULL && file_actions != Py_None) {
7964
        /* There is a bug in old versions of glibc that makes some of the
7965
         * helper functions for manipulating file actions not copy the provided
7966
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7967
         * copy the value of path for some old versions of glibc (<2.20).
7968
         * The use of temp_buffer here is a workaround that keeps the
7969
         * python objects that own the buffers alive until posix_spawn gets called.
7970
         * Check https://bugs.python.org/issue33630 and
7971
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7972
0
        temp_buffer = PyList_New(0);
7973
0
        if (!temp_buffer) {
7974
0
            goto exit;
7975
0
        }
7976
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7977
0
            goto exit;
7978
0
        }
7979
0
        file_actionsp = &file_actions_buf;
7980
0
    }
7981
7982
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7983
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7984
0
        goto exit;
7985
0
    }
7986
0
    attrp = &attr;
7987
7988
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7989
0
        goto exit;
7990
0
    }
7991
7992
0
    _Py_BEGIN_SUPPRESS_IPH
7993
0
#ifdef HAVE_POSIX_SPAWNP
7994
0
    if (use_posix_spawnp) {
7995
0
        err_code = posix_spawnp(&pid, path->narrow,
7996
0
                                file_actionsp, attrp, argvlist, envlist);
7997
0
    }
7998
0
    else
7999
0
#endif /* HAVE_POSIX_SPAWNP */
8000
0
    {
8001
0
        err_code = posix_spawn(&pid, path->narrow,
8002
0
                               file_actionsp, attrp, argvlist, envlist);
8003
0
    }
8004
0
    _Py_END_SUPPRESS_IPH
8005
8006
0
    if (err_code) {
8007
0
        errno = err_code;
8008
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8009
0
        goto exit;
8010
0
    }
8011
#ifdef _Py_MEMORY_SANITIZER
8012
    __msan_unpoison(&pid, sizeof(pid));
8013
#endif
8014
0
    result = PyLong_FromPid(pid);
8015
8016
0
exit:
8017
0
    if (file_actionsp) {
8018
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
8019
0
    }
8020
0
    if (attrp) {
8021
0
        (void)posix_spawnattr_destroy(attrp);
8022
0
    }
8023
0
    if (envlist && envlist != environ) {
8024
0
        free_string_array(envlist, envc);
8025
0
    }
8026
0
    if (argvlist) {
8027
0
        free_string_array(argvlist, argc);
8028
0
    }
8029
0
    Py_XDECREF(temp_buffer);
8030
0
    return result;
8031
0
}
8032
8033
8034
/*[clinic input]
8035
8036
os.posix_spawn
8037
    path: path_t
8038
        Path of executable file.
8039
    argv: object
8040
        Tuple or list of strings.
8041
    env: object
8042
        Dictionary of strings mapping to strings.
8043
    /
8044
    *
8045
    file_actions: object(c_default='NULL') = ()
8046
        A sequence of file action tuples.
8047
    setpgroup: object(c_default='NULL') = None
8048
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8049
    resetids: bool = False
8050
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8051
    setsid: bool = False
8052
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8053
    setsigmask: object(c_default='NULL') = ()
8054
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8055
    setsigdef: object(c_default='NULL') = ()
8056
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8057
    scheduler: object(c_default='NULL') = None
8058
        A tuple with the scheduler policy (optional) and parameters.
8059
8060
Execute the program specified by path in a new process.
8061
[clinic start generated code]*/
8062
8063
static PyObject *
8064
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8065
                    PyObject *env, PyObject *file_actions,
8066
                    PyObject *setpgroup, int resetids, int setsid,
8067
                    PyObject *setsigmask, PyObject *setsigdef,
8068
                    PyObject *scheduler)
8069
/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/
8070
0
{
8071
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8072
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8073
0
                          scheduler);
8074
0
}
8075
 #endif /* HAVE_POSIX_SPAWN */
8076
8077
8078
8079
#ifdef HAVE_POSIX_SPAWNP
8080
/*[clinic input]
8081
8082
os.posix_spawnp
8083
    path: path_t
8084
        Path of executable file.
8085
    argv: object
8086
        Tuple or list of strings.
8087
    env: object
8088
        Dictionary of strings mapping to strings.
8089
    /
8090
    *
8091
    file_actions: object(c_default='NULL') = ()
8092
        A sequence of file action tuples.
8093
    setpgroup: object(c_default='NULL') = None
8094
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8095
    resetids: bool = False
8096
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8097
    setsid: bool = False
8098
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8099
    setsigmask: object(c_default='NULL') = ()
8100
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8101
    setsigdef: object(c_default='NULL') = ()
8102
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8103
    scheduler: object(c_default='NULL') = None
8104
        A tuple with the scheduler policy (optional) and parameters.
8105
8106
Execute the program specified by path in a new process.
8107
[clinic start generated code]*/
8108
8109
static PyObject *
8110
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8111
                     PyObject *env, PyObject *file_actions,
8112
                     PyObject *setpgroup, int resetids, int setsid,
8113
                     PyObject *setsigmask, PyObject *setsigdef,
8114
                     PyObject *scheduler)
8115
/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/
8116
0
{
8117
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8118
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8119
0
                          scheduler);
8120
0
}
8121
#endif /* HAVE_POSIX_SPAWNP */
8122
8123
#ifdef HAVE_RTPSPAWN
8124
static intptr_t
8125
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8126
               const char  *envp[])
8127
{
8128
     RTP_ID rtpid;
8129
     int status;
8130
     pid_t res;
8131
     int async_err = 0;
8132
8133
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8134
        uStackSize=0 cannot be used, the default stack size is too small for
8135
        Python. */
8136
     if (envp) {
8137
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8138
                          100, 0x1000000, 0, VX_FP_TASK);
8139
     }
8140
     else {
8141
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8142
                          100, 0x1000000, 0, VX_FP_TASK);
8143
     }
8144
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8145
         do {
8146
             res = waitpid((pid_t)rtpid, &status, 0);
8147
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8148
8149
         if (res < 0)
8150
             return RTP_ID_ERROR;
8151
         return ((intptr_t)status);
8152
     }
8153
     return ((intptr_t)rtpid);
8154
}
8155
#endif
8156
8157
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8158
/*[clinic input]
8159
os.spawnv
8160
8161
    mode: int
8162
        Mode of process creation.
8163
    path: path_t
8164
        Path of executable file.
8165
    argv: object
8166
        Tuple or list of strings.
8167
    /
8168
8169
Execute the program specified by path in a new process.
8170
[clinic start generated code]*/
8171
8172
static PyObject *
8173
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8174
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8175
{
8176
    EXECV_CHAR **argvlist;
8177
    int i;
8178
    Py_ssize_t argc;
8179
    intptr_t spawnval;
8180
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8181
8182
    /* spawnv has three arguments: (mode, path, argv), where
8183
       argv is a list or tuple of strings. */
8184
8185
    if (PyList_Check(argv)) {
8186
        argc = PyList_Size(argv);
8187
        getitem = PyList_GetItem;
8188
    }
8189
    else if (PyTuple_Check(argv)) {
8190
        argc = PyTuple_Size(argv);
8191
        getitem = PyTuple_GetItem;
8192
    }
8193
    else {
8194
        PyErr_SetString(PyExc_TypeError,
8195
                        "spawnv() arg 2 must be a tuple or list");
8196
        return NULL;
8197
    }
8198
    if (argc == 0) {
8199
        PyErr_SetString(PyExc_ValueError,
8200
            "spawnv() arg 2 cannot be empty");
8201
        return NULL;
8202
    }
8203
8204
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8205
    if (argvlist == NULL) {
8206
        return PyErr_NoMemory();
8207
    }
8208
    for (i = 0; i < argc; i++) {
8209
        if (!fsconvert_strdup((*getitem)(argv, i),
8210
                              &argvlist[i])) {
8211
            free_string_array(argvlist, i);
8212
            PyErr_SetString(
8213
                PyExc_TypeError,
8214
                "spawnv() arg 2 must contain only strings");
8215
            return NULL;
8216
        }
8217
        if (i == 0 && !argvlist[0][0]) {
8218
            free_string_array(argvlist, i + 1);
8219
            PyErr_SetString(
8220
                PyExc_ValueError,
8221
                "spawnv() arg 2 first element cannot be empty");
8222
            return NULL;
8223
        }
8224
    }
8225
    argvlist[argc] = NULL;
8226
8227
#if !defined(HAVE_RTPSPAWN)
8228
    if (mode == _OLD_P_OVERLAY)
8229
        mode = _P_OVERLAY;
8230
#endif
8231
8232
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8233
                    Py_None) < 0) {
8234
        free_string_array(argvlist, argc);
8235
        return NULL;
8236
    }
8237
8238
    Py_BEGIN_ALLOW_THREADS
8239
    _Py_BEGIN_SUPPRESS_IPH
8240
#ifdef HAVE_WSPAWNV
8241
    spawnval = _wspawnv(mode, path->wide, argvlist);
8242
#elif defined(HAVE_RTPSPAWN)
8243
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8244
#else
8245
    spawnval = _spawnv(mode, path->narrow, argvlist);
8246
#endif
8247
    _Py_END_SUPPRESS_IPH
8248
    Py_END_ALLOW_THREADS
8249
8250
    int saved_errno = errno;
8251
    free_string_array(argvlist, argc);
8252
8253
    if (spawnval == -1) {
8254
        errno = saved_errno;
8255
        posix_error();
8256
        return NULL;
8257
    }
8258
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8259
}
8260
8261
/*[clinic input]
8262
os.spawnve
8263
8264
    mode: int
8265
        Mode of process creation.
8266
    path: path_t
8267
        Path of executable file.
8268
    argv: object
8269
        Tuple or list of strings.
8270
    env: object
8271
        Dictionary of strings mapping to strings.
8272
    /
8273
8274
Execute the program specified by path in a new process.
8275
[clinic start generated code]*/
8276
8277
static PyObject *
8278
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8279
                PyObject *env)
8280
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8281
{
8282
    EXECV_CHAR **argvlist;
8283
    EXECV_CHAR **envlist;
8284
    PyObject *res = NULL;
8285
    Py_ssize_t argc, i, envc;
8286
    intptr_t spawnval;
8287
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8288
    Py_ssize_t lastarg = 0;
8289
8290
    /* spawnve has four arguments: (mode, path, argv, env), where
8291
       argv is a list or tuple of strings and env is a dictionary
8292
       like posix.environ. */
8293
8294
    if (PyList_Check(argv)) {
8295
        argc = PyList_Size(argv);
8296
        getitem = PyList_GetItem;
8297
    }
8298
    else if (PyTuple_Check(argv)) {
8299
        argc = PyTuple_Size(argv);
8300
        getitem = PyTuple_GetItem;
8301
    }
8302
    else {
8303
        PyErr_SetString(PyExc_TypeError,
8304
                        "spawnve() arg 2 must be a tuple or list");
8305
        goto fail_0;
8306
    }
8307
    if (argc == 0) {
8308
        PyErr_SetString(PyExc_ValueError,
8309
            "spawnve() arg 2 cannot be empty");
8310
        goto fail_0;
8311
    }
8312
    if (!PyMapping_Check(env)) {
8313
        PyErr_SetString(PyExc_TypeError,
8314
                        "spawnve() arg 3 must be a mapping object");
8315
        goto fail_0;
8316
    }
8317
8318
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8319
    if (argvlist == NULL) {
8320
        PyErr_NoMemory();
8321
        goto fail_0;
8322
    }
8323
    for (i = 0; i < argc; i++) {
8324
        if (!fsconvert_strdup((*getitem)(argv, i),
8325
                              &argvlist[i]))
8326
        {
8327
            lastarg = i;
8328
            goto fail_1;
8329
        }
8330
        if (i == 0 && !argvlist[0][0]) {
8331
            lastarg = i + 1;
8332
            PyErr_SetString(
8333
                PyExc_ValueError,
8334
                "spawnv() arg 2 first element cannot be empty");
8335
            goto fail_1;
8336
        }
8337
    }
8338
    lastarg = argc;
8339
    argvlist[argc] = NULL;
8340
8341
    envlist = parse_envlist(env, &envc);
8342
    if (envlist == NULL)
8343
        goto fail_1;
8344
8345
#if !defined(HAVE_RTPSPAWN)
8346
    if (mode == _OLD_P_OVERLAY)
8347
        mode = _P_OVERLAY;
8348
#endif
8349
8350
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8351
        goto fail_2;
8352
    }
8353
8354
    Py_BEGIN_ALLOW_THREADS
8355
    _Py_BEGIN_SUPPRESS_IPH
8356
#ifdef HAVE_WSPAWNV
8357
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8358
#elif defined(HAVE_RTPSPAWN)
8359
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8360
                           (const char **)envlist);
8361
#else
8362
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8363
#endif
8364
    _Py_END_SUPPRESS_IPH
8365
    Py_END_ALLOW_THREADS
8366
8367
    if (spawnval == -1)
8368
        (void) posix_error();
8369
    else
8370
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8371
8372
  fail_2:
8373
    while (--envc >= 0) {
8374
        PyMem_Free(envlist[envc]);
8375
    }
8376
    PyMem_Free(envlist);
8377
  fail_1:
8378
    free_string_array(argvlist, lastarg);
8379
  fail_0:
8380
    return res;
8381
}
8382
8383
#endif /* HAVE_SPAWNV */
8384
8385
#ifdef HAVE_FORK
8386
8387
/* Helper function to validate arguments.
8388
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8389
   If obj is non-NULL it must be callable.  */
8390
static int
8391
check_null_or_callable(PyObject *obj, const char* obj_name)
8392
84
{
8393
84
    if (obj && !PyCallable_Check(obj)) {
8394
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8395
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8396
0
        return -1;
8397
0
    }
8398
84
    return 0;
8399
84
}
8400
8401
/*[clinic input]
8402
os.register_at_fork
8403
8404
    *
8405
    before: object=NULL
8406
        A callable to be called in the parent before the fork() syscall.
8407
    after_in_child: object=NULL
8408
        A callable to be called in the child after fork().
8409
    after_in_parent: object=NULL
8410
        A callable to be called in the parent after fork().
8411
8412
Register callables to be called when forking a new process.
8413
8414
'before' callbacks are called in reverse order.
8415
'after_in_child' and 'after_in_parent' callbacks are called in order.
8416
8417
[clinic start generated code]*/
8418
8419
static PyObject *
8420
os_register_at_fork_impl(PyObject *module, PyObject *before,
8421
                         PyObject *after_in_child, PyObject *after_in_parent)
8422
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8423
28
{
8424
28
    PyInterpreterState *interp;
8425
8426
28
    if (!before && !after_in_child && !after_in_parent) {
8427
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8428
0
        return NULL;
8429
0
    }
8430
28
    if (check_null_or_callable(before, "before") ||
8431
28
        check_null_or_callable(after_in_child, "after_in_child") ||
8432
28
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8433
0
        return NULL;
8434
0
    }
8435
28
    interp = _PyInterpreterState_GET();
8436
8437
28
    if (register_at_forker(&interp->before_forkers, before)) {
8438
0
        return NULL;
8439
0
    }
8440
28
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8441
0
        return NULL;
8442
0
    }
8443
28
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8444
0
        return NULL;
8445
0
    }
8446
28
    Py_RETURN_NONE;
8447
28
}
8448
#endif /* HAVE_FORK */
8449
8450
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8451
// Common code to raise a warning if we detect there is more than one thread
8452
// running in the process. Best effort, silent if unable to count threads.
8453
// Constraint: Quick. Never overcounts. Never leaves an error set.
8454
//
8455
// This MUST only be called from the parent process after
8456
// PyOS_AfterFork_Parent().
8457
static int
8458
warn_about_fork_with_threads(
8459
    const char* name,  // Name of the API to use in the warning message.
8460
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8461
)
8462
0
{
8463
    // It's not safe to issue the warning while the world is stopped, because
8464
    // other threads might be holding locks that we need, which would deadlock.
8465
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8466
8467
0
    Py_ssize_t num_python_threads = num_os_threads;
8468
0
    if (num_python_threads <= 0) {
8469
        // Fall back to just the number our threading module knows about.
8470
        // An incomplete view of the world, but better than nothing.
8471
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8472
0
        if (!threading) {
8473
0
            PyErr_Clear();
8474
0
            return 0;
8475
0
        }
8476
0
        PyObject *threading_active =
8477
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8478
0
        if (!threading_active) {
8479
0
            PyErr_Clear();
8480
0
            Py_DECREF(threading);
8481
0
            return 0;
8482
0
        }
8483
0
        PyObject *threading_limbo =
8484
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8485
0
        if (!threading_limbo) {
8486
0
            PyErr_Clear();
8487
0
            Py_DECREF(threading);
8488
0
            Py_DECREF(threading_active);
8489
0
            return 0;
8490
0
        }
8491
0
        Py_DECREF(threading);
8492
        // Duplicating what threading.active_count() does but without holding
8493
        // threading._active_limbo_lock so our count could be inaccurate if
8494
        // these dicts are mid-update from another thread.  Not a big deal.
8495
        // Worst case if someone replaced threading._active or threading._limbo
8496
        // with non-dicts, we get -1 from *Length() below and undercount.
8497
        // Nobody should, but we're best effort so we clear errors and move on.
8498
0
        num_python_threads = (PyMapping_Length(threading_active)
8499
0
                              + PyMapping_Length(threading_limbo));
8500
0
        PyErr_Clear();
8501
0
        Py_DECREF(threading_active);
8502
0
        Py_DECREF(threading_limbo);
8503
0
    }
8504
0
    if (num_python_threads > 1) {
8505
0
        return PyErr_WarnFormat(
8506
0
                PyExc_DeprecationWarning, 1,
8507
0
#ifdef HAVE_GETPID
8508
0
                "This process (pid=%d) is multi-threaded, "
8509
#else
8510
                "This process is multi-threaded, "
8511
#endif
8512
0
                "use of %s() may lead to deadlocks in the child.",
8513
0
#ifdef HAVE_GETPID
8514
0
                getpid(),
8515
0
#endif
8516
0
                name);
8517
0
    }
8518
0
    return 0;
8519
0
}
8520
8521
// If this returns <= 0, we were unable to successfully use any OS APIs.
8522
// Returns a positive number of threads otherwise.
8523
static Py_ssize_t get_number_of_os_threads(void)
8524
0
{
8525
    // TODO: Consider making an `os` module API to return the current number
8526
    // of threads in the process. That'd presumably use this platform code but
8527
    // raise an error rather than using the inaccurate fallback.
8528
0
    Py_ssize_t num_python_threads = 0;
8529
#if defined(__APPLE__) && defined(HAVE_GETPID)
8530
    mach_port_t macos_self = mach_task_self();
8531
    mach_port_t macos_task;
8532
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8533
        thread_array_t macos_threads;
8534
        mach_msg_type_number_t macos_n_threads;
8535
        if (task_threads(macos_task, &macos_threads,
8536
                         &macos_n_threads) == KERN_SUCCESS) {
8537
            num_python_threads = macos_n_threads;
8538
        }
8539
    }
8540
#elif defined(__linux__)
8541
    // Linux /proc/self/stat 20th field is the number of threads.
8542
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8543
0
    if (proc_stat) {
8544
0
        size_t n;
8545
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8546
        // observed on the author's workstation.
8547
0
        char stat_line[160];
8548
0
        n = fread(&stat_line, 1, 159, proc_stat);
8549
0
        stat_line[n] = '\0';
8550
0
        fclose(proc_stat);
8551
8552
0
        char *saveptr = NULL;
8553
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8554
0
        unsigned int idx;
8555
0
        for (idx = 19; idx && field; --idx) {
8556
0
            field = strtok_r(NULL, " ", &saveptr);
8557
0
        }
8558
0
        if (idx == 0 && field) {  // found the 20th field
8559
0
            num_python_threads = atoi(field);  // 0 on error
8560
0
        }
8561
0
    }
8562
0
#endif
8563
0
    return num_python_threads;
8564
0
}
8565
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8566
8567
#ifdef HAVE_FORK1
8568
/*[clinic input]
8569
os.fork1
8570
8571
Fork a child process with a single multiplexed (i.e., not bound) thread.
8572
8573
Return 0 to child process and PID of child to parent process.
8574
[clinic start generated code]*/
8575
8576
static PyObject *
8577
os_fork1_impl(PyObject *module)
8578
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8579
{
8580
    pid_t pid;
8581
8582
    PyInterpreterState *interp = _PyInterpreterState_GET();
8583
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8584
        PyErr_SetString(PyExc_PythonFinalizationError,
8585
                        "can't fork at interpreter shutdown");
8586
        return NULL;
8587
    }
8588
    if (!_Py_IsMainInterpreter(interp)) {
8589
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8590
        return NULL;
8591
    }
8592
    PyOS_BeforeFork();
8593
    pid = fork1();
8594
    int saved_errno = errno;
8595
    if (pid == 0) {
8596
        /* child: this clobbers and resets the import lock. */
8597
        PyOS_AfterFork_Child();
8598
    } else {
8599
        // Called before AfterFork_Parent in case those hooks start threads.
8600
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8601
        /* parent: release the import lock. */
8602
        PyOS_AfterFork_Parent();
8603
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8604
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8605
            return NULL;
8606
        }
8607
    }
8608
    if (pid == -1) {
8609
        errno = saved_errno;
8610
        return posix_error();
8611
    }
8612
    return PyLong_FromPid(pid);
8613
}
8614
#endif /* HAVE_FORK1 */
8615
8616
8617
#ifdef HAVE_FORK
8618
/*[clinic input]
8619
os.fork
8620
8621
Fork a child process.
8622
8623
Return 0 to child process and PID of child to parent process.
8624
[clinic start generated code]*/
8625
8626
static PyObject *
8627
os_fork_impl(PyObject *module)
8628
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8629
0
{
8630
0
    pid_t pid;
8631
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8632
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8633
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8634
0
                        "can't fork at interpreter shutdown");
8635
0
        return NULL;
8636
0
    }
8637
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8638
0
        PyErr_SetString(PyExc_RuntimeError,
8639
0
                        "fork not supported for isolated subinterpreters");
8640
0
        return NULL;
8641
0
    }
8642
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8643
0
        return NULL;
8644
0
    }
8645
0
    PyOS_BeforeFork();
8646
0
    pid = fork();
8647
0
    int saved_errno = errno;
8648
0
    if (pid == 0) {
8649
        /* child: this clobbers and resets the import lock. */
8650
0
        PyOS_AfterFork_Child();
8651
0
    } else {
8652
        // Called before AfterFork_Parent in case those hooks start threads.
8653
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8654
        /* parent: release the import lock. */
8655
0
        PyOS_AfterFork_Parent();
8656
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8657
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8658
0
            return NULL;
8659
0
    }
8660
0
    if (pid == -1) {
8661
0
        errno = saved_errno;
8662
0
        return posix_error();
8663
0
    }
8664
0
    return PyLong_FromPid(pid);
8665
0
}
8666
#endif /* HAVE_FORK */
8667
8668
8669
#ifdef HAVE_SCHED_H
8670
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8671
/*[clinic input]
8672
os.sched_get_priority_max
8673
8674
    policy: int
8675
8676
Get the maximum scheduling priority for policy.
8677
[clinic start generated code]*/
8678
8679
static PyObject *
8680
os_sched_get_priority_max_impl(PyObject *module, int policy)
8681
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8682
0
{
8683
    /* make sure that errno is cleared before the call */
8684
0
    errno = 0;
8685
0
    int max = sched_get_priority_max(policy);
8686
0
    if (max == -1 && errno)
8687
0
        return posix_error();
8688
0
    return PyLong_FromLong(max);
8689
0
}
8690
8691
8692
/*[clinic input]
8693
os.sched_get_priority_min
8694
8695
    policy: int
8696
8697
Get the minimum scheduling priority for policy.
8698
[clinic start generated code]*/
8699
8700
static PyObject *
8701
os_sched_get_priority_min_impl(PyObject *module, int policy)
8702
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8703
0
{
8704
    /* make sure that errno is cleared before the call */
8705
0
    errno = 0;
8706
0
    int min = sched_get_priority_min(policy);
8707
0
    if (min == -1 && errno)
8708
0
        return posix_error();
8709
0
    return PyLong_FromLong(min);
8710
0
}
8711
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8712
8713
8714
#ifdef HAVE_SCHED_SETSCHEDULER
8715
/*[clinic input]
8716
os.sched_getscheduler
8717
    pid: pid_t
8718
    /
8719
8720
Get the scheduling policy for the process identified by pid.
8721
8722
Passing 0 for pid returns the scheduling policy for the calling process.
8723
[clinic start generated code]*/
8724
8725
static PyObject *
8726
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8727
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8728
0
{
8729
0
    int policy;
8730
8731
0
    policy = sched_getscheduler(pid);
8732
0
    if (policy < 0)
8733
0
        return posix_error();
8734
0
    return PyLong_FromLong(policy);
8735
0
}
8736
#endif /* HAVE_SCHED_SETSCHEDULER */
8737
8738
8739
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8740
/*[clinic input]
8741
class os.sched_param "PyObject *" "SchedParamType"
8742
8743
@classmethod
8744
os.sched_param.__new__
8745
8746
    sched_priority: object
8747
        A scheduling parameter.
8748
8749
Currently has only one field: sched_priority
8750
[clinic start generated code]*/
8751
8752
static PyObject *
8753
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8754
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8755
0
{
8756
0
    PyObject *res;
8757
8758
0
    res = PyStructSequence_New(type);
8759
0
    if (!res)
8760
0
        return NULL;
8761
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8762
0
    return res;
8763
0
}
8764
8765
static PyObject *
8766
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8767
0
{
8768
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8769
0
}
8770
8771
static PyMethodDef os_sched_param_reduce_method = {
8772
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8773
};
8774
8775
PyDoc_VAR(os_sched_param__doc__);
8776
8777
static PyStructSequence_Field sched_param_fields[] = {
8778
    {"sched_priority", "the scheduling priority"},
8779
    {0}
8780
};
8781
8782
static PyStructSequence_Desc sched_param_desc = {
8783
    MODNAME ".sched_param", /* name */
8784
    os_sched_param__doc__, /* doc */
8785
    sched_param_fields,
8786
    1
8787
};
8788
8789
static int
8790
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8791
0
{
8792
0
    long priority;
8793
8794
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8795
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8796
0
        return 0;
8797
0
    }
8798
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8799
0
    if (priority == -1 && PyErr_Occurred())
8800
0
        return 0;
8801
0
    if (priority > INT_MAX || priority < INT_MIN) {
8802
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8803
0
        return 0;
8804
0
    }
8805
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8806
0
    return 1;
8807
0
}
8808
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8809
8810
8811
#ifdef HAVE_SCHED_SETSCHEDULER
8812
/*[clinic input]
8813
os.sched_setscheduler
8814
8815
    pid: pid_t
8816
    policy: int
8817
    param as param_obj: object
8818
    /
8819
8820
Set the scheduling policy for the process identified by pid.
8821
8822
If pid is 0, the calling process is changed.
8823
param is an instance of sched_param.
8824
[clinic start generated code]*/
8825
8826
static PyObject *
8827
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8828
                           PyObject *param_obj)
8829
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8830
0
{
8831
0
    struct sched_param param;
8832
0
    if (!convert_sched_param(module, param_obj, &param)) {
8833
0
        return NULL;
8834
0
    }
8835
8836
    /*
8837
    ** sched_setscheduler() returns 0 in Linux, but the previous
8838
    ** scheduling policy under Solaris/Illumos, and others.
8839
    ** On error, -1 is returned in all Operating Systems.
8840
    */
8841
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8842
0
        return posix_error();
8843
0
    Py_RETURN_NONE;
8844
0
}
8845
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8846
8847
8848
#ifdef HAVE_SCHED_SETPARAM
8849
/*[clinic input]
8850
os.sched_getparam
8851
    pid: pid_t
8852
    /
8853
8854
Returns scheduling parameters for the process identified by pid.
8855
8856
If pid is 0, returns parameters for the calling process.
8857
Return value is an instance of sched_param.
8858
[clinic start generated code]*/
8859
8860
static PyObject *
8861
os_sched_getparam_impl(PyObject *module, pid_t pid)
8862
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8863
0
{
8864
0
    struct sched_param param;
8865
0
    PyObject *result;
8866
0
    PyObject *priority;
8867
8868
0
    if (sched_getparam(pid, &param))
8869
0
        return posix_error();
8870
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8871
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8872
0
    if (!result)
8873
0
        return NULL;
8874
0
    priority = PyLong_FromLong(param.sched_priority);
8875
0
    if (!priority) {
8876
0
        Py_DECREF(result);
8877
0
        return NULL;
8878
0
    }
8879
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8880
0
    return result;
8881
0
}
8882
8883
8884
/*[clinic input]
8885
os.sched_setparam
8886
    pid: pid_t
8887
    param as param_obj: object
8888
    /
8889
8890
Set scheduling parameters for the process identified by pid.
8891
8892
If pid is 0, sets parameters for the calling process.
8893
param should be an instance of sched_param.
8894
[clinic start generated code]*/
8895
8896
static PyObject *
8897
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8898
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8899
0
{
8900
0
    struct sched_param param;
8901
0
    if (!convert_sched_param(module, param_obj, &param)) {
8902
0
        return NULL;
8903
0
    }
8904
8905
0
    if (sched_setparam(pid, &param))
8906
0
        return posix_error();
8907
0
    Py_RETURN_NONE;
8908
0
}
8909
#endif /* HAVE_SCHED_SETPARAM */
8910
8911
8912
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8913
/*[clinic input]
8914
@permit_long_summary
8915
os.sched_rr_get_interval -> double
8916
    pid: pid_t
8917
    /
8918
8919
Return the round-robin quantum for the process identified by pid, in seconds.
8920
8921
Value returned is a float.
8922
[clinic start generated code]*/
8923
8924
static double
8925
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8926
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8927
0
{
8928
0
    struct timespec interval;
8929
0
    if (sched_rr_get_interval(pid, &interval)) {
8930
0
        posix_error();
8931
0
        return -1.0;
8932
0
    }
8933
#ifdef _Py_MEMORY_SANITIZER
8934
    __msan_unpoison(&interval, sizeof(interval));
8935
#endif
8936
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8937
0
}
8938
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8939
8940
8941
/*[clinic input]
8942
os.sched_yield
8943
8944
Voluntarily relinquish the CPU.
8945
[clinic start generated code]*/
8946
8947
static PyObject *
8948
os_sched_yield_impl(PyObject *module)
8949
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8950
0
{
8951
0
    int result;
8952
0
    Py_BEGIN_ALLOW_THREADS
8953
0
    result = sched_yield();
8954
0
    Py_END_ALLOW_THREADS
8955
0
    if (result < 0) {
8956
0
        return posix_error();
8957
0
    }
8958
0
    Py_RETURN_NONE;
8959
0
}
8960
8961
#ifdef HAVE_SCHED_SETAFFINITY
8962
/* The minimum number of CPUs allocated in a cpu_set_t */
8963
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8964
8965
/*[clinic input]
8966
os.sched_setaffinity
8967
    pid: pid_t
8968
    mask : object
8969
    /
8970
8971
Set the CPU affinity of the process identified by pid to mask.
8972
8973
mask should be an iterable of integers identifying CPUs.
8974
[clinic start generated code]*/
8975
8976
static PyObject *
8977
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8978
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8979
0
{
8980
0
    int ncpus;
8981
0
    size_t setsize;
8982
0
    cpu_set_t *cpu_set = NULL;
8983
0
    PyObject *iterator = NULL, *item;
8984
8985
0
    iterator = PyObject_GetIter(mask);
8986
0
    if (iterator == NULL)
8987
0
        return NULL;
8988
8989
0
    ncpus = NCPUS_START;
8990
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8991
0
    cpu_set = CPU_ALLOC(ncpus);
8992
0
    if (cpu_set == NULL) {
8993
0
        PyErr_NoMemory();
8994
0
        goto error;
8995
0
    }
8996
0
    CPU_ZERO_S(setsize, cpu_set);
8997
8998
0
    while ((item = PyIter_Next(iterator))) {
8999
0
        long cpu;
9000
0
        if (!PyIndex_Check(item)) {
9001
0
            PyErr_Format(PyExc_TypeError,
9002
0
                        "expected an iterator of ints, "
9003
0
                        "but iterator yielded %R",
9004
0
                        Py_TYPE(item));
9005
0
            Py_DECREF(item);
9006
0
            goto error;
9007
0
        }
9008
0
        cpu = PyLong_AsLong(item);
9009
0
        Py_DECREF(item);
9010
0
        if (cpu < 0) {
9011
0
            if (!PyErr_Occurred())
9012
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9013
0
            goto error;
9014
0
        }
9015
0
        if (cpu > INT_MAX - 1) {
9016
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9017
0
            goto error;
9018
0
        }
9019
0
        if (cpu >= ncpus) {
9020
            /* Grow CPU mask to fit the CPU number */
9021
0
            int newncpus = ncpus;
9022
0
            cpu_set_t *newmask;
9023
0
            size_t newsetsize;
9024
0
            while (newncpus <= cpu) {
9025
0
                if (newncpus > INT_MAX / 2)
9026
0
                    newncpus = cpu + 1;
9027
0
                else
9028
0
                    newncpus = newncpus * 2;
9029
0
            }
9030
0
            newmask = CPU_ALLOC(newncpus);
9031
0
            if (newmask == NULL) {
9032
0
                PyErr_NoMemory();
9033
0
                goto error;
9034
0
            }
9035
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9036
0
            CPU_ZERO_S(newsetsize, newmask);
9037
0
            memcpy(newmask, cpu_set, setsize);
9038
0
            CPU_FREE(cpu_set);
9039
0
            setsize = newsetsize;
9040
0
            cpu_set = newmask;
9041
0
            ncpus = newncpus;
9042
0
        }
9043
0
        CPU_SET_S(cpu, setsize, cpu_set);
9044
0
    }
9045
0
    if (PyErr_Occurred()) {
9046
0
        goto error;
9047
0
    }
9048
0
    Py_CLEAR(iterator);
9049
9050
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9051
0
        posix_error();
9052
0
        goto error;
9053
0
    }
9054
0
    CPU_FREE(cpu_set);
9055
0
    Py_RETURN_NONE;
9056
9057
0
error:
9058
0
    if (cpu_set)
9059
0
        CPU_FREE(cpu_set);
9060
0
    Py_XDECREF(iterator);
9061
0
    return NULL;
9062
0
}
9063
9064
9065
/*[clinic input]
9066
@permit_long_summary
9067
os.sched_getaffinity
9068
    pid: pid_t
9069
    /
9070
9071
Return the affinity of the process identified by pid (or the current process if zero).
9072
9073
The affinity is returned as a set of CPU identifiers.
9074
[clinic start generated code]*/
9075
9076
static PyObject *
9077
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9078
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9079
0
{
9080
0
    int ncpus = NCPUS_START;
9081
0
    size_t setsize;
9082
0
    cpu_set_t *mask;
9083
9084
0
    while (1) {
9085
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9086
0
        mask = CPU_ALLOC(ncpus);
9087
0
        if (mask == NULL) {
9088
0
            return PyErr_NoMemory();
9089
0
        }
9090
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9091
0
            break;
9092
0
        }
9093
0
        CPU_FREE(mask);
9094
0
        if (errno != EINVAL) {
9095
0
            return posix_error();
9096
0
        }
9097
0
        if (ncpus > INT_MAX / 2) {
9098
0
            PyErr_SetString(PyExc_OverflowError,
9099
0
                            "could not allocate a large enough CPU set");
9100
0
            return NULL;
9101
0
        }
9102
0
        ncpus *= 2;
9103
0
    }
9104
9105
0
    PyObject *res = PySet_New(NULL);
9106
0
    if (res == NULL) {
9107
0
        goto error;
9108
0
    }
9109
9110
0
    int cpu = 0;
9111
0
    int count = CPU_COUNT_S(setsize, mask);
9112
0
    for (; count; cpu++) {
9113
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9114
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9115
0
            --count;
9116
0
            if (cpu_num == NULL) {
9117
0
                goto error;
9118
0
            }
9119
0
            if (PySet_Add(res, cpu_num)) {
9120
0
                Py_DECREF(cpu_num);
9121
0
                goto error;
9122
0
            }
9123
0
            Py_DECREF(cpu_num);
9124
0
        }
9125
0
    }
9126
0
    CPU_FREE(mask);
9127
0
    return res;
9128
9129
0
error:
9130
0
    if (mask) {
9131
0
        CPU_FREE(mask);
9132
0
    }
9133
0
    Py_XDECREF(res);
9134
0
    return NULL;
9135
0
}
9136
#endif /* HAVE_SCHED_SETAFFINITY */
9137
9138
#endif /* HAVE_SCHED_H */
9139
9140
9141
#ifdef HAVE_POSIX_OPENPT
9142
/*[clinic input]
9143
os.posix_openpt -> int
9144
9145
    oflag: int
9146
    /
9147
9148
Open and return a file descriptor for a master pseudo-terminal device.
9149
9150
Performs a posix_openpt() C function call. The oflag argument is used to
9151
set file status flags and file access modes as specified in the manual page
9152
of posix_openpt() of your system.
9153
[clinic start generated code]*/
9154
9155
static int
9156
os_posix_openpt_impl(PyObject *module, int oflag)
9157
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
9158
0
{
9159
0
    int fd;
9160
9161
0
#if defined(O_CLOEXEC)
9162
0
    oflag |= O_CLOEXEC;
9163
0
#endif
9164
9165
0
    fd = posix_openpt(oflag);
9166
0
    if (fd == -1) {
9167
0
        posix_error();
9168
0
        return -1;
9169
0
    }
9170
9171
    // Just in case, likely a no-op given O_CLOEXEC above.
9172
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9173
0
        close(fd);
9174
0
        return -1;
9175
0
    }
9176
9177
0
    return fd;
9178
0
}
9179
#endif /* HAVE_POSIX_OPENPT */
9180
9181
#ifdef HAVE_GRANTPT
9182
/*[clinic input]
9183
os.grantpt
9184
9185
    fd: fildes
9186
        File descriptor of a master pseudo-terminal device.
9187
    /
9188
9189
Grant access to the slave pseudo-terminal device.
9190
9191
Performs a grantpt() C function call.
9192
[clinic start generated code]*/
9193
9194
static PyObject *
9195
os_grantpt_impl(PyObject *module, int fd)
9196
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9197
0
{
9198
0
    int ret;
9199
0
    int saved_errno;
9200
0
    PyOS_sighandler_t sig_saved;
9201
9202
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9203
9204
0
    ret = grantpt(fd);
9205
0
    if (ret == -1)
9206
0
        saved_errno = errno;
9207
9208
0
    PyOS_setsig(SIGCHLD, sig_saved);
9209
9210
0
    if (ret == -1) {
9211
0
        errno = saved_errno;
9212
0
        return posix_error();
9213
0
    }
9214
9215
0
    Py_RETURN_NONE;
9216
0
}
9217
#endif /* HAVE_GRANTPT */
9218
9219
#ifdef HAVE_UNLOCKPT
9220
/*[clinic input]
9221
os.unlockpt
9222
9223
    fd: fildes
9224
        File descriptor of a master pseudo-terminal device.
9225
    /
9226
9227
Unlock a pseudo-terminal master/slave pair.
9228
9229
Performs an unlockpt() C function call.
9230
[clinic start generated code]*/
9231
9232
static PyObject *
9233
os_unlockpt_impl(PyObject *module, int fd)
9234
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9235
0
{
9236
0
    if (unlockpt(fd) == -1)
9237
0
        return posix_error();
9238
9239
0
    Py_RETURN_NONE;
9240
0
}
9241
#endif /* HAVE_UNLOCKPT */
9242
9243
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9244
static PyObject *
9245
py_ptsname(int fd)
9246
0
{
9247
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9248
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9249
0
    errno = 0;
9250
0
    char *name = ptsname(fd);
9251
0
    if (name == NULL) {
9252
0
        return posix_error();
9253
0
    }
9254
0
    return PyUnicode_DecodeFSDefault(name);
9255
0
}
9256
9257
/*[clinic input]
9258
os.ptsname
9259
9260
    fd: fildes
9261
        File descriptor of a master pseudo-terminal device.
9262
    /
9263
9264
Return the name of the slave pseudo-terminal device.
9265
9266
If the ptsname_r() C function is available, it is called;
9267
otherwise, performs a ptsname() C function call.
9268
[clinic start generated code]*/
9269
9270
static PyObject *
9271
os_ptsname_impl(PyObject *module, int fd)
9272
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9273
0
{
9274
0
#ifdef HAVE_PTSNAME_R
9275
0
    int ret;
9276
0
    char name[MAXPATHLEN+1];
9277
9278
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9279
0
        ret = ptsname_r(fd, name, sizeof(name));
9280
0
    }
9281
0
    else {
9282
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9283
0
        return py_ptsname(fd);
9284
0
    }
9285
0
    if (ret != 0) {
9286
0
        errno = ret;
9287
0
        return posix_error();
9288
0
    }
9289
9290
0
    return PyUnicode_DecodeFSDefault(name);
9291
#else
9292
    return py_ptsname(fd);
9293
#endif /* HAVE_PTSNAME_R */
9294
0
}
9295
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9296
9297
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9298
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9299
#  define DEV_PTY_FILE "/dev/ptc"
9300
#  define HAVE_DEV_PTMX
9301
#else
9302
#  define DEV_PTY_FILE "/dev/ptmx"
9303
#endif
9304
9305
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9306
#ifdef HAVE_PTY_H
9307
#include <pty.h>
9308
#elif defined(HAVE_LIBUTIL_H)
9309
#include <libutil.h>
9310
#elif defined(HAVE_UTIL_H)
9311
#include <util.h>
9312
#endif /* HAVE_PTY_H */
9313
#ifdef HAVE_UTMP_H
9314
#include <utmp.h>
9315
#endif /* HAVE_UTMP_H */
9316
#ifdef HAVE_STROPTS_H
9317
#include <stropts.h>
9318
#endif
9319
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9320
9321
9322
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9323
/*[clinic input]
9324
os.openpty
9325
9326
Open a pseudo-terminal.
9327
9328
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9329
for both the master and slave ends.
9330
[clinic start generated code]*/
9331
9332
static PyObject *
9333
os_openpty_impl(PyObject *module)
9334
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9335
0
{
9336
0
    int master_fd = -1, slave_fd = -1;
9337
#ifndef HAVE_OPENPTY
9338
    char * slave_name;
9339
#endif
9340
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9341
    PyOS_sighandler_t sig_saved;
9342
#if defined(__sun) && defined(__SVR4)
9343
    extern char *ptsname(int fildes);
9344
#endif
9345
#endif
9346
9347
0
#ifdef HAVE_OPENPTY
9348
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9349
0
        goto posix_error;
9350
9351
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9352
0
        goto error;
9353
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9354
0
        goto error;
9355
9356
#elif defined(HAVE__GETPTY)
9357
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9358
    if (slave_name == NULL)
9359
        goto posix_error;
9360
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9361
        goto error;
9362
9363
    slave_fd = _Py_open(slave_name, O_RDWR);
9364
    if (slave_fd < 0)
9365
        goto error;
9366
9367
#else
9368
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9369
    if (master_fd < 0)
9370
        goto posix_error;
9371
9372
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9373
9374
    /* change permission of slave */
9375
    if (grantpt(master_fd) < 0) {
9376
        int saved_errno = errno;
9377
        PyOS_setsig(SIGCHLD, sig_saved);
9378
        errno = saved_errno;
9379
        goto posix_error;
9380
    }
9381
9382
    /* unlock slave */
9383
    if (unlockpt(master_fd) < 0) {
9384
        int saved_errno = errno;
9385
        PyOS_setsig(SIGCHLD, sig_saved);
9386
        errno = saved_errno;
9387
        goto posix_error;
9388
    }
9389
9390
    PyOS_setsig(SIGCHLD, sig_saved);
9391
9392
    slave_name = ptsname(master_fd); /* get name of slave */
9393
    if (slave_name == NULL)
9394
        goto posix_error;
9395
9396
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9397
    if (slave_fd == -1)
9398
        goto error;
9399
9400
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9401
        goto posix_error;
9402
9403
#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC)
9404
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9405
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9406
#ifndef __hpux
9407
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9408
#endif /* __hpux */
9409
#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
9410
#endif /* HAVE_OPENPTY */
9411
9412
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9413
9414
0
posix_error:
9415
0
    posix_error();
9416
0
error:
9417
0
    if (master_fd != -1)
9418
0
        close(master_fd);
9419
0
    if (slave_fd != -1)
9420
0
        close(slave_fd);
9421
0
    return NULL;
9422
0
}
9423
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9424
9425
9426
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9427
#define HAVE_FALLBACK_LOGIN_TTY 1
9428
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9429
9430
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9431
/*[clinic input]
9432
os.login_tty
9433
9434
    fd: fildes
9435
    /
9436
9437
Prepare the tty of which fd is a file descriptor for a new login session.
9438
9439
Make the calling process a session leader; make the tty the
9440
controlling tty, the stdin, the stdout, and the stderr of the
9441
calling process; close fd.
9442
[clinic start generated code]*/
9443
9444
static PyObject *
9445
os_login_tty_impl(PyObject *module, int fd)
9446
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
9447
0
{
9448
0
#ifdef HAVE_LOGIN_TTY
9449
0
    if (login_tty(fd) == -1) {
9450
0
        return posix_error();
9451
0
    }
9452
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9453
    /* Establish a new session. */
9454
    if (setsid() == -1) {
9455
        return posix_error();
9456
    }
9457
9458
    /* The tty becomes the controlling terminal. */
9459
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9460
        return posix_error();
9461
    }
9462
9463
    /* The tty becomes stdin/stdout/stderr */
9464
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9465
        return posix_error();
9466
    }
9467
    if (fd > 2) {
9468
        close(fd);
9469
    }
9470
#endif /* HAVE_LOGIN_TTY */
9471
0
    Py_RETURN_NONE;
9472
0
}
9473
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9474
9475
9476
#ifdef HAVE_FORKPTY
9477
/*[clinic input]
9478
os.forkpty
9479
9480
Fork a new process with a new pseudo-terminal as controlling tty.
9481
9482
Returns a tuple of (pid, master_fd).
9483
Like fork(), return pid of 0 to the child process,
9484
and pid of child to the parent process.
9485
To both, return fd of newly opened pseudo-terminal.
9486
The master_fd is non-inheritable.
9487
[clinic start generated code]*/
9488
9489
static PyObject *
9490
os_forkpty_impl(PyObject *module)
9491
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9492
0
{
9493
0
    int master_fd = -1;
9494
0
    pid_t pid;
9495
9496
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9497
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9498
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9499
0
                        "can't fork at interpreter shutdown");
9500
0
        return NULL;
9501
0
    }
9502
0
    if (!_Py_IsMainInterpreter(interp)) {
9503
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9504
0
        return NULL;
9505
0
    }
9506
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9507
0
        return NULL;
9508
0
    }
9509
0
    PyOS_BeforeFork();
9510
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9511
0
    if (pid == 0) {
9512
        /* child: this clobbers and resets the import lock. */
9513
0
        PyOS_AfterFork_Child();
9514
0
    } else {
9515
        // Called before AfterFork_Parent in case those hooks start threads.
9516
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9517
        /* parent: release the import lock. */
9518
0
        PyOS_AfterFork_Parent();
9519
        /* set O_CLOEXEC on master_fd */
9520
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9521
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9522
0
                                   "non-inheritable in forkpty()");
9523
0
        }
9524
9525
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9526
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9527
0
            return NULL;
9528
0
    }
9529
0
    if (pid == -1) {
9530
0
        return posix_error();
9531
0
    }
9532
9533
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9534
0
}
9535
#endif /* HAVE_FORKPTY */
9536
9537
9538
#ifdef HAVE_GETEGID
9539
/*[clinic input]
9540
os.getegid
9541
9542
Return the current process's effective group id.
9543
[clinic start generated code]*/
9544
9545
static PyObject *
9546
os_getegid_impl(PyObject *module)
9547
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9548
36
{
9549
36
    return _PyLong_FromGid(getegid());
9550
36
}
9551
#endif /* HAVE_GETEGID */
9552
9553
9554
#ifdef HAVE_GETEUID
9555
/*[clinic input]
9556
os.geteuid
9557
9558
Return the current process's effective user id.
9559
[clinic start generated code]*/
9560
9561
static PyObject *
9562
os_geteuid_impl(PyObject *module)
9563
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9564
36
{
9565
36
    return _PyLong_FromUid(geteuid());
9566
36
}
9567
#endif /* HAVE_GETEUID */
9568
9569
9570
#ifdef HAVE_GETGID
9571
/*[clinic input]
9572
os.getgid
9573
9574
Return the current process's group id.
9575
[clinic start generated code]*/
9576
9577
static PyObject *
9578
os_getgid_impl(PyObject *module)
9579
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9580
36
{
9581
36
    return _PyLong_FromGid(getgid());
9582
36
}
9583
#endif /* HAVE_GETGID */
9584
9585
9586
#if defined(HAVE_GETPID)
9587
/*[clinic input]
9588
os.getpid
9589
9590
Return the current process id.
9591
[clinic start generated code]*/
9592
9593
static PyObject *
9594
os_getpid_impl(PyObject *module)
9595
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9596
4.48k
{
9597
4.48k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9598
4.48k
    return PyLong_FromPid(getpid());
9599
#else
9600
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9601
#endif
9602
4.48k
}
9603
#endif /* defined(HAVE_GETPID) */
9604
9605
#ifdef NGROUPS_MAX
9606
0
#define MAX_GROUPS NGROUPS_MAX
9607
#else
9608
    /* defined to be 16 on Solaris7, so this should be a small number */
9609
#define MAX_GROUPS 64
9610
#endif
9611
9612
#ifdef HAVE_GETGROUPLIST
9613
9614
#ifdef __APPLE__
9615
/*[clinic input]
9616
os.getgrouplist
9617
9618
    user: str
9619
        username to lookup
9620
    group as basegid: int
9621
        base group id of the user
9622
    /
9623
9624
Returns a list of groups to which a user belongs.
9625
[clinic start generated code]*/
9626
9627
static PyObject *
9628
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9629
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9630
#else
9631
/*[clinic input]
9632
os.getgrouplist
9633
9634
    user: str
9635
        username to lookup
9636
    group as basegid: gid_t
9637
        base group id of the user
9638
    /
9639
9640
Returns a list of groups to which a user belongs.
9641
[clinic start generated code]*/
9642
9643
static PyObject *
9644
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9645
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9646
#endif
9647
0
{
9648
0
    int i, ngroups;
9649
0
    PyObject *list;
9650
#ifdef __APPLE__
9651
    int *groups;
9652
#else
9653
0
    gid_t *groups;
9654
0
#endif
9655
9656
    /*
9657
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9658
     * number of supplemental groups a users can belong to.
9659
     * We have to increment it by one because
9660
     * getgrouplist() returns both the supplemental groups
9661
     * and the primary group, i.e. all of the groups the
9662
     * user belongs to.
9663
     */
9664
0
    ngroups = 1 + MAX_GROUPS;
9665
9666
0
    while (1) {
9667
#ifdef __APPLE__
9668
        groups = PyMem_New(int, ngroups);
9669
#else
9670
0
        groups = PyMem_New(gid_t, ngroups);
9671
0
#endif
9672
0
        if (groups == NULL) {
9673
0
            return PyErr_NoMemory();
9674
0
        }
9675
9676
0
        int old_ngroups = ngroups;
9677
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9678
            /* Success */
9679
0
            break;
9680
0
        }
9681
9682
        /* getgrouplist() fails if the group list is too small */
9683
0
        PyMem_Free(groups);
9684
9685
0
        if (ngroups > old_ngroups) {
9686
            /* If the group list is too small, the glibc implementation of
9687
               getgrouplist() sets ngroups to the total number of groups and
9688
               returns -1. */
9689
0
        }
9690
0
        else {
9691
            /* Double the group list size */
9692
0
            if (ngroups > INT_MAX / 2) {
9693
0
                return PyErr_NoMemory();
9694
0
            }
9695
0
            ngroups *= 2;
9696
0
        }
9697
9698
        /* Retry getgrouplist() with a larger group list */
9699
0
    }
9700
9701
#ifdef _Py_MEMORY_SANITIZER
9702
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9703
    __msan_unpoison(&ngroups, sizeof(ngroups));
9704
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9705
#endif
9706
9707
0
    list = PyList_New(ngroups);
9708
0
    if (list == NULL) {
9709
0
        PyMem_Free(groups);
9710
0
        return NULL;
9711
0
    }
9712
9713
0
    for (i = 0; i < ngroups; i++) {
9714
#ifdef __APPLE__
9715
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9716
#else
9717
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9718
0
#endif
9719
0
        if (o == NULL) {
9720
0
            Py_DECREF(list);
9721
0
            PyMem_Free(groups);
9722
0
            return NULL;
9723
0
        }
9724
0
        PyList_SET_ITEM(list, i, o);
9725
0
    }
9726
9727
0
    PyMem_Free(groups);
9728
9729
0
    return list;
9730
0
}
9731
#endif /* HAVE_GETGROUPLIST */
9732
9733
9734
#ifdef HAVE_GETGROUPS
9735
/*[clinic input]
9736
os.getgroups
9737
9738
Return list of supplemental group IDs for the process.
9739
[clinic start generated code]*/
9740
9741
static PyObject *
9742
os_getgroups_impl(PyObject *module)
9743
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9744
0
{
9745
    // Call getgroups with length 0 to get the actual number of groups
9746
0
    int n = getgroups(0, NULL);
9747
0
    if (n < 0) {
9748
0
        return posix_error();
9749
0
    }
9750
9751
0
    if (n == 0) {
9752
0
        return PyList_New(0);
9753
0
    }
9754
9755
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9756
0
    if (grouplist == NULL) {
9757
0
        return PyErr_NoMemory();
9758
0
    }
9759
9760
0
    n = getgroups(n, grouplist);
9761
0
    if (n == -1) {
9762
0
        posix_error();
9763
0
        PyMem_Free(grouplist);
9764
0
        return NULL;
9765
0
    }
9766
9767
0
    PyObject *result = PyList_New(n);
9768
0
    if (result == NULL) {
9769
0
        goto error;
9770
0
    }
9771
9772
0
    for (int i = 0; i < n; ++i) {
9773
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9774
0
        if (group == NULL) {
9775
0
            goto error;
9776
0
        }
9777
0
        PyList_SET_ITEM(result, i, group);
9778
0
    }
9779
0
    PyMem_Free(grouplist);
9780
9781
0
    return result;
9782
9783
0
error:
9784
0
    PyMem_Free(grouplist);
9785
0
    Py_XDECREF(result);
9786
0
    return NULL;
9787
0
}
9788
#endif /* HAVE_GETGROUPS */
9789
9790
#ifdef HAVE_INITGROUPS
9791
#ifdef __APPLE__
9792
/*[clinic input]
9793
os.initgroups
9794
9795
    username as oname: unicode_fs_encoded
9796
    gid: int
9797
    /
9798
9799
Initialize the group access list.
9800
9801
Call the system initgroups() to initialize the group access list with all of
9802
the groups of which the specified username is a member, plus the specified
9803
group id.
9804
[clinic start generated code]*/
9805
9806
static PyObject *
9807
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9808
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9809
#else
9810
/*[clinic input]
9811
os.initgroups
9812
9813
    username as oname: unicode_fs_encoded
9814
    gid: gid_t
9815
    /
9816
9817
Initialize the group access list.
9818
9819
Call the system initgroups() to initialize the group access list with all of
9820
the groups of which the specified username is a member, plus the specified
9821
group id.
9822
[clinic start generated code]*/
9823
9824
static PyObject *
9825
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9826
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9827
#endif
9828
0
{
9829
0
    const char *username = PyBytes_AS_STRING(oname);
9830
9831
0
    if (initgroups(username, gid) == -1)
9832
0
        return PyErr_SetFromErrno(PyExc_OSError);
9833
9834
0
    Py_RETURN_NONE;
9835
0
}
9836
#endif /* HAVE_INITGROUPS */
9837
9838
9839
#ifdef HAVE_GETPGID
9840
/*[clinic input]
9841
os.getpgid
9842
9843
    pid: pid_t
9844
9845
Call the system call getpgid(), and return the result.
9846
[clinic start generated code]*/
9847
9848
static PyObject *
9849
os_getpgid_impl(PyObject *module, pid_t pid)
9850
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9851
0
{
9852
0
    pid_t pgid = getpgid(pid);
9853
0
    if (pgid < 0)
9854
0
        return posix_error();
9855
0
    return PyLong_FromPid(pgid);
9856
0
}
9857
#endif /* HAVE_GETPGID */
9858
9859
9860
#ifdef HAVE_GETPGRP
9861
/*[clinic input]
9862
os.getpgrp
9863
9864
Return the current process group id.
9865
[clinic start generated code]*/
9866
9867
static PyObject *
9868
os_getpgrp_impl(PyObject *module)
9869
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9870
0
{
9871
#ifdef GETPGRP_HAVE_ARG
9872
    return PyLong_FromPid(getpgrp(0));
9873
#else /* GETPGRP_HAVE_ARG */
9874
0
    return PyLong_FromPid(getpgrp());
9875
0
#endif /* GETPGRP_HAVE_ARG */
9876
0
}
9877
#endif /* HAVE_GETPGRP */
9878
9879
9880
#ifdef HAVE_SETPGRP
9881
/*[clinic input]
9882
os.setpgrp
9883
9884
Make the current process the leader of its process group.
9885
[clinic start generated code]*/
9886
9887
static PyObject *
9888
os_setpgrp_impl(PyObject *module)
9889
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9890
0
{
9891
#ifdef SETPGRP_HAVE_ARG
9892
    if (setpgrp(0, 0) < 0)
9893
#else /* SETPGRP_HAVE_ARG */
9894
0
    if (setpgrp() < 0)
9895
0
#endif /* SETPGRP_HAVE_ARG */
9896
0
        return posix_error();
9897
0
    Py_RETURN_NONE;
9898
0
}
9899
#endif /* HAVE_SETPGRP */
9900
9901
#ifdef HAVE_GETPPID
9902
9903
#ifdef MS_WINDOWS
9904
#include <winternl.h>
9905
#include <ProcessSnapshot.h>
9906
9907
// The structure definition in winternl.h may be incomplete.
9908
// This structure is the full version from the MSDN documentation.
9909
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9910
    NTSTATUS ExitStatus;
9911
    PVOID PebBaseAddress;
9912
    ULONG_PTR AffinityMask;
9913
    LONG BasePriority;
9914
    ULONG_PTR UniqueProcessId;
9915
    ULONG_PTR InheritedFromUniqueProcessId;
9916
} PROCESS_BASIC_INFORMATION_FULL;
9917
9918
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9919
    IN    HANDLE           ProcessHandle,
9920
    IN    PROCESSINFOCLASS ProcessInformationClass,
9921
    OUT   PVOID            ProcessInformation,
9922
    IN    ULONG            ProcessInformationLength,
9923
    OUT   PULONG           ReturnLength OPTIONAL);
9924
9925
// This function returns the process ID of the parent process.
9926
// Returns 0 on failure.
9927
static ULONG
9928
win32_getppid_fast(void)
9929
{
9930
    NTSTATUS status;
9931
    HMODULE ntdll;
9932
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9933
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9934
    static ULONG cached_ppid = 0;
9935
9936
    if (cached_ppid) {
9937
        // No need to query the kernel again.
9938
        return cached_ppid;
9939
    }
9940
9941
    ntdll = GetModuleHandleW(L"ntdll.dll");
9942
    if (!ntdll) {
9943
        return 0;
9944
    }
9945
9946
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9947
    if (!pNtQueryInformationProcess) {
9948
        return 0;
9949
    }
9950
9951
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9952
                                        ProcessBasicInformation,
9953
                                        &basic_information,
9954
                                        sizeof(basic_information),
9955
                                        NULL);
9956
9957
    if (!NT_SUCCESS(status)) {
9958
        return 0;
9959
    }
9960
9961
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9962
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9963
    // zero and (ULONG) -1.
9964
9965
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9966
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9967
    {
9968
        return 0;
9969
    }
9970
9971
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9972
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9973
    // process. This process ID will be correctly returned even if the parent process has
9974
    // exited or been terminated.
9975
9976
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9977
    return cached_ppid;
9978
}
9979
9980
static PyObject*
9981
win32_getppid(void)
9982
{
9983
    DWORD error;
9984
    PyObject* result = NULL;
9985
    HANDLE process = GetCurrentProcess();
9986
    HPSS snapshot = NULL;
9987
    ULONG pid;
9988
9989
    pid = win32_getppid_fast();
9990
    if (pid != 0) {
9991
        return PyLong_FromUnsignedLong(pid);
9992
    }
9993
9994
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9995
9996
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9997
    if (error != ERROR_SUCCESS) {
9998
        return PyErr_SetFromWindowsErr(error);
9999
    }
10000
10001
    PSS_PROCESS_INFORMATION info;
10002
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
10003
                             sizeof(info));
10004
    if (error == ERROR_SUCCESS) {
10005
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
10006
    }
10007
    else {
10008
        result = PyErr_SetFromWindowsErr(error);
10009
    }
10010
10011
    PssFreeSnapshot(process, snapshot);
10012
    return result;
10013
}
10014
#endif /*MS_WINDOWS*/
10015
10016
10017
/*[clinic input]
10018
os.getppid
10019
10020
Return the parent's process id.
10021
10022
If the parent process has already exited, Windows machines will still
10023
return its id; others systems will return the id of the 'init' process (1).
10024
[clinic start generated code]*/
10025
10026
static PyObject *
10027
os_getppid_impl(PyObject *module)
10028
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
10029
0
{
10030
#ifdef MS_WINDOWS
10031
    return win32_getppid();
10032
#else
10033
0
    return PyLong_FromPid(getppid());
10034
0
#endif
10035
0
}
10036
#endif /* HAVE_GETPPID */
10037
10038
10039
#ifdef HAVE_GETLOGIN
10040
/*[clinic input]
10041
os.getlogin
10042
10043
Return the actual login name.
10044
[clinic start generated code]*/
10045
10046
static PyObject *
10047
os_getlogin_impl(PyObject *module)
10048
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10049
0
{
10050
0
    PyObject *result = NULL;
10051
#ifdef MS_WINDOWS
10052
    wchar_t user_name[UNLEN + 1];
10053
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10054
10055
    if (GetUserNameW(user_name, &num_chars)) {
10056
        /* num_chars is the number of unicode chars plus null terminator */
10057
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10058
    }
10059
    else
10060
        result = PyErr_SetFromWindowsErr(GetLastError());
10061
#elif defined (HAVE_GETLOGIN_R)
10062
# if defined (HAVE_MAXLOGNAME)
10063
    char name[MAXLOGNAME + 1];
10064
# elif defined (HAVE_UT_NAMESIZE)
10065
    char name[UT_NAMESIZE + 1];
10066
# else
10067
    char name[256];
10068
# endif
10069
0
    int err = getlogin_r(name, sizeof(name));
10070
0
    if (err) {
10071
0
        int old_errno = errno;
10072
0
        errno = err;
10073
0
        posix_error();
10074
0
        errno = old_errno;
10075
0
    }
10076
0
    else {
10077
0
        result = PyUnicode_DecodeFSDefault(name);
10078
0
    }
10079
#else
10080
    char *name;
10081
    int old_errno = errno;
10082
10083
    errno = 0;
10084
    name = getlogin();
10085
    if (name == NULL) {
10086
        if (errno)
10087
            posix_error();
10088
        else
10089
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10090
    }
10091
    else
10092
        result = PyUnicode_DecodeFSDefault(name);
10093
    errno = old_errno;
10094
#endif
10095
0
    return result;
10096
0
}
10097
#endif /* HAVE_GETLOGIN */
10098
10099
10100
#ifdef HAVE_GETUID
10101
/*[clinic input]
10102
os.getuid
10103
10104
Return the current process's user id.
10105
[clinic start generated code]*/
10106
10107
static PyObject *
10108
os_getuid_impl(PyObject *module)
10109
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10110
36
{
10111
36
    return _PyLong_FromUid(getuid());
10112
36
}
10113
#endif /* HAVE_GETUID */
10114
10115
10116
#ifdef MS_WINDOWS
10117
#define HAVE_KILL
10118
#endif /* MS_WINDOWS */
10119
10120
#ifdef HAVE_KILL
10121
/*[clinic input]
10122
os.kill
10123
10124
    pid: pid_t
10125
    signal: Py_ssize_t
10126
    /
10127
10128
Kill a process with a signal.
10129
[clinic start generated code]*/
10130
10131
static PyObject *
10132
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10133
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10134
0
{
10135
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10136
0
        return NULL;
10137
0
    }
10138
0
#ifndef MS_WINDOWS
10139
0
    if (kill(pid, (int)signal) == -1) {
10140
0
        return posix_error();
10141
0
    }
10142
10143
    // Check immediately if the signal was sent to the current process.
10144
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10145
    // is cheap.
10146
0
    if (PyErr_CheckSignals()) {
10147
0
        return NULL;
10148
0
    }
10149
10150
0
    Py_RETURN_NONE;
10151
#else /* !MS_WINDOWS */
10152
    DWORD sig = (DWORD)signal;
10153
10154
#ifdef HAVE_WINDOWS_CONSOLE_IO
10155
    /* Console processes which share a common console can be sent CTRL+C or
10156
       CTRL+BREAK events, provided they handle said events. */
10157
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10158
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10159
            return PyErr_SetFromWindowsErr(0);
10160
        }
10161
        Py_RETURN_NONE;
10162
    }
10163
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10164
10165
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10166
       attempt to open and terminate the process. */
10167
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10168
    if (handle == NULL) {
10169
        return PyErr_SetFromWindowsErr(0);
10170
    }
10171
10172
    BOOL res = TerminateProcess(handle, sig);
10173
    CloseHandle(handle);
10174
    if (res == 0) {
10175
        return PyErr_SetFromWindowsErr(0);
10176
    }
10177
10178
    Py_RETURN_NONE;
10179
#endif /* !MS_WINDOWS */
10180
0
}
10181
#endif /* HAVE_KILL */
10182
10183
10184
#ifdef HAVE_KILLPG
10185
/*[clinic input]
10186
os.killpg
10187
10188
    pgid: pid_t
10189
    signal: int
10190
    /
10191
10192
Kill a process group with a signal.
10193
[clinic start generated code]*/
10194
10195
static PyObject *
10196
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10197
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10198
0
{
10199
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10200
0
        return NULL;
10201
0
    }
10202
    /* XXX some man pages make the `pgid` parameter an int, others
10203
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10204
       take the same type. Moreover, pid_t is always at least as wide as
10205
       int (else compilation of this module fails), which is safe. */
10206
0
    if (killpg(pgid, signal) == -1)
10207
0
        return posix_error();
10208
0
    Py_RETURN_NONE;
10209
0
}
10210
#endif /* HAVE_KILLPG */
10211
10212
10213
#ifdef HAVE_PLOCK
10214
#ifdef HAVE_SYS_LOCK_H
10215
#include <sys/lock.h>
10216
#endif
10217
10218
/*[clinic input]
10219
os.plock
10220
    op: int
10221
    /
10222
10223
Lock program segments into memory.");
10224
[clinic start generated code]*/
10225
10226
static PyObject *
10227
os_plock_impl(PyObject *module, int op)
10228
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10229
{
10230
    if (plock(op) == -1)
10231
        return posix_error();
10232
    Py_RETURN_NONE;
10233
}
10234
#endif /* HAVE_PLOCK */
10235
10236
10237
#ifdef HAVE_SETUID
10238
/*[clinic input]
10239
os.setuid
10240
10241
    uid: uid_t
10242
    /
10243
10244
Set the current process's user id.
10245
[clinic start generated code]*/
10246
10247
static PyObject *
10248
os_setuid_impl(PyObject *module, uid_t uid)
10249
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10250
0
{
10251
0
    if (setuid(uid) < 0)
10252
0
        return posix_error();
10253
0
    Py_RETURN_NONE;
10254
0
}
10255
#endif /* HAVE_SETUID */
10256
10257
10258
#ifdef HAVE_SETEUID
10259
/*[clinic input]
10260
os.seteuid
10261
10262
    euid: uid_t
10263
    /
10264
10265
Set the current process's effective user id.
10266
[clinic start generated code]*/
10267
10268
static PyObject *
10269
os_seteuid_impl(PyObject *module, uid_t euid)
10270
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10271
0
{
10272
0
    if (seteuid(euid) < 0)
10273
0
        return posix_error();
10274
0
    Py_RETURN_NONE;
10275
0
}
10276
#endif /* HAVE_SETEUID */
10277
10278
10279
#ifdef HAVE_SETEGID
10280
/*[clinic input]
10281
os.setegid
10282
10283
    egid: gid_t
10284
    /
10285
10286
Set the current process's effective group id.
10287
[clinic start generated code]*/
10288
10289
static PyObject *
10290
os_setegid_impl(PyObject *module, gid_t egid)
10291
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10292
0
{
10293
0
    if (setegid(egid) < 0)
10294
0
        return posix_error();
10295
0
    Py_RETURN_NONE;
10296
0
}
10297
#endif /* HAVE_SETEGID */
10298
10299
10300
#ifdef HAVE_SETREUID
10301
/*[clinic input]
10302
os.setreuid
10303
10304
    ruid: uid_t
10305
    euid: uid_t
10306
    /
10307
10308
Set the current process's real and effective user ids.
10309
[clinic start generated code]*/
10310
10311
static PyObject *
10312
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10313
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10314
0
{
10315
0
    if (setreuid(ruid, euid) < 0) {
10316
0
        return posix_error();
10317
0
    } else {
10318
0
        Py_RETURN_NONE;
10319
0
    }
10320
0
}
10321
#endif /* HAVE_SETREUID */
10322
10323
10324
#ifdef HAVE_SETREGID
10325
/*[clinic input]
10326
os.setregid
10327
10328
    rgid: gid_t
10329
    egid: gid_t
10330
    /
10331
10332
Set the current process's real and effective group ids.
10333
[clinic start generated code]*/
10334
10335
static PyObject *
10336
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10337
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10338
0
{
10339
0
    if (setregid(rgid, egid) < 0)
10340
0
        return posix_error();
10341
0
    Py_RETURN_NONE;
10342
0
}
10343
#endif /* HAVE_SETREGID */
10344
10345
10346
#ifdef HAVE_SETGID
10347
/*[clinic input]
10348
os.setgid
10349
    gid: gid_t
10350
    /
10351
10352
Set the current process's group id.
10353
[clinic start generated code]*/
10354
10355
static PyObject *
10356
os_setgid_impl(PyObject *module, gid_t gid)
10357
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10358
0
{
10359
0
    if (setgid(gid) < 0)
10360
0
        return posix_error();
10361
0
    Py_RETURN_NONE;
10362
0
}
10363
#endif /* HAVE_SETGID */
10364
10365
10366
#ifdef HAVE_SETGROUPS
10367
/*[clinic input]
10368
os.setgroups
10369
10370
    groups: object
10371
    /
10372
10373
Set the groups of the current process to list.
10374
[clinic start generated code]*/
10375
10376
static PyObject *
10377
os_setgroups(PyObject *module, PyObject *groups)
10378
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10379
0
{
10380
0
    if (!PySequence_Check(groups)) {
10381
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10382
0
        return NULL;
10383
0
    }
10384
0
    Py_ssize_t len = PySequence_Size(groups);
10385
0
    if (len < 0) {
10386
0
        return NULL;
10387
0
    }
10388
0
    if (len > MAX_GROUPS) {
10389
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10390
0
        return NULL;
10391
0
    }
10392
10393
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10394
0
    if (grouplist == NULL) {
10395
0
        PyErr_NoMemory();
10396
0
        return NULL;
10397
0
    }
10398
0
    for (Py_ssize_t i = 0; i < len; i++) {
10399
0
        PyObject *elem;
10400
0
        elem = PySequence_GetItem(groups, i);
10401
0
        if (!elem) {
10402
0
            PyMem_Free(grouplist);
10403
0
            return NULL;
10404
0
        }
10405
0
        if (!PyIndex_Check(elem)) {
10406
0
            PyErr_SetString(PyExc_TypeError,
10407
0
                            "groups must be integers");
10408
0
            Py_DECREF(elem);
10409
0
            PyMem_Free(grouplist);
10410
0
            return NULL;
10411
0
        } else {
10412
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10413
0
                Py_DECREF(elem);
10414
0
                PyMem_Free(grouplist);
10415
0
                return NULL;
10416
0
            }
10417
0
        }
10418
0
        Py_DECREF(elem);
10419
0
    }
10420
10421
0
    if (setgroups(len, grouplist) < 0) {
10422
0
        posix_error();
10423
0
        PyMem_Free(grouplist);
10424
0
        return NULL;
10425
0
    }
10426
0
    PyMem_Free(grouplist);
10427
0
    Py_RETURN_NONE;
10428
0
}
10429
#endif /* HAVE_SETGROUPS */
10430
10431
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10432
static PyObject *
10433
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10434
0
{
10435
0
    PyObject *result;
10436
0
    PyObject *struct_rusage;
10437
10438
0
    if (pid == -1)
10439
0
        return posix_error();
10440
10441
    // If wait succeeded but no child was ready to report status, ru will not
10442
    // have been populated.
10443
0
    if (pid == 0) {
10444
0
        memset(ru, 0, sizeof(*ru));
10445
0
    }
10446
10447
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10448
0
    if (struct_rusage == NULL)
10449
0
        return NULL;
10450
10451
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10452
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10453
0
    Py_DECREF(struct_rusage);
10454
0
    if (!result)
10455
0
        return NULL;
10456
10457
0
    int pos = 0;
10458
10459
0
#ifndef doubletime
10460
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10461
0
#endif
10462
10463
0
#define SET_RESULT(CALL)                                     \
10464
0
    do {                                                     \
10465
0
        PyObject *item = (CALL);                             \
10466
0
        if (item == NULL) {                                  \
10467
0
            Py_DECREF(result);                               \
10468
0
            return NULL;                                     \
10469
0
        }                                                    \
10470
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10471
0
    } while(0)
10472
10473
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10474
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10475
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10476
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10477
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10478
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10479
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10480
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10481
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10482
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10483
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10484
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10485
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10486
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10487
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10488
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10489
0
#undef SET_RESULT
10490
10491
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10492
0
}
10493
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10494
10495
10496
#ifdef HAVE_WAIT3
10497
/*[clinic input]
10498
os.wait3
10499
10500
    options: int
10501
Wait for completion of a child process.
10502
10503
Returns a tuple of information about the child process:
10504
  (pid, status, rusage)
10505
[clinic start generated code]*/
10506
10507
static PyObject *
10508
os_wait3_impl(PyObject *module, int options)
10509
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10510
0
{
10511
0
    pid_t pid;
10512
0
    struct rusage ru;
10513
0
    int async_err = 0;
10514
0
    WAIT_TYPE status;
10515
0
    WAIT_STATUS_INT(status) = 0;
10516
10517
0
    do {
10518
0
        Py_BEGIN_ALLOW_THREADS
10519
0
        pid = wait3(&status, options, &ru);
10520
0
        Py_END_ALLOW_THREADS
10521
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10522
0
    if (pid < 0)
10523
0
        return (!async_err) ? posix_error() : NULL;
10524
10525
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10526
0
}
10527
#endif /* HAVE_WAIT3 */
10528
10529
10530
#ifdef HAVE_WAIT4
10531
/*[clinic input]
10532
10533
os.wait4
10534
10535
    pid: pid_t
10536
    options: int
10537
10538
Wait for completion of a specific child process.
10539
10540
Returns a tuple of information about the child process:
10541
  (pid, status, rusage)
10542
[clinic start generated code]*/
10543
10544
static PyObject *
10545
os_wait4_impl(PyObject *module, pid_t pid, int options)
10546
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10547
0
{
10548
0
    pid_t res;
10549
0
    struct rusage ru;
10550
0
    int async_err = 0;
10551
0
    WAIT_TYPE status;
10552
0
    WAIT_STATUS_INT(status) = 0;
10553
10554
0
    do {
10555
0
        Py_BEGIN_ALLOW_THREADS
10556
0
        res = wait4(pid, &status, options, &ru);
10557
0
        Py_END_ALLOW_THREADS
10558
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10559
0
    if (res < 0)
10560
0
        return (!async_err) ? posix_error() : NULL;
10561
10562
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10563
0
}
10564
#endif /* HAVE_WAIT4 */
10565
10566
10567
#if defined(HAVE_WAITID)
10568
/*[clinic input]
10569
os.waitid
10570
10571
    idtype: idtype_t
10572
        Must be one of be P_PID, P_PGID or P_ALL.
10573
    id: id_t
10574
        The id to wait on.
10575
    options: int
10576
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10577
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10578
    /
10579
10580
Returns the result of waiting for a process or processes.
10581
10582
Returns either waitid_result or None if WNOHANG is specified and there are
10583
no children in a waitable state.
10584
[clinic start generated code]*/
10585
10586
static PyObject *
10587
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10588
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10589
0
{
10590
0
    PyObject *result;
10591
0
    int res;
10592
0
    int async_err = 0;
10593
0
    siginfo_t si;
10594
0
    si.si_pid = 0;
10595
10596
0
    do {
10597
0
        Py_BEGIN_ALLOW_THREADS
10598
0
        res = waitid(idtype, id, &si, options);
10599
0
        Py_END_ALLOW_THREADS
10600
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10601
0
    if (res < 0)
10602
0
        return (!async_err) ? posix_error() : NULL;
10603
10604
0
    if (si.si_pid == 0)
10605
0
        Py_RETURN_NONE;
10606
10607
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10608
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10609
0
    if (!result)
10610
0
        return NULL;
10611
10612
0
    int pos = 0;
10613
10614
0
#define SET_RESULT(CALL)                                     \
10615
0
    do {                                                     \
10616
0
        PyObject *item = (CALL);                             \
10617
0
        if (item == NULL) {                                  \
10618
0
            Py_DECREF(result);                               \
10619
0
            return NULL;                                     \
10620
0
        }                                                    \
10621
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10622
0
    } while(0)
10623
10624
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10625
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10626
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10627
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10628
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10629
10630
0
#undef SET_RESULT
10631
10632
0
    return result;
10633
0
}
10634
#endif /* defined(HAVE_WAITID) */
10635
10636
10637
#if defined(HAVE_WAITPID)
10638
/*[clinic input]
10639
os.waitpid
10640
    pid: pid_t
10641
    options: int
10642
    /
10643
10644
Wait for completion of a given child process.
10645
10646
Returns a tuple of information regarding the child process:
10647
    (pid, status)
10648
10649
The options argument is ignored on Windows.
10650
[clinic start generated code]*/
10651
10652
static PyObject *
10653
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10654
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10655
0
{
10656
0
    pid_t res;
10657
0
    int async_err = 0;
10658
0
    WAIT_TYPE status;
10659
0
    WAIT_STATUS_INT(status) = 0;
10660
10661
0
    do {
10662
0
        Py_BEGIN_ALLOW_THREADS
10663
0
        res = waitpid(pid, &status, options);
10664
0
        Py_END_ALLOW_THREADS
10665
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10666
0
    if (res < 0)
10667
0
        return (!async_err) ? posix_error() : NULL;
10668
10669
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10670
0
}
10671
#elif defined(HAVE_CWAIT)
10672
/* MS C has a variant of waitpid() that's usable for most purposes. */
10673
/*[clinic input]
10674
os.waitpid
10675
    pid: intptr_t
10676
    options: int
10677
    /
10678
10679
Wait for completion of a given process.
10680
10681
Returns a tuple of information regarding the process:
10682
    (pid, status << 8)
10683
10684
The options argument is ignored on Windows.
10685
[clinic start generated code]*/
10686
10687
static PyObject *
10688
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10689
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10690
{
10691
    int status;
10692
    intptr_t res;
10693
    int async_err = 0;
10694
10695
    do {
10696
        Py_BEGIN_ALLOW_THREADS
10697
        _Py_BEGIN_SUPPRESS_IPH
10698
        res = _cwait(&status, pid, options);
10699
        _Py_END_SUPPRESS_IPH
10700
        Py_END_ALLOW_THREADS
10701
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10702
    if (res < 0)
10703
        return (!async_err) ? posix_error() : NULL;
10704
10705
    unsigned long long ustatus = (unsigned int)status;
10706
10707
    /* shift the status left a byte so this is more like the POSIX waitpid */
10708
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10709
}
10710
#endif
10711
10712
10713
#ifdef HAVE_WAIT
10714
/*[clinic input]
10715
os.wait
10716
10717
Wait for completion of a child process.
10718
10719
Returns a tuple of information about the child process:
10720
    (pid, status)
10721
[clinic start generated code]*/
10722
10723
static PyObject *
10724
os_wait_impl(PyObject *module)
10725
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10726
0
{
10727
0
    pid_t pid;
10728
0
    int async_err = 0;
10729
0
    WAIT_TYPE status;
10730
0
    WAIT_STATUS_INT(status) = 0;
10731
10732
0
    do {
10733
0
        Py_BEGIN_ALLOW_THREADS
10734
0
        pid = wait(&status);
10735
0
        Py_END_ALLOW_THREADS
10736
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10737
0
    if (pid < 0)
10738
0
        return (!async_err) ? posix_error() : NULL;
10739
10740
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10741
0
}
10742
#endif /* HAVE_WAIT */
10743
10744
10745
// This system call always crashes on older Android versions.
10746
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10747
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10748
/*[clinic input]
10749
os.pidfd_open
10750
  pid: pid_t
10751
  flags: unsigned_int = 0
10752
10753
Return a file descriptor referring to the process *pid*.
10754
10755
The descriptor can be used to perform process management without races and
10756
signals.
10757
[clinic start generated code]*/
10758
10759
static PyObject *
10760
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10761
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10762
4
{
10763
4
    int fd = syscall(__NR_pidfd_open, pid, flags);
10764
4
    if (fd < 0) {
10765
0
        return posix_error();
10766
0
    }
10767
4
    return PyLong_FromLong(fd);
10768
4
}
10769
#endif
10770
10771
10772
#ifdef HAVE_SETNS
10773
/*[clinic input]
10774
os.setns
10775
  fd: fildes
10776
    A file descriptor to a namespace.
10777
  nstype: int = 0
10778
    Type of namespace.
10779
10780
Move the calling thread into different namespaces.
10781
[clinic start generated code]*/
10782
10783
static PyObject *
10784
os_setns_impl(PyObject *module, int fd, int nstype)
10785
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10786
0
{
10787
0
    int res;
10788
10789
0
    Py_BEGIN_ALLOW_THREADS
10790
0
    res = setns(fd, nstype);
10791
0
    Py_END_ALLOW_THREADS
10792
10793
0
    if (res != 0) {
10794
0
        return posix_error();
10795
0
    }
10796
10797
0
    Py_RETURN_NONE;
10798
0
}
10799
#endif
10800
10801
10802
#ifdef HAVE_UNSHARE
10803
/*[clinic input]
10804
os.unshare
10805
  flags: int
10806
    Namespaces to be unshared.
10807
10808
Disassociate parts of a process (or thread) execution context.
10809
[clinic start generated code]*/
10810
10811
static PyObject *
10812
os_unshare_impl(PyObject *module, int flags)
10813
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10814
0
{
10815
0
    int res;
10816
10817
0
    Py_BEGIN_ALLOW_THREADS
10818
0
    res = unshare(flags);
10819
0
    Py_END_ALLOW_THREADS
10820
10821
0
    if (res != 0) {
10822
0
        return posix_error();
10823
0
    }
10824
10825
0
    Py_RETURN_NONE;
10826
0
}
10827
#endif
10828
10829
10830
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10831
/*[clinic input]
10832
os.readlink
10833
10834
    path: path_t
10835
    *
10836
    dir_fd: dir_fd(requires='readlinkat') = None
10837
10838
Return a string representing the path to which the symbolic link points.
10839
10840
If dir_fd is not None, it should be a file descriptor open to a directory,
10841
and path should be relative; path will then be relative to that directory.
10842
10843
dir_fd may not be implemented on your platform.  If it is unavailable,
10844
using it will raise a NotImplementedError.
10845
[clinic start generated code]*/
10846
10847
static PyObject *
10848
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10849
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10850
6
{
10851
6
#if defined(HAVE_READLINK)
10852
6
    char buffer[MAXPATHLEN+1];
10853
6
    ssize_t length;
10854
6
#ifdef HAVE_READLINKAT
10855
6
    int readlinkat_unavailable = 0;
10856
6
#endif
10857
10858
6
    Py_BEGIN_ALLOW_THREADS
10859
6
#ifdef HAVE_READLINKAT
10860
6
    if (dir_fd != DEFAULT_DIR_FD) {
10861
0
        if (HAVE_READLINKAT_RUNTIME) {
10862
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10863
0
        } else {
10864
0
            readlinkat_unavailable = 1;
10865
0
        }
10866
0
    } else
10867
6
#endif
10868
6
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10869
6
    Py_END_ALLOW_THREADS
10870
10871
6
#ifdef HAVE_READLINKAT
10872
6
    if (readlinkat_unavailable) {
10873
0
        argument_unavailable_error(NULL, "dir_fd");
10874
0
        return NULL;
10875
0
    }
10876
6
#endif
10877
10878
6
    if (length < 0) {
10879
0
        return path_error(path);
10880
0
    }
10881
6
    buffer[length] = '\0';
10882
10883
6
    if (PyUnicode_Check(path->object))
10884
6
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10885
0
    else
10886
0
        return PyBytes_FromStringAndSize(buffer, length);
10887
#elif defined(MS_WINDOWS)
10888
    DWORD n_bytes_returned;
10889
    DWORD io_result = 0;
10890
    HANDLE reparse_point_handle;
10891
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10892
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10893
    PyObject *result = NULL;
10894
10895
    /* First get a handle to the reparse point */
10896
    Py_BEGIN_ALLOW_THREADS
10897
    reparse_point_handle = CreateFileW(
10898
        path->wide,
10899
        0,
10900
        0,
10901
        0,
10902
        OPEN_EXISTING,
10903
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10904
        0);
10905
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10906
        /* New call DeviceIoControl to read the reparse point */
10907
        io_result = DeviceIoControl(
10908
            reparse_point_handle,
10909
            FSCTL_GET_REPARSE_POINT,
10910
            0, 0, /* in buffer */
10911
            target_buffer, sizeof(target_buffer),
10912
            &n_bytes_returned,
10913
            0 /* we're not using OVERLAPPED_IO */
10914
            );
10915
        CloseHandle(reparse_point_handle);
10916
    }
10917
    Py_END_ALLOW_THREADS
10918
10919
    if (io_result == 0) {
10920
        return path_error(path);
10921
    }
10922
10923
    wchar_t *name = NULL;
10924
    Py_ssize_t nameLen = 0;
10925
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10926
    {
10927
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10928
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10929
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10930
    }
10931
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10932
    {
10933
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10934
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10935
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10936
    }
10937
    else
10938
    {
10939
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10940
    }
10941
    if (name) {
10942
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10943
            /* Our buffer is mutable, so this is okay */
10944
            name[1] = L'\\';
10945
        }
10946
        result = PyUnicode_FromWideChar(name, nameLen);
10947
        if (result && PyBytes_Check(path->object)) {
10948
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10949
        }
10950
    }
10951
    return result;
10952
#endif
10953
6
}
10954
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10955
10956
#if defined(MS_WINDOWS)
10957
10958
/* Remove the last portion of the path - return 0 on success */
10959
static int
10960
_dirnameW(WCHAR *path)
10961
{
10962
    WCHAR *ptr;
10963
    size_t length = wcsnlen_s(path, MAX_PATH);
10964
    if (length == MAX_PATH) {
10965
        return -1;
10966
    }
10967
10968
    /* walk the path from the end until a backslash is encountered */
10969
    for(ptr = path + length; ptr != path; ptr--) {
10970
        if (*ptr == L'\\' || *ptr == L'/') {
10971
            break;
10972
        }
10973
    }
10974
    *ptr = 0;
10975
    return 0;
10976
}
10977
10978
#endif
10979
10980
#ifdef HAVE_SYMLINK
10981
10982
#if defined(MS_WINDOWS)
10983
10984
/* Is this path absolute? */
10985
static int
10986
_is_absW(const WCHAR *path)
10987
{
10988
    return path[0] == L'\\' || path[0] == L'/' ||
10989
        (path[0] && path[1] == L':');
10990
}
10991
10992
/* join root and rest with a backslash - return 0 on success */
10993
static int
10994
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10995
{
10996
    if (_is_absW(rest)) {
10997
        return wcscpy_s(dest_path, MAX_PATH, rest);
10998
    }
10999
11000
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
11001
        return -1;
11002
    }
11003
11004
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
11005
        return -1;
11006
    }
11007
11008
    return wcscat_s(dest_path, MAX_PATH, rest);
11009
}
11010
11011
/* Return True if the path at src relative to dest is a directory */
11012
static int
11013
_check_dirW(LPCWSTR src, LPCWSTR dest)
11014
{
11015
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11016
    WCHAR dest_parent[MAX_PATH];
11017
    WCHAR src_resolved[MAX_PATH] = L"";
11018
11019
    /* dest_parent = os.path.dirname(dest) */
11020
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11021
        _dirnameW(dest_parent)) {
11022
        return 0;
11023
    }
11024
    /* src_resolved = os.path.join(dest_parent, src) */
11025
    if (_joinW(src_resolved, dest_parent, src)) {
11026
        return 0;
11027
    }
11028
    return (
11029
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11030
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11031
    );
11032
}
11033
#endif
11034
11035
11036
/*[clinic input]
11037
os.symlink
11038
    src: path_t
11039
    dst: path_t
11040
    target_is_directory: bool = False
11041
    *
11042
    dir_fd: dir_fd(requires='symlinkat')=None
11043
11044
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
11045
11046
Create a symbolic link pointing to src named dst.
11047
11048
target_is_directory is required on Windows if the target is to be
11049
  interpreted as a directory.  (On Windows, symlink requires
11050
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
11051
  target_is_directory is ignored on non-Windows platforms.
11052
11053
If dir_fd is not None, it should be a file descriptor open to a directory,
11054
  and path should be relative; path will then be relative to that directory.
11055
dir_fd may not be implemented on your platform.
11056
  If it is unavailable, using it will raise a NotImplementedError.
11057
11058
[clinic start generated code]*/
11059
11060
static PyObject *
11061
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11062
                int target_is_directory, int dir_fd)
11063
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
11064
0
{
11065
#ifdef MS_WINDOWS
11066
    DWORD result;
11067
    DWORD flags = 0;
11068
11069
    /* Assumed true, set to false if detected to not be available. */
11070
    static int windows_has_symlink_unprivileged_flag = TRUE;
11071
#else
11072
0
    int result;
11073
0
#ifdef HAVE_SYMLINKAT
11074
0
    int symlinkat_unavailable = 0;
11075
0
#endif
11076
0
#endif
11077
11078
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11079
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11080
0
        return NULL;
11081
0
    }
11082
11083
#ifdef MS_WINDOWS
11084
11085
    if (windows_has_symlink_unprivileged_flag) {
11086
        /* Allow non-admin symlinks if system allows it. */
11087
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11088
    }
11089
11090
    Py_BEGIN_ALLOW_THREADS
11091
    _Py_BEGIN_SUPPRESS_IPH
11092
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11093
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11094
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11095
    }
11096
11097
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11098
    _Py_END_SUPPRESS_IPH
11099
    Py_END_ALLOW_THREADS
11100
11101
    if (windows_has_symlink_unprivileged_flag && !result &&
11102
        ERROR_INVALID_PARAMETER == GetLastError()) {
11103
11104
        Py_BEGIN_ALLOW_THREADS
11105
        _Py_BEGIN_SUPPRESS_IPH
11106
        /* This error might be caused by
11107
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11108
        Try again, and update windows_has_symlink_unprivileged_flag if we
11109
        are successful this time.
11110
11111
        NOTE: There is a risk of a race condition here if there are other
11112
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11113
        another process (or thread) changes that condition in between our
11114
        calls to CreateSymbolicLink.
11115
        */
11116
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11117
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11118
        _Py_END_SUPPRESS_IPH
11119
        Py_END_ALLOW_THREADS
11120
11121
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11122
            windows_has_symlink_unprivileged_flag = FALSE;
11123
        }
11124
    }
11125
11126
    if (!result)
11127
        return path_error2(src, dst);
11128
11129
#else
11130
11131
0
    Py_BEGIN_ALLOW_THREADS
11132
0
#ifdef HAVE_SYMLINKAT
11133
0
    if (dir_fd != DEFAULT_DIR_FD) {
11134
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11135
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11136
0
        } else {
11137
0
            symlinkat_unavailable = 1;
11138
0
        }
11139
0
    } else
11140
0
#endif
11141
0
        result = symlink(src->narrow, dst->narrow);
11142
0
    Py_END_ALLOW_THREADS
11143
11144
0
#ifdef HAVE_SYMLINKAT
11145
0
    if (symlinkat_unavailable) {
11146
0
          argument_unavailable_error(NULL, "dir_fd");
11147
0
          return NULL;
11148
0
    }
11149
0
#endif
11150
11151
0
    if (result)
11152
0
        return path_error2(src, dst);
11153
0
#endif
11154
11155
0
    Py_RETURN_NONE;
11156
0
}
11157
#endif /* HAVE_SYMLINK */
11158
11159
11160
static PyStructSequence_Field times_result_fields[] = {
11161
    {"user",    "user time"},
11162
    {"system",   "system time"},
11163
    {"children_user",    "user time of children"},
11164
    {"children_system",    "system time of children"},
11165
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11166
    {NULL}
11167
};
11168
11169
PyDoc_STRVAR(times_result__doc__,
11170
"times_result: Result from os.times().\n\n\
11171
This object may be accessed either as a tuple of\n\
11172
  (user, system, children_user, children_system, elapsed),\n\
11173
or via the attributes user, system, children_user, children_system,\n\
11174
and elapsed.\n\
11175
\n\
11176
See os.times for more information.");
11177
11178
static PyStructSequence_Desc times_result_desc = {
11179
    MODNAME ".times_result", /* name */
11180
    times_result__doc__, /* doc */
11181
    times_result_fields,
11182
    5
11183
};
11184
11185
static PyObject *
11186
build_times_result(PyObject *module, double user, double system,
11187
    double children_user, double children_system,
11188
    double elapsed)
11189
0
{
11190
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11191
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11192
0
    if (value == NULL)
11193
0
        return NULL;
11194
11195
0
#define SET(i, field) \
11196
0
    { \
11197
0
    PyObject *o = PyFloat_FromDouble(field); \
11198
0
    if (!o) { \
11199
0
        Py_DECREF(value); \
11200
0
        return NULL; \
11201
0
    } \
11202
0
    PyStructSequence_SET_ITEM(value, i, o); \
11203
0
    } \
11204
0
11205
0
    SET(0, user);
11206
0
    SET(1, system);
11207
0
    SET(2, children_user);
11208
0
    SET(3, children_system);
11209
0
    SET(4, elapsed);
11210
11211
0
#undef SET
11212
11213
0
    return value;
11214
0
}
11215
11216
11217
/*[clinic input]
11218
os.times
11219
11220
Return a collection containing process timing information.
11221
11222
The object returned behaves like a named tuple with these fields:
11223
  (utime, stime, cutime, cstime, elapsed_time)
11224
All fields are floating-point numbers.
11225
[clinic start generated code]*/
11226
11227
static PyObject *
11228
os_times_impl(PyObject *module)
11229
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11230
0
{
11231
#ifdef MS_WINDOWS
11232
    FILETIME create, exit, kernel, user;
11233
    HANDLE hProc;
11234
    hProc = GetCurrentProcess();
11235
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11236
    /* The fields of a FILETIME structure are the hi and lo part
11237
       of a 64-bit value expressed in 100 nanosecond units.
11238
       1e7 is one second in such units; 1e-7 the inverse.
11239
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11240
    */
11241
    return build_times_result(module,
11242
        (double)(user.dwHighDateTime*429.4967296 +
11243
                 user.dwLowDateTime*1e-7),
11244
        (double)(kernel.dwHighDateTime*429.4967296 +
11245
                 kernel.dwLowDateTime*1e-7),
11246
        (double)0,
11247
        (double)0,
11248
        (double)0);
11249
#else /* MS_WINDOWS */
11250
0
    _posixstate *state = get_posix_state(module);
11251
0
    long ticks_per_second = state->ticks_per_second;
11252
11253
0
    struct tms process;
11254
0
    clock_t elapsed;
11255
0
    errno = 0;
11256
0
    elapsed = times(&process);
11257
0
    if (elapsed == (clock_t) -1) {
11258
0
        return posix_error();
11259
0
    }
11260
11261
0
    return build_times_result(module,
11262
0
        (double)process.tms_utime / ticks_per_second,
11263
0
        (double)process.tms_stime / ticks_per_second,
11264
0
        (double)process.tms_cutime / ticks_per_second,
11265
0
        (double)process.tms_cstime / ticks_per_second,
11266
0
        (double)elapsed / ticks_per_second);
11267
0
#endif /* MS_WINDOWS */
11268
0
}
11269
11270
11271
#if defined(HAVE_TIMERFD_CREATE)
11272
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11273
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11274
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11275
11276
static PyObject *
11277
build_itimerspec(const struct itimerspec* curr_value)
11278
0
{
11279
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11280
0
                                                          curr_value->it_value.tv_nsec);
11281
0
    PyObject *value = PyFloat_FromDouble(_value);
11282
0
    if (value == NULL) {
11283
0
        return NULL;
11284
0
    }
11285
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11286
0
                                                   curr_value->it_interval.tv_nsec);
11287
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11288
0
    if (interval == NULL) {
11289
0
        Py_DECREF(value);
11290
0
        return NULL;
11291
0
    }
11292
0
    return _PyTuple_FromPairSteal(value, interval);
11293
0
}
11294
11295
static PyObject *
11296
build_itimerspec_ns(const struct itimerspec* curr_value)
11297
0
{
11298
0
    PyTime_t value, interval;
11299
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11300
0
        return NULL;
11301
0
    }
11302
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11303
0
        return NULL;
11304
0
    }
11305
0
    return Py_BuildValue("LL", value, interval);
11306
0
}
11307
11308
/*[clinic input]
11309
os.timerfd_create
11310
11311
    clockid: int
11312
        A valid clock ID constant as timer file descriptor.
11313
11314
        time.CLOCK_REALTIME
11315
        time.CLOCK_MONOTONIC
11316
        time.CLOCK_BOOTTIME
11317
    /
11318
    *
11319
    flags: int = 0
11320
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11321
11322
        os.TFD_NONBLOCK
11323
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11324
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11325
11326
        os.TFD_CLOEXEC
11327
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11328
11329
Create and return a timer file descriptor.
11330
[clinic start generated code]*/
11331
11332
static PyObject *
11333
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11334
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11335
11336
0
{
11337
0
    int fd;
11338
0
    Py_BEGIN_ALLOW_THREADS
11339
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11340
0
    fd = timerfd_create(clockid, flags);
11341
0
    Py_END_ALLOW_THREADS
11342
0
    if (fd == -1) {
11343
0
        return PyErr_SetFromErrno(PyExc_OSError);
11344
0
    }
11345
0
    return PyLong_FromLong(fd);
11346
0
}
11347
11348
/*[clinic input]
11349
os.timerfd_settime
11350
11351
    fd: fildes
11352
        A timer file descriptor.
11353
    /
11354
    *
11355
    flags: int = 0
11356
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11357
    initial as initial_double: double = 0.0
11358
        The initial expiration time, in seconds.
11359
    interval as interval_double: double = 0.0
11360
        The timer's interval, in seconds.
11361
11362
Alter a timer file descriptor's internal timer in seconds.
11363
[clinic start generated code]*/
11364
11365
static PyObject *
11366
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11367
                        double initial_double, double interval_double)
11368
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11369
0
{
11370
0
    PyTime_t initial, interval;
11371
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11372
0
                                  &initial) < 0) {
11373
0
        return NULL;
11374
0
    }
11375
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11376
0
                                  &interval) < 0) {
11377
0
        return NULL;
11378
0
    }
11379
11380
0
    struct itimerspec new_value, old_value;
11381
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11382
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11383
0
        return NULL;
11384
0
    }
11385
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11386
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11387
0
        return NULL;
11388
0
    }
11389
11390
0
    int result;
11391
0
    Py_BEGIN_ALLOW_THREADS
11392
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11393
0
    Py_END_ALLOW_THREADS
11394
0
    if (result == -1) {
11395
0
        return PyErr_SetFromErrno(PyExc_OSError);
11396
0
    }
11397
0
    return build_itimerspec(&old_value);
11398
0
}
11399
11400
11401
/*[clinic input]
11402
os.timerfd_settime_ns
11403
11404
    fd: fildes
11405
        A timer file descriptor.
11406
    /
11407
    *
11408
    flags: int = 0
11409
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11410
    initial: long_long = 0
11411
        initial expiration timing in seconds.
11412
    interval: long_long = 0
11413
        interval for the timer in seconds.
11414
11415
Alter a timer file descriptor's internal timer in nanoseconds.
11416
[clinic start generated code]*/
11417
11418
static PyObject *
11419
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11420
                           long long initial, long long interval)
11421
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11422
0
{
11423
0
    struct itimerspec new_value;
11424
0
    struct itimerspec old_value;
11425
0
    int result;
11426
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11427
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11428
0
        return NULL;
11429
0
    }
11430
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11431
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11432
0
        return NULL;
11433
0
    }
11434
0
    Py_BEGIN_ALLOW_THREADS
11435
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11436
0
    Py_END_ALLOW_THREADS
11437
0
    if (result == -1) {
11438
0
        return PyErr_SetFromErrno(PyExc_OSError);
11439
0
    }
11440
0
    return build_itimerspec_ns(&old_value);
11441
0
}
11442
11443
/*[clinic input]
11444
@permit_long_summary
11445
os.timerfd_gettime
11446
11447
    fd: fildes
11448
        A timer file descriptor.
11449
    /
11450
11451
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11452
[clinic start generated code]*/
11453
11454
static PyObject *
11455
os_timerfd_gettime_impl(PyObject *module, int fd)
11456
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11457
0
{
11458
0
    struct itimerspec curr_value;
11459
0
    int result;
11460
0
    Py_BEGIN_ALLOW_THREADS
11461
0
    result = timerfd_gettime(fd, &curr_value);
11462
0
    Py_END_ALLOW_THREADS
11463
0
    if (result == -1) {
11464
0
        return PyErr_SetFromErrno(PyExc_OSError);
11465
0
    }
11466
0
    return build_itimerspec(&curr_value);
11467
0
}
11468
11469
11470
/*[clinic input]
11471
@permit_long_summary
11472
os.timerfd_gettime_ns
11473
11474
    fd: fildes
11475
        A timer file descriptor.
11476
    /
11477
11478
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11479
[clinic start generated code]*/
11480
11481
static PyObject *
11482
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11483
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11484
0
{
11485
0
    struct itimerspec curr_value;
11486
0
    int result;
11487
0
    Py_BEGIN_ALLOW_THREADS
11488
0
    result = timerfd_gettime(fd, &curr_value);
11489
0
    Py_END_ALLOW_THREADS
11490
0
    if (result == -1) {
11491
0
        return PyErr_SetFromErrno(PyExc_OSError);
11492
0
    }
11493
0
    return build_itimerspec_ns(&curr_value);
11494
0
}
11495
11496
#undef ONE_SECOND_IN_NS
11497
#undef EXTRACT_NSEC
11498
11499
#endif  /* HAVE_TIMERFD_CREATE */
11500
11501
#ifdef HAVE_GETSID
11502
/*[clinic input]
11503
os.getsid
11504
11505
    pid: pid_t
11506
    /
11507
11508
Call the system call getsid(pid) and return the result.
11509
[clinic start generated code]*/
11510
11511
static PyObject *
11512
os_getsid_impl(PyObject *module, pid_t pid)
11513
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11514
0
{
11515
0
    int sid;
11516
0
    sid = getsid(pid);
11517
0
    if (sid < 0)
11518
0
        return posix_error();
11519
0
    return PyLong_FromLong((long)sid);
11520
0
}
11521
#endif /* HAVE_GETSID */
11522
11523
11524
#ifdef HAVE_SETSID
11525
/*[clinic input]
11526
os.setsid
11527
11528
Call the system call setsid().
11529
[clinic start generated code]*/
11530
11531
static PyObject *
11532
os_setsid_impl(PyObject *module)
11533
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11534
0
{
11535
0
    if (setsid() < 0)
11536
0
        return posix_error();
11537
0
    Py_RETURN_NONE;
11538
0
}
11539
#endif /* HAVE_SETSID */
11540
11541
11542
#ifdef HAVE_SETPGID
11543
/*[clinic input]
11544
os.setpgid
11545
11546
    pid: pid_t
11547
    pgrp: pid_t
11548
    /
11549
11550
Call the system call setpgid(pid, pgrp).
11551
[clinic start generated code]*/
11552
11553
static PyObject *
11554
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11555
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11556
0
{
11557
0
    if (setpgid(pid, pgrp) < 0)
11558
0
        return posix_error();
11559
0
    Py_RETURN_NONE;
11560
0
}
11561
#endif /* HAVE_SETPGID */
11562
11563
11564
#ifdef HAVE_TCGETPGRP
11565
/*[clinic input]
11566
os.tcgetpgrp
11567
11568
    fd: int
11569
    /
11570
11571
Return the process group associated with the terminal specified by fd.
11572
[clinic start generated code]*/
11573
11574
static PyObject *
11575
os_tcgetpgrp_impl(PyObject *module, int fd)
11576
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11577
0
{
11578
0
    pid_t pgid = tcgetpgrp(fd);
11579
0
    if (pgid < 0)
11580
0
        return posix_error();
11581
0
    return PyLong_FromPid(pgid);
11582
0
}
11583
#endif /* HAVE_TCGETPGRP */
11584
11585
11586
#ifdef HAVE_TCSETPGRP
11587
/*[clinic input]
11588
os.tcsetpgrp
11589
11590
    fd: int
11591
    pgid: pid_t
11592
    /
11593
11594
Set the process group associated with the terminal specified by fd.
11595
[clinic start generated code]*/
11596
11597
static PyObject *
11598
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11599
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11600
0
{
11601
0
    if (tcsetpgrp(fd, pgid) < 0)
11602
0
        return posix_error();
11603
0
    Py_RETURN_NONE;
11604
0
}
11605
#endif /* HAVE_TCSETPGRP */
11606
11607
/* Functions acting on file descriptors */
11608
11609
#ifdef O_CLOEXEC
11610
extern int _Py_open_cloexec_works;
11611
#endif
11612
11613
11614
/*[clinic input]
11615
os.open -> int
11616
    path: path_t
11617
    flags: int
11618
    mode: int = 0o777
11619
    *
11620
    dir_fd: dir_fd(requires='openat') = None
11621
11622
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11623
11624
Open a file for low level IO.  Returns a file descriptor (integer).
11625
11626
If dir_fd is not None, it should be a file descriptor open to a directory,
11627
  and path should be relative; path will then be relative to that directory.
11628
dir_fd may not be implemented on your platform.
11629
  If it is unavailable, using it will raise a NotImplementedError.
11630
[clinic start generated code]*/
11631
11632
static int
11633
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11634
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11635
214k
{
11636
214k
    int fd;
11637
214k
    int async_err = 0;
11638
214k
#ifdef HAVE_OPENAT
11639
214k
    int openat_unavailable = 0;
11640
214k
#endif
11641
11642
214k
#ifdef O_CLOEXEC
11643
214k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11644
#elif !defined(MS_WINDOWS)
11645
    int *atomic_flag_works = NULL;
11646
#endif
11647
11648
#ifdef MS_WINDOWS
11649
    flags |= O_NOINHERIT;
11650
#elif defined(O_CLOEXEC)
11651
214k
    flags |= O_CLOEXEC;
11652
214k
#endif
11653
11654
214k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11655
0
        return -1;
11656
0
    }
11657
11658
214k
    _Py_BEGIN_SUPPRESS_IPH
11659
214k
    do {
11660
214k
        Py_BEGIN_ALLOW_THREADS
11661
#ifdef MS_WINDOWS
11662
        fd = _wopen(path->wide, flags, mode);
11663
#else
11664
214k
#ifdef HAVE_OPENAT
11665
214k
        if (dir_fd != DEFAULT_DIR_FD) {
11666
209k
            if (HAVE_OPENAT_RUNTIME) {
11667
209k
                fd = openat(dir_fd, path->narrow, flags, mode);
11668
11669
209k
            } else {
11670
0
                openat_unavailable = 1;
11671
0
                fd = -1;
11672
0
            }
11673
209k
        } else
11674
4.65k
#endif /* HAVE_OPENAT */
11675
4.65k
            fd = open(path->narrow, flags, mode);
11676
214k
#endif /* !MS_WINDOWS */
11677
214k
        Py_END_ALLOW_THREADS
11678
214k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11679
214k
    _Py_END_SUPPRESS_IPH
11680
11681
214k
#ifdef HAVE_OPENAT
11682
214k
    if (openat_unavailable) {
11683
0
        argument_unavailable_error(NULL, "dir_fd");
11684
0
        return -1;
11685
0
    }
11686
214k
#endif
11687
11688
214k
    if (fd < 0) {
11689
0
        if (!async_err)
11690
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11691
0
        return -1;
11692
0
    }
11693
11694
214k
#ifndef MS_WINDOWS
11695
214k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11696
0
        close(fd);
11697
0
        return -1;
11698
0
    }
11699
214k
#endif
11700
11701
214k
    return fd;
11702
214k
}
11703
11704
11705
/*[clinic input]
11706
os.close
11707
11708
    fd: int
11709
11710
Close a file descriptor.
11711
[clinic start generated code]*/
11712
11713
static PyObject *
11714
os_close_impl(PyObject *module, int fd)
11715
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11716
213k
{
11717
213k
    int res;
11718
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11719
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11720
     * for more details.
11721
     */
11722
213k
    Py_BEGIN_ALLOW_THREADS
11723
213k
    _Py_BEGIN_SUPPRESS_IPH
11724
213k
    res = close(fd);
11725
213k
    _Py_END_SUPPRESS_IPH
11726
213k
    Py_END_ALLOW_THREADS
11727
213k
    if (res < 0)
11728
0
        return posix_error();
11729
213k
    Py_RETURN_NONE;
11730
213k
}
11731
11732
/*[clinic input]
11733
os.closerange
11734
11735
    fd_low: int
11736
    fd_high: int
11737
    /
11738
11739
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11740
[clinic start generated code]*/
11741
11742
static PyObject *
11743
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11744
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11745
0
{
11746
0
    Py_BEGIN_ALLOW_THREADS
11747
0
    _Py_closerange(fd_low, fd_high - 1);
11748
0
    Py_END_ALLOW_THREADS
11749
0
    Py_RETURN_NONE;
11750
0
}
11751
11752
11753
/*[clinic input]
11754
os.dup -> int
11755
11756
    fd: int
11757
    /
11758
11759
Return a duplicate of a file descriptor.
11760
[clinic start generated code]*/
11761
11762
static int
11763
os_dup_impl(PyObject *module, int fd)
11764
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11765
0
{
11766
0
    return _Py_dup(fd);
11767
0
}
11768
11769
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11770
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11771
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11772
/*[clinic input]
11773
os.dup2 -> int
11774
    fd: int
11775
    fd2: int
11776
    inheritable: bool=True
11777
11778
Duplicate file descriptor.
11779
[clinic start generated code]*/
11780
11781
static int
11782
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11783
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11784
0
{
11785
0
    int res = 0;
11786
0
#if defined(HAVE_DUP3) && \
11787
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11788
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11789
0
    static int dup3_works = -1;
11790
0
#endif
11791
11792
    /* dup2() can fail with EINTR if the target FD is already open, because it
11793
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11794
     * upon close(), and therefore below.
11795
     */
11796
#ifdef MS_WINDOWS
11797
    Py_BEGIN_ALLOW_THREADS
11798
    _Py_BEGIN_SUPPRESS_IPH
11799
    res = dup2(fd, fd2);
11800
    _Py_END_SUPPRESS_IPH
11801
    Py_END_ALLOW_THREADS
11802
    if (res < 0) {
11803
        posix_error();
11804
        return -1;
11805
    }
11806
    res = fd2; // msvcrt dup2 returns 0 on success.
11807
11808
    /* Character files like console cannot be make non-inheritable */
11809
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11810
        close(fd2);
11811
        return -1;
11812
    }
11813
11814
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11815
    Py_BEGIN_ALLOW_THREADS
11816
    if (!inheritable)
11817
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11818
    else
11819
        res = dup2(fd, fd2);
11820
    Py_END_ALLOW_THREADS
11821
    if (res < 0) {
11822
        posix_error();
11823
        return -1;
11824
    }
11825
11826
#else
11827
11828
0
#ifdef HAVE_DUP3
11829
0
    if (!inheritable && dup3_works != 0) {
11830
0
        Py_BEGIN_ALLOW_THREADS
11831
0
        res = dup3(fd, fd2, O_CLOEXEC);
11832
0
        Py_END_ALLOW_THREADS
11833
0
        if (res < 0) {
11834
0
            if (dup3_works == -1)
11835
0
                dup3_works = (errno != ENOSYS);
11836
0
            if (dup3_works) {
11837
0
                posix_error();
11838
0
                return -1;
11839
0
            }
11840
0
        }
11841
0
    }
11842
11843
0
    if (inheritable || dup3_works == 0)
11844
0
    {
11845
0
#endif
11846
0
        Py_BEGIN_ALLOW_THREADS
11847
0
        res = dup2(fd, fd2);
11848
0
        Py_END_ALLOW_THREADS
11849
0
        if (res < 0) {
11850
0
            posix_error();
11851
0
            return -1;
11852
0
        }
11853
11854
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11855
0
            close(fd2);
11856
0
            return -1;
11857
0
        }
11858
0
#ifdef HAVE_DUP3
11859
0
    }
11860
0
#endif
11861
11862
0
#endif
11863
11864
0
    return res;
11865
0
}
11866
#endif
11867
11868
11869
#ifdef HAVE_LOCKF
11870
/*[clinic input]
11871
os.lockf
11872
11873
    fd: int
11874
        An open file descriptor.
11875
    command: int
11876
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11877
    length: Py_off_t
11878
        The number of bytes to lock, starting at the current position.
11879
    /
11880
11881
Apply, test or remove a POSIX lock on an open file descriptor.
11882
11883
[clinic start generated code]*/
11884
11885
static PyObject *
11886
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11887
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11888
0
{
11889
0
    int res;
11890
11891
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11892
0
        return NULL;
11893
0
    }
11894
11895
0
    Py_BEGIN_ALLOW_THREADS
11896
0
    res = lockf(fd, command, length);
11897
0
    Py_END_ALLOW_THREADS
11898
11899
0
    if (res < 0)
11900
0
        return posix_error();
11901
11902
0
    Py_RETURN_NONE;
11903
0
}
11904
#endif /* HAVE_LOCKF */
11905
11906
11907
/*[clinic input]
11908
@permit_long_docstring_body
11909
os.lseek -> Py_off_t
11910
11911
    fd: int
11912
        An open file descriptor, as returned by os.open().
11913
    position: Py_off_t
11914
        Position, interpreted relative to 'whence'.
11915
    whence as how: int
11916
        The relative position to seek from. Valid values are:
11917
        - SEEK_SET: seek from the start of the file.
11918
        - SEEK_CUR: seek from the current file position.
11919
        - SEEK_END: seek from the end of the file.
11920
    /
11921
11922
Set the position of a file descriptor.  Return the new position.
11923
11924
The return value is the number of bytes relative to the beginning of the file.
11925
[clinic start generated code]*/
11926
11927
static Py_off_t
11928
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11929
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11930
0
{
11931
0
    Py_off_t result;
11932
11933
0
#ifdef SEEK_SET
11934
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11935
0
    switch (how) {
11936
0
        case 0: how = SEEK_SET; break;
11937
0
        case 1: how = SEEK_CUR; break;
11938
0
        case 2: how = SEEK_END; break;
11939
0
    }
11940
0
#endif /* SEEK_END */
11941
11942
0
    Py_BEGIN_ALLOW_THREADS
11943
0
    _Py_BEGIN_SUPPRESS_IPH
11944
#ifdef MS_WINDOWS
11945
    result = _lseeki64(fd, position, how);
11946
#else
11947
0
    result = lseek(fd, position, how);
11948
0
#endif
11949
0
    _Py_END_SUPPRESS_IPH
11950
0
    Py_END_ALLOW_THREADS
11951
0
    if (result < 0)
11952
0
        posix_error();
11953
11954
0
    return result;
11955
0
}
11956
11957
11958
/*[clinic input]
11959
os.read
11960
    fd: int
11961
    length: Py_ssize_t
11962
    /
11963
11964
Read from a file descriptor.  Returns a bytes object.
11965
[clinic start generated code]*/
11966
11967
static PyObject *
11968
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11969
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11970
0
{
11971
0
    if (length < 0) {
11972
0
        errno = EINVAL;
11973
0
        return posix_error();
11974
0
    }
11975
11976
0
    length = Py_MIN(length, _PY_READ_MAX);
11977
11978
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11979
0
    if (writer == NULL) {
11980
0
        return NULL;
11981
0
    }
11982
11983
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11984
0
    if (n == -1) {
11985
0
        PyBytesWriter_Discard(writer);
11986
0
        return NULL;
11987
0
    }
11988
11989
0
    return PyBytesWriter_FinishWithSize(writer, n);
11990
0
}
11991
11992
/*[clinic input]
11993
@permit_long_docstring_body
11994
os.readinto -> Py_ssize_t
11995
    fd: int
11996
    buffer: Py_buffer(accept={rwbuffer})
11997
    /
11998
11999
Read into a buffer object from a file descriptor.
12000
12001
The buffer should be mutable and bytes-like. On success, returns the number of
12002
bytes read. Less bytes may be read than the size of the buffer. The underlying
12003
system call will be retried when interrupted by a signal, unless the signal
12004
handler raises an exception. Other errors will not be retried and an error will
12005
be raised.
12006
12007
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
12008
(which can be used to check for errors without reading data). Never returns
12009
negative.
12010
[clinic start generated code]*/
12011
12012
static Py_ssize_t
12013
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12014
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
12015
0
{
12016
0
    assert(buffer->len >= 0);
12017
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12018
    /* Ensure negative is never returned without an error. Simplifies calling
12019
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12020
        error. */
12021
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12022
0
    return result;
12023
0
}
12024
12025
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12026
                                || defined(__APPLE__))) \
12027
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12028
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12029
static int
12030
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12031
0
{
12032
0
    Py_ssize_t i, j;
12033
12034
0
    *iov = PyMem_New(struct iovec, cnt);
12035
0
    if (*iov == NULL) {
12036
0
        PyErr_NoMemory();
12037
0
        return -1;
12038
0
    }
12039
12040
0
    *buf = PyMem_New(Py_buffer, cnt);
12041
0
    if (*buf == NULL) {
12042
0
        PyMem_Free(*iov);
12043
0
        PyErr_NoMemory();
12044
0
        return -1;
12045
0
    }
12046
12047
0
    for (i = 0; i < cnt; i++) {
12048
0
        PyObject *item = PySequence_GetItem(seq, i);
12049
0
        if (item == NULL)
12050
0
            goto fail;
12051
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12052
0
            Py_DECREF(item);
12053
0
            goto fail;
12054
0
        }
12055
0
        Py_DECREF(item);
12056
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12057
0
        (*iov)[i].iov_len = (*buf)[i].len;
12058
0
    }
12059
0
    return 0;
12060
12061
0
fail:
12062
0
    PyMem_Free(*iov);
12063
0
    for (j = 0; j < i; j++) {
12064
0
        PyBuffer_Release(&(*buf)[j]);
12065
0
    }
12066
0
    PyMem_Free(*buf);
12067
0
    return -1;
12068
0
}
12069
12070
static void
12071
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12072
0
{
12073
0
    int i;
12074
0
    PyMem_Free(iov);
12075
0
    for (i = 0; i < cnt; i++) {
12076
0
        PyBuffer_Release(&buf[i]);
12077
0
    }
12078
0
    PyMem_Free(buf);
12079
0
}
12080
#endif
12081
12082
12083
#ifdef HAVE_READV
12084
/*[clinic input]
12085
os.readv -> Py_ssize_t
12086
12087
    fd: int
12088
    buffers: object
12089
    /
12090
12091
Read from a file descriptor fd into an iterable of buffers.
12092
12093
The buffers should be mutable buffers accepting bytes.
12094
readv will transfer data into each buffer until it is full
12095
and then move on to the next buffer in the sequence to hold
12096
the rest of the data.
12097
12098
readv returns the total number of bytes read,
12099
which may be less than the total capacity of all the buffers.
12100
[clinic start generated code]*/
12101
12102
static Py_ssize_t
12103
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12104
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12105
0
{
12106
0
    Py_ssize_t cnt, n;
12107
0
    int async_err = 0;
12108
0
    struct iovec *iov;
12109
0
    Py_buffer *buf;
12110
12111
0
    if (!PySequence_Check(buffers)) {
12112
0
        PyErr_SetString(PyExc_TypeError,
12113
0
            "readv() arg 2 must be a sequence");
12114
0
        return -1;
12115
0
    }
12116
12117
0
    cnt = PySequence_Size(buffers);
12118
0
    if (cnt < 0)
12119
0
        return -1;
12120
12121
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12122
0
        return -1;
12123
12124
0
    do {
12125
0
        Py_BEGIN_ALLOW_THREADS
12126
0
        n = readv(fd, iov, cnt);
12127
0
        Py_END_ALLOW_THREADS
12128
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12129
12130
0
    int saved_errno = errno;
12131
0
    iov_cleanup(iov, buf, cnt);
12132
0
    if (n < 0) {
12133
0
        if (!async_err) {
12134
0
            errno = saved_errno;
12135
0
            posix_error();
12136
0
        }
12137
0
        return -1;
12138
0
    }
12139
12140
0
    return n;
12141
0
}
12142
#endif /* HAVE_READV */
12143
12144
12145
#ifdef HAVE_PREAD
12146
/*[clinic input]
12147
@permit_long_summary
12148
os.pread
12149
12150
    fd: int
12151
    length: Py_ssize_t
12152
    offset: Py_off_t
12153
    /
12154
12155
Read a number of bytes from a file descriptor starting at a particular offset.
12156
12157
Read length bytes from file descriptor fd, starting at offset bytes from
12158
the beginning of the file.  The file offset remains unchanged.
12159
[clinic start generated code]*/
12160
12161
static PyObject *
12162
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12163
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12164
0
{
12165
0
    Py_ssize_t n;
12166
0
    int async_err = 0;
12167
12168
0
    if (length < 0) {
12169
0
        errno = EINVAL;
12170
0
        return posix_error();
12171
0
    }
12172
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12173
0
    if (writer == NULL) {
12174
0
        return NULL;
12175
0
    }
12176
12177
0
    do {
12178
0
        Py_BEGIN_ALLOW_THREADS
12179
0
        _Py_BEGIN_SUPPRESS_IPH
12180
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12181
0
        _Py_END_SUPPRESS_IPH
12182
0
        Py_END_ALLOW_THREADS
12183
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12184
12185
0
    if (n < 0) {
12186
0
        if (!async_err) {
12187
0
            posix_error();
12188
0
        }
12189
0
        PyBytesWriter_Discard(writer);
12190
0
        return NULL;
12191
0
    }
12192
0
    return PyBytesWriter_FinishWithSize(writer, n);
12193
0
}
12194
#endif /* HAVE_PREAD */
12195
12196
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12197
/*[clinic input]
12198
@permit_long_docstring_body
12199
os.preadv -> Py_ssize_t
12200
12201
    fd: int
12202
    buffers: object
12203
    offset: Py_off_t
12204
    flags: int = 0
12205
    /
12206
12207
Reads from a file descriptor into a number of mutable bytes-like objects.
12208
12209
Combines the functionality of readv() and pread(). As readv(), it will
12210
transfer data into each buffer until it is full and then move on to the next
12211
buffer in the sequence to hold the rest of the data. Its fourth argument,
12212
specifies the file offset at which the input operation is to be performed. It
12213
will return the total number of bytes read (which can be less than the total
12214
capacity of all the objects).
12215
12216
The flags argument contains a bitwise OR of zero or more of the following flags:
12217
12218
- RWF_HIPRI
12219
- RWF_NOWAIT
12220
- RWF_DONTCACHE
12221
12222
Using non-zero flags requires Linux 4.6 or newer.
12223
[clinic start generated code]*/
12224
12225
static Py_ssize_t
12226
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12227
               int flags)
12228
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
12229
0
{
12230
0
    Py_ssize_t cnt, n;
12231
0
    int async_err = 0;
12232
0
    struct iovec *iov;
12233
0
    Py_buffer *buf;
12234
12235
0
    if (!PySequence_Check(buffers)) {
12236
0
        PyErr_SetString(PyExc_TypeError,
12237
0
            "preadv2() arg 2 must be a sequence");
12238
0
        return -1;
12239
0
    }
12240
12241
0
    cnt = PySequence_Size(buffers);
12242
0
    if (cnt < 0) {
12243
0
        return -1;
12244
0
    }
12245
12246
#ifndef HAVE_PREADV2
12247
    if(flags != 0) {
12248
        argument_unavailable_error("preadv2", "flags");
12249
        return -1;
12250
    }
12251
#endif
12252
12253
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12254
0
        return -1;
12255
0
    }
12256
0
#ifdef HAVE_PREADV2
12257
0
    do {
12258
0
        Py_BEGIN_ALLOW_THREADS
12259
0
        _Py_BEGIN_SUPPRESS_IPH
12260
0
        n = preadv2(fd, iov, cnt, offset, flags);
12261
0
        _Py_END_SUPPRESS_IPH
12262
0
        Py_END_ALLOW_THREADS
12263
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12264
#else
12265
    do {
12266
#if defined(__APPLE__) && defined(__clang__)
12267
/* This entire function will be removed from the module dict when the API
12268
 * is not available.
12269
 */
12270
#pragma clang diagnostic push
12271
#pragma clang diagnostic ignored "-Wunguarded-availability"
12272
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12273
#endif
12274
        Py_BEGIN_ALLOW_THREADS
12275
        _Py_BEGIN_SUPPRESS_IPH
12276
        n = preadv(fd, iov, cnt, offset);
12277
        _Py_END_SUPPRESS_IPH
12278
        Py_END_ALLOW_THREADS
12279
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12280
12281
#if defined(__APPLE__) && defined(__clang__)
12282
#pragma clang diagnostic pop
12283
#endif
12284
12285
#endif
12286
12287
0
    int saved_errno = errno;
12288
0
    iov_cleanup(iov, buf, cnt);
12289
0
    if (n < 0) {
12290
0
        if (!async_err) {
12291
0
            errno = saved_errno;
12292
0
            posix_error();
12293
0
        }
12294
0
        return -1;
12295
0
    }
12296
12297
0
    return n;
12298
0
}
12299
#endif /* HAVE_PREADV */
12300
12301
12302
/*[clinic input]
12303
os.write -> Py_ssize_t
12304
12305
    fd: int
12306
    data: Py_buffer
12307
    /
12308
12309
Write a bytes object to a file descriptor.
12310
[clinic start generated code]*/
12311
12312
static Py_ssize_t
12313
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12314
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12315
2
{
12316
2
    return _Py_write(fd, data->buf, data->len);
12317
2
}
12318
12319
#ifdef HAVE_SENDFILE
12320
#ifdef __APPLE__
12321
/*[clinic input]
12322
os.sendfile
12323
12324
    out_fd: int
12325
    in_fd: int
12326
    offset: Py_off_t
12327
    count as sbytes: Py_off_t
12328
    headers: object(c_default="NULL") = ()
12329
    trailers: object(c_default="NULL") = ()
12330
    flags: int = 0
12331
12332
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12333
[clinic start generated code]*/
12334
12335
static PyObject *
12336
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12337
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12338
                 int flags)
12339
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12340
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12341
/*[clinic input]
12342
os.sendfile
12343
12344
    out_fd: int
12345
    in_fd: int
12346
    offset: Py_off_t
12347
    count: Py_ssize_t(allow_negative=False)
12348
    headers: object(c_default="NULL") = ()
12349
    trailers: object(c_default="NULL") = ()
12350
    flags: int = 0
12351
12352
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12353
[clinic start generated code]*/
12354
12355
static PyObject *
12356
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12357
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12358
                 int flags)
12359
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12360
#else
12361
/*[clinic input]
12362
os.sendfile
12363
12364
    out_fd: int
12365
    in_fd: int
12366
    offset as offobj: object
12367
    count: Py_ssize_t(allow_negative=False)
12368
12369
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12370
[clinic start generated code]*/
12371
12372
static PyObject *
12373
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12374
                 Py_ssize_t count)
12375
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12376
#endif
12377
0
{
12378
0
    Py_ssize_t ret;
12379
0
    int async_err = 0;
12380
12381
#ifdef __APPLE__
12382
    if(sbytes < 0) {
12383
        PyErr_SetString(PyExc_ValueError,
12384
                        "count cannot be negative");
12385
        return NULL;
12386
    }
12387
#else
12388
0
    assert(count >= 0);
12389
0
#endif
12390
12391
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12392
#ifndef __APPLE__
12393
    off_t sbytes;
12394
#endif
12395
    Py_buffer *hbuf, *tbuf;
12396
    struct sf_hdtr sf;
12397
12398
    sf.headers = NULL;
12399
    sf.trailers = NULL;
12400
12401
    if (headers != NULL) {
12402
        if (!PySequence_Check(headers)) {
12403
            PyErr_SetString(PyExc_TypeError,
12404
                "sendfile() headers must be a sequence");
12405
            return NULL;
12406
        } else {
12407
            Py_ssize_t i = PySequence_Size(headers);
12408
            if (i < 0)
12409
                return NULL;
12410
            if (i > INT_MAX) {
12411
                PyErr_SetString(PyExc_OverflowError,
12412
                    "sendfile() header is too large");
12413
                return NULL;
12414
            }
12415
            if (i > 0) {
12416
                sf.hdr_cnt = (int)i;
12417
                if (iov_setup(&(sf.headers), &hbuf,
12418
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12419
                    return NULL;
12420
#ifdef __APPLE__
12421
                for (i = 0; i < sf.hdr_cnt; i++) {
12422
                    Py_ssize_t blen = sf.headers[i].iov_len;
12423
# define OFF_T_MAX 0x7fffffffffffffff
12424
                    if (sbytes >= OFF_T_MAX - blen) {
12425
                        PyErr_SetString(PyExc_OverflowError,
12426
                            "sendfile() header is too large");
12427
                        return NULL;
12428
                    }
12429
                    sbytes += blen;
12430
                }
12431
#endif
12432
            }
12433
        }
12434
    }
12435
    if (trailers != NULL) {
12436
        if (!PySequence_Check(trailers)) {
12437
            PyErr_SetString(PyExc_TypeError,
12438
                "sendfile() trailers must be a sequence");
12439
            return NULL;
12440
        } else {
12441
            Py_ssize_t i = PySequence_Size(trailers);
12442
            if (i < 0)
12443
                return NULL;
12444
            if (i > INT_MAX) {
12445
                PyErr_SetString(PyExc_OverflowError,
12446
                    "sendfile() trailer is too large");
12447
                return NULL;
12448
            }
12449
            if (i > 0) {
12450
                sf.trl_cnt = (int)i;
12451
                if (iov_setup(&(sf.trailers), &tbuf,
12452
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12453
                    return NULL;
12454
            }
12455
        }
12456
    }
12457
12458
    _Py_BEGIN_SUPPRESS_IPH
12459
    do {
12460
        Py_BEGIN_ALLOW_THREADS
12461
#ifdef __APPLE__
12462
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12463
#else
12464
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12465
#endif
12466
        Py_END_ALLOW_THREADS
12467
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12468
    _Py_END_SUPPRESS_IPH
12469
12470
    int saved_errno = errno;
12471
    if (sf.headers != NULL)
12472
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12473
    if (sf.trailers != NULL)
12474
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12475
12476
    if (ret < 0) {
12477
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12478
            if (sbytes != 0) {
12479
                // some data has been sent
12480
                goto done;
12481
            }
12482
            // no data has been sent; upper application is supposed
12483
            // to retry on EAGAIN or EBUSY
12484
        }
12485
        if (!async_err) {
12486
            errno = saved_errno;
12487
            posix_error();
12488
        }
12489
        return NULL;
12490
    }
12491
    goto done;
12492
12493
done:
12494
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12495
        return PyLong_FromLong(sbytes);
12496
    #else
12497
        return PyLong_FromLongLong(sbytes);
12498
    #endif
12499
12500
#else
12501
0
#ifdef __linux__
12502
0
    if (offobj == Py_None) {
12503
0
        do {
12504
0
            Py_BEGIN_ALLOW_THREADS
12505
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12506
0
            Py_END_ALLOW_THREADS
12507
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12508
0
        if (ret < 0)
12509
0
            return (!async_err) ? posix_error() : NULL;
12510
0
        return PyLong_FromSsize_t(ret);
12511
0
    }
12512
0
#endif
12513
0
    off_t offset;
12514
0
    if (!Py_off_t_converter(offobj, &offset))
12515
0
        return NULL;
12516
12517
#if defined(__sun) && defined(__SVR4)
12518
    // On Solaris, sendfile raises EINVAL rather than returning 0
12519
    // when the offset is equal or bigger than the in_fd size.
12520
    struct stat st;
12521
12522
    do {
12523
        Py_BEGIN_ALLOW_THREADS
12524
        ret = fstat(in_fd, &st);
12525
        Py_END_ALLOW_THREADS
12526
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12527
    if (ret < 0)
12528
        return (!async_err) ? posix_error() : NULL;
12529
12530
    if (offset >= st.st_size) {
12531
        return PyLong_FromLong(0);
12532
    }
12533
12534
    // On illumos specifically sendfile() may perform a partial write but
12535
    // return -1/an error (in one confirmed case the destination socket
12536
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12537
    // code to check if the offset parameter was modified by sendfile().
12538
    //
12539
    // We need this variable to track said change.
12540
    off_t original_offset = offset;
12541
#endif
12542
12543
0
    do {
12544
0
        Py_BEGIN_ALLOW_THREADS
12545
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12546
#if defined(__sun) && defined(__SVR4)
12547
        // This handles illumos-specific sendfile() partial write behavior,
12548
        // see a comment above for more details.
12549
        if (ret < 0 && offset != original_offset) {
12550
            ret = offset - original_offset;
12551
        }
12552
#endif
12553
0
        Py_END_ALLOW_THREADS
12554
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12555
0
    if (ret < 0)
12556
0
        return (!async_err) ? posix_error() : NULL;
12557
0
    return PyLong_FromSsize_t(ret);
12558
0
#endif
12559
0
}
12560
#endif /* HAVE_SENDFILE */
12561
12562
12563
#if defined(__APPLE__)
12564
/*[clinic input]
12565
os._fcopyfile
12566
12567
    in_fd: int
12568
    out_fd: int
12569
    flags: int
12570
    /
12571
12572
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12573
[clinic start generated code]*/
12574
12575
static PyObject *
12576
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12577
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12578
{
12579
    int ret;
12580
12581
    Py_BEGIN_ALLOW_THREADS
12582
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12583
    Py_END_ALLOW_THREADS
12584
    if (ret < 0)
12585
        return posix_error();
12586
    Py_RETURN_NONE;
12587
}
12588
#endif
12589
12590
12591
/*[clinic input]
12592
os.fstat
12593
12594
    fd : int
12595
12596
Perform a stat system call on the given file descriptor.
12597
12598
Like stat(), but for an open file descriptor.
12599
Equivalent to os.stat(fd).
12600
[clinic start generated code]*/
12601
12602
static PyObject *
12603
os_fstat_impl(PyObject *module, int fd)
12604
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12605
213k
{
12606
213k
    STRUCT_STAT st;
12607
213k
    int res;
12608
213k
    int async_err = 0;
12609
12610
213k
    do {
12611
213k
        Py_BEGIN_ALLOW_THREADS
12612
213k
        res = FSTAT(fd, &st);
12613
213k
        Py_END_ALLOW_THREADS
12614
213k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12615
213k
    if (res != 0) {
12616
#ifdef MS_WINDOWS
12617
        return PyErr_SetFromWindowsErr(0);
12618
#else
12619
0
        return (!async_err) ? posix_error() : NULL;
12620
0
#endif
12621
0
    }
12622
12623
213k
    return _pystat_fromstructstat(module, &st);
12624
213k
}
12625
12626
12627
/*[clinic input]
12628
os.isatty -> bool
12629
    fd: int
12630
    /
12631
12632
Return True if the fd is connected to a terminal.
12633
12634
Return True if the file descriptor is an open file descriptor
12635
connected to the slave end of a terminal.
12636
[clinic start generated code]*/
12637
12638
static int
12639
os_isatty_impl(PyObject *module, int fd)
12640
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12641
0
{
12642
0
    int return_value;
12643
0
    Py_BEGIN_ALLOW_THREADS
12644
0
    _Py_BEGIN_SUPPRESS_IPH
12645
0
    return_value = isatty(fd);
12646
0
    _Py_END_SUPPRESS_IPH
12647
0
    Py_END_ALLOW_THREADS
12648
0
    return return_value;
12649
0
}
12650
12651
12652
#ifdef HAVE_PIPE
12653
/*[clinic input]
12654
os.pipe
12655
12656
Create a pipe.
12657
12658
Returns a tuple of two file descriptors:
12659
  (read_fd, write_fd)
12660
[clinic start generated code]*/
12661
12662
static PyObject *
12663
os_pipe_impl(PyObject *module)
12664
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12665
0
{
12666
0
    int fds[2];
12667
#ifdef MS_WINDOWS
12668
    HANDLE read, write;
12669
    SECURITY_ATTRIBUTES attr;
12670
    BOOL ok;
12671
#else
12672
0
    int res;
12673
0
#endif
12674
12675
#ifdef MS_WINDOWS
12676
    attr.nLength = sizeof(attr);
12677
    attr.lpSecurityDescriptor = NULL;
12678
    attr.bInheritHandle = FALSE;
12679
12680
    Py_BEGIN_ALLOW_THREADS
12681
    ok = CreatePipe(&read, &write, &attr, 0);
12682
    if (ok) {
12683
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12684
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12685
        if (fds[0] == -1 || fds[1] == -1) {
12686
            CloseHandle(read);
12687
            CloseHandle(write);
12688
            ok = 0;
12689
        }
12690
    }
12691
    Py_END_ALLOW_THREADS
12692
12693
    if (!ok)
12694
        return PyErr_SetFromWindowsErr(0);
12695
#else
12696
12697
0
#ifdef HAVE_PIPE2
12698
0
    Py_BEGIN_ALLOW_THREADS
12699
0
    res = pipe2(fds, O_CLOEXEC);
12700
0
    Py_END_ALLOW_THREADS
12701
12702
0
    if (res != 0 && errno == ENOSYS)
12703
0
    {
12704
0
#endif
12705
0
        Py_BEGIN_ALLOW_THREADS
12706
0
        res = pipe(fds);
12707
0
        Py_END_ALLOW_THREADS
12708
12709
0
        if (res == 0) {
12710
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12711
0
                close(fds[0]);
12712
0
                close(fds[1]);
12713
0
                return NULL;
12714
0
            }
12715
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12716
0
                close(fds[0]);
12717
0
                close(fds[1]);
12718
0
                return NULL;
12719
0
            }
12720
0
        }
12721
0
#ifdef HAVE_PIPE2
12722
0
    }
12723
0
#endif
12724
12725
0
    if (res != 0)
12726
0
        return PyErr_SetFromErrno(PyExc_OSError);
12727
0
#endif /* !MS_WINDOWS */
12728
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12729
0
}
12730
#endif  /* HAVE_PIPE */
12731
12732
12733
#ifdef HAVE_PIPE2
12734
/*[clinic input]
12735
os.pipe2
12736
12737
    flags: int
12738
    /
12739
12740
Create a pipe with flags set atomically.
12741
12742
Returns a tuple of two file descriptors:
12743
  (read_fd, write_fd)
12744
12745
flags can be constructed by ORing together one or more of these values:
12746
O_NONBLOCK, O_CLOEXEC.
12747
[clinic start generated code]*/
12748
12749
static PyObject *
12750
os_pipe2_impl(PyObject *module, int flags)
12751
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12752
0
{
12753
0
    int fds[2];
12754
0
    int res;
12755
12756
0
    res = pipe2(fds, flags);
12757
0
    if (res != 0)
12758
0
        return posix_error();
12759
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12760
0
}
12761
#endif /* HAVE_PIPE2 */
12762
12763
12764
#ifdef HAVE_WRITEV
12765
/*[clinic input]
12766
os.writev -> Py_ssize_t
12767
    fd: int
12768
    buffers: object
12769
    /
12770
12771
Iterate over buffers, and write the contents of each to a file descriptor.
12772
12773
Returns the total number of bytes written.
12774
buffers must be a sequence of bytes-like objects.
12775
[clinic start generated code]*/
12776
12777
static Py_ssize_t
12778
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12779
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12780
0
{
12781
0
    Py_ssize_t cnt;
12782
0
    Py_ssize_t result;
12783
0
    int async_err = 0;
12784
0
    struct iovec *iov;
12785
0
    Py_buffer *buf;
12786
12787
0
    if (!PySequence_Check(buffers)) {
12788
0
        PyErr_SetString(PyExc_TypeError,
12789
0
            "writev() arg 2 must be a sequence");
12790
0
        return -1;
12791
0
    }
12792
0
    cnt = PySequence_Size(buffers);
12793
0
    if (cnt < 0)
12794
0
        return -1;
12795
12796
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12797
0
        return -1;
12798
0
    }
12799
12800
0
    do {
12801
0
        Py_BEGIN_ALLOW_THREADS
12802
0
        result = writev(fd, iov, cnt);
12803
0
        Py_END_ALLOW_THREADS
12804
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12805
12806
0
    if (result < 0 && !async_err)
12807
0
        posix_error();
12808
12809
0
    iov_cleanup(iov, buf, cnt);
12810
0
    return result;
12811
0
}
12812
#endif /* HAVE_WRITEV */
12813
12814
12815
#ifdef HAVE_PWRITE
12816
/*[clinic input]
12817
os.pwrite -> Py_ssize_t
12818
12819
    fd: int
12820
    buffer: Py_buffer
12821
    offset: Py_off_t
12822
    /
12823
12824
Write bytes to a file descriptor starting at a particular offset.
12825
12826
Write buffer to fd, starting at offset bytes from the beginning of
12827
the file.  Returns the number of bytes written.  Does not change the
12828
current file offset.
12829
[clinic start generated code]*/
12830
12831
static Py_ssize_t
12832
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12833
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12834
0
{
12835
0
    Py_ssize_t size;
12836
0
    int async_err = 0;
12837
12838
0
    do {
12839
0
        Py_BEGIN_ALLOW_THREADS
12840
0
        _Py_BEGIN_SUPPRESS_IPH
12841
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12842
0
        _Py_END_SUPPRESS_IPH
12843
0
        Py_END_ALLOW_THREADS
12844
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12845
12846
0
    if (size < 0 && !async_err)
12847
0
        posix_error();
12848
0
    return size;
12849
0
}
12850
#endif /* HAVE_PWRITE */
12851
12852
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12853
/*[clinic input]
12854
@permit_long_summary
12855
@permit_long_docstring_body
12856
os.pwritev -> Py_ssize_t
12857
12858
    fd: int
12859
    buffers: object
12860
    offset: Py_off_t
12861
    flags: int = 0
12862
    /
12863
12864
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12865
12866
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12867
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12868
buffer is written before proceeding to second, and so on. The operating system may
12869
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12870
This function writes the contents of each object to the file descriptor and returns
12871
the total number of bytes written.
12872
12873
The flags argument contains a bitwise OR of zero or more of the following flags:
12874
12875
- RWF_DSYNC
12876
- RWF_SYNC
12877
- RWF_APPEND
12878
- RWF_DONTCACHE
12879
- RWF_ATOMIC
12880
12881
Using non-zero flags requires Linux 4.7 or newer.
12882
[clinic start generated code]*/
12883
12884
static Py_ssize_t
12885
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12886
                int flags)
12887
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=7de72245873f56bf]*/
12888
0
{
12889
0
    Py_ssize_t cnt;
12890
0
    Py_ssize_t result;
12891
0
    int async_err = 0;
12892
0
    struct iovec *iov;
12893
0
    Py_buffer *buf;
12894
12895
0
    if (!PySequence_Check(buffers)) {
12896
0
        PyErr_SetString(PyExc_TypeError,
12897
0
            "pwritev() arg 2 must be a sequence");
12898
0
        return -1;
12899
0
    }
12900
12901
0
    cnt = PySequence_Size(buffers);
12902
0
    if (cnt < 0) {
12903
0
        return -1;
12904
0
    }
12905
12906
#ifndef HAVE_PWRITEV2
12907
    if(flags != 0) {
12908
        argument_unavailable_error("pwritev2", "flags");
12909
        return -1;
12910
    }
12911
#endif
12912
12913
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12914
0
        return -1;
12915
0
    }
12916
0
#ifdef HAVE_PWRITEV2
12917
0
    do {
12918
0
        Py_BEGIN_ALLOW_THREADS
12919
0
        _Py_BEGIN_SUPPRESS_IPH
12920
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12921
0
        _Py_END_SUPPRESS_IPH
12922
0
        Py_END_ALLOW_THREADS
12923
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12924
#else
12925
12926
#if defined(__APPLE__) && defined(__clang__)
12927
/* This entire function will be removed from the module dict when the API
12928
 * is not available.
12929
 */
12930
#pragma clang diagnostic push
12931
#pragma clang diagnostic ignored "-Wunguarded-availability"
12932
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12933
#endif
12934
    do {
12935
        Py_BEGIN_ALLOW_THREADS
12936
        _Py_BEGIN_SUPPRESS_IPH
12937
        result = pwritev(fd, iov, cnt, offset);
12938
        _Py_END_SUPPRESS_IPH
12939
        Py_END_ALLOW_THREADS
12940
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12941
12942
#if defined(__APPLE__) && defined(__clang__)
12943
#pragma clang diagnostic pop
12944
#endif
12945
12946
#endif
12947
12948
0
    if (result < 0) {
12949
0
        if (!async_err) {
12950
0
            posix_error();
12951
0
        }
12952
0
        result = -1;
12953
0
    }
12954
0
    iov_cleanup(iov, buf, cnt);
12955
12956
0
    return result;
12957
0
}
12958
#endif /* HAVE_PWRITEV */
12959
12960
#ifdef HAVE_COPY_FILE_RANGE
12961
/*[clinic input]
12962
12963
os.copy_file_range
12964
    src: int
12965
        Source file descriptor.
12966
    dst: int
12967
        Destination file descriptor.
12968
    count: Py_ssize_t(allow_negative=False)
12969
        Number of bytes to copy.
12970
    offset_src: object = None
12971
        Starting offset in src.
12972
    offset_dst: object = None
12973
        Starting offset in dst.
12974
12975
Copy count bytes from one file descriptor to another.
12976
12977
If offset_src is None, then src is read from the current position;
12978
respectively for offset_dst.
12979
[clinic start generated code]*/
12980
12981
static PyObject *
12982
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12983
                        PyObject *offset_src, PyObject *offset_dst)
12984
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12985
0
{
12986
0
    off_t offset_src_val, offset_dst_val;
12987
0
    off_t *p_offset_src = NULL;
12988
0
    off_t *p_offset_dst = NULL;
12989
0
    Py_ssize_t ret;
12990
0
    int async_err = 0;
12991
    /* The flags argument is provided to allow
12992
     * for future extensions and currently must be to 0. */
12993
0
    int flags = 0;
12994
12995
12996
0
    if (offset_src != Py_None) {
12997
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12998
0
            return NULL;
12999
0
        }
13000
0
        p_offset_src = &offset_src_val;
13001
0
    }
13002
13003
0
    if (offset_dst != Py_None) {
13004
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13005
0
            return NULL;
13006
0
        }
13007
0
        p_offset_dst = &offset_dst_val;
13008
0
    }
13009
13010
0
    do {
13011
0
        Py_BEGIN_ALLOW_THREADS
13012
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13013
0
        Py_END_ALLOW_THREADS
13014
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13015
13016
0
    if (ret < 0) {
13017
0
        return (!async_err) ? posix_error() : NULL;
13018
0
    }
13019
13020
0
    return PyLong_FromSsize_t(ret);
13021
0
}
13022
#endif /* HAVE_COPY_FILE_RANGE*/
13023
13024
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13025
/*[clinic input]
13026
13027
os.splice
13028
    src: int
13029
        Source file descriptor.
13030
    dst: int
13031
        Destination file descriptor.
13032
    count: Py_ssize_t(allow_negative=False)
13033
        Number of bytes to copy.
13034
    offset_src: object = None
13035
        Starting offset in src.
13036
    offset_dst: object = None
13037
        Starting offset in dst.
13038
    flags: unsigned_int = 0
13039
        Flags to modify the semantics of the call.
13040
13041
Transfer count bytes from one pipe to a descriptor or vice versa.
13042
13043
If offset_src is None, then src is read from the current position;
13044
respectively for offset_dst. The offset associated to the file
13045
descriptor that refers to a pipe must be None.
13046
[clinic start generated code]*/
13047
13048
static PyObject *
13049
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13050
               PyObject *offset_src, PyObject *offset_dst,
13051
               unsigned int flags)
13052
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13053
0
{
13054
0
    off_t offset_src_val, offset_dst_val;
13055
0
    off_t *p_offset_src = NULL;
13056
0
    off_t *p_offset_dst = NULL;
13057
0
    Py_ssize_t ret;
13058
0
    int async_err = 0;
13059
13060
13061
0
    if (offset_src != Py_None) {
13062
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13063
0
            return NULL;
13064
0
        }
13065
0
        p_offset_src = &offset_src_val;
13066
0
    }
13067
13068
0
    if (offset_dst != Py_None) {
13069
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13070
0
            return NULL;
13071
0
        }
13072
0
        p_offset_dst = &offset_dst_val;
13073
0
    }
13074
13075
0
    do {
13076
0
        Py_BEGIN_ALLOW_THREADS
13077
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13078
0
        Py_END_ALLOW_THREADS
13079
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13080
13081
0
    if (ret < 0) {
13082
0
        return (!async_err) ? posix_error() : NULL;
13083
0
    }
13084
13085
0
    return PyLong_FromSsize_t(ret);
13086
0
}
13087
#endif /* HAVE_SPLICE*/
13088
13089
#ifdef HAVE_MKFIFO
13090
/*[clinic input]
13091
os.mkfifo
13092
13093
    path: path_t
13094
    mode: int=0o666
13095
    *
13096
    dir_fd: dir_fd(requires='mkfifoat')=None
13097
13098
Create a "fifo" (a POSIX named pipe).
13099
13100
If dir_fd is not None, it should be a file descriptor open to a directory,
13101
  and path should be relative; path will then be relative to that directory.
13102
dir_fd may not be implemented on your platform.
13103
  If it is unavailable, using it will raise a NotImplementedError.
13104
[clinic start generated code]*/
13105
13106
static PyObject *
13107
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13108
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
13109
0
{
13110
0
    int result;
13111
0
    int async_err = 0;
13112
0
#ifdef HAVE_MKFIFOAT
13113
0
    int mkfifoat_unavailable = 0;
13114
0
#endif
13115
13116
0
    do {
13117
0
        Py_BEGIN_ALLOW_THREADS
13118
0
#ifdef HAVE_MKFIFOAT
13119
0
        if (dir_fd != DEFAULT_DIR_FD) {
13120
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13121
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13122
13123
0
            } else {
13124
0
                mkfifoat_unavailable = 1;
13125
0
                result = 0;
13126
0
            }
13127
0
        } else
13128
0
#endif
13129
0
            result = mkfifo(path->narrow, mode);
13130
0
        Py_END_ALLOW_THREADS
13131
0
    } while (result != 0 && errno == EINTR &&
13132
0
             !(async_err = PyErr_CheckSignals()));
13133
13134
0
#ifdef HAVE_MKFIFOAT
13135
0
    if (mkfifoat_unavailable) {
13136
0
        argument_unavailable_error(NULL, "dir_fd");
13137
0
        return NULL;
13138
0
    }
13139
0
#endif
13140
13141
0
    if (result != 0)
13142
0
        return (!async_err) ? posix_error() : NULL;
13143
13144
0
    Py_RETURN_NONE;
13145
0
}
13146
#endif /* HAVE_MKFIFO */
13147
13148
13149
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13150
/*[clinic input]
13151
@permit_long_docstring_body
13152
os.mknod
13153
13154
    path: path_t
13155
    mode: int=0o600
13156
    device: dev_t=0
13157
    *
13158
    dir_fd: dir_fd(requires='mknodat')=None
13159
13160
Create a node in the file system.
13161
13162
Create a node in the file system (file, device special file or named pipe)
13163
at path.  mode specifies both the permissions to use and the
13164
type of node to be created, being combined (bitwise OR) with one of
13165
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
13166
device defines the newly created device special file (probably using
13167
os.makedev()).  Otherwise device is ignored.
13168
13169
If dir_fd is not None, it should be a file descriptor open to a directory,
13170
  and path should be relative; path will then be relative to that directory.
13171
dir_fd may not be implemented on your platform.
13172
  If it is unavailable, using it will raise a NotImplementedError.
13173
[clinic start generated code]*/
13174
13175
static PyObject *
13176
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13177
              int dir_fd)
13178
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
13179
0
{
13180
0
    int result;
13181
0
    int async_err = 0;
13182
0
#ifdef HAVE_MKNODAT
13183
0
    int mknodat_unavailable = 0;
13184
0
#endif
13185
13186
0
    do {
13187
0
        Py_BEGIN_ALLOW_THREADS
13188
0
#ifdef HAVE_MKNODAT
13189
0
        if (dir_fd != DEFAULT_DIR_FD) {
13190
0
            if (HAVE_MKNODAT_RUNTIME) {
13191
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13192
13193
0
            } else {
13194
0
                mknodat_unavailable = 1;
13195
0
                result = 0;
13196
0
            }
13197
0
        } else
13198
0
#endif
13199
0
            result = mknod(path->narrow, mode, device);
13200
0
        Py_END_ALLOW_THREADS
13201
0
    } while (result != 0 && errno == EINTR &&
13202
0
             !(async_err = PyErr_CheckSignals()));
13203
0
#ifdef HAVE_MKNODAT
13204
0
    if (mknodat_unavailable) {
13205
0
        argument_unavailable_error(NULL, "dir_fd");
13206
0
        return NULL;
13207
0
    }
13208
0
#endif
13209
0
    if (result != 0)
13210
0
        return (!async_err) ? posix_error() : NULL;
13211
13212
0
    Py_RETURN_NONE;
13213
0
}
13214
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13215
13216
13217
#ifdef HAVE_DEVICE_MACROS
13218
static PyObject *
13219
major_minor_conv(unsigned int value)
13220
0
{
13221
0
#ifdef NODEV
13222
0
    if (value == (unsigned int)NODEV) {
13223
0
        return PyLong_FromLong((int)NODEV);
13224
0
    }
13225
0
#endif
13226
0
    return PyLong_FromUnsignedLong(value);
13227
0
}
13228
13229
static int
13230
major_minor_check(dev_t value)
13231
0
{
13232
0
#ifdef NODEV
13233
0
    if (value == NODEV) {
13234
0
        return 1;
13235
0
    }
13236
0
#endif
13237
0
    return (dev_t)(unsigned int)value == value;
13238
0
}
13239
13240
/*[clinic input]
13241
os.major
13242
13243
    device: dev_t
13244
    /
13245
13246
Extracts a device major number from a raw device number.
13247
[clinic start generated code]*/
13248
13249
static PyObject *
13250
os_major_impl(PyObject *module, dev_t device)
13251
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13252
0
{
13253
0
    return major_minor_conv(major(device));
13254
0
}
13255
13256
13257
/*[clinic input]
13258
os.minor
13259
13260
    device: dev_t
13261
    /
13262
13263
Extracts a device minor number from a raw device number.
13264
[clinic start generated code]*/
13265
13266
static PyObject *
13267
os_minor_impl(PyObject *module, dev_t device)
13268
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13269
0
{
13270
0
    return major_minor_conv(minor(device));
13271
0
}
13272
13273
13274
/*[clinic input]
13275
os.makedev -> dev_t
13276
13277
    major: dev_t
13278
    minor: dev_t
13279
    /
13280
13281
Composes a raw device number from the major and minor device numbers.
13282
[clinic start generated code]*/
13283
13284
static dev_t
13285
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13286
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13287
0
{
13288
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13289
0
        PyErr_SetString(PyExc_OverflowError,
13290
0
                        "Python int too large to convert to C unsigned int");
13291
0
        return (dev_t)-1;
13292
0
    }
13293
0
    return makedev(major, minor);
13294
0
}
13295
#endif /* HAVE_DEVICE_MACROS */
13296
13297
13298
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13299
/*[clinic input]
13300
os.ftruncate
13301
13302
    fd: int
13303
    length: Py_off_t
13304
    /
13305
13306
Truncate a file, specified by file descriptor, to a specific length.
13307
[clinic start generated code]*/
13308
13309
static PyObject *
13310
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13311
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13312
0
{
13313
0
    int result;
13314
0
    int async_err = 0;
13315
13316
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13317
0
        return NULL;
13318
0
    }
13319
13320
0
    do {
13321
0
        Py_BEGIN_ALLOW_THREADS
13322
0
        _Py_BEGIN_SUPPRESS_IPH
13323
#ifdef MS_WINDOWS
13324
        result = _chsize_s(fd, length);
13325
#else
13326
0
        result = ftruncate(fd, length);
13327
0
#endif
13328
0
        _Py_END_SUPPRESS_IPH
13329
0
        Py_END_ALLOW_THREADS
13330
0
    } while (result != 0 && errno == EINTR &&
13331
0
             !(async_err = PyErr_CheckSignals()));
13332
0
    if (result != 0)
13333
0
        return (!async_err) ? posix_error() : NULL;
13334
0
    Py_RETURN_NONE;
13335
0
}
13336
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13337
13338
13339
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13340
/*[clinic input]
13341
os.truncate
13342
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13343
    length: Py_off_t
13344
13345
Truncate a file, specified by path, to a specific length.
13346
13347
On some platforms, path may also be specified as an open file descriptor.
13348
  If this functionality is unavailable, using it raises an exception.
13349
[clinic start generated code]*/
13350
13351
static PyObject *
13352
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13353
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
13354
0
{
13355
0
    int result;
13356
#ifdef MS_WINDOWS
13357
    int fd;
13358
#endif
13359
13360
0
    if (path->is_fd)
13361
0
        return os_ftruncate_impl(module, path->fd, length);
13362
13363
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13364
0
        return NULL;
13365
0
    }
13366
13367
0
    Py_BEGIN_ALLOW_THREADS
13368
0
    _Py_BEGIN_SUPPRESS_IPH
13369
#ifdef MS_WINDOWS
13370
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13371
    if (fd < 0)
13372
        result = -1;
13373
    else {
13374
        result = _chsize_s(fd, length);
13375
        close(fd);
13376
        if (result < 0)
13377
            errno = result;
13378
    }
13379
#else
13380
0
    result = truncate(path->narrow, length);
13381
0
#endif
13382
0
    _Py_END_SUPPRESS_IPH
13383
0
    Py_END_ALLOW_THREADS
13384
0
    if (result < 0)
13385
0
        return posix_path_error(path);
13386
13387
0
    Py_RETURN_NONE;
13388
0
}
13389
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13390
13391
13392
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13393
   OSs, support was dropped in WASI preview2. */
13394
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13395
/*[clinic input]
13396
os.posix_fallocate
13397
13398
    fd: int
13399
    offset: Py_off_t
13400
    length: Py_off_t
13401
    /
13402
13403
Ensure a file has allocated at least a particular number of bytes on disk.
13404
13405
Ensure that the file specified by fd encompasses a range of bytes
13406
starting at offset bytes from the beginning and continuing for length bytes.
13407
[clinic start generated code]*/
13408
13409
static PyObject *
13410
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13411
                        Py_off_t length)
13412
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
13413
0
{
13414
0
    int result;
13415
0
    int async_err = 0;
13416
13417
0
    do {
13418
0
        Py_BEGIN_ALLOW_THREADS
13419
0
        result = posix_fallocate(fd, offset, length);
13420
0
        Py_END_ALLOW_THREADS
13421
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13422
13423
0
    if (result == 0)
13424
0
        Py_RETURN_NONE;
13425
13426
0
    if (async_err)
13427
0
        return NULL;
13428
13429
0
    errno = result;
13430
0
    return posix_error();
13431
0
}
13432
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13433
13434
13435
#if defined(HAVE_POSIX_FADVISE)
13436
/*[clinic input]
13437
os.posix_fadvise
13438
13439
    fd: int
13440
    offset: Py_off_t
13441
    length: Py_off_t
13442
    advice: int
13443
    /
13444
13445
Announce an intention to access data in a specific pattern.
13446
13447
Announce an intention to access data in a specific pattern, thus allowing
13448
the kernel to make optimizations.
13449
The advice applies to the region of the file specified by fd starting at
13450
offset and continuing for length bytes.
13451
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13452
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13453
POSIX_FADV_DONTNEED.
13454
[clinic start generated code]*/
13455
13456
static PyObject *
13457
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13458
                      Py_off_t length, int advice)
13459
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13460
0
{
13461
0
    int result;
13462
0
    int async_err = 0;
13463
13464
0
    do {
13465
0
        Py_BEGIN_ALLOW_THREADS
13466
0
        result = posix_fadvise(fd, offset, length, advice);
13467
0
        Py_END_ALLOW_THREADS
13468
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13469
13470
0
    if (result == 0)
13471
0
        Py_RETURN_NONE;
13472
13473
0
    if (async_err)
13474
0
        return NULL;
13475
13476
0
    errno = result;
13477
0
    return posix_error();
13478
0
}
13479
#endif /* HAVE_POSIX_FADVISE */
13480
13481
13482
#ifdef MS_WINDOWS
13483
static PyObject*
13484
win32_putenv(PyObject *name, PyObject *value)
13485
{
13486
    /* Search from index 1 because on Windows starting '=' is allowed for
13487
       defining hidden environment variables. */
13488
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13489
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13490
    {
13491
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13492
        return NULL;
13493
    }
13494
    PyObject *unicode;
13495
    if (value != NULL) {
13496
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13497
    }
13498
    else {
13499
        unicode = PyUnicode_FromFormat("%U=", name);
13500
    }
13501
    if (unicode == NULL) {
13502
        return NULL;
13503
    }
13504
13505
    Py_ssize_t size;
13506
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13507
    Py_DECREF(unicode);
13508
13509
    if (env == NULL) {
13510
        return NULL;
13511
    }
13512
    if (size > _MAX_ENV) {
13513
        PyErr_Format(PyExc_ValueError,
13514
                     "the environment variable is longer than %u characters",
13515
                     _MAX_ENV);
13516
        PyMem_Free(env);
13517
        return NULL;
13518
    }
13519
    if (wcslen(env) != (size_t)size) {
13520
        PyErr_SetString(PyExc_ValueError,
13521
                        "embedded null character");
13522
        PyMem_Free(env);
13523
        return NULL;
13524
    }
13525
13526
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13527
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13528
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13529
13530
       Prefer _wputenv() to be compatible with C libraries using CRT
13531
       variables and CRT functions using these variables (ex: getenv()). */
13532
    int err = _wputenv(env);
13533
13534
    if (err) {
13535
        posix_error();
13536
        PyMem_Free(env);
13537
        return NULL;
13538
    }
13539
    PyMem_Free(env);
13540
13541
    Py_RETURN_NONE;
13542
}
13543
#endif
13544
13545
13546
#ifdef MS_WINDOWS
13547
/*[clinic input]
13548
os.putenv
13549
13550
    name: unicode
13551
    value: unicode
13552
    /
13553
13554
Change or add an environment variable.
13555
[clinic start generated code]*/
13556
13557
static PyObject *
13558
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13559
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13560
{
13561
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13562
        return NULL;
13563
    }
13564
    return win32_putenv(name, value);
13565
}
13566
#else
13567
/*[clinic input]
13568
os.putenv
13569
13570
    name: unicode_fs_encoded
13571
    value: unicode_fs_encoded
13572
    /
13573
13574
Change or add an environment variable.
13575
[clinic start generated code]*/
13576
13577
static PyObject *
13578
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13579
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13580
0
{
13581
0
    const char *name_string = PyBytes_AS_STRING(name);
13582
0
    const char *value_string = PyBytes_AS_STRING(value);
13583
13584
0
    if (strchr(name_string, '=') != NULL) {
13585
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13586
0
        return NULL;
13587
0
    }
13588
13589
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13590
0
        return NULL;
13591
0
    }
13592
13593
0
    if (setenv(name_string, value_string, 1)) {
13594
0
        return posix_error();
13595
0
    }
13596
0
    Py_RETURN_NONE;
13597
0
}
13598
#endif  /* !defined(MS_WINDOWS) */
13599
13600
13601
#ifdef MS_WINDOWS
13602
/*[clinic input]
13603
os.unsetenv
13604
    name: unicode
13605
    /
13606
13607
Delete an environment variable.
13608
[clinic start generated code]*/
13609
13610
static PyObject *
13611
os_unsetenv_impl(PyObject *module, PyObject *name)
13612
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13613
{
13614
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13615
        return NULL;
13616
    }
13617
    return win32_putenv(name, NULL);
13618
}
13619
#else
13620
/*[clinic input]
13621
os.unsetenv
13622
    name: unicode_fs_encoded
13623
    /
13624
13625
Delete an environment variable.
13626
[clinic start generated code]*/
13627
13628
static PyObject *
13629
os_unsetenv_impl(PyObject *module, PyObject *name)
13630
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13631
0
{
13632
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13633
0
        return NULL;
13634
0
    }
13635
#ifdef HAVE_BROKEN_UNSETENV
13636
    unsetenv(PyBytes_AS_STRING(name));
13637
#else
13638
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13639
0
    if (err) {
13640
0
        return posix_error();
13641
0
    }
13642
0
#endif
13643
13644
0
    Py_RETURN_NONE;
13645
0
}
13646
#endif /* !MS_WINDOWS */
13647
13648
13649
#ifdef HAVE_CLEARENV
13650
/*[clinic input]
13651
os._clearenv
13652
[clinic start generated code]*/
13653
13654
static PyObject *
13655
os__clearenv_impl(PyObject *module)
13656
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13657
0
{
13658
0
    errno = 0;
13659
0
    int err = clearenv();
13660
0
    if (err) {
13661
0
        return posix_error();
13662
0
    }
13663
0
    Py_RETURN_NONE;
13664
0
}
13665
#endif
13666
13667
13668
/*[clinic input]
13669
os.strerror
13670
13671
    code: int
13672
    /
13673
13674
Translate an error code to a message string.
13675
[clinic start generated code]*/
13676
13677
static PyObject *
13678
os_strerror_impl(PyObject *module, int code)
13679
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13680
0
{
13681
0
    char *message = strerror(code);
13682
0
    if (message == NULL) {
13683
0
        PyErr_SetString(PyExc_ValueError,
13684
0
                        "strerror() argument out of range");
13685
0
        return NULL;
13686
0
    }
13687
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13688
0
}
13689
13690
13691
#ifdef HAVE_SYS_WAIT_H
13692
#ifdef WCOREDUMP
13693
/*[clinic input]
13694
os.WCOREDUMP -> bool
13695
13696
    status: int
13697
    /
13698
13699
Return True if the process returning status was dumped to a core file.
13700
[clinic start generated code]*/
13701
13702
static int
13703
os_WCOREDUMP_impl(PyObject *module, int status)
13704
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13705
0
{
13706
0
    WAIT_TYPE wait_status;
13707
0
    WAIT_STATUS_INT(wait_status) = status;
13708
0
    return WCOREDUMP(wait_status);
13709
0
}
13710
#endif /* WCOREDUMP */
13711
13712
13713
#ifdef WIFCONTINUED
13714
/*[clinic input]
13715
os.WIFCONTINUED -> bool
13716
13717
    status: int
13718
13719
Return True if a particular process was continued from a job control stop.
13720
13721
Return True if the process returning status was continued from a
13722
job control stop.
13723
[clinic start generated code]*/
13724
13725
static int
13726
os_WIFCONTINUED_impl(PyObject *module, int status)
13727
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13728
0
{
13729
0
    WAIT_TYPE wait_status;
13730
0
    WAIT_STATUS_INT(wait_status) = status;
13731
0
    return WIFCONTINUED(wait_status);
13732
0
}
13733
#endif /* WIFCONTINUED */
13734
13735
13736
#ifdef WIFSTOPPED
13737
/*[clinic input]
13738
os.WIFSTOPPED -> bool
13739
13740
    status: int
13741
13742
Return True if the process returning status was stopped.
13743
[clinic start generated code]*/
13744
13745
static int
13746
os_WIFSTOPPED_impl(PyObject *module, int status)
13747
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13748
0
{
13749
0
    WAIT_TYPE wait_status;
13750
0
    WAIT_STATUS_INT(wait_status) = status;
13751
0
    return WIFSTOPPED(wait_status);
13752
0
}
13753
#endif /* WIFSTOPPED */
13754
13755
13756
#ifdef WIFSIGNALED
13757
/*[clinic input]
13758
os.WIFSIGNALED -> bool
13759
13760
    status: int
13761
13762
Return True if the process returning status was terminated by a signal.
13763
[clinic start generated code]*/
13764
13765
static int
13766
os_WIFSIGNALED_impl(PyObject *module, int status)
13767
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13768
0
{
13769
0
    WAIT_TYPE wait_status;
13770
0
    WAIT_STATUS_INT(wait_status) = status;
13771
0
    return WIFSIGNALED(wait_status);
13772
0
}
13773
#endif /* WIFSIGNALED */
13774
13775
13776
#ifdef WIFEXITED
13777
/*[clinic input]
13778
@permit_long_summary
13779
os.WIFEXITED -> bool
13780
13781
    status: int
13782
13783
Return True if the process returning status exited via the exit() system call.
13784
[clinic start generated code]*/
13785
13786
static int
13787
os_WIFEXITED_impl(PyObject *module, int status)
13788
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13789
0
{
13790
0
    WAIT_TYPE wait_status;
13791
0
    WAIT_STATUS_INT(wait_status) = status;
13792
0
    return WIFEXITED(wait_status);
13793
0
}
13794
#endif /* WIFEXITED */
13795
13796
13797
#ifdef WEXITSTATUS
13798
/*[clinic input]
13799
os.WEXITSTATUS -> int
13800
13801
    status: int
13802
13803
Return the process return code from status.
13804
[clinic start generated code]*/
13805
13806
static int
13807
os_WEXITSTATUS_impl(PyObject *module, int status)
13808
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13809
0
{
13810
0
    WAIT_TYPE wait_status;
13811
0
    WAIT_STATUS_INT(wait_status) = status;
13812
0
    return WEXITSTATUS(wait_status);
13813
0
}
13814
#endif /* WEXITSTATUS */
13815
13816
13817
#ifdef WTERMSIG
13818
/*[clinic input]
13819
@permit_long_summary
13820
os.WTERMSIG -> int
13821
13822
    status: int
13823
13824
Return the signal that terminated the process that provided the status value.
13825
[clinic start generated code]*/
13826
13827
static int
13828
os_WTERMSIG_impl(PyObject *module, int status)
13829
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13830
0
{
13831
0
    WAIT_TYPE wait_status;
13832
0
    WAIT_STATUS_INT(wait_status) = status;
13833
0
    return WTERMSIG(wait_status);
13834
0
}
13835
#endif /* WTERMSIG */
13836
13837
13838
#ifdef WSTOPSIG
13839
/*[clinic input]
13840
os.WSTOPSIG -> int
13841
13842
    status: int
13843
13844
Return the signal that stopped the process that provided the status value.
13845
[clinic start generated code]*/
13846
13847
static int
13848
os_WSTOPSIG_impl(PyObject *module, int status)
13849
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13850
0
{
13851
0
    WAIT_TYPE wait_status;
13852
0
    WAIT_STATUS_INT(wait_status) = status;
13853
0
    return WSTOPSIG(wait_status);
13854
0
}
13855
#endif /* WSTOPSIG */
13856
#endif /* HAVE_SYS_WAIT_H */
13857
13858
13859
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13860
#ifdef _SCO_DS
13861
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13862
   needed definitions in sys/statvfs.h */
13863
#define _SVID3
13864
#endif
13865
#include <sys/statvfs.h>
13866
13867
#ifdef __APPLE__
13868
/* On macOS struct statvfs uses 32-bit integers for block counts,
13869
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13870
 * os.statvfs is implemented in terms of statfs(2).
13871
 */
13872
13873
static PyObject*
13874
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13875
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13876
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13877
    if (v == NULL) {
13878
        return NULL;
13879
    }
13880
13881
    long flags = 0;
13882
    if (st.f_flags & MNT_RDONLY) {
13883
        flags |= ST_RDONLY;
13884
    }
13885
    if (st.f_flags & MNT_NOSUID) {
13886
        flags |= ST_NOSUID;
13887
    }
13888
13889
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13890
13891
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13892
    do {                                                 \
13893
        PyObject *obj = (EXPR);                          \
13894
        if (obj == NULL) {                               \
13895
            Py_DECREF((SEQ));                            \
13896
            return NULL;                                 \
13897
        }                                                \
13898
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13899
    } while (0)
13900
13901
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13902
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13903
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13904
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13905
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13906
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13907
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13908
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13909
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13910
13911
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13912
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13913
13914
#undef SET_ITEM
13915
13916
    return v;
13917
}
13918
13919
#else
13920
13921
13922
13923
static PyObject*
13924
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13925
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13926
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13927
0
    if (v == NULL)
13928
0
        return NULL;
13929
13930
0
    int pos = 0;
13931
13932
0
#define SET_RESULT(CALL)                                     \
13933
0
    do {                                                     \
13934
0
        PyObject *item = (CALL);                             \
13935
0
        if (item == NULL) {                                  \
13936
0
            Py_DECREF(v);                                    \
13937
0
            return NULL;                                     \
13938
0
        }                                                    \
13939
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13940
0
    } while(0)
13941
13942
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13943
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13944
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13945
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13946
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13947
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13948
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13949
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13950
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13951
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13952
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13953
#else
13954
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13955
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13956
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13957
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13958
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13959
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13960
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13961
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13962
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13963
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13964
#endif
13965
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13966
 * (issue #32390). */
13967
#if defined(_AIX) && defined(_ALL_SOURCE)
13968
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13969
#else
13970
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13971
0
#endif
13972
13973
0
#undef SET_RESULT
13974
13975
0
    return v;
13976
0
}
13977
13978
#endif
13979
13980
13981
/*[clinic input]
13982
os.fstatvfs
13983
    fd: int
13984
    /
13985
13986
Perform an fstatvfs system call on the given fd.
13987
13988
Equivalent to statvfs(fd).
13989
[clinic start generated code]*/
13990
13991
static PyObject *
13992
os_fstatvfs_impl(PyObject *module, int fd)
13993
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13994
0
{
13995
0
    int result;
13996
0
    int async_err = 0;
13997
#ifdef __APPLE__
13998
    struct statfs st;
13999
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
14000
     * the former uses 32-bit values for block counts.
14001
     */
14002
    do {
14003
        Py_BEGIN_ALLOW_THREADS
14004
        result = fstatfs(fd, &st);
14005
        Py_END_ALLOW_THREADS
14006
    } while (result != 0 && errno == EINTR &&
14007
             !(async_err = PyErr_CheckSignals()));
14008
    if (result != 0)
14009
        return (!async_err) ? posix_error() : NULL;
14010
14011
    return _pystatvfs_fromstructstatfs(module, st);
14012
#else
14013
0
    struct statvfs st;
14014
14015
0
    do {
14016
0
        Py_BEGIN_ALLOW_THREADS
14017
0
        result = fstatvfs(fd, &st);
14018
0
        Py_END_ALLOW_THREADS
14019
0
    } while (result != 0 && errno == EINTR &&
14020
0
             !(async_err = PyErr_CheckSignals()));
14021
0
    if (result != 0)
14022
0
        return (!async_err) ? posix_error() : NULL;
14023
14024
0
    return _pystatvfs_fromstructstatvfs(module, st);
14025
0
#endif
14026
0
}
14027
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14028
14029
14030
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14031
#include <sys/statvfs.h>
14032
/*[clinic input]
14033
os.statvfs
14034
14035
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14036
14037
Perform a statvfs system call on the given path.
14038
14039
path may always be specified as a string.
14040
On some platforms, path may also be specified as an open file descriptor.
14041
  If this functionality is unavailable, using it raises an exception.
14042
[clinic start generated code]*/
14043
14044
static PyObject *
14045
os_statvfs_impl(PyObject *module, path_t *path)
14046
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
14047
0
{
14048
0
    int result;
14049
14050
#ifdef __APPLE__
14051
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14052
     * the former uses 32-bit values for block counts.
14053
     */
14054
    struct statfs st;
14055
14056
    Py_BEGIN_ALLOW_THREADS
14057
    if (path->is_fd) {
14058
        result = fstatfs(path->fd, &st);
14059
    }
14060
    else
14061
        result = statfs(path->narrow, &st);
14062
    Py_END_ALLOW_THREADS
14063
14064
    if (result) {
14065
        return path_error(path);
14066
    }
14067
14068
    return _pystatvfs_fromstructstatfs(module, st);
14069
14070
#else
14071
0
    struct statvfs st;
14072
14073
0
    Py_BEGIN_ALLOW_THREADS
14074
0
#ifdef HAVE_FSTATVFS
14075
0
    if (path->is_fd) {
14076
0
        result = fstatvfs(path->fd, &st);
14077
0
    }
14078
0
    else
14079
0
#endif
14080
0
        result = statvfs(path->narrow, &st);
14081
0
    Py_END_ALLOW_THREADS
14082
14083
0
    if (result) {
14084
0
        return path_error(path);
14085
0
    }
14086
14087
0
    return _pystatvfs_fromstructstatvfs(module, st);
14088
0
#endif
14089
0
}
14090
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14091
14092
14093
#ifdef MS_WINDOWS
14094
/*[clinic input]
14095
os._getdiskusage
14096
14097
    path: path_t
14098
14099
Return disk usage statistics about the given path as a (total, free) tuple.
14100
[clinic start generated code]*/
14101
14102
static PyObject *
14103
os__getdiskusage_impl(PyObject *module, path_t *path)
14104
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
14105
{
14106
    BOOL retval;
14107
    ULARGE_INTEGER _, total, free;
14108
    DWORD err = 0;
14109
14110
    Py_BEGIN_ALLOW_THREADS
14111
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14112
    Py_END_ALLOW_THREADS
14113
    if (retval == 0) {
14114
        if (GetLastError() == ERROR_DIRECTORY) {
14115
            wchar_t *dir_path = NULL;
14116
14117
            dir_path = PyMem_New(wchar_t, path->length + 1);
14118
            if (dir_path == NULL) {
14119
                return PyErr_NoMemory();
14120
            }
14121
14122
            wcscpy_s(dir_path, path->length + 1, path->wide);
14123
14124
            if (_dirnameW(dir_path) != -1) {
14125
                Py_BEGIN_ALLOW_THREADS
14126
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14127
                Py_END_ALLOW_THREADS
14128
            }
14129
            /* Record the last error in case it's modified by PyMem_Free. */
14130
            err = GetLastError();
14131
            PyMem_Free(dir_path);
14132
            if (retval) {
14133
                goto success;
14134
            }
14135
        }
14136
        return PyErr_SetFromWindowsErr(err);
14137
    }
14138
14139
success:
14140
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14141
}
14142
#endif /* MS_WINDOWS */
14143
14144
14145
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14146
 * It maps strings representing configuration variable names to
14147
 * integer values, allowing those functions to be called with the
14148
 * magic names instead of polluting the module's namespace with tons of
14149
 * rarely-used constants.  There are three separate tables that use
14150
 * these definitions.
14151
 *
14152
 * This code is always included, even if none of the interfaces that
14153
 * need it are included.  The #if hackery needed to avoid it would be
14154
 * sufficiently pervasive that it's not worth the loss of readability.
14155
 */
14156
struct constdef {
14157
    const char *name;
14158
    int value;
14159
};
14160
14161
static int
14162
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14163
8
{
14164
8
    if (PyUnicode_Check(arg)) {
14165
8
        PyObject *table = PyObject_GetAttrString(module, tablename);
14166
8
        if (table == NULL) {
14167
0
            return 0;
14168
0
        }
14169
14170
8
        arg = PyObject_GetItem(table, arg);
14171
8
        Py_DECREF(table);
14172
8
        if (arg == NULL) {
14173
0
            PyErr_SetString(
14174
0
                PyExc_ValueError, "unrecognized configuration name");
14175
0
            return 0;
14176
0
        }
14177
8
    } else {
14178
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14179
0
    }
14180
14181
8
    int success = 0;
14182
8
    if (!PyIndex_Check(arg)) {
14183
0
        PyErr_SetString(PyExc_TypeError,
14184
0
            "configuration names must be strings or integers");
14185
8
    } else {
14186
8
        int value = PyLong_AsInt(arg);
14187
8
        if (!(value == -1 && PyErr_Occurred())) {
14188
8
            *valuep = value;
14189
8
            success = 1;
14190
8
        }
14191
8
    }
14192
8
    Py_DECREF(arg);
14193
8
    return success;
14194
8
}
14195
14196
14197
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14198
static struct constdef  posix_constants_pathconf[] = {
14199
#ifdef _PC_ABI_AIO_XFER_MAX
14200
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14201
#endif
14202
#ifdef _PC_ABI_ASYNC_IO
14203
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14204
#endif
14205
#ifdef _PC_ASYNC_IO
14206
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14207
#endif
14208
#ifdef _PC_CHOWN_RESTRICTED
14209
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14210
#endif
14211
#ifdef _PC_FILESIZEBITS
14212
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14213
#endif
14214
#ifdef _PC_LAST
14215
    {"PC_LAST", _PC_LAST},
14216
#endif
14217
#ifdef _PC_LINK_MAX
14218
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14219
#endif
14220
#ifdef _PC_MAX_CANON
14221
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14222
#endif
14223
#ifdef _PC_MAX_INPUT
14224
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14225
#endif
14226
#ifdef _PC_NAME_MAX
14227
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14228
#endif
14229
#ifdef _PC_NO_TRUNC
14230
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14231
#endif
14232
#ifdef _PC_PATH_MAX
14233
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14234
#endif
14235
#ifdef _PC_PIPE_BUF
14236
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14237
#endif
14238
#ifdef _PC_PRIO_IO
14239
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14240
#endif
14241
#ifdef _PC_SOCK_MAXBUF
14242
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14243
#endif
14244
#ifdef _PC_SYNC_IO
14245
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14246
#endif
14247
#ifdef _PC_VDISABLE
14248
    {"PC_VDISABLE",     _PC_VDISABLE},
14249
#endif
14250
#ifdef _PC_ACL_ENABLED
14251
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14252
#endif
14253
#ifdef _PC_MIN_HOLE_SIZE
14254
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14255
#endif
14256
#ifdef _PC_ALLOC_SIZE_MIN
14257
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14258
#endif
14259
#ifdef _PC_REC_INCR_XFER_SIZE
14260
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14261
#endif
14262
#ifdef _PC_REC_MAX_XFER_SIZE
14263
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14264
#endif
14265
#ifdef _PC_REC_MIN_XFER_SIZE
14266
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14267
#endif
14268
#ifdef _PC_REC_XFER_ALIGN
14269
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14270
#endif
14271
#ifdef _PC_SYMLINK_MAX
14272
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14273
#endif
14274
#ifdef _PC_XATTR_ENABLED
14275
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14276
#endif
14277
#ifdef _PC_XATTR_EXISTS
14278
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14279
#endif
14280
#ifdef _PC_TIMESTAMP_RESOLUTION
14281
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14282
#endif
14283
};
14284
#endif
14285
14286
14287
#ifdef HAVE_FPATHCONF
14288
/*[clinic input]
14289
os.fpathconf -> long
14290
14291
    fd: fildes
14292
    name: confname(table="pathconf_names")
14293
    /
14294
14295
Return the configuration limit name for the file descriptor fd.
14296
14297
If there is no limit, return -1.
14298
[clinic start generated code]*/
14299
14300
static long
14301
os_fpathconf_impl(PyObject *module, int fd, int name)
14302
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14303
0
{
14304
0
    long limit;
14305
14306
0
    errno = 0;
14307
0
    limit = fpathconf(fd, name);
14308
0
    if (limit == -1 && errno != 0)
14309
0
        posix_error();
14310
14311
0
    return limit;
14312
0
}
14313
#endif /* HAVE_FPATHCONF */
14314
14315
14316
#ifdef HAVE_PATHCONF
14317
/*[clinic input]
14318
os.pathconf -> long
14319
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14320
    name: confname(table="pathconf_names")
14321
14322
Return the configuration limit name for the file or directory path.
14323
14324
If there is no limit, return -1.
14325
On some platforms, path may also be specified as an open file descriptor.
14326
  If this functionality is unavailable, using it raises an exception.
14327
[clinic start generated code]*/
14328
14329
static long
14330
os_pathconf_impl(PyObject *module, path_t *path, int name)
14331
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
14332
0
{
14333
0
    long limit;
14334
14335
0
    errno = 0;
14336
0
#ifdef HAVE_FPATHCONF
14337
0
    if (path->is_fd) {
14338
0
        limit = fpathconf(path->fd, name);
14339
0
    }
14340
0
    else
14341
0
#endif
14342
0
        limit = pathconf(path->narrow, name);
14343
0
    if (limit == -1 && errno != 0) {
14344
0
        if (errno == EINVAL)
14345
            /* could be a path or name problem */
14346
0
            posix_error();
14347
0
        else
14348
0
            path_error(path);
14349
0
    }
14350
14351
0
    return limit;
14352
0
}
14353
#endif /* HAVE_PATHCONF */
14354
14355
#ifdef HAVE_CONFSTR
14356
static struct constdef posix_constants_confstr[] = {
14357
#ifdef _CS_ARCHITECTURE
14358
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14359
#endif
14360
#ifdef _CS_GNU_LIBC_VERSION
14361
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14362
#endif
14363
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14364
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14365
#endif
14366
#ifdef _CS_HOSTNAME
14367
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14368
#endif
14369
#ifdef _CS_HW_PROVIDER
14370
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14371
#endif
14372
#ifdef _CS_HW_SERIAL
14373
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14374
#endif
14375
#ifdef _CS_INITTAB_NAME
14376
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14377
#endif
14378
#ifdef _CS_LFS64_CFLAGS
14379
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14380
#endif
14381
#ifdef _CS_LFS64_LDFLAGS
14382
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14383
#endif
14384
#ifdef _CS_LFS64_LIBS
14385
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14386
#endif
14387
#ifdef _CS_LFS64_LINTFLAGS
14388
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14389
#endif
14390
#ifdef _CS_LFS_CFLAGS
14391
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14392
#endif
14393
#ifdef _CS_LFS_LDFLAGS
14394
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14395
#endif
14396
#ifdef _CS_LFS_LIBS
14397
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14398
#endif
14399
#ifdef _CS_LFS_LINTFLAGS
14400
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14401
#endif
14402
#ifdef _CS_MACHINE
14403
    {"CS_MACHINE",      _CS_MACHINE},
14404
#endif
14405
#ifdef _CS_PATH
14406
    {"CS_PATH", _CS_PATH},
14407
#endif
14408
#ifdef _CS_RELEASE
14409
    {"CS_RELEASE",      _CS_RELEASE},
14410
#endif
14411
#ifdef _CS_SRPC_DOMAIN
14412
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14413
#endif
14414
#ifdef _CS_SYSNAME
14415
    {"CS_SYSNAME",      _CS_SYSNAME},
14416
#endif
14417
#ifdef _CS_VERSION
14418
    {"CS_VERSION",      _CS_VERSION},
14419
#endif
14420
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14421
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14422
#endif
14423
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14424
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14425
#endif
14426
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14427
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14428
#endif
14429
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14430
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14431
#endif
14432
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14433
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14434
#endif
14435
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14436
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14437
#endif
14438
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14439
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14440
#endif
14441
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14442
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14443
#endif
14444
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14445
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14446
#endif
14447
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14448
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14449
#endif
14450
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14451
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14452
#endif
14453
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14454
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14455
#endif
14456
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14457
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14458
#endif
14459
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14460
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14461
#endif
14462
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14463
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14464
#endif
14465
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14466
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14467
#endif
14468
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14469
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14470
#endif
14471
#ifdef _MIPS_CS_BASE
14472
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14473
#endif
14474
#ifdef _MIPS_CS_HOSTID
14475
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14476
#endif
14477
#ifdef _MIPS_CS_HW_NAME
14478
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14479
#endif
14480
#ifdef _MIPS_CS_NUM_PROCESSORS
14481
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14482
#endif
14483
#ifdef _MIPS_CS_OSREL_MAJ
14484
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14485
#endif
14486
#ifdef _MIPS_CS_OSREL_MIN
14487
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14488
#endif
14489
#ifdef _MIPS_CS_OSREL_PATCH
14490
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14491
#endif
14492
#ifdef _MIPS_CS_OS_NAME
14493
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14494
#endif
14495
#ifdef _MIPS_CS_OS_PROVIDER
14496
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14497
#endif
14498
#ifdef _MIPS_CS_PROCESSORS
14499
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14500
#endif
14501
#ifdef _MIPS_CS_SERIAL
14502
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14503
#endif
14504
#ifdef _MIPS_CS_VENDOR
14505
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14506
#endif
14507
};
14508
14509
14510
/*[clinic input]
14511
os.confstr
14512
14513
    name: confname(table="confstr_names")
14514
    /
14515
14516
Return a string-valued system configuration variable.
14517
[clinic start generated code]*/
14518
14519
static PyObject *
14520
os_confstr_impl(PyObject *module, int name)
14521
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14522
4
{
14523
4
    PyObject *result = NULL;
14524
4
    char buffer[255];
14525
4
    size_t len;
14526
14527
4
    errno = 0;
14528
4
    len = confstr(name, buffer, sizeof(buffer));
14529
4
    if (len == 0) {
14530
0
        if (errno) {
14531
0
            posix_error();
14532
0
            return NULL;
14533
0
        }
14534
0
        else {
14535
0
            Py_RETURN_NONE;
14536
0
        }
14537
0
    }
14538
14539
4
    if (len >= sizeof(buffer)) {
14540
0
        size_t len2;
14541
0
        char *buf = PyMem_Malloc(len);
14542
0
        if (buf == NULL)
14543
0
            return PyErr_NoMemory();
14544
0
        len2 = confstr(name, buf, len);
14545
0
        assert(len == len2);
14546
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14547
0
        PyMem_Free(buf);
14548
0
    }
14549
4
    else
14550
4
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14551
4
    return result;
14552
4
}
14553
#endif /* HAVE_CONFSTR */
14554
14555
14556
#ifdef HAVE_SYSCONF
14557
static struct constdef posix_constants_sysconf[] = {
14558
#ifdef _SC_2_CHAR_TERM
14559
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14560
#endif
14561
#ifdef _SC_2_C_BIND
14562
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14563
#endif
14564
#ifdef _SC_2_C_DEV
14565
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14566
#endif
14567
#ifdef _SC_2_C_VERSION
14568
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14569
#endif
14570
#ifdef _SC_2_FORT_DEV
14571
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14572
#endif
14573
#ifdef _SC_2_FORT_RUN
14574
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14575
#endif
14576
#ifdef _SC_2_LOCALEDEF
14577
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14578
#endif
14579
#ifdef _SC_2_SW_DEV
14580
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14581
#endif
14582
#ifdef _SC_2_UPE
14583
    {"SC_2_UPE",        _SC_2_UPE},
14584
#endif
14585
#ifdef _SC_2_VERSION
14586
    {"SC_2_VERSION",    _SC_2_VERSION},
14587
#endif
14588
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14589
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14590
#endif
14591
#ifdef _SC_ACL
14592
    {"SC_ACL",  _SC_ACL},
14593
#endif
14594
#ifdef _SC_AIO_LISTIO_MAX
14595
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14596
#endif
14597
#ifdef _SC_AIO_MAX
14598
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14599
#endif
14600
#ifdef _SC_AIO_PRIO_DELTA_MAX
14601
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14602
#endif
14603
#ifdef _SC_ARG_MAX
14604
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14605
#endif
14606
#ifdef _SC_ASYNCHRONOUS_IO
14607
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14608
#endif
14609
#ifdef _SC_ATEXIT_MAX
14610
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14611
#endif
14612
#ifdef _SC_AUDIT
14613
    {"SC_AUDIT",        _SC_AUDIT},
14614
#endif
14615
#ifdef _SC_AVPHYS_PAGES
14616
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14617
#endif
14618
#ifdef _SC_BC_BASE_MAX
14619
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14620
#endif
14621
#ifdef _SC_BC_DIM_MAX
14622
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14623
#endif
14624
#ifdef _SC_BC_SCALE_MAX
14625
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14626
#endif
14627
#ifdef _SC_BC_STRING_MAX
14628
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14629
#endif
14630
#ifdef _SC_CAP
14631
    {"SC_CAP",  _SC_CAP},
14632
#endif
14633
#ifdef _SC_CHARCLASS_NAME_MAX
14634
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14635
#endif
14636
#ifdef _SC_CHAR_BIT
14637
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14638
#endif
14639
#ifdef _SC_CHAR_MAX
14640
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14641
#endif
14642
#ifdef _SC_CHAR_MIN
14643
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14644
#endif
14645
#ifdef _SC_CHILD_MAX
14646
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14647
#endif
14648
#ifdef _SC_CLK_TCK
14649
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14650
#endif
14651
#ifdef _SC_COHER_BLKSZ
14652
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14653
#endif
14654
#ifdef _SC_COLL_WEIGHTS_MAX
14655
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14656
#endif
14657
#ifdef _SC_DCACHE_ASSOC
14658
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14659
#endif
14660
#ifdef _SC_DCACHE_BLKSZ
14661
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14662
#endif
14663
#ifdef _SC_DCACHE_LINESZ
14664
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14665
#endif
14666
#ifdef _SC_DCACHE_SZ
14667
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14668
#endif
14669
#ifdef _SC_DCACHE_TBLKSZ
14670
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14671
#endif
14672
#ifdef _SC_DELAYTIMER_MAX
14673
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14674
#endif
14675
#ifdef _SC_EQUIV_CLASS_MAX
14676
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14677
#endif
14678
#ifdef _SC_EXPR_NEST_MAX
14679
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14680
#endif
14681
#ifdef _SC_FSYNC
14682
    {"SC_FSYNC",        _SC_FSYNC},
14683
#endif
14684
#ifdef _SC_GETGR_R_SIZE_MAX
14685
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14686
#endif
14687
#ifdef _SC_GETPW_R_SIZE_MAX
14688
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14689
#endif
14690
#ifdef _SC_ICACHE_ASSOC
14691
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14692
#endif
14693
#ifdef _SC_ICACHE_BLKSZ
14694
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14695
#endif
14696
#ifdef _SC_ICACHE_LINESZ
14697
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14698
#endif
14699
#ifdef _SC_ICACHE_SZ
14700
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14701
#endif
14702
#ifdef _SC_INF
14703
    {"SC_INF",  _SC_INF},
14704
#endif
14705
#ifdef _SC_INT_MAX
14706
    {"SC_INT_MAX",      _SC_INT_MAX},
14707
#endif
14708
#ifdef _SC_INT_MIN
14709
    {"SC_INT_MIN",      _SC_INT_MIN},
14710
#endif
14711
#ifdef _SC_IOV_MAX
14712
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14713
#endif
14714
#ifdef _SC_IP_SECOPTS
14715
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14716
#endif
14717
#ifdef _SC_JOB_CONTROL
14718
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14719
#endif
14720
#ifdef _SC_KERN_POINTERS
14721
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14722
#endif
14723
#ifdef _SC_KERN_SIM
14724
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14725
#endif
14726
#ifdef _SC_LINE_MAX
14727
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14728
#endif
14729
#ifdef _SC_LOGIN_NAME_MAX
14730
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14731
#endif
14732
#ifdef _SC_LOGNAME_MAX
14733
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14734
#endif
14735
#ifdef _SC_LONG_BIT
14736
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14737
#endif
14738
#ifdef _SC_MAC
14739
    {"SC_MAC",  _SC_MAC},
14740
#endif
14741
#ifdef _SC_MAPPED_FILES
14742
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14743
#endif
14744
#ifdef _SC_MAXPID
14745
    {"SC_MAXPID",       _SC_MAXPID},
14746
#endif
14747
#ifdef _SC_MB_LEN_MAX
14748
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14749
#endif
14750
#ifdef _SC_MEMLOCK
14751
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14752
#endif
14753
#ifdef _SC_MEMLOCK_RANGE
14754
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14755
#endif
14756
#ifdef _SC_MEMORY_PROTECTION
14757
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14758
#endif
14759
#ifdef _SC_MESSAGE_PASSING
14760
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14761
#endif
14762
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14763
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14764
#endif
14765
#ifdef _SC_MQ_OPEN_MAX
14766
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14767
#endif
14768
#ifdef _SC_MQ_PRIO_MAX
14769
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14770
#endif
14771
#ifdef _SC_NACLS_MAX
14772
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14773
#endif
14774
#ifdef _SC_NGROUPS_MAX
14775
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14776
#endif
14777
#ifdef _SC_NL_ARGMAX
14778
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14779
#endif
14780
#ifdef _SC_NL_LANGMAX
14781
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14782
#endif
14783
#ifdef _SC_NL_MSGMAX
14784
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14785
#endif
14786
#ifdef _SC_NL_NMAX
14787
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14788
#endif
14789
#ifdef _SC_NL_SETMAX
14790
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14791
#endif
14792
#ifdef _SC_NL_TEXTMAX
14793
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14794
#endif
14795
#ifdef _SC_NPROCESSORS_CONF
14796
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14797
#endif
14798
#ifdef _SC_NPROCESSORS_ONLN
14799
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14800
#endif
14801
#ifdef _SC_NPROC_CONF
14802
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14803
#endif
14804
#ifdef _SC_NPROC_ONLN
14805
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14806
#endif
14807
#ifdef _SC_NZERO
14808
    {"SC_NZERO",        _SC_NZERO},
14809
#endif
14810
#ifdef _SC_OPEN_MAX
14811
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14812
#endif
14813
#ifdef _SC_PAGESIZE
14814
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14815
#endif
14816
#ifdef _SC_PAGE_SIZE
14817
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14818
#endif
14819
#ifdef _SC_AIX_REALMEM
14820
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14821
#endif
14822
#ifdef _SC_PASS_MAX
14823
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14824
#endif
14825
#ifdef _SC_PHYS_PAGES
14826
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14827
#endif
14828
#ifdef _SC_PII
14829
    {"SC_PII",  _SC_PII},
14830
#endif
14831
#ifdef _SC_PII_INTERNET
14832
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14833
#endif
14834
#ifdef _SC_PII_INTERNET_DGRAM
14835
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14836
#endif
14837
#ifdef _SC_PII_INTERNET_STREAM
14838
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14839
#endif
14840
#ifdef _SC_PII_OSI
14841
    {"SC_PII_OSI",      _SC_PII_OSI},
14842
#endif
14843
#ifdef _SC_PII_OSI_CLTS
14844
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14845
#endif
14846
#ifdef _SC_PII_OSI_COTS
14847
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14848
#endif
14849
#ifdef _SC_PII_OSI_M
14850
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14851
#endif
14852
#ifdef _SC_PII_SOCKET
14853
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14854
#endif
14855
#ifdef _SC_PII_XTI
14856
    {"SC_PII_XTI",      _SC_PII_XTI},
14857
#endif
14858
#ifdef _SC_POLL
14859
    {"SC_POLL", _SC_POLL},
14860
#endif
14861
#ifdef _SC_PRIORITIZED_IO
14862
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14863
#endif
14864
#ifdef _SC_PRIORITY_SCHEDULING
14865
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14866
#endif
14867
#ifdef _SC_REALTIME_SIGNALS
14868
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14869
#endif
14870
#ifdef _SC_RE_DUP_MAX
14871
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14872
#endif
14873
#ifdef _SC_RTSIG_MAX
14874
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14875
#endif
14876
#ifdef _SC_SAVED_IDS
14877
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14878
#endif
14879
#ifdef _SC_SCHAR_MAX
14880
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14881
#endif
14882
#ifdef _SC_SCHAR_MIN
14883
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14884
#endif
14885
#ifdef _SC_SELECT
14886
    {"SC_SELECT",       _SC_SELECT},
14887
#endif
14888
#ifdef _SC_SEMAPHORES
14889
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14890
#endif
14891
#ifdef _SC_SEM_NSEMS_MAX
14892
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14893
#endif
14894
#ifdef _SC_SEM_VALUE_MAX
14895
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14896
#endif
14897
#ifdef _SC_SHARED_MEMORY_OBJECTS
14898
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14899
#endif
14900
#ifdef _SC_SHRT_MAX
14901
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14902
#endif
14903
#ifdef _SC_SHRT_MIN
14904
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14905
#endif
14906
#ifdef _SC_SIGQUEUE_MAX
14907
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14908
#endif
14909
#ifdef _SC_SIGRT_MAX
14910
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14911
#endif
14912
#ifdef _SC_SIGRT_MIN
14913
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14914
#endif
14915
#ifdef _SC_SOFTPOWER
14916
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14917
#endif
14918
#ifdef _SC_SPLIT_CACHE
14919
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14920
#endif
14921
#ifdef _SC_SSIZE_MAX
14922
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14923
#endif
14924
#ifdef _SC_STACK_PROT
14925
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14926
#endif
14927
#ifdef _SC_STREAM_MAX
14928
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14929
#endif
14930
#ifdef _SC_SYNCHRONIZED_IO
14931
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14932
#endif
14933
#ifdef _SC_THREADS
14934
    {"SC_THREADS",      _SC_THREADS},
14935
#endif
14936
#ifdef _SC_THREAD_ATTR_STACKADDR
14937
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14938
#endif
14939
#ifdef _SC_THREAD_ATTR_STACKSIZE
14940
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14941
#endif
14942
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14943
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14944
#endif
14945
#ifdef _SC_THREAD_KEYS_MAX
14946
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14947
#endif
14948
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14949
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14950
#endif
14951
#ifdef _SC_THREAD_PRIO_INHERIT
14952
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14953
#endif
14954
#ifdef _SC_THREAD_PRIO_PROTECT
14955
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14956
#endif
14957
#ifdef _SC_THREAD_PROCESS_SHARED
14958
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14959
#endif
14960
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14961
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14962
#endif
14963
#ifdef _SC_THREAD_STACK_MIN
14964
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14965
#endif
14966
#ifdef _SC_THREAD_THREADS_MAX
14967
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14968
#endif
14969
#ifdef _SC_TIMERS
14970
    {"SC_TIMERS",       _SC_TIMERS},
14971
#endif
14972
#ifdef _SC_TIMER_MAX
14973
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14974
#endif
14975
#ifdef _SC_TTY_NAME_MAX
14976
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14977
#endif
14978
#ifdef _SC_TZNAME_MAX
14979
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14980
#endif
14981
#ifdef _SC_T_IOV_MAX
14982
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14983
#endif
14984
#ifdef _SC_UCHAR_MAX
14985
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14986
#endif
14987
#ifdef _SC_UINT_MAX
14988
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14989
#endif
14990
#ifdef _SC_UIO_MAXIOV
14991
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14992
#endif
14993
#ifdef _SC_ULONG_MAX
14994
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14995
#endif
14996
#ifdef _SC_USHRT_MAX
14997
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14998
#endif
14999
#ifdef _SC_VERSION
15000
    {"SC_VERSION",      _SC_VERSION},
15001
#endif
15002
#ifdef _SC_WORD_BIT
15003
    {"SC_WORD_BIT",     _SC_WORD_BIT},
15004
#endif
15005
#ifdef _SC_XBS5_ILP32_OFF32
15006
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15007
#endif
15008
#ifdef _SC_XBS5_ILP32_OFFBIG
15009
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15010
#endif
15011
#ifdef _SC_XBS5_LP64_OFF64
15012
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15013
#endif
15014
#ifdef _SC_XBS5_LPBIG_OFFBIG
15015
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15016
#endif
15017
#ifdef _SC_XOPEN_CRYPT
15018
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15019
#endif
15020
#ifdef _SC_XOPEN_ENH_I18N
15021
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15022
#endif
15023
#ifdef _SC_XOPEN_LEGACY
15024
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15025
#endif
15026
#ifdef _SC_XOPEN_REALTIME
15027
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15028
#endif
15029
#ifdef _SC_XOPEN_REALTIME_THREADS
15030
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15031
#endif
15032
#ifdef _SC_XOPEN_SHM
15033
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15034
#endif
15035
#ifdef _SC_XOPEN_UNIX
15036
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15037
#endif
15038
#ifdef _SC_XOPEN_VERSION
15039
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15040
#endif
15041
#ifdef _SC_XOPEN_XCU_VERSION
15042
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15043
#endif
15044
#ifdef _SC_XOPEN_XPG2
15045
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15046
#endif
15047
#ifdef _SC_XOPEN_XPG3
15048
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15049
#endif
15050
#ifdef _SC_XOPEN_XPG4
15051
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15052
#endif
15053
#ifdef _SC_MINSIGSTKSZ
15054
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15055
#endif
15056
};
15057
15058
15059
/*[clinic input]
15060
os.sysconf -> long
15061
    name: confname(table="sysconf_names")
15062
    /
15063
15064
Return an integer-valued system configuration variable.
15065
[clinic start generated code]*/
15066
15067
static long
15068
os_sysconf_impl(PyObject *module, int name)
15069
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15070
4
{
15071
4
    long value;
15072
15073
4
    errno = 0;
15074
4
    value = sysconf(name);
15075
4
    if (value == -1 && errno != 0)
15076
0
        posix_error();
15077
4
    return value;
15078
4
}
15079
#endif /* HAVE_SYSCONF */
15080
15081
15082
static int
15083
setup_confname_table(struct constdef *table, size_t tablesize,
15084
                     const char *tablename, PyObject *module)
15085
108
{
15086
108
    PyObject *d = PyDict_New();
15087
108
    if (d == NULL)
15088
0
        return -1;
15089
15090
6.62k
    for (size_t i=0; i < tablesize; ++i) {
15091
6.51k
        PyObject *o = PyLong_FromLong(table[i].value);
15092
6.51k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15093
0
            Py_XDECREF(o);
15094
0
            Py_DECREF(d);
15095
0
            return -1;
15096
0
        }
15097
6.51k
        Py_DECREF(o);
15098
6.51k
    }
15099
108
    return PyModule_Add(module, tablename, d);
15100
108
}
15101
15102
/* Return -1 on failure, 0 on success. */
15103
static int
15104
setup_confname_tables(PyObject *module)
15105
36
{
15106
36
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15107
36
    if (setup_confname_table(posix_constants_pathconf,
15108
36
                             sizeof(posix_constants_pathconf)
15109
36
                               / sizeof(struct constdef),
15110
36
                             "pathconf_names", module))
15111
0
        return -1;
15112
36
#endif
15113
36
#ifdef HAVE_CONFSTR
15114
36
    if (setup_confname_table(posix_constants_confstr,
15115
36
                             sizeof(posix_constants_confstr)
15116
36
                               / sizeof(struct constdef),
15117
36
                             "confstr_names", module))
15118
0
        return -1;
15119
36
#endif
15120
36
#ifdef HAVE_SYSCONF
15121
36
    if (setup_confname_table(posix_constants_sysconf,
15122
36
                             sizeof(posix_constants_sysconf)
15123
36
                               / sizeof(struct constdef),
15124
36
                             "sysconf_names", module))
15125
0
        return -1;
15126
36
#endif
15127
36
    return 0;
15128
36
}
15129
15130
15131
/*[clinic input]
15132
os.abort
15133
15134
Abort the interpreter immediately.
15135
15136
This function 'dumps core' or otherwise fails in the hardest way possible
15137
on the hosting operating system.  This function never returns.
15138
[clinic start generated code]*/
15139
15140
static PyObject *
15141
os_abort_impl(PyObject *module)
15142
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
15143
0
{
15144
0
    abort();
15145
    /*NOTREACHED*/
15146
#ifndef __clang__
15147
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15148
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15149
       is smarter and emits a warning on the return. */
15150
    Py_FatalError("abort() called from Python code didn't abort!");
15151
    return NULL;
15152
#endif
15153
0
}
15154
15155
#ifdef MS_WINDOWS
15156
/* Grab ShellExecute dynamically from shell32 */
15157
static int has_ShellExecute = -1;
15158
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15159
                                              LPCWSTR, INT);
15160
static int
15161
check_ShellExecute(void)
15162
{
15163
    HINSTANCE hShell32;
15164
15165
    /* only recheck */
15166
    if (-1 == has_ShellExecute) {
15167
        Py_BEGIN_ALLOW_THREADS
15168
        /* Security note: this call is not vulnerable to "DLL hijacking".
15169
           SHELL32 is part of "KnownDLLs" and so Windows always load
15170
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15171
           in the DLL search path. */
15172
        hShell32 = LoadLibraryW(L"SHELL32");
15173
        if (hShell32) {
15174
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15175
                                            "ShellExecuteW");
15176
            has_ShellExecute = Py_ShellExecuteW != NULL;
15177
        } else {
15178
            has_ShellExecute = 0;
15179
        }
15180
        Py_END_ALLOW_THREADS
15181
    }
15182
    return has_ShellExecute;
15183
}
15184
15185
15186
/*[clinic input]
15187
os.startfile
15188
    filepath: path_t
15189
    operation: Py_UNICODE = NULL
15190
    arguments: Py_UNICODE = NULL
15191
    cwd: path_t(nullable=True) = None
15192
    show_cmd: int = 1
15193
15194
Start a file with its associated application.
15195
15196
When "operation" is not specified or "open", this acts like
15197
double-clicking the file in Explorer, or giving the file name as an
15198
argument to the DOS "start" command: the file is opened with whatever
15199
application (if any) its extension is associated.
15200
When another "operation" is given, it specifies what should be done with
15201
the file.  A typical operation is "print".
15202
15203
"arguments" is passed to the application, but should be omitted if the
15204
file is a document.
15205
15206
"cwd" is the working directory for the operation. If "filepath" is
15207
relative, it will be resolved against this directory. This argument
15208
should usually be an absolute path.
15209
15210
"show_cmd" can be used to override the recommended visibility option.
15211
See the Windows ShellExecute documentation for values.
15212
15213
startfile returns as soon as the associated application is launched.
15214
There is no option to wait for the application to close, and no way
15215
to retrieve the application's exit status.
15216
15217
The filepath is relative to the current directory.  If you want to use
15218
an absolute path, make sure the first character is not a slash ("/");
15219
the underlying Win32 ShellExecute function doesn't work if it is.
15220
[clinic start generated code]*/
15221
15222
static PyObject *
15223
os_startfile_impl(PyObject *module, path_t *filepath,
15224
                  const wchar_t *operation, const wchar_t *arguments,
15225
                  path_t *cwd, int show_cmd)
15226
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15227
{
15228
    HINSTANCE rc;
15229
15230
    if(!check_ShellExecute()) {
15231
        /* If the OS doesn't have ShellExecute, return a
15232
           NotImplementedError. */
15233
        return PyErr_Format(PyExc_NotImplementedError,
15234
            "startfile not available on this platform");
15235
    }
15236
15237
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15238
        return NULL;
15239
    }
15240
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15241
                    arguments, cwd->object ? cwd->object : Py_None,
15242
                    show_cmd) < 0) {
15243
        return NULL;
15244
    }
15245
15246
    Py_BEGIN_ALLOW_THREADS
15247
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15248
                          arguments, cwd->wide, show_cmd);
15249
    Py_END_ALLOW_THREADS
15250
15251
    if (rc <= (HINSTANCE)32) {
15252
        win32_error_object("startfile", filepath->object);
15253
        return NULL;
15254
    }
15255
    Py_RETURN_NONE;
15256
}
15257
#endif /* MS_WINDOWS */
15258
15259
15260
#ifdef HAVE_GETLOADAVG
15261
/*[clinic input]
15262
os.getloadavg
15263
15264
Return average recent system load information.
15265
15266
Return the number of processes in the system run queue averaged over
15267
the last 1, 5, and 15 minutes as a tuple of three floats.
15268
Raises OSError if the load average was unobtainable.
15269
[clinic start generated code]*/
15270
15271
static PyObject *
15272
os_getloadavg_impl(PyObject *module)
15273
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15274
0
{
15275
0
    double loadavg[3];
15276
0
    if (getloadavg(loadavg, 3)!=3) {
15277
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15278
0
        return NULL;
15279
0
    } else
15280
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15281
0
}
15282
#endif /* HAVE_GETLOADAVG */
15283
15284
15285
/*[clinic input]
15286
os.device_encoding
15287
    fd: int
15288
15289
Return a string describing the encoding of a terminal's file descriptor.
15290
15291
The file descriptor must be attached to a terminal.
15292
If the device is not a terminal, return None.
15293
[clinic start generated code]*/
15294
15295
static PyObject *
15296
os_device_encoding_impl(PyObject *module, int fd)
15297
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15298
0
{
15299
0
    return _Py_device_encoding(fd);
15300
0
}
15301
15302
15303
#ifdef HAVE_SETRESUID
15304
/*[clinic input]
15305
os.setresuid
15306
15307
    ruid: uid_t
15308
    euid: uid_t
15309
    suid: uid_t
15310
    /
15311
15312
Set the current process's real, effective, and saved user ids.
15313
[clinic start generated code]*/
15314
15315
static PyObject *
15316
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15317
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15318
0
{
15319
0
    if (setresuid(ruid, euid, suid) < 0)
15320
0
        return posix_error();
15321
0
    Py_RETURN_NONE;
15322
0
}
15323
#endif /* HAVE_SETRESUID */
15324
15325
15326
#ifdef HAVE_SETRESGID
15327
/*[clinic input]
15328
os.setresgid
15329
15330
    rgid: gid_t
15331
    egid: gid_t
15332
    sgid: gid_t
15333
    /
15334
15335
Set the current process's real, effective, and saved group ids.
15336
[clinic start generated code]*/
15337
15338
static PyObject *
15339
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15340
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15341
0
{
15342
0
    if (setresgid(rgid, egid, sgid) < 0)
15343
0
        return posix_error();
15344
0
    Py_RETURN_NONE;
15345
0
}
15346
#endif /* HAVE_SETRESGID */
15347
15348
15349
#ifdef HAVE_GETRESUID
15350
/*[clinic input]
15351
os.getresuid
15352
15353
Return a tuple of the current process's real, effective, and saved user ids.
15354
[clinic start generated code]*/
15355
15356
static PyObject *
15357
os_getresuid_impl(PyObject *module)
15358
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
15359
0
{
15360
0
    uid_t ruid, euid, suid;
15361
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15362
0
        return posix_error();
15363
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15364
0
                                  _PyLong_FromUid(euid),
15365
0
                                  _PyLong_FromUid(suid));
15366
0
}
15367
#endif /* HAVE_GETRESUID */
15368
15369
15370
#ifdef HAVE_GETRESGID
15371
/*[clinic input]
15372
@permit_long_summary
15373
os.getresgid
15374
15375
Return a tuple of the current process's real, effective, and saved group ids.
15376
[clinic start generated code]*/
15377
15378
static PyObject *
15379
os_getresgid_impl(PyObject *module)
15380
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15381
0
{
15382
0
    gid_t rgid, egid, sgid;
15383
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15384
0
        return posix_error();
15385
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15386
0
                                  _PyLong_FromGid(egid),
15387
0
                                  _PyLong_FromGid(sgid));
15388
0
}
15389
#endif /* HAVE_GETRESGID */
15390
15391
15392
#ifdef USE_XATTRS
15393
/*[clinic input]
15394
os.getxattr
15395
15396
    path: path_t(allow_fd=True)
15397
    attribute: path_t
15398
    *
15399
    follow_symlinks: bool = True
15400
15401
Return the value of extended attribute attribute on path.
15402
15403
path may be either a string, a path-like object, or an open file descriptor.
15404
If follow_symlinks is False, and the last element of the path is a symbolic
15405
  link, getxattr will examine the symbolic link itself instead of the file
15406
  the link points to.
15407
15408
[clinic start generated code]*/
15409
15410
static PyObject *
15411
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15412
                 int follow_symlinks)
15413
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
15414
0
{
15415
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
15416
0
        return NULL;
15417
15418
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15419
0
        return NULL;
15420
0
    }
15421
15422
0
    for (Py_ssize_t i = 0; ; i++) {
15423
0
        ssize_t result;
15424
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15425
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15426
0
        if (!buffer_size) {
15427
0
            path_error(path);
15428
0
            return NULL;
15429
0
        }
15430
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15431
0
        if (writer == NULL) {
15432
0
            return NULL;
15433
0
        }
15434
0
        void *ptr = PyBytesWriter_GetData(writer);
15435
15436
0
        Py_BEGIN_ALLOW_THREADS;
15437
0
        if (path->is_fd)
15438
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15439
0
        else if (follow_symlinks)
15440
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15441
0
        else
15442
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15443
0
        Py_END_ALLOW_THREADS;
15444
15445
0
        if (result < 0) {
15446
0
            PyBytesWriter_Discard(writer);
15447
0
            if (errno == ERANGE) {
15448
0
                continue;
15449
0
            }
15450
0
            path_error(path);
15451
0
            return NULL;
15452
0
        }
15453
15454
0
        return PyBytesWriter_FinishWithSize(writer, result);
15455
0
    }
15456
0
}
15457
15458
15459
/*[clinic input]
15460
@permit_long_docstring_body
15461
os.setxattr
15462
15463
    path: path_t(allow_fd=True)
15464
    attribute: path_t
15465
    value: Py_buffer
15466
    flags: int = 0
15467
    *
15468
    follow_symlinks: bool = True
15469
15470
Set extended attribute attribute on path to value.
15471
15472
path may be either a string, a path-like object,  or an open file descriptor.
15473
If follow_symlinks is False, and the last element of the path is a symbolic
15474
  link, setxattr will modify the symbolic link itself instead of the file
15475
  the link points to.
15476
15477
[clinic start generated code]*/
15478
15479
static PyObject *
15480
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15481
                 Py_buffer *value, int flags, int follow_symlinks)
15482
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15483
0
{
15484
0
    ssize_t result;
15485
15486
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
15487
0
        return NULL;
15488
15489
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15490
0
                    value->buf, value->len, flags) < 0) {
15491
0
        return NULL;
15492
0
    }
15493
15494
0
    Py_BEGIN_ALLOW_THREADS;
15495
0
    if (path->is_fd)
15496
0
        result = fsetxattr(path->fd, attribute->narrow,
15497
0
                           value->buf, value->len, flags);
15498
0
    else if (follow_symlinks)
15499
0
        result = setxattr(path->narrow, attribute->narrow,
15500
0
                           value->buf, value->len, flags);
15501
0
    else
15502
0
        result = lsetxattr(path->narrow, attribute->narrow,
15503
0
                           value->buf, value->len, flags);
15504
0
    Py_END_ALLOW_THREADS;
15505
15506
0
    if (result) {
15507
0
        path_error(path);
15508
0
        return NULL;
15509
0
    }
15510
15511
0
    Py_RETURN_NONE;
15512
0
}
15513
15514
15515
/*[clinic input]
15516
os.removexattr
15517
15518
    path: path_t(allow_fd=True)
15519
    attribute: path_t
15520
    *
15521
    follow_symlinks: bool = True
15522
15523
Remove extended attribute attribute on path.
15524
15525
path may be either a string, a path-like object, or an open file descriptor.
15526
If follow_symlinks is False, and the last element of the path is a symbolic
15527
  link, removexattr will modify the symbolic link itself instead of the file
15528
  the link points to.
15529
15530
[clinic start generated code]*/
15531
15532
static PyObject *
15533
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15534
                    int follow_symlinks)
15535
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15536
0
{
15537
0
    ssize_t result;
15538
15539
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
15540
0
        return NULL;
15541
15542
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15543
0
        return NULL;
15544
0
    }
15545
15546
0
    Py_BEGIN_ALLOW_THREADS;
15547
0
    if (path->is_fd)
15548
0
        result = fremovexattr(path->fd, attribute->narrow);
15549
0
    else if (follow_symlinks)
15550
0
        result = removexattr(path->narrow, attribute->narrow);
15551
0
    else
15552
0
        result = lremovexattr(path->narrow, attribute->narrow);
15553
0
    Py_END_ALLOW_THREADS;
15554
15555
0
    if (result) {
15556
0
        return path_error(path);
15557
0
    }
15558
15559
0
    Py_RETURN_NONE;
15560
0
}
15561
15562
15563
/*[clinic input]
15564
@permit_long_docstring_body
15565
os.listxattr
15566
15567
    path: path_t(allow_fd=True, nullable=True) = None
15568
    *
15569
    follow_symlinks: bool = True
15570
15571
Return a list of extended attributes on path.
15572
15573
path may be either None, a string, a path-like object, or an open file descriptor.
15574
if path is None, listxattr will examine the current directory.
15575
If follow_symlinks is False, and the last element of the path is a symbolic
15576
  link, listxattr will examine the symbolic link itself instead of the file
15577
  the link points to.
15578
[clinic start generated code]*/
15579
15580
static PyObject *
15581
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15582
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15583
0
{
15584
0
    Py_ssize_t i;
15585
0
    PyObject *result = NULL;
15586
0
    const char *name;
15587
0
    char *buffer = NULL;
15588
15589
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
15590
0
        goto exit;
15591
15592
0
    if (PySys_Audit("os.listxattr", "(O)",
15593
0
                    path->object ? path->object : Py_None) < 0) {
15594
0
        return NULL;
15595
0
    }
15596
15597
0
    name = path->narrow ? path->narrow : ".";
15598
15599
0
    for (i = 0; ; i++) {
15600
0
        const char *start, *trace, *end;
15601
0
        ssize_t length;
15602
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15603
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15604
0
        if (!buffer_size) {
15605
            /* ERANGE */
15606
0
            path_error(path);
15607
0
            break;
15608
0
        }
15609
0
        buffer = PyMem_Malloc(buffer_size);
15610
0
        if (!buffer) {
15611
0
            PyErr_NoMemory();
15612
0
            break;
15613
0
        }
15614
15615
0
        Py_BEGIN_ALLOW_THREADS;
15616
0
        if (path->is_fd)
15617
0
            length = flistxattr(path->fd, buffer, buffer_size);
15618
0
        else if (follow_symlinks)
15619
0
            length = listxattr(name, buffer, buffer_size);
15620
0
        else
15621
0
            length = llistxattr(name, buffer, buffer_size);
15622
0
        Py_END_ALLOW_THREADS;
15623
15624
0
        if (length < 0) {
15625
0
            if (errno == ERANGE) {
15626
0
                PyMem_Free(buffer);
15627
0
                buffer = NULL;
15628
0
                continue;
15629
0
            }
15630
0
            path_error(path);
15631
0
            break;
15632
0
        }
15633
15634
0
        result = PyList_New(0);
15635
0
        if (!result) {
15636
0
            goto exit;
15637
0
        }
15638
15639
0
        end = buffer + length;
15640
0
        for (trace = start = buffer; trace != end; trace++) {
15641
0
            if (!*trace) {
15642
0
                int error;
15643
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15644
0
                                                                 trace - start);
15645
0
                if (!attribute) {
15646
0
                    Py_SETREF(result, NULL);
15647
0
                    goto exit;
15648
0
                }
15649
0
                error = PyList_Append(result, attribute);
15650
0
                Py_DECREF(attribute);
15651
0
                if (error) {
15652
0
                    Py_SETREF(result, NULL);
15653
0
                    goto exit;
15654
0
                }
15655
0
                start = trace + 1;
15656
0
            }
15657
0
        }
15658
0
    break;
15659
0
    }
15660
0
exit:
15661
0
    if (buffer)
15662
0
        PyMem_Free(buffer);
15663
0
    return result;
15664
0
}
15665
#endif /* USE_XATTRS */
15666
15667
15668
/*[clinic input]
15669
@permit_long_summary
15670
os.urandom
15671
15672
    size: Py_ssize_t(allow_negative=False)
15673
    /
15674
15675
Return a bytes object containing random bytes suitable for cryptographic use.
15676
[clinic start generated code]*/
15677
15678
static PyObject *
15679
os_urandom_impl(PyObject *module, Py_ssize_t size)
15680
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15681
0
{
15682
0
    if (size < 0) {
15683
0
        return PyErr_Format(PyExc_ValueError,
15684
0
                            "negative argument not allowed");
15685
0
    }
15686
15687
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15688
0
    if (writer == NULL) {
15689
0
        return NULL;
15690
0
    }
15691
15692
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15693
0
    if (result == -1) {
15694
0
        PyBytesWriter_Discard(writer);
15695
0
        return NULL;
15696
0
    }
15697
0
    return PyBytesWriter_Finish(writer);
15698
0
}
15699
15700
#ifdef HAVE_MEMFD_CREATE
15701
/*[clinic input]
15702
os.memfd_create
15703
15704
    name: unicode_fs_encoded
15705
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15706
15707
[clinic start generated code]*/
15708
15709
static PyObject *
15710
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15711
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15712
0
{
15713
0
    int fd;
15714
0
    const char *bytes = PyBytes_AS_STRING(name);
15715
0
    Py_BEGIN_ALLOW_THREADS
15716
0
    fd = memfd_create(bytes, 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
#endif
15724
15725
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15726
/*[clinic input]
15727
os.eventfd
15728
15729
    initval: unsigned_int
15730
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15731
15732
Creates and returns an event notification file descriptor.
15733
[clinic start generated code]*/
15734
15735
static PyObject *
15736
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15737
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15738
15739
0
{
15740
    /* initval is limited to uint32_t, internal counter is uint64_t */
15741
0
    int fd;
15742
0
    Py_BEGIN_ALLOW_THREADS
15743
0
    fd = eventfd(initval, flags);
15744
0
    Py_END_ALLOW_THREADS
15745
0
    if (fd == -1) {
15746
0
        return PyErr_SetFromErrno(PyExc_OSError);
15747
0
    }
15748
0
    return PyLong_FromLong(fd);
15749
0
}
15750
15751
/*[clinic input]
15752
os.eventfd_read
15753
15754
    fd: fildes
15755
15756
Read eventfd value
15757
[clinic start generated code]*/
15758
15759
static PyObject *
15760
os_eventfd_read_impl(PyObject *module, int fd)
15761
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15762
0
{
15763
0
    eventfd_t value;
15764
0
    int result;
15765
0
    Py_BEGIN_ALLOW_THREADS
15766
0
    result = eventfd_read(fd, &value);
15767
0
    Py_END_ALLOW_THREADS
15768
0
    if (result == -1) {
15769
0
        return PyErr_SetFromErrno(PyExc_OSError);
15770
0
    }
15771
0
    return PyLong_FromUnsignedLongLong(value);
15772
0
}
15773
15774
/*[clinic input]
15775
os.eventfd_write
15776
15777
    fd: fildes
15778
    value: unsigned_long_long
15779
15780
Write eventfd value.
15781
[clinic start generated code]*/
15782
15783
static PyObject *
15784
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15785
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15786
0
{
15787
0
    int result;
15788
0
    Py_BEGIN_ALLOW_THREADS
15789
0
    result = eventfd_write(fd, value);
15790
0
    Py_END_ALLOW_THREADS
15791
0
    if (result == -1) {
15792
0
        return PyErr_SetFromErrno(PyExc_OSError);
15793
0
    }
15794
0
    Py_RETURN_NONE;
15795
0
}
15796
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15797
15798
/* Terminal size querying */
15799
15800
PyDoc_STRVAR(TerminalSize_docstring,
15801
    "A tuple of (columns, lines) for holding terminal window size");
15802
15803
static PyStructSequence_Field TerminalSize_fields[] = {
15804
    {"columns", "width of the terminal window in characters"},
15805
    {"lines", "height of the terminal window in characters"},
15806
    {NULL, NULL}
15807
};
15808
15809
static PyStructSequence_Desc TerminalSize_desc = {
15810
    "os.terminal_size",
15811
    TerminalSize_docstring,
15812
    TerminalSize_fields,
15813
    2,
15814
};
15815
15816
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15817
/*[clinic input]
15818
os.get_terminal_size
15819
15820
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15821
    /
15822
15823
Return the size of the terminal window as (columns, lines).
15824
15825
The optional argument fd (default standard output) specifies
15826
which file descriptor should be queried.
15827
15828
If the file descriptor is not connected to a terminal, an OSError
15829
is thrown.
15830
15831
This function will only be defined if an implementation is
15832
available for this system.
15833
15834
shutil.get_terminal_size is the high-level function which should
15835
normally be used, os.get_terminal_size is the low-level implementation.
15836
[clinic start generated code]*/
15837
15838
static PyObject *
15839
os_get_terminal_size_impl(PyObject *module, int fd)
15840
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15841
0
{
15842
0
    int columns, lines;
15843
0
    PyObject *termsize;
15844
15845
    /* Under some conditions stdout may not be connected and
15846
     * fileno(stdout) may point to an invalid file descriptor. For example
15847
     * GUI apps don't have valid standard streams by default.
15848
     *
15849
     * If this happens, and the optional fd argument is not present,
15850
     * the ioctl below will fail returning EBADF. This is what we want.
15851
     */
15852
15853
0
#ifdef TERMSIZE_USE_IOCTL
15854
0
    {
15855
0
        struct winsize w;
15856
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15857
0
            return PyErr_SetFromErrno(PyExc_OSError);
15858
0
        columns = w.ws_col;
15859
0
        lines = w.ws_row;
15860
0
    }
15861
0
#endif /* TERMSIZE_USE_IOCTL */
15862
15863
#ifdef TERMSIZE_USE_CONIO
15864
    {
15865
        HANDLE handle;
15866
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15867
        handle = _Py_get_osfhandle(fd);
15868
        if (handle == INVALID_HANDLE_VALUE)
15869
            return NULL;
15870
15871
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15872
            return PyErr_SetFromWindowsErr(0);
15873
15874
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15875
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15876
    }
15877
#endif /* TERMSIZE_USE_CONIO */
15878
15879
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15880
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15881
0
    if (termsize == NULL)
15882
0
        return NULL;
15883
15884
0
    int pos = 0;
15885
15886
0
#define SET_TERMSIZE(CALL)                                   \
15887
0
    do {                                                     \
15888
0
        PyObject *item = (CALL);                             \
15889
0
        if (item == NULL) {                                  \
15890
0
            Py_DECREF(termsize);                             \
15891
0
            return NULL;                                     \
15892
0
        }                                                    \
15893
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15894
0
    } while(0)
15895
15896
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15897
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15898
0
#undef SET_TERMSIZE
15899
15900
0
    return termsize;
15901
0
}
15902
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15903
15904
/*[clinic input]
15905
os.cpu_count
15906
15907
Return the number of logical CPUs in the system.
15908
15909
Return None if indeterminable.
15910
[clinic start generated code]*/
15911
15912
static PyObject *
15913
os_cpu_count_impl(PyObject *module)
15914
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15915
0
{
15916
0
    const PyConfig *config = _Py_GetConfig();
15917
0
    if (config->cpu_count > 0) {
15918
0
        return PyLong_FromLong(config->cpu_count);
15919
0
    }
15920
15921
0
    int ncpu = 0;
15922
#ifdef MS_WINDOWS
15923
# ifdef MS_WINDOWS_DESKTOP
15924
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15925
# else
15926
    ncpu = 0;
15927
# endif
15928
15929
#elif defined(__hpux)
15930
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15931
15932
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15933
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15934
15935
#elif defined(__VXWORKS__)
15936
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15937
15938
#elif defined(__DragonFly__) || \
15939
      defined(__OpenBSD__)   || \
15940
      defined(__FreeBSD__)   || \
15941
      defined(__NetBSD__)    || \
15942
      defined(__APPLE__)
15943
    ncpu = 0;
15944
    size_t len = sizeof(ncpu);
15945
    int mib[2] = {CTL_HW, HW_NCPU};
15946
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15947
        ncpu = 0;
15948
    }
15949
#endif
15950
15951
0
    if (ncpu < 1) {
15952
0
        Py_RETURN_NONE;
15953
0
    }
15954
0
    return PyLong_FromLong(ncpu);
15955
0
}
15956
15957
15958
/*[clinic input]
15959
os.get_inheritable -> bool
15960
15961
    fd: int
15962
    /
15963
15964
Get the close-on-exe flag of the specified file descriptor.
15965
[clinic start generated code]*/
15966
15967
static int
15968
os_get_inheritable_impl(PyObject *module, int fd)
15969
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15970
0
{
15971
0
    int return_value;
15972
0
    _Py_BEGIN_SUPPRESS_IPH
15973
0
    return_value = _Py_get_inheritable(fd);
15974
0
    _Py_END_SUPPRESS_IPH
15975
0
    return return_value;
15976
0
}
15977
15978
15979
/*[clinic input]
15980
os.set_inheritable
15981
    fd: int
15982
    inheritable: int
15983
    /
15984
15985
Set the inheritable flag of the specified file descriptor.
15986
[clinic start generated code]*/
15987
15988
static PyObject *
15989
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15990
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15991
0
{
15992
0
    int result;
15993
15994
0
    _Py_BEGIN_SUPPRESS_IPH
15995
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15996
0
    _Py_END_SUPPRESS_IPH
15997
0
    if (result < 0)
15998
0
        return NULL;
15999
0
    Py_RETURN_NONE;
16000
0
}
16001
16002
16003
#ifdef MS_WINDOWS
16004
#ifndef HANDLE_FLAG_INHERIT
16005
#define HANDLE_FLAG_INHERIT 0x00000001
16006
#endif
16007
16008
/*[clinic input]
16009
os.get_handle_inheritable -> bool
16010
    handle: intptr_t
16011
    /
16012
16013
Get the close-on-exe flag of the specified file descriptor.
16014
[clinic start generated code]*/
16015
16016
static int
16017
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16018
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16019
{
16020
    DWORD flags;
16021
16022
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16023
        PyErr_SetFromWindowsErr(0);
16024
        return -1;
16025
    }
16026
16027
    return flags & HANDLE_FLAG_INHERIT;
16028
}
16029
16030
16031
/*[clinic input]
16032
os.set_handle_inheritable
16033
    handle: intptr_t
16034
    inheritable: bool
16035
    /
16036
16037
Set the inheritable flag of the specified handle.
16038
[clinic start generated code]*/
16039
16040
static PyObject *
16041
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16042
                               int inheritable)
16043
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16044
{
16045
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16046
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16047
        PyErr_SetFromWindowsErr(0);
16048
        return NULL;
16049
    }
16050
    Py_RETURN_NONE;
16051
}
16052
#endif /* MS_WINDOWS */
16053
16054
/*[clinic input]
16055
os.get_blocking -> bool
16056
    fd: int
16057
    /
16058
16059
Get the blocking mode of the file descriptor.
16060
16061
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16062
[clinic start generated code]*/
16063
16064
static int
16065
os_get_blocking_impl(PyObject *module, int fd)
16066
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16067
0
{
16068
0
    int blocking;
16069
16070
0
    _Py_BEGIN_SUPPRESS_IPH
16071
0
    blocking = _Py_get_blocking(fd);
16072
0
    _Py_END_SUPPRESS_IPH
16073
0
    return blocking;
16074
0
}
16075
16076
/*[clinic input]
16077
os.set_blocking
16078
    fd: int
16079
    blocking: bool
16080
    /
16081
16082
Set the blocking mode of the specified file descriptor.
16083
16084
Set the O_NONBLOCK flag if blocking is False,
16085
clear the O_NONBLOCK flag otherwise.
16086
[clinic start generated code]*/
16087
16088
static PyObject *
16089
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16090
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16091
0
{
16092
0
    int result;
16093
16094
0
    _Py_BEGIN_SUPPRESS_IPH
16095
0
    result = _Py_set_blocking(fd, blocking);
16096
0
    _Py_END_SUPPRESS_IPH
16097
0
    if (result < 0)
16098
0
        return NULL;
16099
0
    Py_RETURN_NONE;
16100
0
}
16101
16102
16103
/*[clinic input]
16104
class os.DirEntry "DirEntry *" "DirEntryType"
16105
[clinic start generated code]*/
16106
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16107
16108
typedef struct {
16109
    PyObject_HEAD
16110
    PyObject *name;
16111
    PyObject *path;
16112
    PyObject *stat;
16113
    PyObject *lstat;
16114
#ifdef MS_WINDOWS
16115
    struct _Py_stat_struct win32_lstat;
16116
    uint64_t win32_file_index;
16117
    uint64_t win32_file_index_high;
16118
    int got_file_index;
16119
#else /* POSIX */
16120
#ifdef HAVE_DIRENT_D_TYPE
16121
    unsigned char d_type;
16122
#endif
16123
    ino_t d_ino;
16124
    int dir_fd;
16125
#endif
16126
} DirEntry;
16127
16128
234k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16129
16130
static void
16131
DirEntry_dealloc(PyObject *op)
16132
234k
{
16133
234k
    DirEntry *entry = DirEntry_CAST(op);
16134
234k
    PyTypeObject *tp = Py_TYPE(entry);
16135
234k
    Py_XDECREF(entry->name);
16136
234k
    Py_XDECREF(entry->path);
16137
234k
    Py_XDECREF(entry->stat);
16138
234k
    Py_XDECREF(entry->lstat);
16139
234k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16140
234k
    free_func(entry);
16141
234k
    Py_DECREF(tp);
16142
234k
}
16143
16144
/* Forward reference */
16145
static int
16146
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16147
                   int follow_symlinks, unsigned short mode_bits);
16148
16149
/*[clinic input]
16150
os.DirEntry.is_symlink -> bool
16151
    defining_class: defining_class
16152
    /
16153
16154
Return True if the entry is a symbolic link; cached per entry.
16155
[clinic start generated code]*/
16156
16157
static int
16158
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16159
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16160
0
{
16161
#ifdef MS_WINDOWS
16162
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16163
#elif defined(HAVE_DIRENT_D_TYPE)
16164
    /* POSIX */
16165
0
    if (self->d_type != DT_UNKNOWN)
16166
0
        return self->d_type == DT_LNK;
16167
0
    else
16168
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16169
#else
16170
    /* POSIX without d_type */
16171
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16172
#endif
16173
0
}
16174
16175
/*[clinic input]
16176
os.DirEntry.is_junction -> bool
16177
16178
Return True if the entry is a junction; cached per entry.
16179
[clinic start generated code]*/
16180
16181
static int
16182
os_DirEntry_is_junction_impl(DirEntry *self)
16183
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16184
0
{
16185
#ifdef MS_WINDOWS
16186
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16187
#else
16188
0
    return 0;
16189
0
#endif
16190
0
}
16191
16192
static PyObject *
16193
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16194
209k
{
16195
209k
    int result;
16196
209k
    STRUCT_STAT st;
16197
209k
    PyObject *ub;
16198
16199
#ifdef MS_WINDOWS
16200
    if (!PyUnicode_FSDecoder(self->path, &ub))
16201
        return NULL;
16202
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16203
    Py_DECREF(ub);
16204
#else /* POSIX */
16205
209k
    if (!PyUnicode_FSConverter(self->path, &ub))
16206
0
        return NULL;
16207
209k
    const char *path = PyBytes_AS_STRING(ub);
16208
209k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16209
209k
#ifdef HAVE_FSTATAT
16210
209k
      if (HAVE_FSTATAT_RUNTIME) {
16211
209k
        Py_BEGIN_ALLOW_THREADS
16212
209k
        result = fstatat(self->dir_fd, path, &st,
16213
209k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16214
209k
        Py_END_ALLOW_THREADS
16215
209k
      } else
16216
16217
0
#endif /* HAVE_FSTATAT */
16218
0
      {
16219
0
        Py_DECREF(ub);
16220
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16221
0
        return NULL;
16222
0
      }
16223
209k
    }
16224
0
    else
16225
0
#endif
16226
0
    {
16227
0
        Py_BEGIN_ALLOW_THREADS
16228
0
        if (follow_symlinks) {
16229
0
            result = STAT(path, &st);
16230
0
        }
16231
0
        else {
16232
0
            result = LSTAT(path, &st);
16233
0
        }
16234
0
        Py_END_ALLOW_THREADS
16235
0
    }
16236
16237
209k
    int saved_errno = errno;
16238
#if defined(MS_WINDOWS)
16239
    PyMem_Free(path);
16240
#else
16241
209k
    Py_DECREF(ub);
16242
209k
#endif
16243
16244
209k
    if (result != 0) {
16245
0
        errno = saved_errno;
16246
0
        path_object_error(self->path);
16247
0
        return NULL;
16248
0
    }
16249
16250
209k
    return _pystat_fromstructstat(module, &st);
16251
209k
}
16252
16253
static PyObject *
16254
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16255
209k
{
16256
209k
    if (!self->lstat) {
16257
209k
        PyObject *module = PyType_GetModule(defining_class);
16258
#ifdef MS_WINDOWS
16259
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16260
#else /* POSIX */
16261
209k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16262
209k
#endif
16263
209k
    }
16264
209k
    return Py_XNewRef(self->lstat);
16265
209k
}
16266
16267
/*[clinic input]
16268
os.DirEntry.stat
16269
    defining_class: defining_class
16270
    /
16271
    *
16272
    follow_symlinks: bool = True
16273
16274
Return stat_result object for the entry; cached per entry.
16275
[clinic start generated code]*/
16276
16277
static PyObject *
16278
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16279
                      int follow_symlinks)
16280
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16281
209k
{
16282
209k
    if (!follow_symlinks) {
16283
209k
        return DirEntry_get_lstat(defining_class, self);
16284
209k
    }
16285
16286
0
    if (!self->stat) {
16287
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16288
0
        if (result == -1) {
16289
0
            return NULL;
16290
0
        }
16291
0
        if (result) {
16292
0
            PyObject *module = PyType_GetModule(defining_class);
16293
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16294
0
        }
16295
0
        else {
16296
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16297
0
        }
16298
0
    }
16299
16300
0
    return Py_XNewRef(self->stat);
16301
0
}
16302
16303
/* Set exception and return -1 on error, 0 for False, 1 for True */
16304
static int
16305
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16306
                   int follow_symlinks, unsigned short mode_bits)
16307
234k
{
16308
234k
    PyObject *stat = NULL;
16309
234k
    PyObject *st_mode = NULL;
16310
234k
    long mode;
16311
234k
    int result;
16312
234k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16313
234k
    int is_symlink;
16314
234k
    int need_stat;
16315
234k
#endif
16316
#ifdef MS_WINDOWS
16317
    unsigned long dir_bits;
16318
#endif
16319
16320
#ifdef MS_WINDOWS
16321
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16322
    need_stat = follow_symlinks && is_symlink;
16323
#elif defined(HAVE_DIRENT_D_TYPE)
16324
234k
    is_symlink = self->d_type == DT_LNK;
16325
234k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16326
234k
#endif
16327
16328
234k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16329
234k
    if (need_stat) {
16330
0
#endif
16331
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16332
0
        if (!stat) {
16333
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16334
                /* If file doesn't exist (anymore), then return False
16335
                   (i.e., say it's not a file/directory) */
16336
0
                PyErr_Clear();
16337
0
                return 0;
16338
0
            }
16339
0
            goto error;
16340
0
        }
16341
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16342
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16343
0
        if (!st_mode)
16344
0
            goto error;
16345
16346
0
        mode = PyLong_AsLong(st_mode);
16347
0
        if (mode == -1 && PyErr_Occurred())
16348
0
            goto error;
16349
0
        Py_CLEAR(st_mode);
16350
0
        Py_CLEAR(stat);
16351
0
        result = (mode & S_IFMT) == mode_bits;
16352
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16353
0
    }
16354
234k
    else if (is_symlink) {
16355
0
        assert(mode_bits != S_IFLNK);
16356
0
        result = 0;
16357
0
    }
16358
234k
    else {
16359
234k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16360
#ifdef MS_WINDOWS
16361
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16362
        if (mode_bits == S_IFDIR)
16363
            result = dir_bits != 0;
16364
        else
16365
            result = dir_bits == 0;
16366
#else /* POSIX */
16367
234k
        if (mode_bits == S_IFDIR)
16368
234k
            result = self->d_type == DT_DIR;
16369
0
        else
16370
0
            result = self->d_type == DT_REG;
16371
234k
#endif
16372
234k
    }
16373
234k
#endif
16374
16375
234k
    return result;
16376
16377
0
error:
16378
0
    Py_XDECREF(st_mode);
16379
0
    Py_XDECREF(stat);
16380
0
    return -1;
16381
234k
}
16382
16383
/*[clinic input]
16384
os.DirEntry.is_dir -> bool
16385
    defining_class: defining_class
16386
    /
16387
    *
16388
    follow_symlinks: bool = True
16389
16390
Return True if the entry is a directory; cached per entry.
16391
[clinic start generated code]*/
16392
16393
static int
16394
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16395
                        int follow_symlinks)
16396
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16397
234k
{
16398
234k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16399
234k
}
16400
16401
/*[clinic input]
16402
os.DirEntry.is_file -> bool
16403
    defining_class: defining_class
16404
    /
16405
    *
16406
    follow_symlinks: bool = True
16407
16408
Return True if the entry is a file; cached per entry.
16409
[clinic start generated code]*/
16410
16411
static int
16412
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16413
                         int follow_symlinks)
16414
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16415
0
{
16416
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16417
0
}
16418
16419
/*[clinic input]
16420
os.DirEntry.inode
16421
16422
Return inode of the entry; cached per entry.
16423
[clinic start generated code]*/
16424
16425
static PyObject *
16426
os_DirEntry_inode_impl(DirEntry *self)
16427
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16428
0
{
16429
#ifdef MS_WINDOWS
16430
    if (!self->got_file_index) {
16431
        PyObject *unicode;
16432
        STRUCT_STAT stat;
16433
        int result;
16434
16435
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16436
            return NULL;
16437
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16438
        Py_DECREF(unicode);
16439
        result = LSTAT(path, &stat);
16440
16441
        int saved_errno = errno;
16442
        PyMem_Free(path);
16443
16444
        if (result != 0) {
16445
            errno = saved_errno;
16446
            return path_object_error(self->path);
16447
        }
16448
16449
        self->win32_file_index = stat.st_ino;
16450
        self->win32_file_index_high = stat.st_ino_high;
16451
        self->got_file_index = 1;
16452
    }
16453
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16454
#else /* POSIX */
16455
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16456
0
                  "DirEntry.d_ino is larger than unsigned long long");
16457
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16458
0
#endif
16459
0
}
16460
16461
static PyObject *
16462
DirEntry_repr(PyObject *op)
16463
0
{
16464
0
    DirEntry *self = DirEntry_CAST(op);
16465
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16466
0
}
16467
16468
/*[clinic input]
16469
os.DirEntry.__fspath__
16470
16471
Returns the path for the entry.
16472
[clinic start generated code]*/
16473
16474
static PyObject *
16475
os_DirEntry___fspath___impl(DirEntry *self)
16476
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16477
0
{
16478
0
    return Py_NewRef(self->path);
16479
0
}
16480
16481
static PyMemberDef DirEntry_members[] = {
16482
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16483
     "the entry's base filename, relative to scandir() \"path\" argument"},
16484
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16485
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16486
    {NULL}
16487
};
16488
16489
#include "clinic/posixmodule.c.h"
16490
16491
static PyMethodDef DirEntry_methods[] = {
16492
    OS_DIRENTRY_IS_DIR_METHODDEF
16493
    OS_DIRENTRY_IS_FILE_METHODDEF
16494
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16495
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16496
    OS_DIRENTRY_STAT_METHODDEF
16497
    OS_DIRENTRY_INODE_METHODDEF
16498
    OS_DIRENTRY___FSPATH___METHODDEF
16499
    {"__class_getitem__",       Py_GenericAlias,
16500
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16501
    {NULL}
16502
};
16503
16504
static PyType_Slot DirEntryType_slots[] = {
16505
    {Py_tp_dealloc, DirEntry_dealloc},
16506
    {Py_tp_repr, DirEntry_repr},
16507
    {Py_tp_methods, DirEntry_methods},
16508
    {Py_tp_members, DirEntry_members},
16509
    {0, 0},
16510
};
16511
16512
static PyType_Spec DirEntryType_spec = {
16513
    .name = MODNAME ".DirEntry",
16514
    .basicsize = sizeof(DirEntry),
16515
    .flags = (
16516
        Py_TPFLAGS_DEFAULT
16517
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16518
        | Py_TPFLAGS_IMMUTABLETYPE
16519
    ),
16520
    .slots = DirEntryType_slots
16521
};
16522
16523
16524
#ifdef MS_WINDOWS
16525
16526
static wchar_t *
16527
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16528
{
16529
    Py_ssize_t path_len;
16530
    Py_ssize_t size;
16531
    wchar_t *result;
16532
    wchar_t ch;
16533
16534
    if (!path_wide) { /* Default arg: "." */
16535
        path_wide = L".";
16536
        path_len = 1;
16537
    }
16538
    else {
16539
        path_len = wcslen(path_wide);
16540
    }
16541
16542
    /* The +1's are for the path separator and the NUL */
16543
    size = path_len + 1 + wcslen(filename) + 1;
16544
    result = PyMem_New(wchar_t, size);
16545
    if (!result) {
16546
        PyErr_NoMemory();
16547
        return NULL;
16548
    }
16549
    wcscpy(result, path_wide);
16550
    if (path_len > 0) {
16551
        ch = result[path_len - 1];
16552
        if (ch != SEP && ch != ALTSEP && ch != L':')
16553
            result[path_len++] = SEP;
16554
        wcscpy(result + path_len, filename);
16555
    }
16556
    return result;
16557
}
16558
16559
static PyObject *
16560
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16561
{
16562
    DirEntry *entry;
16563
    BY_HANDLE_FILE_INFORMATION file_info;
16564
    ULONG reparse_tag;
16565
    wchar_t *joined_path;
16566
16567
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16568
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16569
    if (!entry)
16570
        return NULL;
16571
    entry->name = NULL;
16572
    entry->path = NULL;
16573
    entry->stat = NULL;
16574
    entry->lstat = NULL;
16575
    entry->got_file_index = 0;
16576
16577
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16578
    if (!entry->name)
16579
        goto error;
16580
    int return_bytes = path->wide && PyBytes_Check(path->object);
16581
    if (return_bytes) {
16582
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16583
        if (!entry->name)
16584
            goto error;
16585
    }
16586
16587
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16588
    if (!joined_path)
16589
        goto error;
16590
16591
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16592
    PyMem_Free(joined_path);
16593
    if (!entry->path)
16594
        goto error;
16595
    if (return_bytes) {
16596
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16597
        if (!entry->path)
16598
            goto error;
16599
    }
16600
16601
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16602
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16603
16604
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16605
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16606
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16607
16608
    return (PyObject *)entry;
16609
16610
error:
16611
    Py_DECREF(entry);
16612
    return NULL;
16613
}
16614
16615
#else /* POSIX */
16616
16617
static char *
16618
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16619
0
{
16620
0
    Py_ssize_t path_len;
16621
0
    Py_ssize_t size;
16622
0
    char *result;
16623
16624
0
    if (!path_narrow) { /* Default arg: "." */
16625
0
        path_narrow = ".";
16626
0
        path_len = 1;
16627
0
    }
16628
0
    else {
16629
0
        path_len = strlen(path_narrow);
16630
0
    }
16631
16632
0
    if (filename_len == -1)
16633
0
        filename_len = strlen(filename);
16634
16635
    /* The +1's are for the path separator and the NUL */
16636
0
    size = path_len + 1 + filename_len + 1;
16637
0
    result = PyMem_New(char, size);
16638
0
    if (!result) {
16639
0
        PyErr_NoMemory();
16640
0
        return NULL;
16641
0
    }
16642
0
    strcpy(result, path_narrow);
16643
0
    if (path_len > 0 && result[path_len - 1] != '/')
16644
0
        result[path_len++] = '/';
16645
0
    strcpy(result + path_len, filename);
16646
0
    return result;
16647
0
}
16648
16649
static PyObject *
16650
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16651
                         Py_ssize_t name_len, ino_t d_ino
16652
#ifdef HAVE_DIRENT_D_TYPE
16653
                         , unsigned char d_type
16654
#endif
16655
                         )
16656
234k
{
16657
234k
    DirEntry *entry;
16658
234k
    char *joined_path;
16659
16660
234k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16661
234k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16662
234k
    if (!entry)
16663
0
        return NULL;
16664
234k
    entry->name = NULL;
16665
234k
    entry->path = NULL;
16666
234k
    entry->stat = NULL;
16667
234k
    entry->lstat = NULL;
16668
16669
234k
    if (path->is_fd) {
16670
234k
        entry->dir_fd = path->fd;
16671
234k
        joined_path = NULL;
16672
234k
    }
16673
0
    else {
16674
0
        entry->dir_fd = DEFAULT_DIR_FD;
16675
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16676
0
        if (!joined_path)
16677
0
            goto error;
16678
0
    }
16679
16680
234k
    if (!path->narrow || !PyBytes_Check(path->object)) {
16681
234k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16682
234k
        if (joined_path)
16683
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16684
234k
    }
16685
0
    else {
16686
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16687
0
        if (joined_path)
16688
0
            entry->path = PyBytes_FromString(joined_path);
16689
0
    }
16690
234k
    PyMem_Free(joined_path);
16691
234k
    if (!entry->name)
16692
0
        goto error;
16693
16694
234k
    if (path->is_fd) {
16695
234k
        entry->path = Py_NewRef(entry->name);
16696
234k
    }
16697
0
    else if (!entry->path)
16698
0
        goto error;
16699
16700
234k
#ifdef HAVE_DIRENT_D_TYPE
16701
234k
    entry->d_type = d_type;
16702
234k
#endif
16703
234k
    entry->d_ino = d_ino;
16704
16705
234k
    return (PyObject *)entry;
16706
16707
0
error:
16708
0
    Py_XDECREF(entry);
16709
0
    return NULL;
16710
234k
}
16711
16712
#endif
16713
16714
16715
typedef struct {
16716
    PyObject_HEAD
16717
    path_t path;
16718
#ifdef MS_WINDOWS
16719
    HANDLE handle;
16720
    WIN32_FIND_DATAW file_data;
16721
    int first_time;
16722
#else /* POSIX */
16723
    DIR *dirp;
16724
#endif
16725
#ifdef HAVE_FDOPENDIR
16726
    int fd;
16727
#endif
16728
} ScandirIterator;
16729
16730
876k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16731
16732
#ifdef MS_WINDOWS
16733
16734
static int
16735
ScandirIterator_is_closed(ScandirIterator *iterator)
16736
{
16737
    return iterator->handle == INVALID_HANDLE_VALUE;
16738
}
16739
16740
static void
16741
ScandirIterator_closedir(ScandirIterator *iterator)
16742
{
16743
    HANDLE handle = iterator->handle;
16744
16745
    if (handle == INVALID_HANDLE_VALUE)
16746
        return;
16747
16748
    iterator->handle = INVALID_HANDLE_VALUE;
16749
    Py_BEGIN_ALLOW_THREADS
16750
    FindClose(handle);
16751
    Py_END_ALLOW_THREADS
16752
}
16753
16754
static PyObject *
16755
ScandirIterator_iternext(PyObject *op)
16756
{
16757
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16758
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16759
    BOOL success;
16760
    PyObject *entry;
16761
16762
    /* Happens if the iterator is iterated twice, or closed explicitly */
16763
    if (iterator->handle == INVALID_HANDLE_VALUE)
16764
        return NULL;
16765
16766
    while (1) {
16767
        if (!iterator->first_time) {
16768
            Py_BEGIN_ALLOW_THREADS
16769
            success = FindNextFileW(iterator->handle, file_data);
16770
            Py_END_ALLOW_THREADS
16771
            if (!success) {
16772
                /* Error or no more files */
16773
                if (GetLastError() != ERROR_NO_MORE_FILES)
16774
                    path_error(&iterator->path);
16775
                break;
16776
            }
16777
        }
16778
        iterator->first_time = 0;
16779
16780
        /* Skip over . and .. */
16781
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16782
            wcscmp(file_data->cFileName, L"..") != 0)
16783
        {
16784
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16785
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16786
            if (!entry)
16787
                break;
16788
            return entry;
16789
        }
16790
16791
        /* Loop till we get a non-dot directory or finish iterating */
16792
    }
16793
16794
    /* Error or no more files */
16795
    ScandirIterator_closedir(iterator);
16796
    return NULL;
16797
}
16798
16799
#else /* POSIX */
16800
16801
static int
16802
ScandirIterator_is_closed(ScandirIterator *iterator)
16803
213k
{
16804
213k
    return !iterator->dirp;
16805
213k
}
16806
16807
static void
16808
ScandirIterator_closedir(ScandirIterator *iterator)
16809
427k
{
16810
427k
    DIR *dirp = iterator->dirp;
16811
16812
427k
    if (!dirp)
16813
213k
        return;
16814
16815
213k
    iterator->dirp = NULL;
16816
213k
    Py_BEGIN_ALLOW_THREADS
16817
213k
#ifdef HAVE_FDOPENDIR
16818
213k
    if (iterator->path.is_fd) {
16819
213k
        rewinddir(dirp);
16820
213k
    }
16821
213k
#endif
16822
213k
    closedir(dirp);
16823
213k
    Py_END_ALLOW_THREADS
16824
213k
    return;
16825
427k
}
16826
16827
static PyObject *
16828
ScandirIterator_iternext(PyObject *op)
16829
448k
{
16830
448k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16831
448k
    struct dirent *direntp;
16832
448k
    Py_ssize_t name_len;
16833
448k
    int is_dot;
16834
448k
    PyObject *entry;
16835
16836
    /* Happens if the iterator is iterated twice, or closed explicitly */
16837
448k
    if (!iterator->dirp)
16838
0
        return NULL;
16839
16840
876k
    while (1) {
16841
876k
        errno = 0;
16842
876k
        Py_BEGIN_ALLOW_THREADS
16843
876k
        direntp = readdir(iterator->dirp);
16844
876k
        Py_END_ALLOW_THREADS
16845
16846
876k
        if (!direntp) {
16847
            /* Error or no more files */
16848
213k
            if (errno != 0)
16849
0
                path_error(&iterator->path);
16850
213k
            break;
16851
213k
        }
16852
16853
        /* Skip over . and .. */
16854
662k
        name_len = NAMLEN(direntp);
16855
662k
        is_dot = direntp->d_name[0] == '.' &&
16856
429k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16857
662k
        if (!is_dot) {
16858
234k
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16859
234k
            entry = DirEntry_from_posix_info(module,
16860
234k
                                             &iterator->path, direntp->d_name,
16861
234k
                                             name_len, direntp->d_ino
16862
234k
#ifdef HAVE_DIRENT_D_TYPE
16863
234k
                                             , direntp->d_type
16864
234k
#endif
16865
234k
                                            );
16866
234k
            if (!entry)
16867
0
                break;
16868
234k
            return entry;
16869
234k
        }
16870
16871
        /* Loop till we get a non-dot directory or finish iterating */
16872
662k
    }
16873
16874
    /* Error or no more files */
16875
213k
    ScandirIterator_closedir(iterator);
16876
213k
    return NULL;
16877
448k
}
16878
16879
#endif
16880
16881
static PyObject *
16882
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16883
0
{
16884
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16885
0
    ScandirIterator_closedir(self);
16886
0
    Py_RETURN_NONE;
16887
0
}
16888
16889
static PyObject *
16890
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16891
213k
{
16892
213k
    return Py_NewRef(self);
16893
213k
}
16894
16895
static PyObject *
16896
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16897
213k
{
16898
213k
    ScandirIterator *self = ScandirIterator_CAST(op);
16899
213k
    ScandirIterator_closedir(self);
16900
213k
    Py_RETURN_NONE;
16901
213k
}
16902
16903
static void
16904
ScandirIterator_finalize(PyObject *op)
16905
213k
{
16906
213k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16907
    /* Save the current exception, if any. */
16908
213k
    PyObject *exc = PyErr_GetRaisedException();
16909
16910
213k
    if (!ScandirIterator_is_closed(iterator)) {
16911
0
        ScandirIterator_closedir(iterator);
16912
16913
0
        if (PyErr_ResourceWarning(op, 1,
16914
0
                                  "unclosed scandir iterator %R", iterator))
16915
0
        {
16916
            /* Spurious errors can appear at shutdown */
16917
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16918
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16919
0
                                       "scandir iterator %R", iterator);
16920
0
            }
16921
0
        }
16922
0
    }
16923
16924
213k
    path_cleanup(&iterator->path);
16925
16926
    /* Restore the saved exception. */
16927
213k
    PyErr_SetRaisedException(exc);
16928
213k
}
16929
16930
static void
16931
ScandirIterator_dealloc(PyObject *op)
16932
213k
{
16933
213k
    PyTypeObject *tp = Py_TYPE(op);
16934
213k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16935
0
        return;
16936
16937
213k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16938
213k
    free_func(op);
16939
213k
    Py_DECREF(tp);
16940
213k
}
16941
16942
static PyMethodDef ScandirIterator_methods[] = {
16943
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16944
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16945
    {"close", ScandirIterator_close, METH_NOARGS},
16946
    {NULL}
16947
};
16948
16949
static PyType_Slot ScandirIteratorType_slots[] = {
16950
    {Py_tp_dealloc, ScandirIterator_dealloc},
16951
    {Py_tp_finalize, ScandirIterator_finalize},
16952
    {Py_tp_iter, PyObject_SelfIter},
16953
    {Py_tp_iternext, ScandirIterator_iternext},
16954
    {Py_tp_methods, ScandirIterator_methods},
16955
    {0, 0},
16956
};
16957
16958
static PyType_Spec ScandirIteratorType_spec = {
16959
    .name = MODNAME ".ScandirIterator",
16960
    .basicsize = sizeof(ScandirIterator),
16961
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16962
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16963
    .flags = (
16964
        Py_TPFLAGS_DEFAULT
16965
        | Py_TPFLAGS_HAVE_FINALIZE
16966
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16967
        | Py_TPFLAGS_IMMUTABLETYPE
16968
    ),
16969
    .slots = ScandirIteratorType_slots
16970
};
16971
16972
/*[clinic input]
16973
os.scandir
16974
16975
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16976
16977
Return an iterator of DirEntry objects for given path.
16978
16979
path can be specified as either str, bytes, or a path-like object.  If path
16980
is bytes, the names of yielded DirEntry objects will also be bytes; in
16981
all other circumstances they will be str.
16982
16983
If path is None, uses the path='.'.
16984
[clinic start generated code]*/
16985
16986
static PyObject *
16987
os_scandir_impl(PyObject *module, path_t *path)
16988
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16989
213k
{
16990
213k
    ScandirIterator *iterator;
16991
#ifdef MS_WINDOWS
16992
    wchar_t *path_strW;
16993
#else
16994
213k
    const char *path_str;
16995
213k
#ifdef HAVE_FDOPENDIR
16996
213k
    int fd = -1;
16997
213k
#endif
16998
213k
#endif
16999
17000
213k
    if (PySys_Audit("os.scandir", "O",
17001
213k
                    path->object ? path->object : Py_None) < 0) {
17002
0
        return NULL;
17003
0
    }
17004
17005
213k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
17006
213k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
17007
213k
    if (!iterator)
17008
0
        return NULL;
17009
17010
#ifdef MS_WINDOWS
17011
    iterator->handle = INVALID_HANDLE_VALUE;
17012
#else
17013
213k
    iterator->dirp = NULL;
17014
213k
#endif
17015
17016
    /* Move the ownership to iterator->path */
17017
213k
    memcpy(&iterator->path, path, sizeof(path_t));
17018
213k
    memset(path, 0, sizeof(path_t));
17019
17020
#ifdef MS_WINDOWS
17021
    iterator->first_time = 1;
17022
17023
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
17024
    if (!path_strW)
17025
        goto error;
17026
17027
    Py_BEGIN_ALLOW_THREADS
17028
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17029
    Py_END_ALLOW_THREADS
17030
17031
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17032
        path_error(&iterator->path);
17033
        PyMem_Free(path_strW);
17034
        goto error;
17035
    }
17036
    PyMem_Free(path_strW);
17037
#else /* POSIX */
17038
213k
    errno = 0;
17039
213k
#ifdef HAVE_FDOPENDIR
17040
213k
    if (iterator->path.is_fd) {
17041
213k
      if (HAVE_FDOPENDIR_RUNTIME) {
17042
        /* closedir() closes the FD, so we duplicate it */
17043
213k
        fd = _Py_dup(iterator->path.fd);
17044
213k
        if (fd == -1)
17045
0
            goto error;
17046
17047
213k
        Py_BEGIN_ALLOW_THREADS
17048
213k
        iterator->dirp = fdopendir(fd);
17049
213k
        Py_END_ALLOW_THREADS
17050
213k
      } else {
17051
0
        PyErr_SetString(PyExc_TypeError,
17052
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17053
0
        return NULL;
17054
0
      }
17055
213k
    }
17056
0
    else
17057
0
#endif
17058
0
    {
17059
0
        if (iterator->path.narrow)
17060
0
            path_str = iterator->path.narrow;
17061
0
        else
17062
0
            path_str = ".";
17063
17064
0
        Py_BEGIN_ALLOW_THREADS
17065
0
        iterator->dirp = opendir(path_str);
17066
0
        Py_END_ALLOW_THREADS
17067
0
    }
17068
17069
213k
    if (!iterator->dirp) {
17070
0
        path_error(&iterator->path);
17071
0
#ifdef HAVE_FDOPENDIR
17072
0
        if (fd != -1) {
17073
0
            Py_BEGIN_ALLOW_THREADS
17074
0
            close(fd);
17075
0
            Py_END_ALLOW_THREADS
17076
0
        }
17077
0
#endif
17078
0
        goto error;
17079
0
    }
17080
213k
#endif
17081
17082
213k
    return (PyObject *)iterator;
17083
17084
0
error:
17085
0
    Py_DECREF(iterator);
17086
0
    return NULL;
17087
213k
}
17088
17089
/*
17090
    Return the file system path representation of the object.
17091
17092
    If the object is str or bytes, then allow it to pass through with
17093
    an incremented refcount. If the object defines __fspath__(), then
17094
    return the result of that method. All other types raise a TypeError.
17095
*/
17096
PyObject *
17097
PyOS_FSPath(PyObject *path)
17098
1.82M
{
17099
    /* For error message reasons, this function is manually inlined in
17100
       path_converter(). */
17101
1.82M
    PyObject *func = NULL;
17102
1.82M
    PyObject *path_repr = NULL;
17103
17104
1.82M
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17105
1.82M
        return Py_NewRef(path);
17106
1.82M
    }
17107
17108
61
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17109
61
    if ((NULL == func) || (func == Py_None)) {
17110
0
        return PyErr_Format(PyExc_TypeError,
17111
0
                            "expected str, bytes or os.PathLike object, "
17112
0
                            "not %.200s",
17113
0
                            _PyType_Name(Py_TYPE(path)));
17114
0
    }
17115
17116
61
    path_repr = _PyObject_CallNoArgs(func);
17117
61
    Py_DECREF(func);
17118
61
    if (NULL == path_repr) {
17119
0
        return NULL;
17120
0
    }
17121
17122
61
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17123
0
        PyErr_Format(PyExc_TypeError,
17124
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17125
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17126
0
                     _PyType_Name(Py_TYPE(path_repr)));
17127
0
        Py_DECREF(path_repr);
17128
0
        return NULL;
17129
0
    }
17130
17131
61
    return path_repr;
17132
61
}
17133
17134
/*[clinic input]
17135
@permit_long_docstring_body
17136
os.fspath
17137
17138
    path: object
17139
17140
Return the file system path representation of the object.
17141
17142
If the object is str or bytes, then allow it to pass through as-is. If the
17143
object defines __fspath__(), then return the result of that method. All other
17144
types raise a TypeError.
17145
[clinic start generated code]*/
17146
17147
static PyObject *
17148
os_fspath_impl(PyObject *module, PyObject *path)
17149
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
17150
1.36M
{
17151
1.36M
    return PyOS_FSPath(path);
17152
1.36M
}
17153
17154
#ifdef HAVE_GETRANDOM_SYSCALL
17155
/*[clinic input]
17156
os.getrandom
17157
17158
    size: Py_ssize_t
17159
    flags: int=0
17160
17161
Obtain a series of random bytes.
17162
[clinic start generated code]*/
17163
17164
static PyObject *
17165
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17166
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17167
0
{
17168
0
    if (size < 0) {
17169
0
        errno = EINVAL;
17170
0
        return posix_error();
17171
0
    }
17172
17173
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17174
0
    if (writer == NULL) {
17175
0
        return NULL;
17176
0
    }
17177
0
    void *data = PyBytesWriter_GetData(writer);
17178
17179
0
    Py_ssize_t n;
17180
0
    while (1) {
17181
0
        n = syscall(SYS_getrandom, data, size, flags);
17182
0
        if (n < 0 && errno == EINTR) {
17183
0
            if (PyErr_CheckSignals() < 0) {
17184
0
                goto error;
17185
0
            }
17186
17187
            /* getrandom() was interrupted by a signal: retry */
17188
0
            continue;
17189
0
        }
17190
0
        break;
17191
0
    }
17192
17193
0
    if (n < 0) {
17194
0
        PyErr_SetFromErrno(PyExc_OSError);
17195
0
        goto error;
17196
0
    }
17197
17198
0
    return PyBytesWriter_FinishWithSize(writer, n);
17199
17200
0
error:
17201
0
    PyBytesWriter_Discard(writer);
17202
0
    return NULL;
17203
0
}
17204
#endif   /* HAVE_GETRANDOM_SYSCALL */
17205
17206
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17207
17208
/* bpo-36085: Helper functions for managing DLL search directories
17209
 * on win32
17210
 */
17211
17212
/*[clinic input]
17213
os._add_dll_directory
17214
17215
    path: path_t
17216
17217
Add a path to the DLL search path.
17218
17219
This search path is used when resolving dependencies for imported
17220
extension modules (the module itself is resolved through sys.path),
17221
and also by ctypes.
17222
17223
Returns an opaque value that may be passed to os.remove_dll_directory
17224
to remove this directory from the search path.
17225
[clinic start generated code]*/
17226
17227
static PyObject *
17228
os__add_dll_directory_impl(PyObject *module, path_t *path)
17229
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17230
{
17231
    DLL_DIRECTORY_COOKIE cookie = 0;
17232
    DWORD err = 0;
17233
17234
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17235
        return NULL;
17236
    }
17237
17238
    Py_BEGIN_ALLOW_THREADS
17239
    if (!(cookie = AddDllDirectory(path->wide))) {
17240
        err = GetLastError();
17241
    }
17242
    Py_END_ALLOW_THREADS
17243
17244
    if (err) {
17245
        return win32_error_object_err("add_dll_directory",
17246
                                      path->object, err);
17247
    }
17248
17249
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17250
}
17251
17252
/*[clinic input]
17253
os._remove_dll_directory
17254
17255
    cookie: object
17256
17257
Removes a path from the DLL search path.
17258
17259
The parameter is an opaque value that was returned from
17260
os.add_dll_directory. You can only remove directories that you added
17261
yourself.
17262
[clinic start generated code]*/
17263
17264
static PyObject *
17265
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17266
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17267
{
17268
    DLL_DIRECTORY_COOKIE cookieValue;
17269
    DWORD err = 0;
17270
17271
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17272
        PyErr_SetString(PyExc_TypeError,
17273
            "Provided cookie was not returned from os.add_dll_directory");
17274
        return NULL;
17275
    }
17276
17277
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17278
        cookie, "DLL directory cookie");
17279
17280
    Py_BEGIN_ALLOW_THREADS
17281
    if (!RemoveDllDirectory(cookieValue)) {
17282
        err = GetLastError();
17283
    }
17284
    Py_END_ALLOW_THREADS
17285
17286
    if (err) {
17287
        return win32_error_object_err("remove_dll_directory",
17288
                                      NULL, err);
17289
    }
17290
17291
    if (PyCapsule_SetName(cookie, NULL)) {
17292
        return NULL;
17293
    }
17294
17295
    Py_RETURN_NONE;
17296
}
17297
17298
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17299
17300
17301
/* Only check if WIFEXITED is available: expect that it comes
17302
   with WEXITSTATUS, WIFSIGNALED, etc.
17303
17304
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17305
   subprocess can safely call it during late Python finalization without
17306
   risking that used os attributes were set to None by finalize_modules(). */
17307
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17308
/*[clinic input]
17309
os.waitstatus_to_exitcode
17310
17311
    status as status_obj: object
17312
17313
Convert a wait status to an exit code.
17314
17315
On Unix:
17316
17317
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17318
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17319
* Otherwise, raise a ValueError.
17320
17321
On Windows, return status shifted right by 8 bits.
17322
17323
On Unix, if the process is being traced or if waitpid() was called with
17324
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
17325
This function must not be called if WIFSTOPPED(status) is true.
17326
[clinic start generated code]*/
17327
17328
static PyObject *
17329
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17330
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
17331
0
{
17332
0
#ifndef MS_WINDOWS
17333
0
    int status = PyLong_AsInt(status_obj);
17334
0
    if (status == -1 && PyErr_Occurred()) {
17335
0
        return NULL;
17336
0
    }
17337
17338
0
    WAIT_TYPE wait_status;
17339
0
    WAIT_STATUS_INT(wait_status) = status;
17340
0
    int exitcode;
17341
0
    if (WIFEXITED(wait_status)) {
17342
0
        exitcode = WEXITSTATUS(wait_status);
17343
        /* Sanity check to provide warranty on the function behavior.
17344
           It should not occur in practice */
17345
0
        if (exitcode < 0) {
17346
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17347
0
            return NULL;
17348
0
        }
17349
0
    }
17350
0
    else if (WIFSIGNALED(wait_status)) {
17351
0
        int signum = WTERMSIG(wait_status);
17352
        /* Sanity check to provide warranty on the function behavior.
17353
           It should not occurs in practice */
17354
0
        if (signum <= 0) {
17355
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17356
0
            return NULL;
17357
0
        }
17358
0
        exitcode = -signum;
17359
0
    } else if (WIFSTOPPED(wait_status)) {
17360
        /* Status only received if the process is being traced
17361
           or if waitpid() was called with WUNTRACED option. */
17362
0
        int signum = WSTOPSIG(wait_status);
17363
0
        PyErr_Format(PyExc_ValueError,
17364
0
                     "process stopped by delivery of signal %i",
17365
0
                     signum);
17366
0
        return NULL;
17367
0
    }
17368
0
    else {
17369
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17370
0
        return NULL;
17371
0
    }
17372
0
    return PyLong_FromLong(exitcode);
17373
#else
17374
    /* Windows implementation: see os.waitpid() implementation
17375
       which uses _cwait(). */
17376
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17377
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17378
        return NULL;
17379
    }
17380
17381
    unsigned long long exitcode = (status >> 8);
17382
    /* ExitProcess() accepts an UINT type:
17383
       reject exit code which doesn't fit in an UINT */
17384
    if (exitcode > UINT_MAX) {
17385
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17386
        return NULL;
17387
    }
17388
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17389
#endif
17390
0
}
17391
#endif
17392
17393
#if defined(MS_WINDOWS)
17394
/*[clinic input]
17395
os._supports_virtual_terminal
17396
17397
Checks if virtual terminal is supported in windows
17398
[clinic start generated code]*/
17399
17400
static PyObject *
17401
os__supports_virtual_terminal_impl(PyObject *module)
17402
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17403
{
17404
#ifdef HAVE_WINDOWS_CONSOLE_IO
17405
    DWORD mode = 0;
17406
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17407
    if (!GetConsoleMode(handle, &mode)) {
17408
        Py_RETURN_FALSE;
17409
    }
17410
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17411
#else
17412
    Py_RETURN_FALSE;
17413
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17414
}
17415
#endif
17416
17417
/*[clinic input]
17418
os._inputhook
17419
17420
Calls PyOS_InputHook dropping the GIL first
17421
[clinic start generated code]*/
17422
17423
static PyObject *
17424
os__inputhook_impl(PyObject *module)
17425
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17426
0
{
17427
0
     int result = 0;
17428
0
     if (PyOS_InputHook) {
17429
0
         Py_BEGIN_ALLOW_THREADS;
17430
0
         result = PyOS_InputHook();
17431
0
         Py_END_ALLOW_THREADS;
17432
0
     }
17433
0
     return PyLong_FromLong(result);
17434
0
}
17435
17436
/*[clinic input]
17437
os._is_inputhook_installed
17438
17439
Checks if PyOS_InputHook is set
17440
[clinic start generated code]*/
17441
17442
static PyObject *
17443
os__is_inputhook_installed_impl(PyObject *module)
17444
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17445
0
{
17446
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17447
0
}
17448
17449
/*[clinic input]
17450
os._create_environ
17451
17452
Create the environment dictionary.
17453
[clinic start generated code]*/
17454
17455
static PyObject *
17456
os__create_environ_impl(PyObject *module)
17457
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17458
0
{
17459
0
    return convertenviron();
17460
0
}
17461
17462
17463
#ifdef __EMSCRIPTEN__
17464
/*[clinic input]
17465
os._emscripten_debugger
17466
17467
Create a breakpoint for the JavaScript debugger. Emscripten only.
17468
[clinic start generated code]*/
17469
17470
static PyObject *
17471
os__emscripten_debugger_impl(PyObject *module)
17472
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17473
{
17474
    emscripten_debugger();
17475
    Py_RETURN_NONE;
17476
}
17477
17478
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17479
    console.warn(UTF8ToString(arg));
17480
});
17481
17482
/*[clinic input]
17483
os._emscripten_log
17484
   arg: str
17485
17486
Log something to the JS console. Emscripten only.
17487
[clinic start generated code]*/
17488
17489
static PyObject *
17490
os__emscripten_log_impl(PyObject *module, const char *arg)
17491
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17492
{
17493
    emscripten_log_impl_js(arg);
17494
    Py_RETURN_NONE;
17495
}
17496
#endif /* __EMSCRIPTEN__ */
17497
17498
17499
static PyMethodDef posix_methods[] = {
17500
    OS_STAT_METHODDEF
17501
    OS_STATX_METHODDEF
17502
    OS_ACCESS_METHODDEF
17503
    OS_TTYNAME_METHODDEF
17504
    OS_CHDIR_METHODDEF
17505
    OS_CHFLAGS_METHODDEF
17506
    OS_CHMOD_METHODDEF
17507
    OS_FCHMOD_METHODDEF
17508
    OS_LCHMOD_METHODDEF
17509
    OS_CHOWN_METHODDEF
17510
    OS_FCHOWN_METHODDEF
17511
    OS_LCHOWN_METHODDEF
17512
    OS_LCHFLAGS_METHODDEF
17513
    OS_CHROOT_METHODDEF
17514
    OS_CTERMID_METHODDEF
17515
    OS_GETCWD_METHODDEF
17516
    OS_GETCWDB_METHODDEF
17517
    OS_LINK_METHODDEF
17518
    OS_LISTDIR_METHODDEF
17519
    OS_LISTDRIVES_METHODDEF
17520
    OS_LISTMOUNTS_METHODDEF
17521
    OS_LISTVOLUMES_METHODDEF
17522
    OS_LSTAT_METHODDEF
17523
    OS_MKDIR_METHODDEF
17524
    OS_NICE_METHODDEF
17525
    OS_GETPRIORITY_METHODDEF
17526
    OS_SETPRIORITY_METHODDEF
17527
    OS_POSIX_SPAWN_METHODDEF
17528
    OS_POSIX_SPAWNP_METHODDEF
17529
    OS_READLINK_METHODDEF
17530
    OS_COPY_FILE_RANGE_METHODDEF
17531
    OS_SPLICE_METHODDEF
17532
    OS_RENAME_METHODDEF
17533
    OS_REPLACE_METHODDEF
17534
    OS_RMDIR_METHODDEF
17535
    OS_SYMLINK_METHODDEF
17536
    OS_SYSTEM_METHODDEF
17537
    OS_UMASK_METHODDEF
17538
    OS_UNAME_METHODDEF
17539
    OS_UNLINK_METHODDEF
17540
    OS_REMOVE_METHODDEF
17541
    OS_UTIME_METHODDEF
17542
    OS_TIMES_METHODDEF
17543
    OS__EXIT_METHODDEF
17544
    OS__FCOPYFILE_METHODDEF
17545
    OS_EXECV_METHODDEF
17546
    OS_EXECVE_METHODDEF
17547
    OS_SPAWNV_METHODDEF
17548
    OS_SPAWNVE_METHODDEF
17549
    OS_FORK1_METHODDEF
17550
    OS_FORK_METHODDEF
17551
    OS_REGISTER_AT_FORK_METHODDEF
17552
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17553
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17554
    OS_SCHED_GETPARAM_METHODDEF
17555
    OS_SCHED_GETSCHEDULER_METHODDEF
17556
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17557
    OS_SCHED_SETPARAM_METHODDEF
17558
    OS_SCHED_SETSCHEDULER_METHODDEF
17559
    OS_SCHED_YIELD_METHODDEF
17560
    OS_SCHED_SETAFFINITY_METHODDEF
17561
    OS_SCHED_GETAFFINITY_METHODDEF
17562
    OS_POSIX_OPENPT_METHODDEF
17563
    OS_GRANTPT_METHODDEF
17564
    OS_UNLOCKPT_METHODDEF
17565
    OS_PTSNAME_METHODDEF
17566
    OS_OPENPTY_METHODDEF
17567
    OS_LOGIN_TTY_METHODDEF
17568
    OS_FORKPTY_METHODDEF
17569
    OS_GETEGID_METHODDEF
17570
    OS_GETEUID_METHODDEF
17571
    OS_GETGID_METHODDEF
17572
    OS_GETGROUPLIST_METHODDEF
17573
    OS_GETGROUPS_METHODDEF
17574
    OS_GETPID_METHODDEF
17575
    OS_GETPGRP_METHODDEF
17576
    OS_GETPPID_METHODDEF
17577
    OS_GETUID_METHODDEF
17578
    OS_GETLOGIN_METHODDEF
17579
    OS_KILL_METHODDEF
17580
    OS_KILLPG_METHODDEF
17581
    OS_PLOCK_METHODDEF
17582
    OS_STARTFILE_METHODDEF
17583
    OS_SETUID_METHODDEF
17584
    OS_SETEUID_METHODDEF
17585
    OS_SETREUID_METHODDEF
17586
    OS_SETGID_METHODDEF
17587
    OS_SETEGID_METHODDEF
17588
    OS_SETREGID_METHODDEF
17589
    OS_SETGROUPS_METHODDEF
17590
    OS_INITGROUPS_METHODDEF
17591
    OS_GETPGID_METHODDEF
17592
    OS_SETPGRP_METHODDEF
17593
    OS_WAIT_METHODDEF
17594
    OS_WAIT3_METHODDEF
17595
    OS_WAIT4_METHODDEF
17596
    OS_WAITID_METHODDEF
17597
    OS_WAITPID_METHODDEF
17598
    OS_PIDFD_OPEN_METHODDEF
17599
    OS_GETSID_METHODDEF
17600
    OS_SETSID_METHODDEF
17601
    OS_SETPGID_METHODDEF
17602
    OS_TCGETPGRP_METHODDEF
17603
    OS_TCSETPGRP_METHODDEF
17604
    OS_OPEN_METHODDEF
17605
    OS_CLOSE_METHODDEF
17606
    OS_CLOSERANGE_METHODDEF
17607
    OS_DEVICE_ENCODING_METHODDEF
17608
    OS_DUP_METHODDEF
17609
    OS_DUP2_METHODDEF
17610
    OS_LOCKF_METHODDEF
17611
    OS_LSEEK_METHODDEF
17612
    OS_READ_METHODDEF
17613
    OS_READINTO_METHODDEF
17614
    OS_READV_METHODDEF
17615
    OS_PREAD_METHODDEF
17616
    OS_PREADV_METHODDEF
17617
    OS_WRITE_METHODDEF
17618
    OS_WRITEV_METHODDEF
17619
    OS_PWRITE_METHODDEF
17620
    OS_PWRITEV_METHODDEF
17621
    OS_SENDFILE_METHODDEF
17622
    OS_FSTAT_METHODDEF
17623
    OS_ISATTY_METHODDEF
17624
    OS_PIPE_METHODDEF
17625
    OS_PIPE2_METHODDEF
17626
    OS_MKFIFO_METHODDEF
17627
    OS_MKNOD_METHODDEF
17628
    OS_MAJOR_METHODDEF
17629
    OS_MINOR_METHODDEF
17630
    OS_MAKEDEV_METHODDEF
17631
    OS_FTRUNCATE_METHODDEF
17632
    OS_TRUNCATE_METHODDEF
17633
    OS_POSIX_FALLOCATE_METHODDEF
17634
    OS_POSIX_FADVISE_METHODDEF
17635
    OS_PUTENV_METHODDEF
17636
    OS_UNSETENV_METHODDEF
17637
    OS__CLEARENV_METHODDEF
17638
    OS_STRERROR_METHODDEF
17639
    OS_FCHDIR_METHODDEF
17640
    OS_FSYNC_METHODDEF
17641
    OS_SYNC_METHODDEF
17642
    OS_FDATASYNC_METHODDEF
17643
    OS_WCOREDUMP_METHODDEF
17644
    OS_WIFCONTINUED_METHODDEF
17645
    OS_WIFSTOPPED_METHODDEF
17646
    OS_WIFSIGNALED_METHODDEF
17647
    OS_WIFEXITED_METHODDEF
17648
    OS_WEXITSTATUS_METHODDEF
17649
    OS_WTERMSIG_METHODDEF
17650
    OS_WSTOPSIG_METHODDEF
17651
    OS_FSTATVFS_METHODDEF
17652
    OS_STATVFS_METHODDEF
17653
    OS_CONFSTR_METHODDEF
17654
    OS_SYSCONF_METHODDEF
17655
    OS_FPATHCONF_METHODDEF
17656
    OS_PATHCONF_METHODDEF
17657
    OS_ABORT_METHODDEF
17658
    OS__GETFULLPATHNAME_METHODDEF
17659
    OS__GETDISKUSAGE_METHODDEF
17660
    OS__GETFINALPATHNAME_METHODDEF
17661
    OS__FINDFIRSTFILE_METHODDEF
17662
    OS__GETVOLUMEPATHNAME_METHODDEF
17663
    OS__PATH_SPLITROOT_METHODDEF
17664
    OS__PATH_SPLITROOT_EX_METHODDEF
17665
    OS__PATH_NORMPATH_METHODDEF
17666
    OS_GETLOADAVG_METHODDEF
17667
    OS_URANDOM_METHODDEF
17668
    OS_SETRESUID_METHODDEF
17669
    OS_SETRESGID_METHODDEF
17670
    OS_GETRESUID_METHODDEF
17671
    OS_GETRESGID_METHODDEF
17672
17673
    OS_GETXATTR_METHODDEF
17674
    OS_SETXATTR_METHODDEF
17675
    OS_REMOVEXATTR_METHODDEF
17676
    OS_LISTXATTR_METHODDEF
17677
17678
    OS_GET_TERMINAL_SIZE_METHODDEF
17679
    OS_CPU_COUNT_METHODDEF
17680
    OS_GET_INHERITABLE_METHODDEF
17681
    OS_SET_INHERITABLE_METHODDEF
17682
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17683
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17684
    OS_GET_BLOCKING_METHODDEF
17685
    OS_SET_BLOCKING_METHODDEF
17686
    OS_SCANDIR_METHODDEF
17687
    OS_FSPATH_METHODDEF
17688
    OS_GETRANDOM_METHODDEF
17689
    OS_MEMFD_CREATE_METHODDEF
17690
    OS_EVENTFD_METHODDEF
17691
    OS_EVENTFD_READ_METHODDEF
17692
    OS_EVENTFD_WRITE_METHODDEF
17693
    OS__ADD_DLL_DIRECTORY_METHODDEF
17694
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17695
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17696
    OS_SETNS_METHODDEF
17697
    OS_UNSHARE_METHODDEF
17698
    OS_TIMERFD_CREATE_METHODDEF
17699
    OS_TIMERFD_SETTIME_METHODDEF
17700
    OS_TIMERFD_SETTIME_NS_METHODDEF
17701
    OS_TIMERFD_GETTIME_METHODDEF
17702
    OS_TIMERFD_GETTIME_NS_METHODDEF
17703
17704
    OS__PATH_ISDEVDRIVE_METHODDEF
17705
    OS__PATH_ISDIR_METHODDEF
17706
    OS__PATH_ISFILE_METHODDEF
17707
    OS__PATH_ISLINK_METHODDEF
17708
    OS__PATH_ISJUNCTION_METHODDEF
17709
    OS__PATH_EXISTS_METHODDEF
17710
    OS__PATH_LEXISTS_METHODDEF
17711
17712
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17713
    OS__INPUTHOOK_METHODDEF
17714
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17715
    OS__CREATE_ENVIRON_METHODDEF
17716
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17717
    OS__EMSCRIPTEN_LOG_METHODDEF
17718
    {NULL,              NULL}            /* Sentinel */
17719
};
17720
17721
static int
17722
all_ins(PyObject *m)
17723
36
{
17724
36
#ifdef F_OK
17725
36
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17726
36
#endif
17727
36
#ifdef R_OK
17728
36
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17729
36
#endif
17730
36
#ifdef W_OK
17731
36
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17732
36
#endif
17733
36
#ifdef X_OK
17734
36
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17735
36
#endif
17736
36
#ifdef NGROUPS_MAX
17737
36
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17738
36
#endif
17739
36
#ifdef TMP_MAX
17740
36
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17741
36
#endif
17742
36
#ifdef WCONTINUED
17743
36
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17744
36
#endif
17745
36
#ifdef WNOHANG
17746
36
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17747
36
#endif
17748
36
#ifdef WUNTRACED
17749
36
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17750
36
#endif
17751
36
#ifdef O_RDONLY
17752
36
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17753
36
#endif
17754
36
#ifdef O_WRONLY
17755
36
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17756
36
#endif
17757
36
#ifdef O_RDWR
17758
36
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17759
36
#endif
17760
36
#ifdef O_NDELAY
17761
36
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17762
36
#endif
17763
36
#ifdef O_NONBLOCK
17764
36
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17765
36
#endif
17766
36
#ifdef O_APPEND
17767
36
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17768
36
#endif
17769
36
#ifdef O_DSYNC
17770
36
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17771
36
#endif
17772
36
#ifdef O_RSYNC
17773
36
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17774
36
#endif
17775
36
#ifdef O_SYNC
17776
36
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17777
36
#endif
17778
36
#ifdef O_NOCTTY
17779
36
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17780
36
#endif
17781
36
#ifdef O_CREAT
17782
36
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17783
36
#endif
17784
36
#ifdef O_EXCL
17785
36
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17786
36
#endif
17787
36
#ifdef O_TRUNC
17788
36
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17789
36
#endif
17790
#ifdef O_BINARY
17791
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17792
#endif
17793
#ifdef O_TEXT
17794
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17795
#endif
17796
#ifdef O_XATTR
17797
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17798
#endif
17799
36
#ifdef O_LARGEFILE
17800
36
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17801
36
#endif
17802
36
#ifndef __GNU__
17803
#ifdef O_SHLOCK
17804
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17805
#endif
17806
#ifdef O_EXLOCK
17807
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17808
#endif
17809
36
#endif
17810
#ifdef O_EXEC
17811
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17812
#endif
17813
#ifdef O_SEARCH
17814
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17815
#endif
17816
36
#ifdef O_PATH
17817
36
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17818
36
#endif
17819
#ifdef O_TTY_INIT
17820
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17821
#endif
17822
36
#ifdef O_TMPFILE
17823
36
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17824
36
#endif
17825
36
#ifdef PRIO_PROCESS
17826
36
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17827
36
#endif
17828
36
#ifdef PRIO_PGRP
17829
36
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17830
36
#endif
17831
36
#ifdef PRIO_USER
17832
36
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17833
36
#endif
17834
#ifdef PRIO_DARWIN_THREAD
17835
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17836
#endif
17837
#ifdef PRIO_DARWIN_PROCESS
17838
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17839
#endif
17840
#ifdef PRIO_DARWIN_BG
17841
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17842
#endif
17843
#ifdef PRIO_DARWIN_NONUI
17844
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17845
#endif
17846
36
#ifdef O_CLOEXEC
17847
36
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17848
36
#endif
17849
36
#ifdef O_ACCMODE
17850
36
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17851
36
#endif
17852
#ifdef O_EVTONLY
17853
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17854
#endif
17855
36
#ifdef O_FSYNC
17856
36
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17857
36
#endif
17858
#ifdef O_SYMLINK
17859
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17860
#endif
17861
17862
36
#ifdef SEEK_HOLE
17863
36
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17864
36
#endif
17865
36
#ifdef SEEK_DATA
17866
36
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17867
36
#endif
17868
17869
/* MS Windows */
17870
#ifdef O_NOINHERIT
17871
    /* Don't inherit in child processes. */
17872
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17873
#endif
17874
#ifdef _O_SHORT_LIVED
17875
    /* Optimize for short life (keep in memory). */
17876
    /* MS forgot to define this one with a non-underscore form too. */
17877
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17878
#endif
17879
#ifdef O_TEMPORARY
17880
    /* Automatically delete when last handle is closed. */
17881
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17882
#endif
17883
#ifdef O_RANDOM
17884
    /* Optimize for random access. */
17885
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17886
#endif
17887
#ifdef O_SEQUENTIAL
17888
    /* Optimize for sequential access. */
17889
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17890
#endif
17891
17892
/* GNU extensions. */
17893
36
#ifdef O_ASYNC
17894
    /* Send a SIGIO signal whenever input or output
17895
       becomes available on file descriptor */
17896
36
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17897
36
#endif
17898
36
#ifdef O_DIRECT
17899
    /* Direct disk access. */
17900
36
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17901
36
#endif
17902
36
#ifdef O_DIRECTORY
17903
    /* Must be a directory.      */
17904
36
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17905
36
#endif
17906
36
#ifdef O_NOFOLLOW
17907
    /* Do not follow links.      */
17908
36
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17909
36
#endif
17910
#ifdef O_NOFOLLOW_ANY
17911
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17912
#endif
17913
#ifdef O_NOLINKS
17914
    /* Fails if link count of the named file is greater than 1 */
17915
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17916
#endif
17917
36
#ifdef O_NOATIME
17918
    /* Do not update the access time. */
17919
36
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17920
36
#endif
17921
17922
    /* These come from sysexits.h */
17923
36
#ifdef EX_OK
17924
36
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17925
36
#endif /* EX_OK */
17926
36
#ifdef EX_USAGE
17927
36
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17928
36
#endif /* EX_USAGE */
17929
36
#ifdef EX_DATAERR
17930
36
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17931
36
#endif /* EX_DATAERR */
17932
36
#ifdef EX_NOINPUT
17933
36
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17934
36
#endif /* EX_NOINPUT */
17935
36
#ifdef EX_NOUSER
17936
36
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17937
36
#endif /* EX_NOUSER */
17938
36
#ifdef EX_NOHOST
17939
36
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17940
36
#endif /* EX_NOHOST */
17941
36
#ifdef EX_UNAVAILABLE
17942
36
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17943
36
#endif /* EX_UNAVAILABLE */
17944
36
#ifdef EX_SOFTWARE
17945
36
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17946
36
#endif /* EX_SOFTWARE */
17947
36
#ifdef EX_OSERR
17948
36
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17949
36
#endif /* EX_OSERR */
17950
36
#ifdef EX_OSFILE
17951
36
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17952
36
#endif /* EX_OSFILE */
17953
36
#ifdef EX_CANTCREAT
17954
36
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17955
36
#endif /* EX_CANTCREAT */
17956
36
#ifdef EX_IOERR
17957
36
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17958
36
#endif /* EX_IOERR */
17959
36
#ifdef EX_TEMPFAIL
17960
36
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17961
36
#endif /* EX_TEMPFAIL */
17962
36
#ifdef EX_PROTOCOL
17963
36
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17964
36
#endif /* EX_PROTOCOL */
17965
36
#ifdef EX_NOPERM
17966
36
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17967
36
#endif /* EX_NOPERM */
17968
36
#ifdef EX_CONFIG
17969
36
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17970
36
#endif /* EX_CONFIG */
17971
#ifdef EX_NOTFOUND
17972
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17973
#endif /* EX_NOTFOUND */
17974
17975
    /* statvfs */
17976
36
#ifdef ST_RDONLY
17977
36
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17978
36
#endif /* ST_RDONLY */
17979
36
#ifdef ST_NOSUID
17980
36
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17981
36
#endif /* ST_NOSUID */
17982
17983
       /* GNU extensions */
17984
36
#ifdef ST_NODEV
17985
36
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17986
36
#endif /* ST_NODEV */
17987
36
#ifdef ST_NOEXEC
17988
36
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17989
36
#endif /* ST_NOEXEC */
17990
36
#ifdef ST_SYNCHRONOUS
17991
36
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17992
36
#endif /* ST_SYNCHRONOUS */
17993
36
#ifdef ST_MANDLOCK
17994
36
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17995
36
#endif /* ST_MANDLOCK */
17996
36
#ifdef ST_WRITE
17997
36
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17998
36
#endif /* ST_WRITE */
17999
36
#ifdef ST_APPEND
18000
36
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
18001
36
#endif /* ST_APPEND */
18002
36
#ifdef ST_NOATIME
18003
36
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
18004
36
#endif /* ST_NOATIME */
18005
36
#ifdef ST_NODIRATIME
18006
36
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
18007
36
#endif /* ST_NODIRATIME */
18008
36
#ifdef ST_RELATIME
18009
36
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18010
36
#endif /* ST_RELATIME */
18011
18012
    /* FreeBSD sendfile() constants */
18013
#ifdef SF_NODISKIO
18014
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18015
#endif
18016
    /* is obsolete since the 11.x release */
18017
#ifdef SF_MNOWAIT
18018
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18019
#endif
18020
#ifdef SF_SYNC
18021
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18022
#endif
18023
#ifdef SF_NOCACHE
18024
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18025
#endif
18026
18027
36
#ifdef TFD_NONBLOCK
18028
36
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18029
36
#endif
18030
36
#ifdef TFD_CLOEXEC
18031
36
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18032
36
#endif
18033
36
#ifdef TFD_TIMER_ABSTIME
18034
36
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18035
36
#endif
18036
36
#ifdef TFD_TIMER_CANCEL_ON_SET
18037
36
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18038
36
#endif
18039
18040
    /* constants for posix_fadvise */
18041
36
#ifdef POSIX_FADV_NORMAL
18042
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18043
36
#endif
18044
36
#ifdef POSIX_FADV_SEQUENTIAL
18045
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18046
36
#endif
18047
36
#ifdef POSIX_FADV_RANDOM
18048
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18049
36
#endif
18050
36
#ifdef POSIX_FADV_NOREUSE
18051
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18052
36
#endif
18053
36
#ifdef POSIX_FADV_WILLNEED
18054
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18055
36
#endif
18056
36
#ifdef POSIX_FADV_DONTNEED
18057
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18058
36
#endif
18059
18060
    /* constants for waitid */
18061
36
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18062
36
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18063
36
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18064
36
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18065
36
#ifdef P_PIDFD
18066
36
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18067
36
#endif
18068
#ifdef PIDFD_NONBLOCK
18069
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18070
#endif
18071
36
#endif
18072
36
#ifdef WEXITED
18073
36
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18074
36
#endif
18075
36
#ifdef WNOWAIT
18076
36
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18077
36
#endif
18078
36
#ifdef WSTOPPED
18079
36
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18080
36
#endif
18081
36
#ifdef CLD_EXITED
18082
36
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18083
36
#endif
18084
36
#ifdef CLD_KILLED
18085
36
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18086
36
#endif
18087
36
#ifdef CLD_DUMPED
18088
36
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18089
36
#endif
18090
36
#ifdef CLD_TRAPPED
18091
36
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18092
36
#endif
18093
36
#ifdef CLD_STOPPED
18094
36
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18095
36
#endif
18096
36
#ifdef CLD_CONTINUED
18097
36
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18098
36
#endif
18099
18100
    /* constants for lockf */
18101
36
#ifdef F_LOCK
18102
36
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18103
36
#endif
18104
36
#ifdef F_TLOCK
18105
36
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18106
36
#endif
18107
36
#ifdef F_ULOCK
18108
36
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18109
36
#endif
18110
36
#ifdef F_TEST
18111
36
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18112
36
#endif
18113
18114
36
#ifdef RWF_DSYNC
18115
36
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18116
36
#endif
18117
36
#ifdef RWF_HIPRI
18118
36
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18119
36
#endif
18120
36
#ifdef RWF_SYNC
18121
36
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18122
36
#endif
18123
36
#ifdef RWF_NOWAIT
18124
36
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18125
36
#endif
18126
#ifdef RWF_DONTCACHE
18127
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18128
#endif
18129
#ifdef RWF_ATOMIC
18130
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18131
#endif
18132
36
#ifdef RWF_APPEND
18133
36
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18134
36
#endif
18135
18136
/* constants for splice */
18137
36
#if defined(HAVE_SPLICE) && defined(__linux__)
18138
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18139
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18140
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18141
36
#endif
18142
18143
/* constants for posix_spawn */
18144
36
#ifdef HAVE_POSIX_SPAWN
18145
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18146
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18147
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18148
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18149
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18150
#endif
18151
36
#endif
18152
18153
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18154
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18155
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18156
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18157
#endif
18158
#ifdef HAVE_SPAWNV
18159
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18160
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18161
#endif
18162
18163
36
#ifdef HAVE_SCHED_H
18164
36
#ifdef SCHED_OTHER
18165
36
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18166
36
#endif
18167
36
#ifdef SCHED_DEADLINE
18168
36
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18169
36
#endif
18170
36
#ifdef SCHED_FIFO
18171
36
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18172
36
#endif
18173
36
#ifdef SCHED_NORMAL
18174
36
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18175
36
#endif
18176
36
#ifdef SCHED_RR
18177
36
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18178
36
#endif
18179
#ifdef SCHED_SPORADIC
18180
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18181
#endif
18182
36
#ifdef SCHED_BATCH
18183
36
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18184
36
#endif
18185
36
#ifdef SCHED_IDLE
18186
36
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18187
36
#endif
18188
36
#ifdef SCHED_RESET_ON_FORK
18189
36
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18190
36
#endif
18191
#ifdef SCHED_SYS
18192
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18193
#endif
18194
#ifdef SCHED_IA
18195
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18196
#endif
18197
#ifdef SCHED_FSS
18198
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18199
#endif
18200
#ifdef SCHED_FX
18201
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18202
#endif
18203
18204
/* constants for namespaces */
18205
36
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18206
36
#ifdef CLONE_FS
18207
36
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18208
36
#endif
18209
36
#ifdef CLONE_FILES
18210
36
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18211
36
#endif
18212
36
#ifdef CLONE_NEWNS
18213
36
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18214
36
#endif
18215
36
#ifdef CLONE_NEWCGROUP
18216
36
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18217
36
#endif
18218
36
#ifdef CLONE_NEWUTS
18219
36
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18220
36
#endif
18221
36
#ifdef CLONE_NEWIPC
18222
36
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18223
36
#endif
18224
36
#ifdef CLONE_NEWUSER
18225
36
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18226
36
#endif
18227
36
#ifdef CLONE_NEWPID
18228
36
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18229
36
#endif
18230
36
#ifdef CLONE_NEWNET
18231
36
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18232
36
#endif
18233
#ifdef CLONE_NEWTIME
18234
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18235
#endif
18236
36
#ifdef CLONE_SYSVSEM
18237
36
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18238
36
#endif
18239
36
#ifdef CLONE_THREAD
18240
36
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18241
36
#endif
18242
36
#ifdef CLONE_SIGHAND
18243
36
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18244
36
#endif
18245
36
#ifdef CLONE_VM
18246
36
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18247
36
#endif
18248
36
#endif
18249
18250
36
#endif
18251
18252
36
#ifdef USE_XATTRS
18253
36
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18254
36
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18255
36
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18256
36
#endif
18257
18258
36
#if HAVE_DECL_RTLD_LAZY
18259
36
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18260
36
#endif
18261
36
#if HAVE_DECL_RTLD_NOW
18262
36
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18263
36
#endif
18264
36
#if HAVE_DECL_RTLD_GLOBAL
18265
36
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18266
36
#endif
18267
36
#if HAVE_DECL_RTLD_LOCAL
18268
36
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18269
36
#endif
18270
36
#if HAVE_DECL_RTLD_NODELETE
18271
36
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18272
36
#endif
18273
36
#if HAVE_DECL_RTLD_NOLOAD
18274
36
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18275
36
#endif
18276
36
#if HAVE_DECL_RTLD_DEEPBIND
18277
36
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18278
36
#endif
18279
#if HAVE_DECL_RTLD_MEMBER
18280
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18281
#endif
18282
18283
36
#ifdef HAVE_GETRANDOM_SYSCALL
18284
36
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18285
36
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18286
36
#endif
18287
36
#ifdef HAVE_MEMFD_CREATE
18288
36
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18289
36
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18290
36
#ifdef MFD_HUGETLB
18291
36
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18292
36
#endif
18293
36
#ifdef MFD_HUGE_SHIFT
18294
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18295
36
#endif
18296
36
#ifdef MFD_HUGE_MASK
18297
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18298
36
#endif
18299
36
#ifdef MFD_HUGE_64KB
18300
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18301
36
#endif
18302
36
#ifdef MFD_HUGE_512KB
18303
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18304
36
#endif
18305
36
#ifdef MFD_HUGE_1MB
18306
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18307
36
#endif
18308
36
#ifdef MFD_HUGE_2MB
18309
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18310
36
#endif
18311
36
#ifdef MFD_HUGE_8MB
18312
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18313
36
#endif
18314
36
#ifdef MFD_HUGE_16MB
18315
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18316
36
#endif
18317
36
#ifdef MFD_HUGE_32MB
18318
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18319
36
#endif
18320
36
#ifdef MFD_HUGE_256MB
18321
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18322
36
#endif
18323
36
#ifdef MFD_HUGE_512MB
18324
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18325
36
#endif
18326
36
#ifdef MFD_HUGE_1GB
18327
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18328
36
#endif
18329
36
#ifdef MFD_HUGE_2GB
18330
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18331
36
#endif
18332
36
#ifdef MFD_HUGE_16GB
18333
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18334
36
#endif
18335
36
#endif /* HAVE_MEMFD_CREATE */
18336
18337
36
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18338
36
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18339
36
#ifdef EFD_NONBLOCK
18340
36
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18341
36
#endif
18342
36
#ifdef EFD_SEMAPHORE
18343
36
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18344
36
#endif
18345
36
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18346
18347
36
#ifdef NODEV
18348
36
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18349
36
#endif
18350
18351
36
#ifdef AT_NO_AUTOMOUNT
18352
36
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18353
36
#endif
18354
18355
36
#ifdef HAVE_STATX
18356
36
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18357
36
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18358
36
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18359
36
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18360
36
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18361
36
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18362
36
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18363
36
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18364
36
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18365
36
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18366
36
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18367
36
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18368
36
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18369
#ifdef STATX_MNT_ID
18370
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18371
#endif
18372
#ifdef STATX_DIOALIGN
18373
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18374
#endif
18375
#ifdef STATX_MNT_ID_UNIQUE
18376
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18377
#endif
18378
#ifdef STATX_SUBVOL
18379
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18380
#endif
18381
#ifdef STATX_WRITE_ATOMIC
18382
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18383
#endif
18384
#ifdef STATX_DIO_READ_ALIGN
18385
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18386
#endif
18387
    /* STATX_ALL intentionally omitted because it is deprecated */
18388
36
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18389
36
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18390
36
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18391
    /* STATX_ATTR_* constants are in the stat module */
18392
36
#endif /* HAVE_STATX */
18393
18394
#if defined(__APPLE__)
18395
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18396
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18397
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18398
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18399
#endif
18400
18401
#ifdef MS_WINDOWS
18402
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18403
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18404
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18405
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18406
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18407
#endif
18408
18409
36
    return 0;
18410
36
}
18411
18412
18413
18414
#define PROBE(name, test) \
18415
   static int name(void)  \
18416
612
   {                      \
18417
612
      if (test) {        \
18418
612
          return 1;       \
18419
612
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
612
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_futimens
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_linkat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_openat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_renameat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18416
36
   {                      \
18417
36
      if (test) {        \
18418
36
          return 1;       \
18419
36
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
36
   }
18423
18424
#ifdef HAVE_FSTATAT
18425
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18426
#endif
18427
18428
#ifdef HAVE_FACCESSAT
18429
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18430
#endif
18431
18432
#ifdef HAVE_FCHMODAT
18433
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18434
#endif
18435
18436
#ifdef HAVE_FCHOWNAT
18437
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18438
#endif
18439
18440
#ifdef HAVE_LINKAT
18441
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18442
#endif
18443
18444
#ifdef HAVE_FDOPENDIR
18445
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18446
#endif
18447
18448
#ifdef HAVE_MKDIRAT
18449
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18450
#endif
18451
18452
#ifdef HAVE_MKFIFOAT
18453
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18454
#endif
18455
18456
#ifdef HAVE_MKNODAT
18457
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18458
#endif
18459
18460
#ifdef HAVE_RENAMEAT
18461
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18462
#endif
18463
18464
#ifdef HAVE_UNLINKAT
18465
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18466
#endif
18467
18468
#ifdef HAVE_OPENAT
18469
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18470
#endif
18471
18472
#ifdef HAVE_READLINKAT
18473
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18474
#endif
18475
18476
#ifdef HAVE_SYMLINKAT
18477
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18478
#endif
18479
18480
#ifdef HAVE_FUTIMENS
18481
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18482
#endif
18483
18484
#ifdef HAVE_UTIMENSAT
18485
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18486
#endif
18487
18488
#ifdef HAVE_PTSNAME_R
18489
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18490
#endif
18491
18492
18493
18494
static const struct have_function {
18495
    const char * const label;
18496
    int (*probe)(void);
18497
} have_functions[] = {
18498
18499
#ifdef HAVE_EVENTFD
18500
    {"HAVE_EVENTFD", NULL},
18501
#endif
18502
18503
#ifdef HAVE_TIMERFD_CREATE
18504
    {"HAVE_TIMERFD_CREATE", NULL},
18505
#endif
18506
18507
#ifdef HAVE_FACCESSAT
18508
    { "HAVE_FACCESSAT", probe_faccessat },
18509
#endif
18510
18511
#ifdef HAVE_FCHDIR
18512
    { "HAVE_FCHDIR", NULL },
18513
#endif
18514
18515
#ifdef HAVE_FCHMOD
18516
    { "HAVE_FCHMOD", NULL },
18517
#endif
18518
18519
#ifdef HAVE_FCHMODAT
18520
    { "HAVE_FCHMODAT", probe_fchmodat },
18521
#endif
18522
18523
#ifdef HAVE_FCHOWN
18524
    { "HAVE_FCHOWN", NULL },
18525
#endif
18526
18527
#ifdef HAVE_FCHOWNAT
18528
    { "HAVE_FCHOWNAT", probe_fchownat },
18529
#endif
18530
18531
#ifdef HAVE_FEXECVE
18532
    { "HAVE_FEXECVE", NULL },
18533
#endif
18534
18535
#ifdef HAVE_FDOPENDIR
18536
    { "HAVE_FDOPENDIR", probe_fdopendir },
18537
#endif
18538
18539
#ifdef HAVE_FPATHCONF
18540
    { "HAVE_FPATHCONF", NULL },
18541
#endif
18542
18543
#ifdef HAVE_FSTATAT
18544
    { "HAVE_FSTATAT", probe_fstatat },
18545
#endif
18546
18547
#ifdef HAVE_FSTATVFS
18548
    { "HAVE_FSTATVFS", NULL },
18549
#endif
18550
18551
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18552
    { "HAVE_FTRUNCATE", NULL },
18553
#endif
18554
18555
#ifdef HAVE_FUTIMENS
18556
    { "HAVE_FUTIMENS", probe_futimens },
18557
#endif
18558
18559
#ifdef HAVE_FUTIMES
18560
    { "HAVE_FUTIMES", NULL },
18561
#endif
18562
18563
#ifdef HAVE_FUTIMESAT
18564
    { "HAVE_FUTIMESAT", NULL },
18565
#endif
18566
18567
#ifdef HAVE_LINKAT
18568
    { "HAVE_LINKAT", probe_linkat },
18569
#endif
18570
18571
#ifdef HAVE_LCHFLAGS
18572
    { "HAVE_LCHFLAGS", NULL },
18573
#endif
18574
18575
#ifdef HAVE_LCHMOD
18576
    { "HAVE_LCHMOD", NULL },
18577
#endif
18578
18579
#ifdef HAVE_LCHOWN
18580
    { "HAVE_LCHOWN", NULL },
18581
#endif
18582
18583
#ifdef HAVE_LSTAT
18584
    { "HAVE_LSTAT", NULL },
18585
#endif
18586
18587
#ifdef HAVE_LUTIMES
18588
    { "HAVE_LUTIMES", NULL },
18589
#endif
18590
18591
#ifdef HAVE_MEMFD_CREATE
18592
    { "HAVE_MEMFD_CREATE", NULL },
18593
#endif
18594
18595
#ifdef HAVE_MKDIRAT
18596
    { "HAVE_MKDIRAT", probe_mkdirat },
18597
#endif
18598
18599
#ifdef HAVE_MKFIFOAT
18600
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18601
#endif
18602
18603
#ifdef HAVE_MKNODAT
18604
    { "HAVE_MKNODAT", probe_mknodat },
18605
#endif
18606
18607
#ifdef HAVE_OPENAT
18608
    { "HAVE_OPENAT", probe_openat },
18609
#endif
18610
18611
#ifdef HAVE_READLINKAT
18612
    { "HAVE_READLINKAT", probe_readlinkat },
18613
#endif
18614
18615
#ifdef HAVE_RENAMEAT
18616
    { "HAVE_RENAMEAT", probe_renameat },
18617
#endif
18618
18619
#ifdef HAVE_SYMLINKAT
18620
    { "HAVE_SYMLINKAT", probe_symlinkat },
18621
#endif
18622
18623
#ifdef HAVE_UNLINKAT
18624
    { "HAVE_UNLINKAT", probe_unlinkat },
18625
#endif
18626
18627
#ifdef HAVE_UTIMENSAT
18628
    { "HAVE_UTIMENSAT", probe_utimensat },
18629
#endif
18630
18631
#ifdef HAVE_PTSNAME_R
18632
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18633
#endif
18634
18635
#ifdef MS_WINDOWS
18636
    { "MS_WINDOWS", NULL },
18637
#endif
18638
18639
    { NULL, NULL }
18640
};
18641
18642
18643
static int
18644
posixmodule_exec(PyObject *m)
18645
36
{
18646
36
    _posixstate *state = get_posix_state(m);
18647
18648
36
#if defined(HAVE_PWRITEV)
18649
36
    if (HAVE_PWRITEV_RUNTIME) {} else {
18650
0
        PyObject* dct = PyModule_GetDict(m);
18651
18652
0
        if (dct == NULL) {
18653
0
            return -1;
18654
0
        }
18655
18656
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18657
0
            return -1;
18658
0
        }
18659
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18660
0
            return -1;
18661
0
        }
18662
0
    }
18663
36
#endif
18664
18665
36
#ifdef HAVE_STATX
18666
36
    if (statx == NULL) {
18667
0
        PyObject* dct = PyModule_GetDict(m);
18668
0
        if (dct == NULL) {
18669
0
            return -1;
18670
0
        }
18671
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18672
0
            return -1;
18673
0
        }
18674
0
    }
18675
36
    else {
18676
36
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18677
36
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18678
0
            return -1;
18679
0
        }
18680
36
    }
18681
36
#endif
18682
18683
    /* Initialize environ dictionary */
18684
36
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18685
0
        return -1;
18686
0
    }
18687
18688
36
    if (all_ins(m))
18689
0
        return -1;
18690
18691
36
    if (setup_confname_tables(m))
18692
0
        return -1;
18693
18694
36
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18695
0
        return -1;
18696
0
    }
18697
18698
36
#if defined(HAVE_WAITID)
18699
36
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18700
36
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18701
0
        return -1;
18702
0
    }
18703
36
#endif
18704
18705
36
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18706
36
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18707
36
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18708
36
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18709
36
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18710
0
        return -1;
18711
0
    }
18712
36
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18713
36
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18714
18715
36
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18716
36
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18717
0
        return -1;
18718
0
    }
18719
18720
36
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18721
36
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18722
36
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18723
0
        return -1;
18724
0
    }
18725
36
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18726
36
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18727
36
                          &os_sched_param_reduce_method) < 0)
18728
0
    {
18729
0
        return -1;
18730
0
    }
18731
36
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18732
36
#endif
18733
18734
    /* initialize TerminalSize_info */
18735
36
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18736
36
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18737
0
        return -1;
18738
0
    }
18739
18740
    /* initialize scandir types */
18741
36
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18742
36
    if (ScandirIteratorType == NULL) {
18743
0
        return -1;
18744
0
    }
18745
36
    state->ScandirIteratorType = ScandirIteratorType;
18746
18747
36
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18748
36
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18749
0
        return -1;
18750
0
    }
18751
18752
36
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18753
36
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18754
0
        return -1;
18755
0
    }
18756
18757
36
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18758
36
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18759
0
        return -1;
18760
0
    }
18761
18762
36
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18763
0
        return -1;
18764
36
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18765
36
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18766
36
    if (state->struct_rusage == NULL)
18767
0
        return -1;
18768
36
#endif
18769
36
    state->st_mode = PyUnicode_InternFromString("st_mode");
18770
36
    if (state->st_mode == NULL)
18771
0
        return -1;
18772
18773
    /* suppress "function not used" warnings */
18774
36
    {
18775
36
    int ignored;
18776
36
    fd_specified("", -1);
18777
36
    follow_symlinks_specified("", 1);
18778
36
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18779
36
    dir_fd_converter(Py_None, &ignored);
18780
36
    dir_fd_unavailable(Py_None, &ignored);
18781
36
    }
18782
18783
    /*
18784
     * provide list of locally available functions
18785
     * so os.py can populate support_* lists
18786
     */
18787
36
    PyObject *list = PyList_New(0);
18788
36
    if (!list) {
18789
0
        return -1;
18790
0
    }
18791
1.18k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18792
1.15k
        PyObject *unicode;
18793
1.15k
        if (trace->probe && !trace->probe()) continue;
18794
1.15k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18795
1.15k
        if (!unicode)
18796
0
            return -1;
18797
1.15k
        if (PyList_Append(list, unicode))
18798
0
            return -1;
18799
1.15k
        Py_DECREF(unicode);
18800
1.15k
    }
18801
18802
36
#ifndef MS_WINDOWS
18803
36
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18804
0
        PyErr_SetString(PyExc_RuntimeError,
18805
0
                        "cannot read ticks_per_second");
18806
0
        return -1;
18807
0
    }
18808
36
    assert(state->ticks_per_second >= 1);
18809
36
#endif
18810
18811
36
    return PyModule_Add(m, "_have_functions", list);
18812
36
}
18813
18814
18815
static PyModuleDef_Slot posixmodile_slots[] = {
18816
    _Py_ABI_SLOT,
18817
    {Py_mod_exec, posixmodule_exec},
18818
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18819
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18820
    {0, NULL}
18821
};
18822
18823
static struct PyModuleDef posixmodule = {
18824
    PyModuleDef_HEAD_INIT,
18825
    .m_name = MODNAME,
18826
    .m_doc = posix__doc__,
18827
    .m_size = sizeof(_posixstate),
18828
    .m_methods = posix_methods,
18829
    .m_slots = posixmodile_slots,
18830
    .m_traverse = _posix_traverse,
18831
    .m_clear = _posix_clear,
18832
    .m_free = _posix_free,
18833
};
18834
18835
PyMODINIT_FUNC
18836
INITFUNC(void)
18837
36
{
18838
36
    return PyModuleDef_Init(&posixmodule);
18839
36
}