Coverage Report

Created: 2026-02-26 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Modules/posixmodule.c
Line
Count
Source
1
/* POSIX module implementation */
2
3
/* This file is also used for Windows NT/MS-Win.  In that case the
4
   module actually calls itself 'nt', not 'posix', and a few
5
   functions are either unimplemented or implemented differently.  The source
6
   assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
7
   of the compiler used.  Different compilers define their own feature
8
   test macro, e.g. '_MSC_VER'. */
9
10
// --- Python includes ------------------------------------------------------
11
12
#include "Python.h"
13
14
#ifdef __VXWORKS__
15
#  include "pycore_bitutils.h"    // _Py_popcount32()
16
#endif
17
#include "pycore_abstract.h"      // _PyNumber_Index()
18
#include "pycore_call.h"          // _PyObject_CallNoArgs()
19
#include "pycore_ceval.h"         // _PyEval_ReInitThreads()
20
#include "pycore_fileutils.h"     // _Py_closerange()
21
#include "pycore_import.h"        // _PyImport_AcquireLock()
22
#include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
23
#include "pycore_long.h"          // _PyLong_IsNegative()
24
#include "pycore_moduleobject.h"  // _PyModule_GetState()
25
#include "pycore_object.h"        // _PyObject_LookupSpecial()
26
#include "pycore_pylifecycle.h"   // _PyOS_URandom()
27
#include "pycore_pystate.h"       // _PyInterpreterState_GET()
28
#include "pycore_signal.h"        // Py_NSIG
29
#include "pycore_time.h"          // _PyLong_FromTime_t()
30
#include "pycore_typeobject.h"    // _PyType_AddMethod()
31
32
#ifndef MS_WINDOWS
33
#  include "posixmodule.h"        // _PyLong_FromUid()
34
#else
35
#  include "pycore_fileutils_windows.h" // _Py_GetFileInformationByName()
36
#  include "osdefs.h"             // SEP
37
#  include "winreparse.h"         // _Py_REPARSE_DATA_BUFFER
38
#endif
39
40
41
// --- System includes ------------------------------------------------------
42
43
#include <stddef.h>               // offsetof()
44
#include <stdio.h>                // ctermid()
45
#include <stdlib.h>               // system()
46
47
#ifdef HAVE_UNISTD_H
48
#  include <unistd.h>             // symlink()
49
#endif
50
51
#ifdef __APPLE__
52
   /* Needed for the implementation of os.statvfs */
53
#  include <sys/param.h>
54
#  include <sys/mount.h>
55
#endif
56
57
#ifdef HAVE_SYS_TIME_H
58
#  include <sys/time.h>           // futimes()
59
#endif
60
61
#ifdef HAVE_SYS_PIDFD_H
62
#  include <sys/pidfd.h>          // PIDFD_NONBLOCK
63
#endif
64
65
#ifdef __EMSCRIPTEN__
66
#  include "emscripten.h"         // emscripten_debugger()
67
#endif
68
69
#ifdef HAVE_SYS_UIO_H
70
#  include <sys/uio.h>
71
#endif
72
73
#ifdef HAVE_SYS_TYPES_H
74
   /* Should be included before <sys/sysmacros.h> on HP-UX v3 */
75
#  include <sys/types.h>
76
#endif
77
#ifdef HAVE_SYS_SYSMACROS_H
78
   /* GNU C Library: major(), minor(), makedev() */
79
#  include <sys/sysmacros.h>
80
#endif
81
82
#ifdef HAVE_SYS_STAT_H
83
#  include <sys/stat.h>
84
#endif
85
86
#ifdef HAVE_SYS_WAIT_H
87
#  include <sys/wait.h>           // WNOHANG
88
#endif
89
90
#ifdef HAVE_LINUX_WAIT_H
91
#  include <linux/wait.h>         // P_PIDFD
92
#endif
93
94
#ifdef HAVE_SIGNAL_H
95
#  include <signal.h>
96
#endif
97
98
#ifdef HAVE_FCNTL_H
99
#  include <fcntl.h>              // fcntl()
100
#endif
101
102
#ifdef HAVE_GRP_H
103
#  include <grp.h>                // setgroups()
104
#endif
105
106
#ifdef HAVE_SYSEXITS_H
107
#  include <sysexits.h>           // EX_OK
108
#endif
109
110
#ifdef HAVE_SYS_LOADAVG_H
111
#  include <sys/loadavg.h>        // getloadavg()
112
#endif
113
114
#ifdef HAVE_SYS_SENDFILE_H
115
#  include <sys/sendfile.h>       // sendfile()
116
#endif
117
118
#if defined(__APPLE__)
119
#  include <copyfile.h>           // fcopyfile()
120
#endif
121
122
#ifdef HAVE_SCHED_H
123
#  include <sched.h>              // sched_setscheduler()
124
#endif
125
#ifdef HAVE_LINUX_SCHED_H
126
#  include <linux/sched.h>        // SCHED_IDLE, SCHED_RR
127
#endif
128
129
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
130
#  ifdef HAVE_SYS_SOCKET_H
131
#    include <sys/socket.h>
132
#  endif
133
#endif
134
135
#ifdef HAVE_DLFCN_H
136
#  include <dlfcn.h>
137
#endif
138
139
#ifdef __hpux
140
#  include <sys/mpctl.h>
141
#endif
142
143
#if defined(__DragonFly__) || \
144
    defined(__OpenBSD__)   || \
145
    defined(__FreeBSD__)   || \
146
    defined(__NetBSD__)    || \
147
    defined(__APPLE__)
148
#  include <sys/sysctl.h>
149
#endif
150
151
#ifdef HAVE_LINUX_RANDOM_H
152
#  include <linux/random.h>       // GRND_RANDOM
153
#endif
154
#ifdef HAVE_GETRANDOM_SYSCALL
155
#  include <sys/syscall.h>        // syscall()
156
#endif
157
158
#ifdef HAVE_POSIX_SPAWN
159
#  include <spawn.h>              // posix_spawn()
160
#endif
161
162
#ifdef HAVE_UTIME_H
163
#  include <utime.h>              // utime()
164
#endif
165
166
#ifdef HAVE_SYS_UTIME_H
167
#  include <sys/utime.h>
168
#  define HAVE_UTIME_H /* pretend we do for the rest of this file */
169
#endif
170
171
#ifdef HAVE_SYS_TIMES_H
172
#  include <sys/times.h>          // times()
173
#endif
174
175
#ifdef HAVE_SYS_PARAM_H
176
#  include <sys/param.h>
177
#endif
178
179
#ifdef HAVE_SYS_UTSNAME_H
180
#  include <sys/utsname.h>        // uname()
181
#endif
182
183
/* memfd_create is either defined in sys/mman.h or sys/memfd.h
184
 * linux/memfd.h defines additional flags
185
 */
186
#ifdef HAVE_SYS_MMAN_H
187
#  include <sys/mman.h>           // memfd_create()
188
#endif
189
#ifdef HAVE_SYS_MEMFD_H
190
#  include <sys/memfd.h>          // memfd_create()
191
#endif
192
#ifdef HAVE_LINUX_MEMFD_H
193
#  include <linux/memfd.h>        // memfd_create(), MFD_CLOEXEC
194
#endif
195
196
#ifdef HAVE_SYS_EVENTFD_H
197
#  include <sys/eventfd.h>        // eventfd()
198
#endif
199
200
#ifdef HAVE_SYS_TIMERFD_H
201
#  include <sys/timerfd.h>        // timerfd_create()
202
#endif
203
204
#ifdef _Py_MEMORY_SANITIZER
205
#  include <sanitizer/msan_interface.h> // __msan_unpoison()
206
#endif
207
208
209
// --- More complex system includes -----------------------------------------
210
211
#ifdef MS_WINDOWS
212
#  include <windows.h>
213
#  if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP)
214
#    include <pathcch.h>          // PathCchSkipRoot()
215
#  endif
216
#  include <aclapi.h>             // SetEntriesInAcl
217
#  include <lmcons.h>             // UNLEN
218
#  include <sddl.h>               // SDDL_REVISION_1
219
#  include <winioctl.h>           // FSCTL_GET_REPARSE_POINT
220
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
221
#    define HAVE_SYMLINK
222
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
223
#endif
224
225
226
#ifdef _MSC_VER
227
#  ifdef HAVE_DIRECT_H
228
#    include <direct.h>
229
#  endif
230
#  ifdef HAVE_IO_H
231
#    include <io.h>
232
#  endif
233
#  ifdef HAVE_PROCESS_H
234
#    include <process.h>          // getpid(), _cwait()
235
#  endif
236
#  include <malloc.h>
237
#endif /* _MSC_VER */
238
239
240
#ifdef HAVE__GETPTY
241
#  include <sys/types.h>          // mode_t
242
   // SGI apparently needs this forward declaration
243
   extern char * _getpty(int *, int, mode_t, int);
244
#endif
245
246
247
#if defined(HAVE_SYS_XATTR_H)
248
#  if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
249
#    define USE_XATTRS
250
#    include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
251
#  endif
252
#  if defined(__CYGWIN__)
253
#    define USE_XATTRS
254
#    include <cygwin/limits.h>  // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX.
255
#  endif
256
#endif
257
#ifdef USE_XATTRS
258
#  include <sys/xattr.h>          // fgetxattr()
259
#endif
260
261
262
#ifdef HAVE_WINDOWS_CONSOLE_IO
263
#  define TERMSIZE_USE_CONIO
264
#elif defined(HAVE_SYS_IOCTL_H)
265
#  include <sys/ioctl.h>          // ioctl(), TIOCGWINSZ
266
#  if defined(HAVE_TERMIOS_H)
267
#    include <termios.h>
268
#  endif
269
#  if defined(TIOCGWINSZ)
270
#    define TERMSIZE_USE_IOCTL
271
#  endif
272
#endif
273
274
275
/* Various compilers have only certain posix functions */
276
/* XXX Gosh I wish these were all moved into pyconfig.h */
277
#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
278
#  define HAVE_OPENDIR    1
279
#  define HAVE_SYSTEM     1
280
#  include <process.h>
281
#elif defined( _MSC_VER)
282
  /* Microsoft compiler */
283
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
284
#    define HAVE_GETPPID    1
285
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */
286
#  if defined(MS_WINDOWS_DESKTOP)
287
#    define HAVE_GETLOGIN   1
288
#  endif /* MS_WINDOWS_DESKTOP */
289
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
290
#    define HAVE_SPAWNV     1
291
#    define HAVE_EXECV      1
292
#    define HAVE_WSPAWNV    1
293
#    define HAVE_WEXECV     1
294
#    define HAVE_SYSTEM     1
295
#    define HAVE_CWAIT      1
296
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
297
#  define HAVE_PIPE       1
298
#  define HAVE_FSYNC      1
299
#  define fsync _commit
300
#endif
301
302
303
#if !defined(_MSC_VER) && defined(__sgi) && _COMPILER_VERSION>=700
304
/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
305
   (default) */
306
extern char *ctermid_r(char *);
307
#endif
308
309
310
#if defined(__VXWORKS__)
311
#  include <vxCpuLib.h>
312
#  include <rtpLib.h>
313
#  include <wait.h>
314
#  include <taskLib.h>
315
#  ifndef _P_WAIT
316
#    define _P_WAIT          0
317
#    define _P_NOWAIT        1
318
#    define _P_NOWAITO       1
319
#  endif
320
#endif /* __VXWORKS__ */
321
322
323
#ifdef HAVE_DIRENT_H
324
#  include <dirent.h>             // opendir()
325
602k
#  define NAMLEN(dirent) strlen((dirent)->d_name)
326
#else
327
#  if defined(__WATCOMC__) && !defined(__QNX__)
328
#    include <direct.h>
329
#    define NAMLEN(dirent) strlen((dirent)->d_name)
330
#  else
331
#    define dirent direct
332
#    define NAMLEN(dirent) (dirent)->d_namlen
333
#  endif
334
#  ifdef HAVE_SYS_NDIR_H
335
#    include <sys/ndir.h>
336
#  endif
337
#  ifdef HAVE_SYS_DIR_H
338
#    include <sys/dir.h>
339
#  endif
340
#  ifdef HAVE_NDIR_H
341
#    include <ndir.h>
342
#  endif
343
#endif
344
345
346
#if defined(MAJOR_IN_MKDEV)
347
#  include <sys/mkdev.h>
348
#else
349
#  if defined(MAJOR_IN_SYSMACROS)
350
#    include <sys/sysmacros.h>
351
#  endif
352
#  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
353
#    include <sys/mkdev.h>
354
#  endif
355
#endif
356
357
358
// --- Macros ---------------------------------------------------------------
359
360
#ifndef MAXPATHLEN
361
#  if defined(PATH_MAX) && PATH_MAX > 1024
362
#    define MAXPATHLEN PATH_MAX
363
#  else
364
#    define MAXPATHLEN 1024
365
#  endif
366
#endif /* MAXPATHLEN */
367
368
369
#ifdef UNION_WAIT
370
   /* Emulate some macros on systems that have a union instead of macros */
371
#  ifndef WIFEXITED
372
#    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
373
#  endif
374
#  ifndef WEXITSTATUS
375
#    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
376
#  endif
377
#  ifndef WTERMSIG
378
#    define WTERMSIG(u_wait) ((u_wait).w_termsig)
379
#  endif
380
#  define WAIT_TYPE union wait
381
#  define WAIT_STATUS_INT(s) (s.w_status)
382
#else
383
   /* !UNION_WAIT */
384
0
#  define WAIT_TYPE int
385
0
#  define WAIT_STATUS_INT(s) (s)
386
#endif /* UNION_WAIT */
387
388
389
/* Don't use the "_r" form if we don't need it (also, won't have a
390
   prototype for it, at least on Solaris -- maybe others as well?). */
391
#if defined(HAVE_CTERMID_R)
392
#  define USE_CTERMID_R
393
#endif
394
395
396
/* choose the appropriate stat and fstat functions and return structs */
397
#undef STAT
398
#undef FSTAT
399
#undef STRUCT_STAT
400
#ifdef MS_WINDOWS
401
#  define STAT win32_stat
402
#  define LSTAT win32_lstat
403
#  define FSTAT _Py_fstat_noraise
404
#  define STRUCT_STAT struct _Py_stat_struct
405
#else
406
330k
#  define STAT stat
407
13.8k
#  define LSTAT lstat
408
184k
#  define FSTAT fstat
409
708k
#  define STRUCT_STAT struct stat
410
#endif
411
412
#ifdef HAVE_STATX
413
/* until we can assume glibc 2.28 at runtime, we must weakly link */
414
#  pragma weak statx
415
static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
416
#ifdef STATX_MNT_ID
417
                                             | STATX_MNT_ID
418
#endif
419
#ifdef STATX_DIOALIGN
420
                                             | STATX_DIOALIGN
421
#endif
422
#ifdef STATX_MNT_ID_UNIQUE
423
                                             | STATX_MNT_ID_UNIQUE
424
#endif
425
#ifdef STATX_SUBVOL
426
                                             | STATX_SUBVOL
427
#endif
428
#ifdef STATX_WRITE_ATOMIC
429
                                             | STATX_WRITE_ATOMIC
430
#endif
431
#ifdef STATX_DIO_READ_ALIGN
432
                                             | STATX_DIO_READ_ALIGN
433
#endif
434
                                            );
435
#endif /* HAVE_STATX */
436
437
438
#if !defined(EX_OK) && defined(EXIT_SUCCESS)
439
#  define EX_OK EXIT_SUCCESS
440
#endif
441
442
#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
443
#  undef HAVE_SCHED_SETAFFINITY
444
#endif
445
446
/* On android API level 21, 'AT_EACCESS' is not declared although
447
 * HAVE_FACCESSAT is defined. */
448
#ifdef __ANDROID__
449
#  undef HAVE_FACCESSAT
450
#endif
451
452
#if defined(__sun)
453
/* Something to implement in autoconf, not present in autoconf 2.69 */
454
#  define HAVE_STRUCT_STAT_ST_FSTYPE 1
455
#endif
456
457
458
// --- Apple __builtin_available() macros -----------------------------------
459
460
/*
461
 * A number of APIs are available on macOS from a certain macOS version.
462
 * To support building with a new SDK while deploying to older versions
463
 * the availability test is split into two:
464
 *   - HAVE_<FUNCTION>:  The configure check for compile time availability
465
 *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
466
 *
467
 * The latter is always true when not on macOS, or when using a compiler
468
 * that does not support __has_builtin (older versions of Xcode).
469
 *
470
 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
471
 *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
472
 *
473
 * In mixing the test with other tests or using negations will result in compile
474
 * errors.
475
 */
476
#if defined(__APPLE__)
477
478
#include <mach/mach.h>
479
480
#if defined(__has_builtin)
481
#if __has_builtin(__builtin_available)
482
#define HAVE_BUILTIN_AVAILABLE 1
483
#endif
484
#endif
485
486
#ifdef HAVE_BUILTIN_AVAILABLE
487
#  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
488
#  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
489
#  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
490
#  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
491
#  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
492
#  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
493
#  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
494
#  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
495
#  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
496
#  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
497
#  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
498
#  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
499
#  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
500
#  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
501
#  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
502
#  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
503
#  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
504
#  define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
505
506
#  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
507
508
#else /* Xcode 8 or earlier */
509
510
   /* __builtin_available is not present in these compilers, but
511
    * some of the symbols might be weak linked (10.10 SDK or later
512
    * deploying on 10.9.
513
    *
514
    * Fall back to the older style of availability checking for
515
    * symbols introduced in macOS 10.10.
516
    */
517
518
#  ifdef HAVE_FSTATAT
519
#    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
520
#  endif
521
522
#  ifdef HAVE_FACCESSAT
523
#    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
524
#  endif
525
526
#  ifdef HAVE_FCHMODAT
527
#    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
528
#  endif
529
530
#  ifdef HAVE_FCHOWNAT
531
#    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
532
#  endif
533
534
#  ifdef HAVE_LINKAT
535
#    define HAVE_LINKAT_RUNTIME (linkat != NULL)
536
#  endif
537
538
#  ifdef HAVE_FDOPENDIR
539
#    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
540
#  endif
541
542
#  ifdef HAVE_MKDIRAT
543
#    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
544
#  endif
545
546
#  ifdef HAVE_RENAMEAT
547
#    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
548
#  endif
549
550
#  ifdef HAVE_UNLINKAT
551
#    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
552
#  endif
553
554
#  ifdef HAVE_OPENAT
555
#    define HAVE_OPENAT_RUNTIME (openat != NULL)
556
#  endif
557
558
#  ifdef HAVE_READLINKAT
559
#    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
560
#  endif
561
562
#  ifdef HAVE_SYMLINKAT
563
#    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
564
#  endif
565
566
#  ifdef HAVE_UTIMENSAT
567
#    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
568
#  endif
569
570
#  ifdef HAVE_FUTIMENS
571
#    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
572
#  endif
573
574
#  ifdef HAVE_PWRITEV
575
#    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
576
#  endif
577
578
#  ifdef HAVE_MKFIFOAT
579
#    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
580
#  endif
581
582
#  ifdef HAVE_MKNODAT
583
#    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
584
#  endif
585
586
#  ifdef HAVE_PTSNAME_R
587
#    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
588
#  endif
589
590
#endif
591
592
#ifdef HAVE_FUTIMESAT
593
/* Some of the logic for weak linking depends on this assertion */
594
# error "HAVE_FUTIMESAT unexpectedly defined"
595
#endif
596
597
#else
598
180k
#  define HAVE_FSTATAT_RUNTIME 1
599
0
#  define HAVE_FACCESSAT_RUNTIME 1
600
0
#  define HAVE_FCHMODAT_RUNTIME 1
601
0
#  define HAVE_FCHOWNAT_RUNTIME 1
602
#ifdef __wasi__
603
#  define HAVE_LINKAT_RUNTIME 0
604
# else
605
0
#  define HAVE_LINKAT_RUNTIME 1
606
# endif
607
184k
#  define HAVE_FDOPENDIR_RUNTIME 1
608
0
#  define HAVE_MKDIRAT_RUNTIME 1
609
0
#  define HAVE_RENAMEAT_RUNTIME 1
610
216k
#  define HAVE_UNLINKAT_RUNTIME 1
611
180k
#  define HAVE_OPENAT_RUNTIME 1
612
0
#  define HAVE_READLINKAT_RUNTIME 1
613
0
#  define HAVE_SYMLINKAT_RUNTIME 1
614
0
#  define HAVE_FUTIMENS_RUNTIME 1
615
0
#  define HAVE_UTIMENSAT_RUNTIME 1
616
32
#  define HAVE_PWRITEV_RUNTIME 1
617
0
#  define HAVE_MKFIFOAT_RUNTIME 1
618
0
#  define HAVE_MKNODAT_RUNTIME 1
619
0
#  define HAVE_PTSNAME_R_RUNTIME 1
620
#endif
621
622
623
// --- os module ------------------------------------------------------------
624
625
#ifdef MS_WINDOWS
626
#  define INITFUNC PyInit_nt
627
#  define MODNAME "nt"
628
#  define MODNAME_OBJ &_Py_ID(nt)
629
#else
630
#  define INITFUNC PyInit_posix
631
#  define MODNAME "posix"
632
0
#  define MODNAME_OBJ &_Py_ID(posix)
633
#endif
634
635
/*[clinic input]
636
# one of the few times we lie about this name!
637
module os
638
[clinic start generated code]*/
639
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
640
641
PyDoc_STRVAR(posix__doc__,
642
"This module provides access to operating system functionality that is\n\
643
standardized by the C Standard and the POSIX standard (a thinly\n\
644
disguised Unix interface).  Refer to the library manual and\n\
645
corresponding Unix manual entries for more information on calls.");
646
647
648
// --- Functions ------------------------------------------------------------
649
650
#ifdef HAVE_FORK
651
static void
652
run_at_forkers(PyObject *lst, int reverse)
653
0
{
654
0
    Py_ssize_t i;
655
0
    PyObject *cpy;
656
657
0
    if (lst != NULL) {
658
0
        assert(PyList_CheckExact(lst));
659
660
        /* Use a list copy in case register_at_fork() is called from
661
         * one of the callbacks.
662
         */
663
0
        cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
664
0
        if (cpy == NULL) {
665
0
            PyErr_FormatUnraisable("Exception ignored in atfork callback "
666
0
                                   "while copying list %R", lst);
667
0
        }
668
0
        else {
669
0
            if (reverse)
670
0
                PyList_Reverse(cpy);
671
0
            for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
672
0
                PyObject *func, *res;
673
0
                func = PyList_GET_ITEM(cpy, i);
674
0
                res = _PyObject_CallNoArgs(func);
675
0
                if (res == NULL) {
676
0
                    PyErr_FormatUnraisable("Exception ignored "
677
0
                                           "in atfork callback %R", func);
678
0
                }
679
0
                else {
680
0
                    Py_DECREF(res);
681
0
                }
682
0
            }
683
0
            Py_DECREF(cpy);
684
0
        }
685
0
    }
686
0
}
687
688
void
689
PyOS_BeforeFork(void)
690
0
{
691
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
692
0
    run_at_forkers(interp->before_forkers, 1);
693
694
0
    _PyImport_AcquireLock(interp);
695
0
    _PyEval_StopTheWorldAll(&_PyRuntime);
696
0
    HEAD_LOCK(&_PyRuntime);
697
0
}
698
699
void
700
PyOS_AfterFork_Parent(void)
701
0
{
702
0
    HEAD_UNLOCK(&_PyRuntime);
703
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
704
705
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
706
0
    _PyImport_ReleaseLock(interp);
707
0
    run_at_forkers(interp->after_forkers_parent, 0);
708
0
}
709
710
static void
711
reset_remotedebug_data(PyThreadState *tstate)
712
0
{
713
0
    tstate->remote_debugger_support.debugger_pending_call = 0;
714
0
    memset(tstate->remote_debugger_support.debugger_script_path, 0,
715
0
           _Py_MAX_SCRIPT_PATH_SIZE);
716
0
}
717
718
static void
719
reset_asyncio_state(_PyThreadStateImpl *tstate)
720
0
{
721
0
    llist_init(&tstate->asyncio_tasks_head);
722
0
    tstate->asyncio_running_loop = NULL;
723
0
    tstate->asyncio_running_task = NULL;
724
0
}
725
726
727
void
728
PyOS_AfterFork_Child(void)
729
0
{
730
0
    PyStatus status;
731
0
    _PyRuntimeState *runtime = &_PyRuntime;
732
733
    // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
734
0
    status = _PyRuntimeState_ReInitThreads(runtime);
735
0
    if (_PyStatus_EXCEPTION(status)) {
736
0
        goto fatal_error;
737
0
    }
738
739
0
    PyThreadState *tstate = _PyThreadState_GET();
740
0
    _Py_EnsureTstateNotNULL(tstate);
741
742
0
    assert(tstate->thread_id == PyThread_get_thread_ident());
743
0
#ifdef PY_HAVE_THREAD_NATIVE_ID
744
0
    tstate->native_thread_id = PyThread_get_thread_native_id();
745
0
#endif
746
747
#ifdef Py_GIL_DISABLED
748
    _Py_brc_after_fork(tstate->interp);
749
    _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
750
#endif
751
752
    // Ideally we could guarantee tstate is running main.
753
0
    _PyInterpreterState_ReinitRunningMain(tstate);
754
755
0
    status = _PyEval_ReInitThreads(tstate);
756
0
    if (_PyStatus_EXCEPTION(status)) {
757
0
        goto fatal_error;
758
0
    }
759
760
0
    reset_remotedebug_data(tstate);
761
762
0
    reset_asyncio_state((_PyThreadStateImpl *)tstate);
763
764
    // Remove the dead thread states. We "start the world" once we are the only
765
    // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
766
    // That needs to happen before `_PyThreadState_DeleteList`, because that
767
    // may call destructors.
768
0
    PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
769
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
770
0
    _PyThreadState_DeleteList(list, /*is_after_fork=*/1);
771
772
0
    _PyImport_ReInitLock(tstate->interp);
773
0
    _PyImport_ReleaseLock(tstate->interp);
774
775
0
    _PySignal_AfterFork();
776
777
0
    status = _PyInterpreterState_DeleteExceptMain(runtime);
778
0
    if (_PyStatus_EXCEPTION(status)) {
779
0
        goto fatal_error;
780
0
    }
781
0
    assert(_PyThreadState_GET() == tstate);
782
783
0
    status = _PyPerfTrampoline_AfterFork_Child();
784
0
    if (_PyStatus_EXCEPTION(status)) {
785
0
        goto fatal_error;
786
0
    }
787
788
0
    run_at_forkers(tstate->interp->after_forkers_child, 0);
789
0
    return;
790
791
0
fatal_error:
792
0
    Py_ExitStatusException(status);
793
0
}
794
795
static int
796
register_at_forker(PyObject **lst, PyObject *func)
797
48
{
798
48
    if (func == NULL)  /* nothing to register? do nothing. */
799
28
        return 0;
800
20
    if (*lst == NULL) {
801
12
        *lst = PyList_New(0);
802
12
        if (*lst == NULL)
803
0
            return -1;
804
12
    }
805
20
    return PyList_Append(*lst, func);
806
20
}
807
#endif  /* HAVE_FORK */
808
809
810
/* Legacy wrapper */
811
void
812
PyOS_AfterFork(void)
813
0
{
814
0
#ifdef HAVE_FORK
815
0
    PyOS_AfterFork_Child();
816
0
#endif
817
0
}
818
819
820
#ifdef MS_WINDOWS
821
/* defined in fileutils.c */
822
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
823
void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
824
                                FILE_BASIC_INFO *, FILE_ID_INFO *,
825
                                struct _Py_stat_struct *);
826
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
827
                                 struct _Py_stat_struct *);
828
#endif
829
830
831
#ifndef MS_WINDOWS
832
PyObject *
833
_PyLong_FromUid(uid_t uid)
834
435k
{
835
435k
    if (uid == (uid_t)-1)
836
0
        return PyLong_FromLong(-1);
837
435k
    return PyLong_FromUnsignedLong(uid);
838
435k
}
839
840
PyObject *
841
_PyLong_FromGid(gid_t gid)
842
435k
{
843
435k
    if (gid == (gid_t)-1)
844
0
        return PyLong_FromLong(-1);
845
435k
    return PyLong_FromUnsignedLong(gid);
846
435k
}
847
848
int
849
_Py_Uid_Converter(PyObject *obj, uid_t *p)
850
0
{
851
0
    uid_t uid;
852
0
    PyObject *index;
853
0
    int overflow;
854
0
    long result;
855
0
    unsigned long uresult;
856
857
0
    index = _PyNumber_Index(obj);
858
0
    if (index == NULL) {
859
0
        PyErr_Format(PyExc_TypeError,
860
0
                     "uid should be integer, not %.200s",
861
0
                     _PyType_Name(Py_TYPE(obj)));
862
0
        return 0;
863
0
    }
864
865
    /*
866
     * Handling uid_t is complicated for two reasons:
867
     *  * Although uid_t is (always?) unsigned, it still
868
     *    accepts -1.
869
     *  * We don't know its size in advance--it may be
870
     *    bigger than an int, or it may be smaller than
871
     *    a long.
872
     *
873
     * So a bit of defensive programming is in order.
874
     * Start with interpreting the value passed
875
     * in as a signed long and see if it works.
876
     */
877
878
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
879
880
0
    if (!overflow) {
881
0
        uid = (uid_t)result;
882
883
0
        if (result == -1) {
884
0
            if (PyErr_Occurred())
885
0
                goto fail;
886
            /* It's a legitimate -1, we're done. */
887
0
            goto success;
888
0
        }
889
890
        /* Any other negative number is disallowed. */
891
0
        if (result < 0)
892
0
            goto underflow;
893
894
        /* Ensure the value wasn't truncated. */
895
0
        if (sizeof(uid_t) < sizeof(long) &&
896
0
            (long)uid != result)
897
0
            goto underflow;
898
0
        goto success;
899
0
    }
900
901
0
    if (overflow < 0)
902
0
        goto underflow;
903
904
    /*
905
     * Okay, the value overflowed a signed long.  If it
906
     * fits in an *unsigned* long, it may still be okay,
907
     * as uid_t may be unsigned long on this platform.
908
     */
909
0
    uresult = PyLong_AsUnsignedLong(index);
910
0
    if (PyErr_Occurred()) {
911
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
912
0
            goto overflow;
913
0
        goto fail;
914
0
    }
915
916
0
    uid = (uid_t)uresult;
917
918
    /*
919
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
920
     * but this value would get interpreted as (uid_t)-1  by chown
921
     * and its siblings.   That's not what the user meant!  So we
922
     * throw an overflow exception instead.   (We already
923
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
924
     */
925
0
    if (uid == (uid_t)-1)
926
0
        goto overflow;
927
928
    /* Ensure the value wasn't truncated. */
929
0
    if (sizeof(uid_t) < sizeof(long) &&
930
0
        (unsigned long)uid != uresult)
931
0
        goto overflow;
932
    /* fallthrough */
933
934
0
success:
935
0
    Py_DECREF(index);
936
0
    *p = uid;
937
0
    return 1;
938
939
0
underflow:
940
0
    PyErr_SetString(PyExc_OverflowError,
941
0
                    "uid is less than minimum");
942
0
    goto fail;
943
944
0
overflow:
945
0
    PyErr_SetString(PyExc_OverflowError,
946
0
                    "uid is greater than maximum");
947
    /* fallthrough */
948
949
0
fail:
950
0
    Py_DECREF(index);
951
0
    return 0;
952
0
}
953
954
int
955
_Py_Gid_Converter(PyObject *obj, gid_t *p)
956
0
{
957
0
    gid_t gid;
958
0
    PyObject *index;
959
0
    int overflow;
960
0
    long result;
961
0
    unsigned long uresult;
962
963
0
    index = _PyNumber_Index(obj);
964
0
    if (index == NULL) {
965
0
        PyErr_Format(PyExc_TypeError,
966
0
                     "gid should be integer, not %.200s",
967
0
                     _PyType_Name(Py_TYPE(obj)));
968
0
        return 0;
969
0
    }
970
971
    /*
972
     * Handling gid_t is complicated for two reasons:
973
     *  * Although gid_t is (always?) unsigned, it still
974
     *    accepts -1.
975
     *  * We don't know its size in advance--it may be
976
     *    bigger than an int, or it may be smaller than
977
     *    a long.
978
     *
979
     * So a bit of defensive programming is in order.
980
     * Start with interpreting the value passed
981
     * in as a signed long and see if it works.
982
     */
983
984
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
985
986
0
    if (!overflow) {
987
0
        gid = (gid_t)result;
988
989
0
        if (result == -1) {
990
0
            if (PyErr_Occurred())
991
0
                goto fail;
992
            /* It's a legitimate -1, we're done. */
993
0
            goto success;
994
0
        }
995
996
        /* Any other negative number is disallowed. */
997
0
        if (result < 0) {
998
0
            goto underflow;
999
0
        }
1000
1001
        /* Ensure the value wasn't truncated. */
1002
0
        if (sizeof(gid_t) < sizeof(long) &&
1003
0
            (long)gid != result)
1004
0
            goto underflow;
1005
0
        goto success;
1006
0
    }
1007
1008
0
    if (overflow < 0)
1009
0
        goto underflow;
1010
1011
    /*
1012
     * Okay, the value overflowed a signed long.  If it
1013
     * fits in an *unsigned* long, it may still be okay,
1014
     * as gid_t may be unsigned long on this platform.
1015
     */
1016
0
    uresult = PyLong_AsUnsignedLong(index);
1017
0
    if (PyErr_Occurred()) {
1018
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1019
0
            goto overflow;
1020
0
        goto fail;
1021
0
    }
1022
1023
0
    gid = (gid_t)uresult;
1024
1025
    /*
1026
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
1027
     * but this value would get interpreted as (gid_t)-1  by chown
1028
     * and its siblings.   That's not what the user meant!  So we
1029
     * throw an overflow exception instead.   (We already
1030
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
1031
     */
1032
0
    if (gid == (gid_t)-1)
1033
0
        goto overflow;
1034
1035
    /* Ensure the value wasn't truncated. */
1036
0
    if (sizeof(gid_t) < sizeof(long) &&
1037
0
        (unsigned long)gid != uresult)
1038
0
        goto overflow;
1039
    /* fallthrough */
1040
1041
0
success:
1042
0
    Py_DECREF(index);
1043
0
    *p = gid;
1044
0
    return 1;
1045
1046
0
underflow:
1047
0
    PyErr_SetString(PyExc_OverflowError,
1048
0
                    "gid is less than minimum");
1049
0
    goto fail;
1050
1051
0
overflow:
1052
0
    PyErr_SetString(PyExc_OverflowError,
1053
0
                    "gid is greater than maximum");
1054
    /* fallthrough */
1055
1056
0
fail:
1057
0
    Py_DECREF(index);
1058
0
    return 0;
1059
0
}
1060
#endif /* MS_WINDOWS */
1061
1062
1063
static PyObject *
1064
_PyLong_FromDev(dev_t dev)
1065
871k
{
1066
871k
#ifdef NODEV
1067
871k
    if (dev == NODEV) {
1068
32
        return PyLong_FromLongLong((long long)dev);
1069
32
    }
1070
871k
#endif
1071
871k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1072
871k
}
1073
1074
1075
#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
1076
static int
1077
_Py_Dev_Converter(PyObject *obj, void *p)
1078
0
{
1079
0
    if (!PyLong_Check(obj)) {
1080
0
        obj = _PyNumber_Index(obj);
1081
0
        if (obj == NULL) {
1082
0
            return 0;
1083
0
        }
1084
0
    }
1085
0
    else {
1086
0
        Py_INCREF(obj);
1087
0
    }
1088
0
    assert(PyLong_Check(obj));
1089
0
#ifdef NODEV
1090
0
    if (_PyLong_IsNegative((PyLongObject *)obj)) {
1091
0
        int overflow;
1092
0
        long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
1093
0
        if (result == -1 && PyErr_Occurred()) {
1094
0
            Py_DECREF(obj);
1095
0
            return 0;
1096
0
        }
1097
0
        if (!overflow && result == (long long)NODEV) {
1098
0
            *((dev_t *)p) = NODEV;
1099
0
            Py_DECREF(obj);
1100
0
            return 1;
1101
0
        }
1102
0
    }
1103
0
#endif
1104
1105
0
    unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1106
0
    Py_DECREF(obj);
1107
0
    if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1108
0
        return 0;
1109
0
    }
1110
0
    if ((unsigned long long)(dev_t)result != result) {
1111
0
        PyErr_SetString(PyExc_OverflowError,
1112
0
                        "Python int too large to convert to C dev_t");
1113
0
        return 0;
1114
0
    }
1115
0
    *((dev_t *)p) = (dev_t)result;
1116
0
    return 1;
1117
0
}
1118
#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1119
1120
1121
#ifdef AT_FDCWD
1122
/*
1123
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1124
 * without the int cast, the value gets interpreted as uint (4291925331),
1125
 * which doesn't play nicely with all the initializer lines in this file that
1126
 * look like this:
1127
 *      int dir_fd = DEFAULT_DIR_FD;
1128
 */
1129
3.16M
#define DEFAULT_DIR_FD (int)AT_FDCWD
1130
#else
1131
#define DEFAULT_DIR_FD (-100)
1132
#endif
1133
1134
static int
1135
_fd_converter(PyObject *o, int *p)
1136
581k
{
1137
581k
    int overflow;
1138
581k
    long long_value;
1139
1140
581k
    if (PyBool_Check(o)) {
1141
0
        if (PyErr_WarnEx(PyExc_RuntimeWarning,
1142
0
                "bool is used as a file descriptor", 1))
1143
0
        {
1144
0
            return 0;
1145
0
        }
1146
0
    }
1147
581k
    PyObject *index = _PyNumber_Index(o);
1148
581k
    if (index == NULL) {
1149
0
        return 0;
1150
0
    }
1151
1152
581k
    assert(PyLong_Check(index));
1153
581k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1154
581k
    Py_DECREF(index);
1155
581k
    assert(!PyErr_Occurred());
1156
581k
    if (overflow > 0 || long_value > INT_MAX) {
1157
0
        PyErr_SetString(PyExc_OverflowError,
1158
0
                        "fd is greater than maximum");
1159
0
        return 0;
1160
0
    }
1161
581k
    if (overflow < 0 || long_value < INT_MIN) {
1162
0
        PyErr_SetString(PyExc_OverflowError,
1163
0
                        "fd is less than minimum");
1164
0
        return 0;
1165
0
    }
1166
1167
581k
    *p = (int)long_value;
1168
581k
    return 1;
1169
581k
}
1170
1171
static int
1172
dir_fd_converter(PyObject *o, void *p)
1173
415k
{
1174
415k
    if (o == Py_None) {
1175
19.0k
        *(int *)p = DEFAULT_DIR_FD;
1176
19.0k
        return 1;
1177
19.0k
    }
1178
396k
    else if (PyIndex_Check(o)) {
1179
396k
        return _fd_converter(o, (int *)p);
1180
396k
    }
1181
0
    else {
1182
0
        PyErr_Format(PyExc_TypeError,
1183
0
                     "argument should be integer or None, not %.200s",
1184
0
                     _PyType_Name(Py_TYPE(o)));
1185
0
        return 0;
1186
0
    }
1187
415k
}
1188
1189
typedef struct {
1190
    PyObject *billion;
1191
    PyObject *DirEntryType;
1192
    PyObject *ScandirIteratorType;
1193
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1194
    PyObject *SchedParamType;
1195
#endif
1196
    newfunc statresult_new_orig;
1197
    PyObject *StatResultType;
1198
#ifdef HAVE_STATX
1199
    PyObject *StatxResultType;
1200
#endif
1201
    PyObject *StatVFSResultType;
1202
    PyObject *TerminalSizeType;
1203
    PyObject *TimesResultType;
1204
    PyObject *UnameResultType;
1205
#if defined(HAVE_WAITID)
1206
    PyObject *WaitidResultType;
1207
#endif
1208
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1209
    PyObject *struct_rusage;
1210
#endif
1211
    PyObject *st_mode;
1212
#ifndef MS_WINDOWS
1213
    // times() clock frequency in hertz; used by os.times()
1214
    long ticks_per_second;
1215
#endif
1216
} _posixstate;
1217
1218
1219
static inline _posixstate*
1220
get_posix_state(PyObject *module)
1221
838k
{
1222
838k
    void *state = _PyModule_GetState(module);
1223
838k
    assert(state != NULL);
1224
838k
    return (_posixstate *)state;
1225
838k
}
1226
1227
/*
1228
 * A PyArg_ParseTuple "converter" function
1229
 * that handles filesystem paths in the manner
1230
 * preferred by the os module.
1231
 *
1232
 * path_converter accepts (Unicode) strings and their
1233
 * subclasses, and bytes and their subclasses.  What
1234
 * it does with the argument depends on path.make_wide:
1235
 *
1236
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1237
 *     string we extract the wchar_t * and return it; if we
1238
 *     get bytes we decode to wchar_t * and return that.
1239
 *
1240
 *   * If path.make_wide is zero, if we get bytes we extract
1241
 *     the char_t * and return it; if we get a (Unicode)
1242
 *     string we encode to char_t * and return that.
1243
 *
1244
 * path_converter also optionally accepts signed
1245
 * integers (representing open file descriptors) instead
1246
 * of path strings.
1247
 *
1248
 * Input fields:
1249
 *   path.nullable
1250
 *     If nonzero, the path is permitted to be None.
1251
 *   path.nonstrict
1252
 *     If nonzero, the path is permitted to contain
1253
 *     embedded null characters and have any length.
1254
 *   path.make_wide
1255
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1256
 *     it always uses narrow, encoding if necessary. The default value is
1257
 *     nonzero on Windows, else zero.
1258
 *   path.suppress_value_error
1259
 *     If nonzero, raising ValueError is suppressed.
1260
 *   path.allow_fd
1261
 *     If nonzero, the path is permitted to be a file handle
1262
 *     (a signed int) instead of a string.
1263
 *   path.function_name
1264
 *     If non-NULL, path_converter will use that as the name
1265
 *     of the function in error messages.
1266
 *     (If path.function_name is NULL it omits the function name.)
1267
 *   path.argument_name
1268
 *     If non-NULL, path_converter will use that as the name
1269
 *     of the parameter in error messages.
1270
 *     (If path.argument_name is NULL it uses "path".)
1271
 *
1272
 * Output fields:
1273
 *   path.wide
1274
 *     Points to the path if it was expressed as Unicode
1275
 *     or if it was bytes and decoded to Unicode.
1276
 *   path.narrow
1277
 *     Points to the path if it was expressed as bytes,
1278
 *     or if it was Unicode and encoded to bytes.
1279
 *   path.fd
1280
 *     Contains a file descriptor if path.accept_fd was true
1281
 *     and the caller provided a signed integer instead of any
1282
 *     sort of string.
1283
 *
1284
 *     WARNING: if your "path" parameter is optional, and is
1285
 *     unspecified, path_converter will never get called.
1286
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1287
 *     yourself!
1288
 *   path.value_error
1289
 *     If nonzero, then suppress_value_error was specified and a ValueError
1290
 *     occurred.
1291
 *   path.length
1292
 *     The length of the path in characters, if specified as
1293
 *     a string.
1294
 *   path.object
1295
 *     The original object passed in (if get a PathLike object,
1296
 *     the result of PyOS_FSPath() is treated as the original object).
1297
 *     Own a reference to the object.
1298
 *   path.cleanup
1299
 *     For internal use only.  May point to a temporary object.
1300
 *     (Pay no attention to the man behind the curtain.)
1301
 *
1302
 *   At most one of path.wide or path.narrow will be non-NULL.
1303
 *   If path was None and path.nullable was set,
1304
 *     or if path was an integer and path.allow_fd was set,
1305
 *     both path.wide and path.narrow will be NULL
1306
 *     and path.length will be 0.
1307
 *
1308
 *   path_converter takes care to not write to the path_t
1309
 *   unless it's successful.  However it must reset the
1310
 *   "cleanup" field each time it's called.
1311
 *
1312
 * Use as follows:
1313
 *      path_t path;
1314
 *      memset(&path, 0, sizeof(path));
1315
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1316
 *      // ... use values from path ...
1317
 *      path_cleanup(&path);
1318
 *
1319
 * (Note that if PyArg_Parse fails you don't need to call
1320
 * path_cleanup().  However it is safe to do so.)
1321
 */
1322
typedef struct {
1323
    // Input fields
1324
    const char *function_name;
1325
    const char *argument_name;
1326
    int nullable;
1327
    int nonstrict;
1328
    int make_wide;
1329
    int suppress_value_error;
1330
    int allow_fd;
1331
    // Output fields
1332
    const wchar_t *wide;
1333
    const char *narrow;
1334
    int fd;
1335
    int value_error;
1336
    Py_ssize_t length;
1337
    PyObject *object;
1338
    PyObject *cleanup;
1339
} path_t;
1340
1341
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1342
                          make_wide, suppress_value_error, allow_fd) \
1343
1.38M
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1344
1.38M
     suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL}
1345
#ifdef MS_WINDOWS
1346
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1347
                            nonstrict, suppress_value_error, allow_fd) \
1348
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1349
                      suppress_value_error, allow_fd)
1350
#else
1351
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1352
                            nonstrict, suppress_value_error, allow_fd) \
1353
1.12M
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1354
1.12M
                      suppress_value_error, allow_fd)
1355
#endif
1356
1357
static void
1358
path_cleanup(path_t *path)
1359
1.57M
{
1360
1.57M
    wchar_t *wide = (wchar_t *)path->wide;
1361
1.57M
    path->wide = NULL;
1362
1.57M
    PyMem_Free(wide);
1363
1.57M
    Py_CLEAR(path->object);
1364
1.57M
    Py_CLEAR(path->cleanup);
1365
1.57M
}
1366
1367
static int
1368
path_converter(PyObject *o, void *p)
1369
1.38M
{
1370
1.38M
    path_t *path = (path_t *)p;
1371
1.38M
    PyObject *bytes = NULL;
1372
1.38M
    Py_ssize_t length = 0;
1373
1.38M
    int is_index, is_bytes, is_unicode;
1374
1.38M
    const char *narrow;
1375
1.38M
    PyObject *wo = NULL;
1376
1.38M
    wchar_t *wide = NULL;
1377
1378
1.38M
#define FORMAT_EXCEPTION(exc, fmt) \
1379
1.38M
    PyErr_Format(exc, "%s%s" fmt, \
1380
0
        path->function_name ? path->function_name : "", \
1381
0
        path->function_name ? ": "                : "", \
1382
0
        path->argument_name ? path->argument_name : "path")
1383
1384
    /* Py_CLEANUP_SUPPORTED support */
1385
1.38M
    if (o == NULL) {
1386
0
        path_cleanup(path);
1387
0
        return 1;
1388
0
    }
1389
1390
    /* Ensure it's always safe to call path_cleanup(). */
1391
1.38M
    path->object = path->cleanup = NULL;
1392
    /* path->object owns a reference to the original object */
1393
1.38M
    Py_INCREF(o);
1394
1395
1.38M
    if ((o == Py_None) && path->nullable) {
1396
0
        path->wide = NULL;
1397
0
        path->narrow = NULL;
1398
0
        path->fd = -1;
1399
0
        goto success_exit;
1400
0
    }
1401
1402
    /* Only call this here so that we don't treat the return value of
1403
       os.fspath() as an fd or buffer. */
1404
1.38M
    is_index = path->allow_fd && PyIndex_Check(o);
1405
1.38M
    is_bytes = PyBytes_Check(o);
1406
1.38M
    is_unicode = PyUnicode_Check(o);
1407
1408
1.38M
    if (!is_index && !is_unicode && !is_bytes) {
1409
        /* Inline PyOS_FSPath() for better error messages. */
1410
8
        PyObject *func, *res;
1411
1412
8
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1413
8
        if ((NULL == func) || (func == Py_None)) {
1414
0
            goto error_format;
1415
0
        }
1416
8
        res = _PyObject_CallNoArgs(func);
1417
8
        Py_DECREF(func);
1418
8
        if (NULL == res) {
1419
0
            goto error_exit;
1420
0
        }
1421
8
        else if (PyUnicode_Check(res)) {
1422
8
            is_unicode = 1;
1423
8
        }
1424
0
        else if (PyBytes_Check(res)) {
1425
0
            is_bytes = 1;
1426
0
        }
1427
0
        else {
1428
0
            PyErr_Format(PyExc_TypeError,
1429
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1430
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1431
0
                 _PyType_Name(Py_TYPE(res)));
1432
0
            Py_DECREF(res);
1433
0
            goto error_exit;
1434
0
        }
1435
1436
        /* still owns a reference to the original object */
1437
8
        Py_SETREF(o, res);
1438
8
    }
1439
1440
1.38M
    if (is_unicode) {
1441
1.20M
        if (path->make_wide) {
1442
268k
            wide = PyUnicode_AsWideCharString(o, &length);
1443
268k
            if (!wide) {
1444
0
                goto error_exit;
1445
0
            }
1446
#ifdef MS_WINDOWS
1447
            if (!path->nonstrict && length > 32767) {
1448
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1449
                goto error_exit;
1450
            }
1451
#endif
1452
268k
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1453
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1454
0
                                 "embedded null character in %s");
1455
0
                goto error_exit;
1456
0
            }
1457
1458
268k
            path->wide = wide;
1459
268k
            path->narrow = NULL;
1460
268k
            path->fd = -1;
1461
268k
            wide = NULL;
1462
268k
            goto success_exit;
1463
268k
        }
1464
936k
        bytes = PyUnicode_EncodeFSDefault(o);
1465
936k
        if (!bytes) {
1466
0
            goto error_exit;
1467
0
        }
1468
936k
    }
1469
184k
    else if (is_bytes) {
1470
0
        bytes = Py_NewRef(o);
1471
0
    }
1472
184k
    else if (is_index) {
1473
184k
        if (!_fd_converter(o, &path->fd)) {
1474
0
            goto error_exit;
1475
0
        }
1476
184k
        path->wide = NULL;
1477
184k
        path->narrow = NULL;
1478
184k
        goto success_exit;
1479
184k
    }
1480
0
    else {
1481
0
 error_format:
1482
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1483
0
            path->function_name ? path->function_name : "",
1484
0
            path->function_name ? ": "                : "",
1485
0
            path->argument_name ? path->argument_name : "path",
1486
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1487
0
                                               "integer or None" :
1488
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1489
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1490
0
                             "string, bytes or os.PathLike",
1491
0
            _PyType_Name(Py_TYPE(o)));
1492
0
        goto error_exit;
1493
0
    }
1494
1495
936k
    length = PyBytes_GET_SIZE(bytes);
1496
936k
    narrow = PyBytes_AS_STRING(bytes);
1497
936k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1498
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1499
0
        goto error_exit;
1500
0
    }
1501
1502
936k
    if (path->make_wide) {
1503
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1504
0
        if (!wo) {
1505
0
            goto error_exit;
1506
0
        }
1507
1508
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1509
0
        Py_DECREF(wo);
1510
0
        if (!wide) {
1511
0
            goto error_exit;
1512
0
        }
1513
#ifdef MS_WINDOWS
1514
        if (!path->nonstrict && length > 32767) {
1515
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1516
            goto error_exit;
1517
        }
1518
#endif
1519
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1520
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1521
0
                             "embedded null character in %s");
1522
0
            goto error_exit;
1523
0
        }
1524
0
        path->wide = wide;
1525
0
        path->narrow = NULL;
1526
0
        Py_DECREF(bytes);
1527
0
        wide = NULL;
1528
0
    }
1529
936k
    else {
1530
936k
        path->wide = NULL;
1531
936k
        path->narrow = narrow;
1532
936k
        if (bytes == o) {
1533
            /* Still a reference owned by path->object, don't have to
1534
            worry about path->narrow is used after free. */
1535
0
            Py_DECREF(bytes);
1536
0
        }
1537
936k
        else {
1538
936k
            path->cleanup = bytes;
1539
936k
        }
1540
936k
    }
1541
936k
    path->fd = -1;
1542
1543
1.38M
 success_exit:
1544
1.38M
    path->value_error = 0;
1545
1.38M
    path->length = length;
1546
1.38M
    path->object = o;
1547
1.38M
    return Py_CLEANUP_SUPPORTED;
1548
1549
0
 error_exit:
1550
0
    Py_XDECREF(o);
1551
0
    Py_XDECREF(bytes);
1552
0
    PyMem_Free(wide);
1553
0
    if (!path->suppress_value_error ||
1554
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1555
0
    {
1556
0
        return 0;
1557
0
    }
1558
0
    PyErr_Clear();
1559
0
    path->wide = NULL;
1560
0
    path->narrow = NULL;
1561
0
    path->fd = -1;
1562
0
    path->value_error = 1;
1563
0
    path->length = 0;
1564
0
    path->object = NULL;
1565
0
    return Py_CLEANUP_SUPPORTED;
1566
0
}
1567
1568
static void
1569
argument_unavailable_error(const char *function_name, const char *argument_name)
1570
0
{
1571
0
    PyErr_Format(PyExc_NotImplementedError,
1572
0
        "%s%s%s unavailable on this platform",
1573
0
        (function_name != NULL) ? function_name : "",
1574
0
        (function_name != NULL) ? ": ": "",
1575
0
        argument_name);
1576
0
}
1577
1578
static int
1579
dir_fd_unavailable(PyObject *o, void *p)
1580
32
{
1581
32
    int dir_fd;
1582
32
    if (!dir_fd_converter(o, &dir_fd))
1583
0
        return 0;
1584
32
    if (dir_fd != DEFAULT_DIR_FD) {
1585
0
        argument_unavailable_error(NULL, "dir_fd");
1586
0
        return 0;
1587
0
    }
1588
32
    *(int *)p = dir_fd;
1589
32
    return 1;
1590
32
}
1591
1592
static int
1593
fd_specified(const char *function_name, int fd)
1594
32
{
1595
32
    if (fd == -1)
1596
32
        return 0;
1597
1598
0
    argument_unavailable_error(function_name, "fd");
1599
0
    return 1;
1600
32
}
1601
1602
static int
1603
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1604
32
{
1605
32
    if (follow_symlinks)
1606
32
        return 0;
1607
1608
0
    argument_unavailable_error(function_name, "follow_symlinks");
1609
0
    return 1;
1610
32
}
1611
1612
static int
1613
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1614
343k
{
1615
343k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1616
0
        PyErr_Format(PyExc_ValueError,
1617
0
                     "%s: can't specify dir_fd without matching path",
1618
0
                     function_name);
1619
0
        return 1;
1620
0
    }
1621
343k
    return 0;
1622
343k
}
1623
1624
static int
1625
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1626
343k
{
1627
343k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1628
0
        PyErr_Format(PyExc_ValueError,
1629
0
                     "%s: can't specify both dir_fd and fd",
1630
0
                     function_name);
1631
0
        return 1;
1632
0
    }
1633
343k
    return 0;
1634
343k
}
1635
1636
static int
1637
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1638
                               int follow_symlinks)
1639
343k
{
1640
343k
    if ((fd >= 0) && (!follow_symlinks)) {
1641
0
        PyErr_Format(PyExc_ValueError,
1642
0
                     "%s: cannot use fd and follow_symlinks together",
1643
0
                     function_name);
1644
0
        return 1;
1645
0
    }
1646
343k
    return 0;
1647
343k
}
1648
1649
static int
1650
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1651
                                   int follow_symlinks)
1652
32
{
1653
32
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1654
0
        PyErr_Format(PyExc_ValueError,
1655
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1656
0
                     function_name);
1657
0
        return 1;
1658
0
    }
1659
32
    return 0;
1660
32
}
1661
1662
#if defined(HAVE_WAITID)
1663
static int
1664
idtype_t_converter(PyObject *arg, void *addr)
1665
0
{
1666
0
    int value = PyLong_AsInt(arg);
1667
0
    if (value == -1 && PyErr_Occurred()) {
1668
0
        return 0;
1669
0
    }
1670
0
    *((idtype_t *)addr) = (idtype_t)(value);
1671
0
    return 1;
1672
0
}
1673
#endif
1674
1675
#ifdef MS_WINDOWS
1676
    typedef long long Py_off_t;
1677
#else
1678
    typedef off_t Py_off_t;
1679
#endif
1680
1681
static int
1682
Py_off_t_converter(PyObject *arg, void *addr)
1683
0
{
1684
#ifdef HAVE_LARGEFILE_SUPPORT
1685
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1686
#else
1687
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1688
0
#endif
1689
0
    if (PyErr_Occurred())
1690
0
        return 0;
1691
0
    return 1;
1692
0
}
1693
1694
static PyObject *
1695
PyLong_FromPy_off_t(Py_off_t offset)
1696
0
{
1697
#ifdef HAVE_LARGEFILE_SUPPORT
1698
    return PyLong_FromLongLong(offset);
1699
#else
1700
0
    return PyLong_FromLong(offset);
1701
0
#endif
1702
0
}
1703
1704
#ifdef HAVE_SIGSET_T
1705
/* Convert an iterable of integers to a sigset.
1706
   Return 1 on success, return 0 and raise an exception on error. */
1707
int
1708
_Py_Sigset_Converter(PyObject *obj, void *addr)
1709
0
{
1710
0
    sigset_t *mask = (sigset_t *)addr;
1711
0
    PyObject *iterator, *item;
1712
0
    long signum;
1713
0
    int overflow;
1714
1715
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1716
0
    if (sigemptyset(mask) < (0)) {
1717
        /* Probably only if mask == NULL. */
1718
0
        PyErr_SetFromErrno(PyExc_OSError);
1719
0
        return 0;
1720
0
    }
1721
1722
0
    iterator = PyObject_GetIter(obj);
1723
0
    if (iterator == NULL) {
1724
0
        return 0;
1725
0
    }
1726
1727
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1728
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1729
0
        Py_DECREF(item);
1730
0
        if (signum <= 0 || signum >= Py_NSIG) {
1731
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1732
0
                PyErr_Format(PyExc_ValueError,
1733
0
                             "signal number %ld out of range [1; %i]",
1734
0
                             signum, Py_NSIG - 1);
1735
0
            }
1736
0
            goto error;
1737
0
        }
1738
0
        if (sigaddset(mask, (int)signum)) {
1739
0
            if (errno != EINVAL) {
1740
                /* Probably impossible */
1741
0
                PyErr_SetFromErrno(PyExc_OSError);
1742
0
                goto error;
1743
0
            }
1744
            /* For backwards compatibility, allow idioms such as
1745
             * `range(1, NSIG)` but warn about invalid signal numbers
1746
             */
1747
0
            const char msg[] =
1748
0
                "invalid signal number %ld, please use valid_signals()";
1749
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1750
0
                goto error;
1751
0
            }
1752
0
        }
1753
0
    }
1754
0
    if (!PyErr_Occurred()) {
1755
0
        Py_DECREF(iterator);
1756
0
        return 1;
1757
0
    }
1758
1759
0
error:
1760
0
    Py_DECREF(iterator);
1761
0
    return 0;
1762
0
}
1763
#endif /* HAVE_SIGSET_T */
1764
1765
/* Return a dictionary corresponding to the POSIX environment table */
1766
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1767
/* On Darwin/MacOSX a shared library or framework has no access to
1768
** environ directly, we must obtain it with _NSGetEnviron(). See also
1769
** man environ(7).
1770
*/
1771
#include <crt_externs.h>
1772
#define USE_DARWIN_NS_GET_ENVIRON 1
1773
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1774
extern char **environ;
1775
#endif /* !_MSC_VER */
1776
1777
static PyObject *
1778
convertenviron(void)
1779
32
{
1780
32
    PyObject *d;
1781
#ifdef MS_WINDOWS
1782
    wchar_t **e;
1783
#else
1784
32
    char **e;
1785
32
#endif
1786
1787
32
    d = PyDict_New();
1788
32
    if (d == NULL)
1789
0
        return NULL;
1790
#ifdef MS_WINDOWS
1791
    /* _wenviron must be initialized in this way if the program is started
1792
       through main() instead of wmain(). */
1793
    (void)_wgetenv(L"");
1794
    e = _wenviron;
1795
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1796
    /* environ is not accessible as an extern in a shared object on OSX; use
1797
       _NSGetEnviron to resolve it. The value changes if you add environment
1798
       variables between calls to Py_Initialize, so don't cache the value. */
1799
    e = *_NSGetEnviron();
1800
#else
1801
32
    e = environ;
1802
32
#endif
1803
32
    if (e == NULL)
1804
0
        return d;
1805
1.12k
    for (; *e != NULL; e++) {
1806
1.08k
        PyObject *k;
1807
1.08k
        PyObject *v;
1808
#ifdef MS_WINDOWS
1809
        const wchar_t *p = wcschr(*e, L'=');
1810
#else
1811
1.08k
        const char *p = strchr(*e, '=');
1812
1.08k
#endif
1813
1.08k
        if (p == NULL)
1814
0
            continue;
1815
#ifdef MS_WINDOWS
1816
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1817
#else
1818
1.08k
        k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
1819
1.08k
#endif
1820
1.08k
        if (k == NULL) {
1821
0
            Py_DECREF(d);
1822
0
            return NULL;
1823
0
        }
1824
#ifdef MS_WINDOWS
1825
        v = PyUnicode_FromWideChar(p+1, -1);
1826
#else
1827
1.08k
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1828
1.08k
#endif
1829
1.08k
        if (v == NULL) {
1830
0
            Py_DECREF(k);
1831
0
            Py_DECREF(d);
1832
0
            return NULL;
1833
0
        }
1834
1.08k
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1835
0
            Py_DECREF(v);
1836
0
            Py_DECREF(k);
1837
0
            Py_DECREF(d);
1838
0
            return NULL;
1839
0
        }
1840
1.08k
        Py_DECREF(k);
1841
1.08k
        Py_DECREF(v);
1842
1.08k
    }
1843
32
    return d;
1844
32
}
1845
1846
/* Set a POSIX-specific error from errno, and return NULL */
1847
1848
static PyObject *
1849
posix_error(void)
1850
0
{
1851
0
    return PyErr_SetFromErrno(PyExc_OSError);
1852
0
}
1853
1854
#ifdef MS_WINDOWS
1855
static PyObject *
1856
win32_error(const char* function, const char* filename)
1857
{
1858
    /* XXX We should pass the function name along in the future.
1859
       (winreg.c also wants to pass the function name.)
1860
       This would however require an additional param to the
1861
       Windows error object, which is non-trivial.
1862
    */
1863
    errno = GetLastError();
1864
    if (filename)
1865
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1866
    else
1867
        return PyErr_SetFromWindowsErr(errno);
1868
}
1869
1870
static PyObject *
1871
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1872
{
1873
    /* XXX - see win32_error for comments on 'function' */
1874
    if (filename)
1875
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1876
                    PyExc_OSError,
1877
                    err,
1878
                    filename);
1879
    else
1880
        return PyErr_SetFromWindowsErr(err);
1881
}
1882
1883
static PyObject *
1884
win32_error_object(const char* function, PyObject* filename)
1885
{
1886
    errno = GetLastError();
1887
    return win32_error_object_err(function, filename, errno);
1888
}
1889
1890
#endif /* MS_WINDOWS */
1891
1892
static PyObject *
1893
posix_path_object_error(PyObject *path)
1894
273k
{
1895
273k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1896
273k
}
1897
1898
static PyObject *
1899
path_object_error(PyObject *path)
1900
273k
{
1901
#ifdef MS_WINDOWS
1902
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1903
                PyExc_OSError, 0, path);
1904
#else
1905
273k
    return posix_path_object_error(path);
1906
273k
#endif
1907
273k
}
1908
1909
static PyObject *
1910
path_object_error2(PyObject *path, PyObject *path2)
1911
0
{
1912
#ifdef MS_WINDOWS
1913
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1914
                PyExc_OSError, 0, path, path2);
1915
#else
1916
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1917
0
#endif
1918
0
}
1919
1920
static PyObject *
1921
path_error(path_t *path)
1922
273k
{
1923
273k
    return path_object_error(path->object);
1924
273k
}
1925
1926
static PyObject *
1927
posix_path_error(path_t *path)
1928
0
{
1929
0
    return posix_path_object_error(path->object);
1930
0
}
1931
1932
static PyObject *
1933
path_error2(path_t *path, path_t *path2)
1934
0
{
1935
0
    return path_object_error2(path->object, path2->object);
1936
0
}
1937
1938
1939
/* POSIX generic methods */
1940
1941
static PyObject *
1942
posix_fildes_fd(int fd, int (*func)(int))
1943
0
{
1944
0
    int res;
1945
0
    int async_err = 0;
1946
1947
0
    do {
1948
0
        Py_BEGIN_ALLOW_THREADS
1949
0
        _Py_BEGIN_SUPPRESS_IPH
1950
0
        res = (*func)(fd);
1951
0
        _Py_END_SUPPRESS_IPH
1952
0
        Py_END_ALLOW_THREADS
1953
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1954
0
    if (res != 0)
1955
0
        return (!async_err) ? posix_error() : NULL;
1956
0
    Py_RETURN_NONE;
1957
0
}
1958
1959
1960
#ifdef MS_WINDOWS
1961
/* This is a reimplementation of the C library's chdir function,
1962
   but one that produces Win32 errors instead of DOS error codes.
1963
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1964
   it also needs to set "magic" environment variables indicating
1965
   the per-drive current directory, which are of the form =<drive>: */
1966
static BOOL __stdcall
1967
win32_wchdir(LPCWSTR path)
1968
{
1969
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1970
    int result;
1971
    wchar_t env[4] = L"=x:";
1972
1973
    if(!SetCurrentDirectoryW(path))
1974
        return FALSE;
1975
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1976
    if (!result)
1977
        return FALSE;
1978
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1979
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1980
        if (!new_path) {
1981
            SetLastError(ERROR_OUTOFMEMORY);
1982
            return FALSE;
1983
        }
1984
        result = GetCurrentDirectoryW(result, new_path);
1985
        if (!result) {
1986
            PyMem_RawFree(new_path);
1987
            return FALSE;
1988
        }
1989
    }
1990
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1991
                            wcsncmp(new_path, L"//", 2) == 0);
1992
    if (!is_unc_like_path) {
1993
        env[1] = new_path[0];
1994
        result = SetEnvironmentVariableW(env, new_path);
1995
    }
1996
    if (new_path != path_buf)
1997
        PyMem_RawFree(new_path);
1998
    return result ? TRUE : FALSE;
1999
}
2000
#endif
2001
2002
#ifdef MS_WINDOWS
2003
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2004
   - time stamps are restricted to second resolution
2005
   - file modification times suffer from forth-and-back conversions between
2006
     UTC and local time
2007
   Therefore, we implement our own stat, based on the Win32 API directly.
2008
*/
2009
#define HAVE_STAT_NSEC 1
2010
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2011
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2012
2013
static void
2014
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2015
                       BY_HANDLE_FILE_INFORMATION *info,
2016
                       ULONG *reparse_tag)
2017
{
2018
    memset(info, 0, sizeof(*info));
2019
    info->dwFileAttributes = pFileData->dwFileAttributes;
2020
    info->ftCreationTime   = pFileData->ftCreationTime;
2021
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
2022
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
2023
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
2024
    info->nFileSizeLow     = pFileData->nFileSizeLow;
2025
/*  info->nNumberOfLinks   = 1; */
2026
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2027
        *reparse_tag = pFileData->dwReserved0;
2028
    else
2029
        *reparse_tag = 0;
2030
}
2031
2032
static BOOL
2033
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
2034
{
2035
    HANDLE hFindFile;
2036
    WIN32_FIND_DATAW FileData;
2037
    LPCWSTR filename = pszFile;
2038
    size_t n = wcslen(pszFile);
2039
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2040
        // cannot use PyMem_Malloc here because we do not hold the GIL
2041
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2042
        if(!filename) {
2043
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2044
            return FALSE;
2045
        }
2046
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2047
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2048
            ((LPWSTR)filename)[n] = L'\0';
2049
        }
2050
        if (!n || (n == 1 && filename[1] == L':')) {
2051
            // Nothing left to query
2052
            free((void *)filename);
2053
            return FALSE;
2054
        }
2055
    }
2056
    hFindFile = FindFirstFileW(filename, &FileData);
2057
    if (pszFile != filename) {
2058
        free((void *)filename);
2059
    }
2060
    if (hFindFile == INVALID_HANDLE_VALUE) {
2061
        return FALSE;
2062
    }
2063
    FindClose(hFindFile);
2064
    find_data_to_file_info(&FileData, info, reparse_tag);
2065
    return TRUE;
2066
}
2067
2068
2069
static void
2070
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2071
                         struct _Py_stat_struct *result)
2072
{
2073
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2074
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2075
           the filename has an extension that is commonly used by files
2076
           that CreateProcessW can execute. A real implementation calls
2077
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2078
           AccessCheck to check for generic read, write, and execute
2079
           access. */
2080
        const wchar_t *fileExtension = wcsrchr(path, '.');
2081
        if (fileExtension) {
2082
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2083
                _wcsicmp(fileExtension, L".bat") == 0 ||
2084
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2085
                _wcsicmp(fileExtension, L".com") == 0) {
2086
                result->st_mode |= 0111;
2087
            }
2088
        }
2089
    }
2090
}
2091
2092
2093
static int
2094
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2095
                      BOOL traverse)
2096
{
2097
    HANDLE hFile;
2098
    BY_HANDLE_FILE_INFORMATION fileInfo;
2099
    FILE_BASIC_INFO basicInfo;
2100
    FILE_BASIC_INFO *pBasicInfo = NULL;
2101
    FILE_ID_INFO idInfo;
2102
    FILE_ID_INFO *pIdInfo = NULL;
2103
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2104
    DWORD fileType, error;
2105
    BOOL isUnhandledTag = FALSE;
2106
    int retval = 0;
2107
2108
    DWORD access = FILE_READ_ATTRIBUTES;
2109
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2110
    if (!traverse) {
2111
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2112
    }
2113
2114
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2115
    if (hFile == INVALID_HANDLE_VALUE) {
2116
        /* Either the path doesn't exist, or the caller lacks access. */
2117
        error = GetLastError();
2118
        switch (error) {
2119
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2120
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2121
            /* Try reading the parent directory. */
2122
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2123
                /* Cannot read the parent directory. */
2124
                switch (GetLastError()) {
2125
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2126
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2127
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2128
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2129
                    break;
2130
                /* Restore the error from CreateFileW(). */
2131
                default:
2132
                    SetLastError(error);
2133
                }
2134
2135
                return -1;
2136
            }
2137
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2138
                if (traverse ||
2139
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2140
                    /* The stat call has to traverse but cannot, so fail. */
2141
                    SetLastError(error);
2142
                    return -1;
2143
                }
2144
            }
2145
            break;
2146
2147
        case ERROR_INVALID_PARAMETER:
2148
            /* \\.\con requires read or write access. */
2149
            hFile = CreateFileW(path, access | GENERIC_READ,
2150
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2151
                        OPEN_EXISTING, flags, NULL);
2152
            if (hFile == INVALID_HANDLE_VALUE) {
2153
                SetLastError(error);
2154
                return -1;
2155
            }
2156
            break;
2157
2158
        case ERROR_CANT_ACCESS_FILE:
2159
            /* bpo37834: open unhandled reparse points if traverse fails. */
2160
            if (traverse) {
2161
                traverse = FALSE;
2162
                isUnhandledTag = TRUE;
2163
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2164
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2165
            }
2166
            if (hFile == INVALID_HANDLE_VALUE) {
2167
                SetLastError(error);
2168
                return -1;
2169
            }
2170
            break;
2171
2172
        default:
2173
            return -1;
2174
        }
2175
    }
2176
2177
    if (hFile != INVALID_HANDLE_VALUE) {
2178
        /* Handle types other than files on disk. */
2179
        fileType = GetFileType(hFile);
2180
        if (fileType != FILE_TYPE_DISK) {
2181
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2182
                retval = -1;
2183
                goto cleanup;
2184
            }
2185
            DWORD fileAttributes = GetFileAttributesW(path);
2186
            memset(result, 0, sizeof(*result));
2187
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2188
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2189
                /* \\.\pipe\ or \\.\mailslot\ */
2190
                result->st_mode = _S_IFDIR;
2191
            } else if (fileType == FILE_TYPE_CHAR) {
2192
                /* \\.\nul */
2193
                result->st_mode = _S_IFCHR;
2194
            } else if (fileType == FILE_TYPE_PIPE) {
2195
                /* \\.\pipe\spam */
2196
                result->st_mode = _S_IFIFO;
2197
            }
2198
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2199
            goto cleanup;
2200
        }
2201
2202
        /* Query the reparse tag, and traverse a non-link. */
2203
        if (!traverse) {
2204
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2205
                    &tagInfo, sizeof(tagInfo))) {
2206
                /* Allow devices that do not support FileAttributeTagInfo. */
2207
                switch (GetLastError()) {
2208
                case ERROR_INVALID_PARAMETER:
2209
                case ERROR_INVALID_FUNCTION:
2210
                case ERROR_NOT_SUPPORTED:
2211
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2212
                    tagInfo.ReparseTag = 0;
2213
                    break;
2214
                default:
2215
                    retval = -1;
2216
                    goto cleanup;
2217
                }
2218
            } else if (tagInfo.FileAttributes &
2219
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2220
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2221
                    if (isUnhandledTag) {
2222
                        /* Traversing previously failed for either this link
2223
                           or its target. */
2224
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2225
                        retval = -1;
2226
                        goto cleanup;
2227
                    }
2228
                /* Traverse a non-link, but not if traversing already failed
2229
                   for an unhandled tag. */
2230
                } else if (!isUnhandledTag) {
2231
                    CloseHandle(hFile);
2232
                    return win32_xstat_slow_impl(path, result, TRUE);
2233
                }
2234
            }
2235
        }
2236
2237
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2238
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2239
                                          &basicInfo, sizeof(basicInfo))) {
2240
            switch (GetLastError()) {
2241
            case ERROR_INVALID_PARAMETER:
2242
            case ERROR_INVALID_FUNCTION:
2243
            case ERROR_NOT_SUPPORTED:
2244
                /* Volumes and physical disks are block devices, e.g.
2245
                   \\.\C: and \\.\PhysicalDrive0. */
2246
                memset(result, 0, sizeof(*result));
2247
                result->st_mode = 0x6000; /* S_IFBLK */
2248
                goto cleanup;
2249
            }
2250
            retval = -1;
2251
            goto cleanup;
2252
        }
2253
2254
        /* Successfully got FileBasicInfo, so we'll pass it along */
2255
        pBasicInfo = &basicInfo;
2256
2257
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2258
            /* Successfully got FileIdInfo, so pass it along */
2259
            pIdInfo = &idInfo;
2260
        }
2261
    }
2262
2263
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2264
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2265
2266
cleanup:
2267
    if (hFile != INVALID_HANDLE_VALUE) {
2268
        /* Preserve last error if we are failing */
2269
        error = retval ? GetLastError() : 0;
2270
        if (!CloseHandle(hFile)) {
2271
            retval = -1;
2272
        } else if (retval) {
2273
            /* Restore last error */
2274
            SetLastError(error);
2275
        }
2276
    }
2277
2278
    return retval;
2279
}
2280
2281
static int
2282
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2283
                 BOOL traverse)
2284
{
2285
    FILE_STAT_BASIC_INFORMATION statInfo;
2286
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2287
                                     &statInfo, sizeof(statInfo))) {
2288
        if (// Cannot use fast path for reparse points ...
2289
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2290
            // ... unless it's a name surrogate (symlink) and we're not following
2291
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2292
        ) {
2293
            _Py_stat_basic_info_to_stat(&statInfo, result);
2294
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2295
            return 0;
2296
        }
2297
    } else {
2298
        switch(GetLastError()) {
2299
        case ERROR_FILE_NOT_FOUND:
2300
        case ERROR_PATH_NOT_FOUND:
2301
        case ERROR_NOT_READY:
2302
        case ERROR_BAD_NET_NAME:
2303
            /* These errors aren't worth retrying with the slow path */
2304
            return -1;
2305
        case ERROR_NOT_SUPPORTED:
2306
            /* indicates the API couldn't be loaded */
2307
            break;
2308
        }
2309
    }
2310
2311
    return win32_xstat_slow_impl(path, result, traverse);
2312
}
2313
2314
static int
2315
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2316
{
2317
    /* Protocol violation: we explicitly clear errno, instead of
2318
       setting it to a POSIX error. Callers should use GetLastError. */
2319
    int code = win32_xstat_impl(path, result, traverse);
2320
    errno = 0;
2321
2322
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2323
    result->st_ctime = result->st_birthtime;
2324
    result->st_ctime_nsec = result->st_birthtime_nsec;
2325
    return code;
2326
}
2327
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2328
2329
   In Posix, stat automatically traverses symlinks and returns the stat
2330
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2331
   default does not traverse symlinks and instead returns attributes for
2332
   the symlink.
2333
2334
   Instead, we will open the file (which *does* traverse symlinks by default)
2335
   and GetFileInformationByHandle(). */
2336
2337
static int
2338
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2339
{
2340
    return win32_xstat(path, result, FALSE);
2341
}
2342
2343
static int
2344
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2345
{
2346
    return win32_xstat(path, result, TRUE);
2347
}
2348
2349
#endif /* MS_WINDOWS */
2350
2351
PyDoc_STRVAR(stat_result__doc__,
2352
"stat_result: Result from stat, fstat, or lstat.\n\n\
2353
This object may be accessed either as a tuple of\n\
2354
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2355
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2356
\n\
2357
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2358
or st_flags, they are available as attributes only.\n\
2359
\n\
2360
See os.stat for more information.");
2361
2362
static PyStructSequence_Field stat_result_fields[] = {
2363
    {"st_mode",    "protection bits"},
2364
    {"st_ino",     "inode"},
2365
    {"st_dev",     "device"},
2366
    {"st_nlink",   "number of hard links"},
2367
    {"st_uid",     "user ID of owner"},
2368
    {"st_gid",     "group ID of owner"},
2369
    {"st_size",    "total size, in bytes"},
2370
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2371
    {NULL,   "integer time of last access"},
2372
    {NULL,   "integer time of last modification"},
2373
    {NULL,   "integer time of last change"},
2374
    {"st_atime",   "time of last access"},
2375
    {"st_mtime",   "time of last modification"},
2376
    {"st_ctime",   "time of last change"},
2377
    {"st_atime_ns",   "time of last access in nanoseconds"},
2378
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2379
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2380
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2381
    {"st_blksize", "blocksize for filesystem I/O"},
2382
#endif
2383
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2384
    {"st_blocks",  "number of blocks allocated"},
2385
#endif
2386
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2387
    {"st_rdev",    "device type (if inode device)"},
2388
#endif
2389
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2390
    {"st_flags",   "user defined flags for file"},
2391
#endif
2392
#ifdef HAVE_STRUCT_STAT_ST_GEN
2393
    {"st_gen",    "generation number"},
2394
#endif
2395
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2396
    {"st_birthtime",   "time of creation"},
2397
#endif
2398
#ifdef MS_WINDOWS
2399
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2400
#endif
2401
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2402
    {"st_file_attributes", "Windows file attribute bits"},
2403
#endif
2404
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2405
    {"st_fstype",  "Type of filesystem"},
2406
#endif
2407
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2408
    {"st_reparse_tag", "Windows reparse tag"},
2409
#endif
2410
    {0}
2411
};
2412
2413
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2414
#define ST_BLKSIZE_IDX 16
2415
#else
2416
#define ST_BLKSIZE_IDX 15
2417
#endif
2418
2419
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2420
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2421
#else
2422
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2423
#endif
2424
2425
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2426
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2427
#else
2428
#define ST_RDEV_IDX ST_BLOCKS_IDX
2429
#endif
2430
2431
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2432
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2433
#else
2434
#define ST_FLAGS_IDX ST_RDEV_IDX
2435
#endif
2436
2437
#ifdef HAVE_STRUCT_STAT_ST_GEN
2438
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2439
#else
2440
#define ST_GEN_IDX ST_FLAGS_IDX
2441
#endif
2442
2443
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2444
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2445
#else
2446
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2447
#endif
2448
2449
#ifdef MS_WINDOWS
2450
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2451
#else
2452
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2453
#endif
2454
2455
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2456
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2457
#else
2458
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2459
#endif
2460
2461
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2462
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2463
#else
2464
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2465
#endif
2466
2467
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2468
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2469
#else
2470
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2471
#endif
2472
2473
static PyStructSequence_Desc stat_result_desc = {
2474
    "os.stat_result", /* name; see issue gh-63408 */
2475
    stat_result__doc__, /* doc */
2476
    stat_result_fields,
2477
    10
2478
};
2479
2480
PyDoc_STRVAR(statvfs_result__doc__,
2481
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2482
This object may be accessed either as a tuple of\n\
2483
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2484
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2485
\n\
2486
See os.statvfs for more information.");
2487
2488
static PyStructSequence_Field statvfs_result_fields[] = {
2489
    {"f_bsize",  },
2490
    {"f_frsize", },
2491
    {"f_blocks", },
2492
    {"f_bfree",  },
2493
    {"f_bavail", },
2494
    {"f_files",  },
2495
    {"f_ffree",  },
2496
    {"f_favail", },
2497
    {"f_flag",   },
2498
    {"f_namemax",},
2499
    {"f_fsid",   },
2500
    {0}
2501
};
2502
2503
static PyStructSequence_Desc statvfs_result_desc = {
2504
    "os.statvfs_result", /* name; see issue gh-63408 */
2505
    statvfs_result__doc__, /* doc */
2506
    statvfs_result_fields,
2507
    10
2508
};
2509
2510
#if defined(HAVE_WAITID)
2511
PyDoc_STRVAR(waitid_result__doc__,
2512
"waitid_result: Result from waitid.\n\n\
2513
This object may be accessed either as a tuple of\n\
2514
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2515
or via the attributes si_pid, si_uid, and so on.\n\
2516
\n\
2517
See os.waitid for more information.");
2518
2519
static PyStructSequence_Field waitid_result_fields[] = {
2520
    {"si_pid",  },
2521
    {"si_uid", },
2522
    {"si_signo", },
2523
    {"si_status",  },
2524
    {"si_code", },
2525
    {0}
2526
};
2527
2528
static PyStructSequence_Desc waitid_result_desc = {
2529
    MODNAME ".waitid_result", /* name */
2530
    waitid_result__doc__, /* doc */
2531
    waitid_result_fields,
2532
    5
2533
};
2534
#endif
2535
2536
static PyObject *
2537
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2538
0
{
2539
0
    PyStructSequence *result;
2540
0
    int i;
2541
2542
    // ht_module doesn't get set in PyStructSequence_NewType(),
2543
    // so we can't use PyType_GetModule().
2544
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2545
0
    if (mod == NULL) {
2546
0
        return NULL;
2547
0
    }
2548
0
    _posixstate *state = get_posix_state(mod);
2549
0
    Py_DECREF(mod);
2550
0
    if (state == NULL) {
2551
0
        return NULL;
2552
0
    }
2553
0
#define structseq_new state->statresult_new_orig
2554
2555
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2556
0
    if (!result)
2557
0
        return NULL;
2558
    /* If we have been initialized from a tuple,
2559
       st_?time might be set to None. Initialize it
2560
       from the int slots.  */
2561
0
    for (i = 7; i <= 9; i++) {
2562
0
        if (result->ob_item[i+3] == Py_None) {
2563
0
            Py_DECREF(Py_None);
2564
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2565
0
        }
2566
0
    }
2567
0
    return (PyObject*)result;
2568
0
}
2569
2570
static int
2571
_posix_clear(PyObject *module)
2572
0
{
2573
0
    _posixstate *state = get_posix_state(module);
2574
0
    Py_CLEAR(state->billion);
2575
0
    Py_CLEAR(state->DirEntryType);
2576
0
    Py_CLEAR(state->ScandirIteratorType);
2577
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2578
0
    Py_CLEAR(state->SchedParamType);
2579
0
#endif
2580
0
    Py_CLEAR(state->StatResultType);
2581
0
#ifdef HAVE_STATX
2582
0
    Py_CLEAR(state->StatxResultType);
2583
0
#endif
2584
0
    Py_CLEAR(state->StatVFSResultType);
2585
0
    Py_CLEAR(state->TerminalSizeType);
2586
0
    Py_CLEAR(state->TimesResultType);
2587
0
    Py_CLEAR(state->UnameResultType);
2588
0
#if defined(HAVE_WAITID)
2589
0
    Py_CLEAR(state->WaitidResultType);
2590
0
#endif
2591
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2592
0
    Py_CLEAR(state->struct_rusage);
2593
0
#endif
2594
0
    Py_CLEAR(state->st_mode);
2595
0
    return 0;
2596
0
}
2597
2598
static int
2599
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2600
1.52k
{
2601
1.52k
    _posixstate *state = get_posix_state(module);
2602
1.52k
    Py_VISIT(state->billion);
2603
1.52k
    Py_VISIT(state->DirEntryType);
2604
1.52k
    Py_VISIT(state->ScandirIteratorType);
2605
1.52k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2606
1.52k
    Py_VISIT(state->SchedParamType);
2607
1.52k
#endif
2608
1.52k
    Py_VISIT(state->StatResultType);
2609
1.52k
#ifdef HAVE_STATX
2610
1.52k
    Py_VISIT(state->StatxResultType);
2611
1.52k
#endif
2612
1.52k
    Py_VISIT(state->StatVFSResultType);
2613
1.52k
    Py_VISIT(state->TerminalSizeType);
2614
1.52k
    Py_VISIT(state->TimesResultType);
2615
1.52k
    Py_VISIT(state->UnameResultType);
2616
1.52k
#if defined(HAVE_WAITID)
2617
1.52k
    Py_VISIT(state->WaitidResultType);
2618
1.52k
#endif
2619
1.52k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2620
1.52k
    Py_VISIT(state->struct_rusage);
2621
1.52k
#endif
2622
1.52k
    Py_VISIT(state->st_mode);
2623
1.52k
    return 0;
2624
1.52k
}
2625
2626
static void
2627
_posix_free(void *module)
2628
0
{
2629
0
   _posix_clear((PyObject *)module);
2630
0
}
2631
2632
2633
3.92M
#define SEC_TO_NS (1000000000LL)
2634
static PyObject *
2635
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2636
1.30M
{
2637
#if SIZEOF_TIME_T == 4
2638
    return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2639
#else
2640
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2641
1.30M
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2642
1.30M
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2643
1.30M
    }
2644
0
    else
2645
0
    {
2646
0
        PyObject *ns_total = NULL;
2647
0
        PyObject *s_in_ns = NULL;
2648
0
        PyObject *s = _PyLong_FromTime_t(sec);
2649
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2650
0
        if (s == NULL || ns_fractional == NULL) {
2651
0
            goto exit;
2652
0
        }
2653
2654
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2655
0
        if (s_in_ns == NULL) {
2656
0
            goto exit;
2657
0
        }
2658
2659
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2660
2661
0
    exit:
2662
0
        Py_XDECREF(s);
2663
0
        Py_XDECREF(ns_fractional);
2664
0
        Py_XDECREF(s_in_ns);
2665
0
        return ns_total;
2666
0
    }
2667
1.30M
#endif
2668
1.30M
}
2669
2670
static int
2671
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2672
          int ns_index, time_t sec, unsigned long nsec)
2673
1.30M
{
2674
1.30M
    assert(!PyErr_Occurred());
2675
1.30M
    assert(nsec < SEC_TO_NS);
2676
2677
1.30M
    if (s_index >= 0) {
2678
1.30M
        PyObject *s = _PyLong_FromTime_t(sec);
2679
1.30M
        if (s == NULL) {
2680
0
            return -1;
2681
0
        }
2682
1.30M
        PyStructSequence_SET_ITEM(v, s_index, s);
2683
1.30M
    }
2684
2685
1.30M
    if (f_index >= 0) {
2686
1.30M
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2687
1.30M
        if (float_s == NULL) {
2688
0
            return -1;
2689
0
        }
2690
1.30M
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2691
1.30M
    }
2692
2693
1.30M
    if (ns_index >= 0) {
2694
1.30M
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2695
1.30M
        if (ns_total == NULL) {
2696
0
            return -1;
2697
0
        }
2698
1.30M
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2699
1.30M
    }
2700
2701
1.30M
    assert(!PyErr_Occurred());
2702
1.30M
    return 0;
2703
1.30M
}
2704
#undef SEC_TO_NS
2705
2706
#ifdef MS_WINDOWS
2707
static PyObject*
2708
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2709
{
2710
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2711
    if (!o_low || !high) {
2712
        return o_low;
2713
    }
2714
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2715
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2716
    if (!l64) {
2717
        Py_XDECREF(o_high);
2718
        Py_DECREF(o_low);
2719
        return NULL;
2720
    }
2721
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2722
    Py_DECREF(l64);
2723
    if (!o_high) {
2724
        Py_DECREF(o_low);
2725
        return NULL;
2726
    }
2727
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2728
    Py_DECREF(o_high);
2729
    return o_low;
2730
}
2731
#endif
2732
2733
/* pack a system stat C structure into the Python stat tuple
2734
   (used by posix_stat() and posix_fstat()) */
2735
static PyObject*
2736
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2737
435k
{
2738
435k
    assert(!PyErr_Occurred());
2739
2740
435k
    _posixstate *state = get_posix_state(module);
2741
435k
    PyObject *StatResultType = state->StatResultType;
2742
435k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2743
435k
    if (v == NULL) {
2744
0
        return NULL;
2745
0
    }
2746
2747
435k
#define SET_ITEM(pos, expr) \
2748
4.35M
    do { \
2749
4.35M
        PyObject *obj = (expr); \
2750
4.35M
        if (obj == NULL) { \
2751
0
            goto error; \
2752
0
        } \
2753
4.35M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2754
4.35M
    } while (0)
2755
2756
435k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2757
#ifdef MS_WINDOWS
2758
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2759
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2760
#else
2761
435k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2762
435k
                  "stat.st_ino is larger than unsigned long long");
2763
435k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2764
435k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2765
435k
#endif
2766
435k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2767
#if defined(MS_WINDOWS)
2768
    SET_ITEM(4, PyLong_FromLong(0));
2769
    SET_ITEM(5, PyLong_FromLong(0));
2770
#else
2771
435k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2772
435k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2773
435k
#endif
2774
435k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2775
435k
                  "stat.st_size is larger than long long");
2776
435k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2777
2778
    // Set st_atime, st_mtime and st_ctime
2779
435k
    unsigned long ansec, mnsec, cnsec;
2780
435k
#if defined(HAVE_STAT_TV_NSEC)
2781
435k
    ansec = st->st_atim.tv_nsec;
2782
435k
    mnsec = st->st_mtim.tv_nsec;
2783
435k
    cnsec = st->st_ctim.tv_nsec;
2784
#elif defined(HAVE_STAT_TV_NSEC2)
2785
    ansec = st->st_atimespec.tv_nsec;
2786
    mnsec = st->st_mtimespec.tv_nsec;
2787
    cnsec = st->st_ctimespec.tv_nsec;
2788
#elif defined(HAVE_STAT_NSEC)
2789
    ansec = st->st_atime_nsec;
2790
    mnsec = st->st_mtime_nsec;
2791
    cnsec = st->st_ctime_nsec;
2792
#else
2793
    ansec = mnsec = cnsec = 0;
2794
#endif
2795
435k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2796
0
        goto error;
2797
0
    }
2798
435k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2799
0
        goto error;
2800
0
    }
2801
435k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2802
0
        goto error;
2803
0
    }
2804
2805
435k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2806
435k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2807
435k
#endif
2808
435k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2809
435k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2810
435k
#endif
2811
435k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2812
435k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2813
435k
#endif
2814
#ifdef HAVE_STRUCT_STAT_ST_GEN
2815
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2816
#endif
2817
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2818
    {
2819
      unsigned long bsec, bnsec;
2820
      bsec = (long)st->st_birthtime;
2821
#ifdef HAVE_STAT_TV_NSEC2
2822
      bnsec = st->st_birthtimespec.tv_nsec;
2823
#else
2824
      bnsec = 0;
2825
#endif
2826
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2827
    }
2828
#elif defined(MS_WINDOWS)
2829
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2830
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2831
        goto error;
2832
    }
2833
#endif
2834
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2835
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2836
#endif
2837
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2838
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2839
             PyLong_FromUnsignedLong(st->st_file_attributes));
2840
#endif
2841
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2842
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2843
#endif
2844
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2845
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2846
#endif
2847
2848
435k
    assert(!PyErr_Occurred());
2849
435k
    return v;
2850
2851
0
error:
2852
0
    Py_DECREF(v);
2853
0
    return NULL;
2854
2855
435k
#undef SET_ITEM
2856
435k
}
2857
2858
/* POSIX methods */
2859
2860
2861
static PyObject *
2862
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2863
              int dir_fd, int follow_symlinks)
2864
343k
{
2865
343k
    STRUCT_STAT st;
2866
343k
    int result;
2867
2868
343k
#ifdef HAVE_FSTATAT
2869
343k
    int fstatat_unavailable = 0;
2870
343k
#endif
2871
2872
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2873
    if (follow_symlinks_specified(function_name, follow_symlinks))
2874
        return NULL;
2875
#endif
2876
2877
343k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2878
343k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2879
343k
        fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2880
0
        return NULL;
2881
2882
343k
    Py_BEGIN_ALLOW_THREADS
2883
343k
    if (path->fd != -1)
2884
0
        result = FSTAT(path->fd, &st);
2885
#ifdef MS_WINDOWS
2886
    else if (follow_symlinks)
2887
        result = win32_stat(path->wide, &st);
2888
    else
2889
        result = win32_lstat(path->wide, &st);
2890
#else
2891
343k
    else
2892
343k
#if defined(HAVE_LSTAT)
2893
343k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2894
13.8k
        result = LSTAT(path->narrow, &st);
2895
330k
    else
2896
330k
#endif /* HAVE_LSTAT */
2897
330k
#ifdef HAVE_FSTATAT
2898
330k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2899
0
        if (HAVE_FSTATAT_RUNTIME) {
2900
0
            result = fstatat(dir_fd, path->narrow, &st,
2901
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2902
2903
0
        } else {
2904
0
            fstatat_unavailable = 1;
2905
0
        }
2906
0
    } else
2907
330k
#endif /* HAVE_FSTATAT */
2908
330k
        result = STAT(path->narrow, &st);
2909
343k
#endif /* MS_WINDOWS */
2910
343k
    Py_END_ALLOW_THREADS
2911
2912
343k
#ifdef HAVE_FSTATAT
2913
343k
    if (fstatat_unavailable) {
2914
0
        argument_unavailable_error("stat", "dir_fd");
2915
0
        return NULL;
2916
0
    }
2917
343k
#endif
2918
2919
343k
    if (result != 0) {
2920
273k
        return path_error(path);
2921
273k
    }
2922
2923
70.6k
    return _pystat_fromstructstat(module, &st);
2924
343k
}
2925
2926
/*[python input]
2927
2928
for s in """
2929
2930
FACCESSAT
2931
FCHMODAT
2932
FCHOWNAT
2933
FSTATAT
2934
LINKAT
2935
MKDIRAT
2936
MKFIFOAT
2937
MKNODAT
2938
OPENAT
2939
READLINKAT
2940
SYMLINKAT
2941
UNLINKAT
2942
2943
""".strip().split():
2944
    s = s.strip()
2945
    print("""
2946
#ifdef HAVE_{s}
2947
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2948
#else
2949
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2950
#endif
2951
""".rstrip().format(s=s))
2952
2953
for s in """
2954
2955
FCHDIR
2956
FCHMOD
2957
FCHOWN
2958
FDOPENDIR
2959
FEXECVE
2960
FPATHCONF
2961
FSTATVFS
2962
FTRUNCATE
2963
2964
""".strip().split():
2965
    s = s.strip()
2966
    print("""
2967
#ifdef HAVE_{s}
2968
    #define PATH_HAVE_{s} 1
2969
#else
2970
    #define PATH_HAVE_{s} 0
2971
#endif
2972
2973
""".rstrip().format(s=s))
2974
[python start generated code]*/
2975
2976
#ifdef HAVE_FACCESSAT
2977
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2978
#else
2979
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2980
#endif
2981
2982
#ifdef HAVE_FCHMODAT
2983
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2984
#else
2985
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2986
#endif
2987
2988
#ifdef HAVE_FCHOWNAT
2989
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2990
#else
2991
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2992
#endif
2993
2994
#ifdef HAVE_FSTATAT
2995
9.47k
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2996
#else
2997
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2998
#endif
2999
3000
#ifdef HAVE_LINKAT
3001
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
3002
#else
3003
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3004
#endif
3005
3006
#ifdef HAVE_MKDIRAT
3007
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3008
#else
3009
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3010
#endif
3011
3012
#ifdef HAVE_MKFIFOAT
3013
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3014
#else
3015
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3016
#endif
3017
3018
#ifdef HAVE_MKNODAT
3019
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3020
#else
3021
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3022
#endif
3023
3024
#ifdef HAVE_OPENAT
3025
184k
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3026
#else
3027
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3028
#endif
3029
3030
#ifdef HAVE_READLINKAT
3031
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3032
#else
3033
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3034
#endif
3035
3036
#ifdef HAVE_SYMLINKAT
3037
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3038
#else
3039
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3040
#endif
3041
3042
#ifdef HAVE_UNLINKAT
3043
221k
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3044
#else
3045
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3046
#endif
3047
3048
#ifdef HAVE_FCHDIR
3049
    #define PATH_HAVE_FCHDIR 1
3050
#else
3051
    #define PATH_HAVE_FCHDIR 0
3052
#endif
3053
3054
#ifdef HAVE_FCHMOD
3055
    #define PATH_HAVE_FCHMOD 1
3056
#else
3057
    #define PATH_HAVE_FCHMOD 0
3058
#endif
3059
3060
#ifdef HAVE_FCHOWN
3061
    #define PATH_HAVE_FCHOWN 1
3062
#else
3063
    #define PATH_HAVE_FCHOWN 0
3064
#endif
3065
3066
#ifdef HAVE_FDOPENDIR
3067
    #define PATH_HAVE_FDOPENDIR 1
3068
#else
3069
    #define PATH_HAVE_FDOPENDIR 0
3070
#endif
3071
3072
#ifdef HAVE_FEXECVE
3073
    #define PATH_HAVE_FEXECVE 1
3074
#else
3075
    #define PATH_HAVE_FEXECVE 0
3076
#endif
3077
3078
#ifdef HAVE_FPATHCONF
3079
    #define PATH_HAVE_FPATHCONF 1
3080
#else
3081
    #define PATH_HAVE_FPATHCONF 0
3082
#endif
3083
3084
#ifdef HAVE_FSTATVFS
3085
    #define PATH_HAVE_FSTATVFS 1
3086
#else
3087
    #define PATH_HAVE_FSTATVFS 0
3088
#endif
3089
3090
#ifdef HAVE_FTRUNCATE
3091
    #define PATH_HAVE_FTRUNCATE 1
3092
#else
3093
    #define PATH_HAVE_FTRUNCATE 0
3094
#endif
3095
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3096
3097
#ifdef MS_WINDOWS
3098
    #undef PATH_HAVE_FTRUNCATE
3099
    #define PATH_HAVE_FTRUNCATE 1
3100
    #undef PATH_HAVE_FCHMOD
3101
    #define PATH_HAVE_FCHMOD 1
3102
#endif
3103
3104
/*[python input]
3105
3106
class path_t_converter(CConverter):
3107
3108
    type = "path_t"
3109
    impl_by_reference = True
3110
    parse_by_reference = True
3111
3112
    converter = 'path_converter'
3113
3114
    def converter_init(self, *, allow_fd=False, make_wide=None,
3115
                       nonstrict=False, nullable=False,
3116
                       suppress_value_error=False):
3117
        # right now path_t doesn't support default values.
3118
        # to support a default value, you'll need to override initialize().
3119
        if self.default not in (unspecified, None):
3120
            fail("Can't specify a default to the path_t converter!")
3121
3122
        if self.c_default not in (None, 'Py_None'):
3123
            raise RuntimeError("Can't specify a c_default to the path_t converter!")
3124
3125
        self.nullable = nullable
3126
        self.nonstrict = nonstrict
3127
        self.make_wide = make_wide
3128
        self.suppress_value_error = suppress_value_error
3129
        self.allow_fd = allow_fd
3130
3131
    def pre_render(self):
3132
        def strify(value):
3133
            if isinstance(value, str):
3134
                return value
3135
            return str(int(bool(value)))
3136
3137
        # add self.py_name here when merging with posixmodule conversion
3138
        if self.make_wide is None:
3139
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3140
                self.function.name,
3141
                self.name,
3142
                strify(self.nullable),
3143
                strify(self.nonstrict),
3144
                strify(self.suppress_value_error),
3145
                strify(self.allow_fd),
3146
            )
3147
        else:
3148
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3149
                self.function.name,
3150
                self.name,
3151
                strify(self.nullable),
3152
                strify(self.nonstrict),
3153
                strify(self.make_wide),
3154
                strify(self.suppress_value_error),
3155
                strify(self.allow_fd),
3156
            )
3157
3158
    def cleanup(self):
3159
        return "path_cleanup(&" + self.name + ");\n"
3160
3161
3162
class dir_fd_converter(CConverter):
3163
    type = 'int'
3164
3165
    def converter_init(self, requires=None):
3166
        if self.default in (unspecified, None):
3167
            self.c_default = 'DEFAULT_DIR_FD'
3168
        if isinstance(requires, str):
3169
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3170
        else:
3171
            self.converter = 'dir_fd_converter'
3172
3173
class uid_t_converter(CConverter):
3174
    type = "uid_t"
3175
    converter = '_Py_Uid_Converter'
3176
3177
class gid_t_converter(CConverter):
3178
    type = "gid_t"
3179
    converter = '_Py_Gid_Converter'
3180
3181
class dev_t_converter(CConverter):
3182
    type = 'dev_t'
3183
    converter = '_Py_Dev_Converter'
3184
3185
class dev_t_return_converter(unsigned_long_return_converter):
3186
    type = 'dev_t'
3187
    conversion_fn = '_PyLong_FromDev'
3188
    unsigned_cast = '(dev_t)'
3189
3190
class pid_t_converter(CConverter):
3191
    type = 'pid_t'
3192
    format_unit = '" _Py_PARSE_PID "'
3193
3194
    def parse_arg(self, argname, displayname, *, limited_capi):
3195
        return self.format_code("""
3196
            {paramname} = PyLong_AsPid({argname});
3197
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3198
                goto exit;
3199
            }}}}
3200
            """, argname=argname)
3201
3202
class idtype_t_converter(CConverter):
3203
    type = 'idtype_t'
3204
    converter = 'idtype_t_converter'
3205
3206
class id_t_converter(CConverter):
3207
    type = 'id_t'
3208
    format_unit = '" _Py_PARSE_PID "'
3209
3210
    def parse_arg(self, argname, displayname, *, limited_capi):
3211
        return self.format_code("""
3212
            {paramname} = (id_t)PyLong_AsPid({argname});
3213
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3214
                goto exit;
3215
            }}}}
3216
            """, argname=argname)
3217
3218
class intptr_t_converter(CConverter):
3219
    type = 'intptr_t'
3220
    format_unit = '" _Py_PARSE_INTPTR "'
3221
3222
    def parse_arg(self, argname, displayname, *, limited_capi):
3223
        return self.format_code("""
3224
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3225
            if (!{paramname} && PyErr_Occurred()) {{{{
3226
                goto exit;
3227
            }}}}
3228
            """, argname=argname)
3229
3230
class Py_off_t_converter(CConverter):
3231
    type = 'Py_off_t'
3232
    converter = 'Py_off_t_converter'
3233
3234
class Py_off_t_return_converter(long_return_converter):
3235
    type = 'Py_off_t'
3236
    conversion_fn = 'PyLong_FromPy_off_t'
3237
3238
class confname_converter(CConverter):
3239
    type="int"
3240
    converter="conv_confname"
3241
3242
    def converter_init(self, *, table):
3243
        self.table = table
3244
3245
    def parse_arg(self, argname, displayname, *, limited_capi):
3246
        return self.format_code("""
3247
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3248
                goto exit;
3249
            }}}}
3250
        """, argname=argname, converter=self.converter, table=self.table)
3251
3252
[python start generated code]*/
3253
/*[python end generated code: output=da39a3ee5e6b4b0d input=d2759f2332cd39b3]*/
3254
3255
/*[clinic input]
3256
3257
os.stat
3258
3259
    path : path_t(allow_fd=True)
3260
        Path to be examined; can be string, bytes, a path-like object or
3261
        open-file-descriptor int.
3262
3263
    *
3264
3265
    dir_fd : dir_fd(requires='fstatat') = None
3266
        If not None, it should be a file descriptor open to a directory,
3267
        and path should be a relative string; path will then be relative to
3268
        that directory.
3269
3270
    follow_symlinks: bool = True
3271
        If False, and the last element of the path is a symbolic link,
3272
        stat will examine the symbolic link itself instead of the file
3273
        the link points to.
3274
3275
Perform a stat system call on the given path.
3276
3277
dir_fd and follow_symlinks may not be implemented
3278
  on your platform.  If they are unavailable, using them will raise a
3279
  NotImplementedError.
3280
3281
It's an error to use dir_fd or follow_symlinks when specifying path as
3282
  an open file descriptor.
3283
3284
[clinic start generated code]*/
3285
3286
static PyObject *
3287
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3288
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3289
330k
{
3290
330k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3291
330k
}
3292
3293
3294
/*[clinic input]
3295
@permit_long_summary
3296
os.lstat
3297
3298
    path : path_t
3299
3300
    *
3301
3302
    dir_fd : dir_fd(requires='fstatat') = None
3303
3304
Perform a stat system call on the given path, without following symbolic links.
3305
3306
Like stat(), but do not follow symbolic links.
3307
Equivalent to stat(path, follow_symlinks=False).
3308
[clinic start generated code]*/
3309
3310
static PyObject *
3311
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3312
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3313
13.8k
{
3314
13.8k
    int follow_symlinks = 0;
3315
13.8k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3316
13.8k
}
3317
3318
3319
#ifdef HAVE_STATX
3320
typedef struct {
3321
    PyObject_HEAD
3322
    dev_t rdev, dev;
3323
    struct statx stx;
3324
} Py_statx_result;
3325
3326
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3327
3328
#define M(attr, type, offset, doc) \
3329
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3330
#define MM(attr, type, member, doc) \
3331
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3332
#define MX(attr, type, member, doc) \
3333
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3334
3335
static PyMemberDef pystatx_result_members[] = {
3336
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3337
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3338
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3339
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3340
        "Mask of supported bits in stx_attributes"),
3341
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3342
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3343
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3344
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3345
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3346
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3347
    {NULL},
3348
};
3349
3350
#undef MX
3351
#undef MM
3352
#undef M
3353
3354
3355
#define STATX_GET_UINT(ATTR, MASK) \
3356
    static PyObject* \
3357
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3358
0
    { \
3359
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3360
0
        if (!(self->stx.stx_mask & MASK)) { \
3361
0
            Py_RETURN_NONE; \
3362
0
        } \
3363
0
        unsigned long value = self->stx.ATTR; \
3364
0
        return PyLong_FromUnsignedLong(value); \
3365
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_nlink
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_uid
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_gid
3366
3367
STATX_GET_UINT(stx_uid, STATX_UID)
3368
STATX_GET_UINT(stx_gid, STATX_GID)
3369
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3370
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3371
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3372
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3373
#endif
3374
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3375
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3376
#endif
3377
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3378
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3379
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3380
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3381
#endif
3382
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3383
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3384
#endif
3385
3386
3387
static PyObject*
3388
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3389
0
{
3390
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3391
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3392
0
        Py_RETURN_NONE;
3393
0
    }
3394
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3395
0
}
3396
3397
3398
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3399
    static PyObject* \
3400
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3401
0
    { \
3402
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3403
0
        if (!(self->stx.stx_mask & MASK)) { \
3404
0
            Py_RETURN_NONE; \
3405
0
        } \
3406
0
        unsigned long long value = self->stx.ATTR; \
3407
0
        return PyLong_FromUnsignedLongLong(value); \
3408
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_ino
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_size
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_blocks
3409
3410
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3411
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3412
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3413
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3414
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3415
#endif
3416
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3417
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3418
#endif
3419
3420
3421
#define STATX_GET_DOUBLE(ATTR, MASK) \
3422
    static PyObject* \
3423
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3424
0
    { \
3425
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3426
0
        if (!(self->stx.stx_mask & MASK)) { \
3427
0
            Py_RETURN_NONE; \
3428
0
        } \
3429
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3430
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3431
0
        return PyFloat_FromDouble(sec); \
3432
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_atime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_btime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_ctime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_mtime
3433
3434
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3435
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3436
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3437
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3438
3439
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3440
    static PyObject* \
3441
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3442
0
    { \
3443
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3444
0
        if (!(self->stx.stx_mask & MASK)) { \
3445
0
            Py_RETURN_NONE; \
3446
0
        } \
3447
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3448
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3449
0
        assert(state != NULL); \
3450
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3451
0
    }
3452
3453
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3454
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3455
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3456
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3457
3458
#define G(attr, doc) \
3459
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3460
3461
static PyGetSetDef pystatx_result_getset[] = {
3462
    G(stx_mode, "protection bits"),
3463
    G(stx_nlink, "number of hard links"),
3464
    G(stx_uid, "user ID of owner"),
3465
    G(stx_gid, "group ID of owner"),
3466
    G(stx_ino, "inode"),
3467
    G(stx_size, "total size, in bytes"),
3468
    G(stx_blocks, "number of blocks allocated"),
3469
    G(stx_atime, "time of last access"),
3470
    G(stx_atime_ns, "time of last access in nanoseconds"),
3471
    G(stx_btime, "time of creation"),
3472
    G(stx_btime_ns, "time of creation in nanoseconds"),
3473
    G(stx_ctime, "time of last change"),
3474
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3475
    G(stx_mtime, "time of last modification"),
3476
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3477
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3478
    G(stx_mnt_id, "mount ID"),
3479
#endif
3480
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3481
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3482
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3483
#endif
3484
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3485
    G(stx_subvol, "subvolume ID"),
3486
#endif
3487
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3488
    G(stx_atomic_write_unit_min,
3489
      "minimum size for direct I/O with torn-write protection"),
3490
    G(stx_atomic_write_unit_max,
3491
        "maximum size for direct I/O with torn-write protection"),
3492
    G(stx_atomic_write_segments_max,
3493
        "maximum iovecs for direct I/O with torn-write protection"),
3494
#endif
3495
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3496
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3497
#endif
3498
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3499
    G(stx_atomic_write_unit_max_opt,
3500
        "maximum optimized size for direct I/O with torn-write protection"),
3501
#endif
3502
    {NULL},
3503
};
3504
3505
#undef G
3506
3507
static PyObject *
3508
pystatx_result_repr(PyObject *op)
3509
0
{
3510
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3511
0
    if (writer == NULL) {
3512
0
        return NULL;
3513
0
    }
3514
0
#define WRITE_ASCII(s) \
3515
0
    do { \
3516
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3517
0
            goto error; \
3518
0
        } \
3519
0
    } while (0)
3520
3521
0
    WRITE_ASCII("os.statx_result(");
3522
3523
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3524
0
        if (i > 0) {
3525
0
            WRITE_ASCII(", ");
3526
0
        }
3527
3528
0
        PyMemberDef *d = &pystatx_result_members[i];
3529
0
        WRITE_ASCII(d->name);
3530
0
        WRITE_ASCII("=");
3531
3532
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3533
0
        if (o == NULL) {
3534
0
            goto error;
3535
0
        }
3536
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3537
0
            Py_DECREF(o);
3538
0
            goto error;
3539
0
        }
3540
0
        Py_DECREF(o);
3541
0
    }
3542
3543
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3544
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3545
0
        PyObject *o = d->get(op, d->closure);
3546
0
        if (o == NULL) {
3547
0
            goto error;
3548
0
        }
3549
0
        if (o == Py_None) {
3550
0
            continue;
3551
0
        }
3552
3553
0
        WRITE_ASCII(", ");
3554
0
        WRITE_ASCII(d->name);
3555
0
        WRITE_ASCII("=");
3556
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3557
0
            Py_DECREF(o);
3558
0
            goto error;
3559
0
        }
3560
0
        Py_DECREF(o);
3561
0
    }
3562
3563
0
    WRITE_ASCII(")");
3564
0
    return PyUnicodeWriter_Finish(writer);
3565
0
#undef WRITE_ASCII
3566
3567
0
error:
3568
0
    PyUnicodeWriter_Discard(writer);
3569
0
    return NULL;
3570
0
}
3571
3572
static int
3573
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3574
0
{
3575
0
    Py_VISIT(Py_TYPE(self));
3576
0
    return 0;
3577
0
}
3578
3579
static void
3580
pystatx_result_dealloc(PyObject *op)
3581
0
{
3582
0
    Py_statx_result *self = (Py_statx_result *) op;
3583
0
    PyTypeObject *tp = Py_TYPE(self);
3584
0
    PyObject_GC_UnTrack(self);
3585
0
    tp->tp_free(self);
3586
0
    Py_DECREF(tp);
3587
0
}
3588
3589
static PyType_Slot pystatx_result_slots[] = {
3590
    {Py_tp_repr, pystatx_result_repr},
3591
    {Py_tp_traverse, pystatx_result_traverse},
3592
    {Py_tp_dealloc, pystatx_result_dealloc},
3593
    {Py_tp_members, pystatx_result_members},
3594
    {Py_tp_getset, pystatx_result_getset},
3595
    {0, NULL},
3596
};
3597
3598
static PyType_Spec pystatx_result_spec = {
3599
    .name = "os.statx_result",
3600
    .basicsize = sizeof(Py_statx_result),
3601
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3602
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3603
    .slots = pystatx_result_slots,
3604
};
3605
3606
/*[clinic input]
3607
3608
os.statx
3609
3610
    path : path_t(allow_fd=True)
3611
        Path to be examined; can be string, bytes, a path-like object or
3612
        open-file-descriptor int.
3613
3614
    mask: unsigned_int(bitwise=True)
3615
        A bitmask of STATX_* constants defining the requested information.
3616
3617
    *
3618
3619
    flags: int = 0
3620
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3621
3622
    dir_fd : dir_fd = None
3623
        If not None, it should be a file descriptor open to a directory,
3624
        and path should be a relative string; path will then be relative to
3625
        that directory.
3626
3627
    follow_symlinks: bool = True
3628
        If False, and the last element of the path is a symbolic link,
3629
        statx will examine the symbolic link itself instead of the file
3630
        the link points to.
3631
3632
Perform a statx system call on the given path.
3633
3634
It's an error to use dir_fd or follow_symlinks when specifying path as
3635
  an open file descriptor.
3636
3637
[clinic start generated code]*/
3638
3639
static PyObject *
3640
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3641
              int dir_fd, int follow_symlinks)
3642
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3643
0
{
3644
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3645
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3646
0
        fd_and_follow_symlinks_invalid("statx", path->fd, follow_symlinks)) {
3647
0
        return NULL;
3648
0
    }
3649
3650
    /* reject flags covered by kwargs, but allow unknown flags that may be
3651
       future AT_STATX_* extensions */
3652
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3653
0
        PyErr_Format(PyExc_ValueError,
3654
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3655
0
        return NULL;
3656
0
    }
3657
0
    if (flags & AT_EMPTY_PATH) {
3658
0
        PyErr_Format(PyExc_ValueError,
3659
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3660
0
        return NULL;
3661
0
    }
3662
3663
    /* Future bits may refer to members beyond the current size of struct
3664
       statx, so we need to mask them off to prevent memory corruption. */
3665
0
    mask &= _Py_STATX_KNOWN;
3666
3667
0
    _posixstate *state = get_posix_state(module);
3668
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3669
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3670
0
    if (v == NULL) {
3671
0
        return NULL;
3672
0
    }
3673
3674
0
    int result;
3675
0
    Py_BEGIN_ALLOW_THREADS
3676
0
    if (path->fd != -1) {
3677
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3678
0
    }
3679
0
    else {
3680
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3681
0
    }
3682
0
    Py_END_ALLOW_THREADS
3683
3684
0
    if (result != 0) {
3685
0
        Py_DECREF(v);
3686
0
        return path_error(path);
3687
0
    }
3688
3689
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3690
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3691
3692
0
    assert(!PyErr_Occurred());
3693
0
    return (PyObject *)v;
3694
0
}
3695
#endif /* HAVE_STATX */
3696
3697
3698
/*[clinic input]
3699
os.access -> bool
3700
3701
    path: path_t
3702
        Path to be tested; can be string, bytes, or a path-like object.
3703
3704
    mode: int
3705
        Operating-system mode bitfield.  Can be F_OK to test existence,
3706
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3707
3708
    *
3709
3710
    dir_fd : dir_fd(requires='faccessat') = None
3711
        If not None, it should be a file descriptor open to a directory,
3712
        and path should be relative; path will then be relative to that
3713
        directory.
3714
3715
    effective_ids: bool = False
3716
        If True, access will use the effective uid/gid instead of
3717
        the real uid/gid.
3718
3719
    follow_symlinks: bool = True
3720
        If False, and the last element of the path is a symbolic link,
3721
        access will examine the symbolic link itself instead of the file
3722
        the link points to.
3723
3724
Use the real uid/gid to test for access to a path.
3725
3726
{parameters}
3727
dir_fd, effective_ids, and follow_symlinks may not be implemented
3728
  on your platform.  If they are unavailable, using them will raise a
3729
  NotImplementedError.
3730
3731
Note that most operations will use the effective uid/gid, therefore this
3732
  routine can be used in a suid/sgid environment to test if the invoking
3733
  user has the specified access to the path.
3734
3735
[clinic start generated code]*/
3736
3737
static int
3738
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3739
               int effective_ids, int follow_symlinks)
3740
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3741
0
{
3742
0
    int return_value;
3743
3744
#ifdef MS_WINDOWS
3745
    DWORD attr;
3746
#else
3747
0
    int result;
3748
0
#endif
3749
3750
0
#ifdef HAVE_FACCESSAT
3751
0
    int faccessat_unavailable = 0;
3752
0
#endif
3753
3754
#ifndef HAVE_FACCESSAT
3755
    if (follow_symlinks_specified("access", follow_symlinks))
3756
        return -1;
3757
3758
    if (effective_ids) {
3759
        argument_unavailable_error("access", "effective_ids");
3760
        return -1;
3761
    }
3762
#endif
3763
3764
#ifdef MS_WINDOWS
3765
    Py_BEGIN_ALLOW_THREADS
3766
    attr = GetFileAttributesW(path->wide);
3767
    Py_END_ALLOW_THREADS
3768
3769
    /*
3770
     * Access is possible if
3771
     *   * we didn't get a -1, and
3772
     *     * write access wasn't requested,
3773
     *     * or the file isn't read-only,
3774
     *     * or it's a directory.
3775
     * (Directories cannot be read-only on Windows.)
3776
    */
3777
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3778
            (!(mode & 2) ||
3779
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3780
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3781
#else
3782
3783
0
    Py_BEGIN_ALLOW_THREADS
3784
0
#ifdef HAVE_FACCESSAT
3785
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3786
0
        effective_ids ||
3787
0
        !follow_symlinks) {
3788
3789
0
        if (HAVE_FACCESSAT_RUNTIME) {
3790
0
            int flags = 0;
3791
0
            if (!follow_symlinks)
3792
0
                flags |= AT_SYMLINK_NOFOLLOW;
3793
0
            if (effective_ids)
3794
0
                flags |= AT_EACCESS;
3795
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3796
0
        } else {
3797
0
            faccessat_unavailable = 1;
3798
0
        }
3799
0
    }
3800
0
    else
3801
0
#endif
3802
0
        result = access(path->narrow, mode);
3803
0
    Py_END_ALLOW_THREADS
3804
3805
0
#ifdef HAVE_FACCESSAT
3806
0
    if (faccessat_unavailable) {
3807
0
        if (dir_fd != DEFAULT_DIR_FD) {
3808
0
            argument_unavailable_error("access", "dir_fd");
3809
0
            return -1;
3810
0
        }
3811
0
        if (follow_symlinks_specified("access", follow_symlinks))
3812
0
            return -1;
3813
3814
0
        if (effective_ids) {
3815
0
            argument_unavailable_error("access", "effective_ids");
3816
0
            return -1;
3817
0
        }
3818
        /* should be unreachable */
3819
0
        return -1;
3820
0
    }
3821
0
#endif
3822
0
    return_value = !result;
3823
0
#endif
3824
3825
0
    return return_value;
3826
0
}
3827
3828
#ifndef F_OK
3829
#define F_OK 0
3830
#endif
3831
#ifndef R_OK
3832
#define R_OK 4
3833
#endif
3834
#ifndef W_OK
3835
#define W_OK 2
3836
#endif
3837
#ifndef X_OK
3838
#define X_OK 1
3839
#endif
3840
3841
3842
#ifdef HAVE_TTYNAME_R
3843
/*[clinic input]
3844
os.ttyname
3845
3846
    fd: int
3847
        Integer file descriptor handle.
3848
3849
    /
3850
3851
Return the name of the terminal device connected to 'fd'.
3852
[clinic start generated code]*/
3853
3854
static PyObject *
3855
os_ttyname_impl(PyObject *module, int fd)
3856
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3857
0
{
3858
3859
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3860
0
    if (size == -1) {
3861
0
        return posix_error();
3862
0
    }
3863
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3864
0
    if (buffer == NULL) {
3865
0
        return PyErr_NoMemory();
3866
0
    }
3867
0
    int ret = ttyname_r(fd, buffer, size);
3868
0
    if (ret != 0) {
3869
0
        PyMem_RawFree(buffer);
3870
0
        errno = ret;
3871
0
        return posix_error();
3872
0
    }
3873
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3874
0
    PyMem_RawFree(buffer);
3875
0
    return res;
3876
0
}
3877
#endif
3878
3879
#ifdef HAVE_CTERMID
3880
/*[clinic input]
3881
os.ctermid
3882
3883
Return the name of the controlling terminal for this process.
3884
[clinic start generated code]*/
3885
3886
static PyObject *
3887
os_ctermid_impl(PyObject *module)
3888
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3889
0
{
3890
0
    char *ret;
3891
0
    char buffer[L_ctermid];
3892
3893
#ifdef USE_CTERMID_R
3894
    ret = ctermid_r(buffer);
3895
#else
3896
0
    ret = ctermid(buffer);
3897
0
#endif
3898
0
    if (ret == NULL)
3899
0
        return posix_error();
3900
0
    return PyUnicode_DecodeFSDefault(buffer);
3901
0
}
3902
#endif /* HAVE_CTERMID */
3903
3904
3905
/*[clinic input]
3906
os.chdir
3907
3908
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3909
3910
Change the current working directory to the specified path.
3911
3912
path may always be specified as a string.
3913
On some platforms, path may also be specified as an open file descriptor.
3914
If this functionality is unavailable, using it raises an exception.
3915
[clinic start generated code]*/
3916
3917
static PyObject *
3918
os_chdir_impl(PyObject *module, path_t *path)
3919
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3920
0
{
3921
0
    int result;
3922
3923
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3924
0
        return NULL;
3925
0
    }
3926
3927
0
    Py_BEGIN_ALLOW_THREADS
3928
#ifdef MS_WINDOWS
3929
    /* on unix, success = 0, on windows, success = !0 */
3930
    result = !win32_wchdir(path->wide);
3931
#else
3932
0
#ifdef HAVE_FCHDIR
3933
0
    if (path->fd != -1)
3934
0
        result = fchdir(path->fd);
3935
0
    else
3936
0
#endif
3937
0
        result = chdir(path->narrow);
3938
0
#endif
3939
0
    Py_END_ALLOW_THREADS
3940
3941
0
    if (result) {
3942
0
        return path_error(path);
3943
0
    }
3944
3945
0
    Py_RETURN_NONE;
3946
0
}
3947
3948
3949
#ifdef HAVE_FCHDIR
3950
/*[clinic input]
3951
os.fchdir
3952
3953
    fd: fildes
3954
3955
Change to the directory of the given file descriptor.
3956
3957
fd must be opened on a directory, not a file.
3958
Equivalent to os.chdir(fd).
3959
3960
[clinic start generated code]*/
3961
3962
static PyObject *
3963
os_fchdir_impl(PyObject *module, int fd)
3964
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3965
0
{
3966
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3967
0
        return NULL;
3968
0
    }
3969
0
    return posix_fildes_fd(fd, fchdir);
3970
0
}
3971
#endif /* HAVE_FCHDIR */
3972
3973
#ifdef MS_WINDOWS
3974
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3975
#else
3976
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3977
#endif
3978
3979
#ifdef MS_WINDOWS
3980
static int
3981
win32_lchmod(LPCWSTR path, int mode)
3982
{
3983
    DWORD attr = GetFileAttributesW(path);
3984
    if (attr == INVALID_FILE_ATTRIBUTES) {
3985
        return 0;
3986
    }
3987
    if (mode & _S_IWRITE) {
3988
        attr &= ~FILE_ATTRIBUTE_READONLY;
3989
    }
3990
    else {
3991
        attr |= FILE_ATTRIBUTE_READONLY;
3992
    }
3993
    return SetFileAttributesW(path, attr);
3994
}
3995
3996
static int
3997
win32_hchmod(HANDLE hfile, int mode)
3998
{
3999
    FILE_BASIC_INFO info;
4000
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4001
                                      &info, sizeof(info)))
4002
    {
4003
        return 0;
4004
    }
4005
    if (mode & _S_IWRITE) {
4006
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4007
    }
4008
    else {
4009
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4010
    }
4011
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4012
                                      &info, sizeof(info));
4013
}
4014
4015
static int
4016
win32_fchmod(int fd, int mode)
4017
{
4018
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4019
    if (hfile == INVALID_HANDLE_VALUE) {
4020
        SetLastError(ERROR_INVALID_HANDLE);
4021
        return 0;
4022
    }
4023
    return win32_hchmod(hfile, mode);
4024
}
4025
4026
#endif /* MS_WINDOWS */
4027
4028
/*[clinic input]
4029
os.chmod
4030
4031
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4032
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
4033
        On some platforms, path may also be specified as an open file descriptor.
4034
        If this functionality is unavailable, using it raises an exception.
4035
4036
    mode: int
4037
        Operating-system mode bitfield.
4038
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4039
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4040
        Python.
4041
4042
    *
4043
4044
    dir_fd : dir_fd(requires='fchmodat') = None
4045
        If not None, it should be a file descriptor open to a directory,
4046
        and path should be relative; path will then be relative to that
4047
        directory.
4048
4049
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4050
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4051
        If False, and the last element of the path is a symbolic link,
4052
        chmod will modify the symbolic link itself instead of the file
4053
        the link points to.
4054
4055
Change the access permissions of a file.
4056
4057
It is an error to use dir_fd or follow_symlinks when specifying path as
4058
  an open file descriptor.
4059
dir_fd and follow_symlinks may not be implemented on your platform.
4060
  If they are unavailable, using them will raise a NotImplementedError.
4061
4062
[clinic start generated code]*/
4063
4064
static PyObject *
4065
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4066
              int follow_symlinks)
4067
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
4068
0
{
4069
0
    int result;
4070
4071
0
#ifdef HAVE_FCHMODAT
4072
0
    int fchmodat_nofollow_unsupported = 0;
4073
0
    int fchmodat_unsupported = 0;
4074
0
#endif
4075
4076
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4077
    if (follow_symlinks_specified("chmod", follow_symlinks))
4078
        return NULL;
4079
#endif
4080
4081
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4082
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4083
0
        return NULL;
4084
0
    }
4085
4086
#ifdef MS_WINDOWS
4087
    result = 0;
4088
    Py_BEGIN_ALLOW_THREADS
4089
    if (path->fd != -1) {
4090
        result = win32_fchmod(path->fd, mode);
4091
    }
4092
    else if (follow_symlinks) {
4093
        HANDLE hfile = CreateFileW(path->wide,
4094
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4095
                                   0, NULL,
4096
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4097
        if (hfile != INVALID_HANDLE_VALUE) {
4098
            result = win32_hchmod(hfile, mode);
4099
            (void)CloseHandle(hfile);
4100
        }
4101
    }
4102
    else {
4103
        result = win32_lchmod(path->wide, mode);
4104
    }
4105
    Py_END_ALLOW_THREADS
4106
    if (!result) {
4107
        return path_error(path);
4108
    }
4109
#else /* MS_WINDOWS */
4110
0
    Py_BEGIN_ALLOW_THREADS
4111
0
#ifdef HAVE_FCHMOD
4112
0
    if (path->fd != -1)
4113
0
        result = fchmod(path->fd, mode);
4114
0
    else
4115
0
#endif /* HAVE_CHMOD */
4116
#ifdef HAVE_LCHMOD
4117
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4118
        result = lchmod(path->narrow, mode);
4119
    else
4120
#endif /* HAVE_LCHMOD */
4121
0
#ifdef HAVE_FCHMODAT
4122
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4123
0
        if (HAVE_FCHMODAT_RUNTIME) {
4124
            /*
4125
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4126
             * The documentation specifically shows how to use it,
4127
             * and then says it isn't implemented yet.
4128
             * (true on linux with glibc 2.15, and openindiana 3.x)
4129
             *
4130
             * Once it is supported, os.chmod will automatically
4131
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4132
             * Until then, we need to be careful what exception we raise.
4133
             */
4134
0
            result = fchmodat(dir_fd, path->narrow, mode,
4135
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4136
            /*
4137
             * But wait!  We can't throw the exception without allowing threads,
4138
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4139
             */
4140
0
            fchmodat_nofollow_unsupported =
4141
0
                             result &&
4142
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4143
0
                             !follow_symlinks;
4144
0
        } else {
4145
0
            fchmodat_unsupported = 1;
4146
0
            fchmodat_nofollow_unsupported = 1;
4147
4148
0
            result = -1;
4149
0
        }
4150
0
    }
4151
0
    else
4152
0
#endif /* HAVE_FHCMODAT */
4153
0
    {
4154
0
#ifdef HAVE_CHMOD
4155
0
        result = chmod(path->narrow, mode);
4156
#elif defined(__wasi__)
4157
        // WASI SDK 15.0 does not support chmod.
4158
        // Ignore missing syscall for now.
4159
        result = 0;
4160
#else
4161
        result = -1;
4162
        errno = ENOSYS;
4163
#endif
4164
0
    }
4165
0
    Py_END_ALLOW_THREADS
4166
4167
0
    if (result) {
4168
0
#ifdef HAVE_FCHMODAT
4169
0
        if (fchmodat_unsupported) {
4170
0
            if (dir_fd != DEFAULT_DIR_FD) {
4171
0
                argument_unavailable_error("chmod", "dir_fd");
4172
0
                return NULL;
4173
0
            }
4174
0
        }
4175
4176
0
        if (fchmodat_nofollow_unsupported) {
4177
0
            if (dir_fd != DEFAULT_DIR_FD)
4178
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4179
0
                                                   dir_fd, follow_symlinks);
4180
0
            else
4181
0
                follow_symlinks_specified("chmod", follow_symlinks);
4182
0
            return NULL;
4183
0
        }
4184
0
        else
4185
0
#endif /* HAVE_FCHMODAT */
4186
0
        return path_error(path);
4187
0
    }
4188
0
#endif /* MS_WINDOWS */
4189
4190
0
    Py_RETURN_NONE;
4191
0
}
4192
4193
4194
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4195
/*[clinic input]
4196
os.fchmod
4197
4198
    fd: int
4199
        The file descriptor of the file to be modified.
4200
    mode: int
4201
        Operating-system mode bitfield.
4202
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4203
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4204
        Python.
4205
4206
Change the access permissions of the file given by file descriptor fd.
4207
4208
Equivalent to os.chmod(fd, mode).
4209
[clinic start generated code]*/
4210
4211
static PyObject *
4212
os_fchmod_impl(PyObject *module, int fd, int mode)
4213
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
4214
0
{
4215
0
    int res;
4216
4217
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4218
0
        return NULL;
4219
0
    }
4220
4221
#ifdef MS_WINDOWS
4222
    res = 0;
4223
    Py_BEGIN_ALLOW_THREADS
4224
    res = win32_fchmod(fd, mode);
4225
    Py_END_ALLOW_THREADS
4226
    if (!res) {
4227
        return PyErr_SetFromWindowsErr(0);
4228
    }
4229
#else /* MS_WINDOWS */
4230
0
    int async_err = 0;
4231
0
    do {
4232
0
        Py_BEGIN_ALLOW_THREADS
4233
0
        res = fchmod(fd, mode);
4234
0
        Py_END_ALLOW_THREADS
4235
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4236
0
    if (res != 0)
4237
0
        return (!async_err) ? posix_error() : NULL;
4238
0
#endif /* MS_WINDOWS */
4239
4240
0
    Py_RETURN_NONE;
4241
0
}
4242
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4243
4244
4245
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4246
/*[clinic input]
4247
os.lchmod
4248
4249
    path: path_t
4250
    mode: int
4251
4252
Change the access permissions of a file, without following symbolic links.
4253
4254
If path is a symlink, this affects the link itself rather than the target.
4255
Equivalent to chmod(path, mode, follow_symlinks=False)."
4256
[clinic start generated code]*/
4257
4258
static PyObject *
4259
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4260
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
4261
{
4262
    int res;
4263
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4264
        return NULL;
4265
    }
4266
#ifdef MS_WINDOWS
4267
    Py_BEGIN_ALLOW_THREADS
4268
    res = win32_lchmod(path->wide, mode);
4269
    Py_END_ALLOW_THREADS
4270
    if (!res) {
4271
        path_error(path);
4272
        return NULL;
4273
    }
4274
#else /* MS_WINDOWS */
4275
    Py_BEGIN_ALLOW_THREADS
4276
    res = lchmod(path->narrow, mode);
4277
    Py_END_ALLOW_THREADS
4278
    if (res < 0) {
4279
        path_error(path);
4280
        return NULL;
4281
    }
4282
#endif /* MS_WINDOWS */
4283
    Py_RETURN_NONE;
4284
}
4285
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4286
4287
4288
#ifdef HAVE_CHFLAGS
4289
/*[clinic input]
4290
os.chflags
4291
4292
    path: path_t
4293
    flags: unsigned_long(bitwise=True)
4294
    follow_symlinks: bool=True
4295
4296
Set file flags.
4297
4298
If follow_symlinks is False, and the last element of the path is a symbolic
4299
  link, chflags will change flags on the symbolic link itself instead of the
4300
  file the link points to.
4301
follow_symlinks may not be implemented on your platform.  If it is
4302
unavailable, using it will raise a NotImplementedError.
4303
4304
[clinic start generated code]*/
4305
4306
static PyObject *
4307
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4308
                int follow_symlinks)
4309
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
4310
{
4311
    int result;
4312
4313
#ifndef HAVE_LCHFLAGS
4314
    if (follow_symlinks_specified("chflags", follow_symlinks))
4315
        return NULL;
4316
#endif
4317
4318
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4319
        return NULL;
4320
    }
4321
4322
    Py_BEGIN_ALLOW_THREADS
4323
#ifdef HAVE_LCHFLAGS
4324
    if (!follow_symlinks)
4325
        result = lchflags(path->narrow, flags);
4326
    else
4327
#endif
4328
        result = chflags(path->narrow, flags);
4329
    Py_END_ALLOW_THREADS
4330
4331
    if (result)
4332
        return path_error(path);
4333
4334
    Py_RETURN_NONE;
4335
}
4336
#endif /* HAVE_CHFLAGS */
4337
4338
4339
#ifdef HAVE_LCHFLAGS
4340
/*[clinic input]
4341
os.lchflags
4342
4343
    path: path_t
4344
    flags: unsigned_long(bitwise=True)
4345
4346
Set file flags.
4347
4348
This function will not follow symbolic links.
4349
Equivalent to chflags(path, flags, follow_symlinks=False).
4350
[clinic start generated code]*/
4351
4352
static PyObject *
4353
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4354
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4355
{
4356
    int res;
4357
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4358
        return NULL;
4359
    }
4360
    Py_BEGIN_ALLOW_THREADS
4361
    res = lchflags(path->narrow, flags);
4362
    Py_END_ALLOW_THREADS
4363
    if (res < 0) {
4364
        return path_error(path);
4365
    }
4366
    Py_RETURN_NONE;
4367
}
4368
#endif /* HAVE_LCHFLAGS */
4369
4370
4371
#ifdef HAVE_CHROOT
4372
/*[clinic input]
4373
os.chroot
4374
    path: path_t
4375
4376
Change root directory to path.
4377
4378
[clinic start generated code]*/
4379
4380
static PyObject *
4381
os_chroot_impl(PyObject *module, path_t *path)
4382
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4383
0
{
4384
0
    int res;
4385
0
    Py_BEGIN_ALLOW_THREADS
4386
0
    res = chroot(path->narrow);
4387
0
    Py_END_ALLOW_THREADS
4388
0
    if (res < 0)
4389
0
        return path_error(path);
4390
0
    Py_RETURN_NONE;
4391
0
}
4392
#endif /* HAVE_CHROOT */
4393
4394
4395
#ifdef HAVE_FSYNC
4396
/*[clinic input]
4397
os.fsync
4398
4399
    fd: fildes
4400
4401
Force write of fd to disk.
4402
[clinic start generated code]*/
4403
4404
static PyObject *
4405
os_fsync_impl(PyObject *module, int fd)
4406
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4407
0
{
4408
0
    return posix_fildes_fd(fd, fsync);
4409
0
}
4410
#endif /* HAVE_FSYNC */
4411
4412
4413
#ifdef HAVE_SYNC
4414
/*[clinic input]
4415
os.sync
4416
4417
Force write of everything to disk.
4418
[clinic start generated code]*/
4419
4420
static PyObject *
4421
os_sync_impl(PyObject *module)
4422
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4423
0
{
4424
0
    Py_BEGIN_ALLOW_THREADS
4425
0
    sync();
4426
0
    Py_END_ALLOW_THREADS
4427
0
    Py_RETURN_NONE;
4428
0
}
4429
#endif /* HAVE_SYNC */
4430
4431
4432
#ifdef HAVE_FDATASYNC
4433
#ifdef __hpux
4434
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4435
#endif
4436
4437
/*[clinic input]
4438
os.fdatasync
4439
4440
    fd: fildes
4441
4442
Force write of fd to disk without forcing update of metadata.
4443
[clinic start generated code]*/
4444
4445
static PyObject *
4446
os_fdatasync_impl(PyObject *module, int fd)
4447
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4448
0
{
4449
0
    return posix_fildes_fd(fd, fdatasync);
4450
0
}
4451
#endif /* HAVE_FDATASYNC */
4452
4453
4454
#ifdef HAVE_CHOWN
4455
/*[clinic input]
4456
os.chown
4457
4458
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4459
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4460
4461
    uid: uid_t
4462
4463
    gid: gid_t
4464
4465
    *
4466
4467
    dir_fd : dir_fd(requires='fchownat') = None
4468
        If not None, it should be a file descriptor open to a directory,
4469
        and path should be relative; path will then be relative to that
4470
        directory.
4471
4472
    follow_symlinks: bool = True
4473
        If False, and the last element of the path is a symbolic link,
4474
        stat will examine the symbolic link itself instead of the file
4475
        the link points to.
4476
4477
Change the owner and group id of path to the numeric uid and gid.\
4478
4479
path may always be specified as a string.
4480
On some platforms, path may also be specified as an open file descriptor.
4481
  If this functionality is unavailable, using it raises an exception.
4482
If dir_fd is not None, it should be a file descriptor open to a directory,
4483
  and path should be relative; path will then be relative to that directory.
4484
If follow_symlinks is False, and the last element of the path is a symbolic
4485
  link, chown will modify the symbolic link itself instead of the file the
4486
  link points to.
4487
It is an error to use dir_fd or follow_symlinks when specifying path as
4488
  an open file descriptor.
4489
dir_fd and follow_symlinks may not be implemented on your platform.
4490
  If they are unavailable, using them will raise a NotImplementedError.
4491
4492
[clinic start generated code]*/
4493
4494
static PyObject *
4495
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4496
              int dir_fd, int follow_symlinks)
4497
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4498
0
{
4499
0
    int result;
4500
4501
0
#if defined(HAVE_FCHOWNAT)
4502
0
    int fchownat_unsupported = 0;
4503
0
#endif
4504
4505
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4506
    if (follow_symlinks_specified("chown", follow_symlinks))
4507
        return NULL;
4508
#endif
4509
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4510
0
        fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
4511
0
        return NULL;
4512
4513
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4514
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4515
0
        return NULL;
4516
0
    }
4517
4518
0
    Py_BEGIN_ALLOW_THREADS
4519
0
#ifdef HAVE_FCHOWN
4520
0
    if (path->fd != -1)
4521
0
        result = fchown(path->fd, uid, gid);
4522
0
    else
4523
0
#endif
4524
0
#ifdef HAVE_LCHOWN
4525
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4526
0
        result = lchown(path->narrow, uid, gid);
4527
0
    else
4528
0
#endif
4529
0
#ifdef HAVE_FCHOWNAT
4530
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4531
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4532
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4533
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4534
0
      } else {
4535
0
         fchownat_unsupported = 1;
4536
0
      }
4537
0
    } else
4538
0
#endif
4539
0
        result = chown(path->narrow, uid, gid);
4540
0
    Py_END_ALLOW_THREADS
4541
4542
0
#ifdef HAVE_FCHOWNAT
4543
0
    if (fchownat_unsupported) {
4544
        /* This would be incorrect if the current platform
4545
         * doesn't support lchown.
4546
         */
4547
0
        argument_unavailable_error(NULL, "dir_fd");
4548
0
        return NULL;
4549
0
    }
4550
0
#endif
4551
4552
0
    if (result)
4553
0
        return path_error(path);
4554
4555
0
    Py_RETURN_NONE;
4556
0
}
4557
#endif /* HAVE_CHOWN */
4558
4559
4560
#ifdef HAVE_FCHOWN
4561
/*[clinic input]
4562
os.fchown
4563
4564
    fd: int
4565
    uid: uid_t
4566
    gid: gid_t
4567
4568
Change the owner and group id of the file specified by file descriptor.
4569
4570
Equivalent to os.chown(fd, uid, gid).
4571
4572
[clinic start generated code]*/
4573
4574
static PyObject *
4575
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4576
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4577
0
{
4578
0
    int res;
4579
0
    int async_err = 0;
4580
4581
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4582
0
        return NULL;
4583
0
    }
4584
4585
0
    do {
4586
0
        Py_BEGIN_ALLOW_THREADS
4587
0
        res = fchown(fd, uid, gid);
4588
0
        Py_END_ALLOW_THREADS
4589
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4590
0
    if (res != 0)
4591
0
        return (!async_err) ? posix_error() : NULL;
4592
4593
0
    Py_RETURN_NONE;
4594
0
}
4595
#endif /* HAVE_FCHOWN */
4596
4597
4598
#ifdef HAVE_LCHOWN
4599
/*[clinic input]
4600
os.lchown
4601
4602
    path : path_t
4603
    uid: uid_t
4604
    gid: gid_t
4605
4606
Change the owner and group id of path to the numeric uid and gid.
4607
4608
This function will not follow symbolic links.
4609
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4610
[clinic start generated code]*/
4611
4612
static PyObject *
4613
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4614
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4615
0
{
4616
0
    int res;
4617
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4618
0
        return NULL;
4619
0
    }
4620
0
    Py_BEGIN_ALLOW_THREADS
4621
0
    res = lchown(path->narrow, uid, gid);
4622
0
    Py_END_ALLOW_THREADS
4623
0
    if (res < 0) {
4624
0
        return path_error(path);
4625
0
    }
4626
0
    Py_RETURN_NONE;
4627
0
}
4628
#endif /* HAVE_LCHOWN */
4629
4630
4631
static PyObject *
4632
posix_getcwd(int use_bytes)
4633
4
{
4634
#ifdef MS_WINDOWS
4635
    wchar_t wbuf[MAXPATHLEN];
4636
    wchar_t *wbuf2 = wbuf;
4637
    DWORD len;
4638
4639
    Py_BEGIN_ALLOW_THREADS
4640
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4641
    /* If the buffer is large enough, len does not include the
4642
       terminating \0. If the buffer is too small, len includes
4643
       the space needed for the terminator. */
4644
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4645
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4646
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4647
        }
4648
        else {
4649
            wbuf2 = NULL;
4650
        }
4651
        if (wbuf2) {
4652
            len = GetCurrentDirectoryW(len, wbuf2);
4653
        }
4654
    }
4655
    Py_END_ALLOW_THREADS
4656
4657
    if (!wbuf2) {
4658
        PyErr_NoMemory();
4659
        return NULL;
4660
    }
4661
    if (!len) {
4662
        PyErr_SetFromWindowsErr(0);
4663
        if (wbuf2 != wbuf)
4664
            PyMem_RawFree(wbuf2);
4665
        return NULL;
4666
    }
4667
4668
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4669
    if (wbuf2 != wbuf) {
4670
        PyMem_RawFree(wbuf2);
4671
    }
4672
4673
    if (use_bytes) {
4674
        if (resobj == NULL) {
4675
            return NULL;
4676
        }
4677
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4678
    }
4679
4680
    return resobj;
4681
#else
4682
4
    const size_t chunk = 1024;
4683
4684
4
    char *buf = NULL;
4685
4
    char *cwd = NULL;
4686
4
    size_t buflen = 0;
4687
4688
4
    Py_BEGIN_ALLOW_THREADS
4689
4
    do {
4690
4
        char *newbuf;
4691
4
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4692
4
            buflen += chunk;
4693
4
            newbuf = PyMem_RawRealloc(buf, buflen);
4694
4
        }
4695
0
        else {
4696
0
            newbuf = NULL;
4697
0
        }
4698
4
        if (newbuf == NULL) {
4699
0
            PyMem_RawFree(buf);
4700
0
            buf = NULL;
4701
0
            break;
4702
0
        }
4703
4
        buf = newbuf;
4704
4705
4
        cwd = getcwd(buf, buflen);
4706
4
    } while (cwd == NULL && errno == ERANGE);
4707
4
    Py_END_ALLOW_THREADS
4708
4709
4
    if (buf == NULL) {
4710
0
        return PyErr_NoMemory();
4711
0
    }
4712
4
    if (cwd == NULL) {
4713
0
        posix_error();
4714
0
        PyMem_RawFree(buf);
4715
0
        return NULL;
4716
0
    }
4717
4718
4
    PyObject *obj;
4719
4
    if (use_bytes) {
4720
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4721
0
    }
4722
4
    else {
4723
4
        obj = PyUnicode_DecodeFSDefault(buf);
4724
4
    }
4725
4
#ifdef __linux__
4726
4
    if (buf[0] != '/') {
4727
        /*
4728
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4729
         * relative pathname starting with '(unreachable)'. We detect this
4730
         * and fail with ENOENT, matching newer glibc behaviour.
4731
         */
4732
0
        errno = ENOENT;
4733
0
        path_object_error(obj);
4734
0
        PyMem_RawFree(buf);
4735
0
        return NULL;
4736
0
    }
4737
4
#endif
4738
4
    assert(buf[0] == '/');
4739
4
    PyMem_RawFree(buf);
4740
4741
4
    return obj;
4742
4
#endif   /* !MS_WINDOWS */
4743
4
}
4744
4745
4746
/*[clinic input]
4747
os.getcwd
4748
4749
Return a unicode string representing the current working directory.
4750
[clinic start generated code]*/
4751
4752
static PyObject *
4753
os_getcwd_impl(PyObject *module)
4754
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4755
4
{
4756
4
    return posix_getcwd(0);
4757
4
}
4758
4759
4760
/*[clinic input]
4761
os.getcwdb
4762
4763
Return a bytes string representing the current working directory.
4764
[clinic start generated code]*/
4765
4766
static PyObject *
4767
os_getcwdb_impl(PyObject *module)
4768
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4769
0
{
4770
0
    return posix_getcwd(1);
4771
0
}
4772
4773
4774
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4775
#define HAVE_LINK 1
4776
#endif
4777
4778
#ifdef HAVE_LINK
4779
/*[clinic input]
4780
4781
@permit_long_docstring_body
4782
os.link
4783
4784
    src : path_t
4785
    dst : path_t
4786
    *
4787
    src_dir_fd : dir_fd = None
4788
    dst_dir_fd : dir_fd = None
4789
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4790
4791
Create a hard link to a file.
4792
4793
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4794
  descriptor open to a directory, and the respective path string (src or dst)
4795
  should be relative; the path will then be relative to that directory.
4796
If follow_symlinks is False, and the last element of src is a symbolic
4797
  link, link will create a link to the symbolic link itself instead of the
4798
  file the link points to.
4799
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4800
  platform.  If they are unavailable, using them will raise a
4801
  NotImplementedError.
4802
[clinic start generated code]*/
4803
4804
static PyObject *
4805
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4806
             int dst_dir_fd, int follow_symlinks)
4807
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4808
0
{
4809
#ifdef MS_WINDOWS
4810
    BOOL result = FALSE;
4811
#else
4812
0
    int result;
4813
0
#endif
4814
4815
0
#ifdef HAVE_LINKAT
4816
0
    if (HAVE_LINKAT_RUNTIME) {
4817
0
        if (follow_symlinks < 0) {
4818
0
            follow_symlinks = 1;
4819
0
        }
4820
0
    }
4821
0
    else
4822
0
#endif
4823
0
    {
4824
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4825
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4826
0
            return NULL;
4827
0
        }
4828
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4829
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4830
0
#if defined(MS_WINDOWS) || defined(__linux__)
4831
0
        if (follow_symlinks == 1) {
4832
0
            argument_unavailable_error("link", "follow_symlinks=True");
4833
0
            return NULL;
4834
0
        }
4835
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4836
        if (follow_symlinks == 0) {
4837
            argument_unavailable_error("link", "follow_symlinks=False");
4838
            return NULL;
4839
        }
4840
#else
4841
        if (follow_symlinks >= 0) {
4842
            argument_unavailable_error("link", "follow_symlinks");
4843
            return NULL;
4844
        }
4845
#endif
4846
0
    }
4847
4848
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4849
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4850
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4851
0
        return NULL;
4852
0
    }
4853
4854
#ifdef MS_WINDOWS
4855
    Py_BEGIN_ALLOW_THREADS
4856
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4857
    Py_END_ALLOW_THREADS
4858
4859
    if (!result)
4860
        return path_error2(src, dst);
4861
#else
4862
0
    Py_BEGIN_ALLOW_THREADS
4863
0
#ifdef HAVE_LINKAT
4864
0
    if (HAVE_LINKAT_RUNTIME) {
4865
0
        result = linkat(src_dir_fd, src->narrow,
4866
0
            dst_dir_fd, dst->narrow,
4867
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4868
0
    }
4869
0
    else
4870
0
#endif
4871
0
    {
4872
        /* linkat not available */
4873
0
        result = link(src->narrow, dst->narrow);
4874
0
    }
4875
0
    Py_END_ALLOW_THREADS
4876
4877
0
    if (result)
4878
0
        return path_error2(src, dst);
4879
0
#endif /* MS_WINDOWS */
4880
4881
0
    Py_RETURN_NONE;
4882
0
}
4883
#endif
4884
4885
4886
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4887
static PyObject *
4888
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4889
{
4890
    PyObject *v;
4891
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4892
    BOOL result, return_bytes;
4893
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4894
    /* only claim to have space for MAX_PATH */
4895
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4896
    wchar_t *wnamebuf = NULL;
4897
4898
    WIN32_FIND_DATAW wFileData;
4899
    const wchar_t *po_wchars;
4900
4901
    if (!path->wide) { /* Default arg: "." */
4902
        po_wchars = L".";
4903
        len = 1;
4904
        return_bytes = 0;
4905
    } else {
4906
        po_wchars = path->wide;
4907
        len = wcslen(path->wide);
4908
        return_bytes = PyBytes_Check(path->object);
4909
    }
4910
    /* The +5 is so we can append "\\*.*\0" */
4911
    wnamebuf = PyMem_New(wchar_t, len + 5);
4912
    if (!wnamebuf) {
4913
        PyErr_NoMemory();
4914
        goto exit;
4915
    }
4916
    wcscpy(wnamebuf, po_wchars);
4917
    if (len > 0) {
4918
        wchar_t wch = wnamebuf[len-1];
4919
        if (wch != SEP && wch != ALTSEP && wch != L':')
4920
            wnamebuf[len++] = SEP;
4921
        wcscpy(wnamebuf + len, L"*.*");
4922
    }
4923
    if ((list = PyList_New(0)) == NULL) {
4924
        goto exit;
4925
    }
4926
    Py_BEGIN_ALLOW_THREADS
4927
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4928
    Py_END_ALLOW_THREADS
4929
    if (hFindFile == INVALID_HANDLE_VALUE) {
4930
        int error = GetLastError();
4931
        if (error == ERROR_FILE_NOT_FOUND)
4932
            goto exit;
4933
        path_error(path);
4934
        Py_CLEAR(list);
4935
        goto exit;
4936
    }
4937
    do {
4938
        /* Skip over . and .. */
4939
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4940
            wcscmp(wFileData.cFileName, L"..") != 0) {
4941
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4942
                                       wcslen(wFileData.cFileName));
4943
            if (return_bytes && v) {
4944
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4945
            }
4946
            if (v == NULL) {
4947
                Py_CLEAR(list);
4948
                break;
4949
            }
4950
            if (PyList_Append(list, v) != 0) {
4951
                Py_DECREF(v);
4952
                Py_CLEAR(list);
4953
                break;
4954
            }
4955
            Py_DECREF(v);
4956
        }
4957
        Py_BEGIN_ALLOW_THREADS
4958
        result = FindNextFileW(hFindFile, &wFileData);
4959
        Py_END_ALLOW_THREADS
4960
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4961
           it got to the end of the directory. */
4962
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4963
            path_error(path);
4964
            Py_CLEAR(list);
4965
            goto exit;
4966
        }
4967
    } while (result == TRUE);
4968
4969
exit:
4970
    if (hFindFile != INVALID_HANDLE_VALUE) {
4971
        if (FindClose(hFindFile) == FALSE) {
4972
            if (list != NULL) {
4973
                path_error(path);
4974
                Py_CLEAR(list);
4975
            }
4976
        }
4977
    }
4978
    PyMem_Free(wnamebuf);
4979
4980
    return list;
4981
}  /* end of _listdir_windows_no_opendir */
4982
4983
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4984
4985
static PyObject *
4986
_posix_listdir(path_t *path, PyObject *list)
4987
306
{
4988
306
    PyObject *v;
4989
306
    DIR *dirp = NULL;
4990
306
    struct dirent *ep;
4991
306
    int return_str; /* if false, return bytes */
4992
306
#ifdef HAVE_FDOPENDIR
4993
306
    int fd = -1;
4994
306
#endif
4995
4996
306
    errno = 0;
4997
306
#ifdef HAVE_FDOPENDIR
4998
306
    if (path->fd != -1) {
4999
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5000
        /* closedir() closes the FD, so we duplicate it */
5001
0
        fd = _Py_dup(path->fd);
5002
0
        if (fd == -1)
5003
0
            return NULL;
5004
5005
0
        return_str = 1;
5006
5007
0
        Py_BEGIN_ALLOW_THREADS
5008
0
        dirp = fdopendir(fd);
5009
0
        Py_END_ALLOW_THREADS
5010
0
      } else {
5011
0
        PyErr_SetString(PyExc_TypeError,
5012
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5013
0
        return NULL;
5014
0
      }
5015
0
    }
5016
306
    else
5017
306
#endif
5018
306
    {
5019
306
        const char *name;
5020
306
        if (path->narrow) {
5021
306
            name = path->narrow;
5022
            /* only return bytes if they specified a bytes object */
5023
306
            return_str = !PyBytes_Check(path->object);
5024
306
        }
5025
0
        else {
5026
0
            name = ".";
5027
0
            return_str = 1;
5028
0
        }
5029
5030
306
        Py_BEGIN_ALLOW_THREADS
5031
306
        dirp = opendir(name);
5032
306
        Py_END_ALLOW_THREADS
5033
306
    }
5034
5035
306
    if (dirp == NULL) {
5036
4
        path_error(path);
5037
4
        list = NULL;
5038
4
#ifdef HAVE_FDOPENDIR
5039
4
        if (fd != -1) {
5040
0
            Py_BEGIN_ALLOW_THREADS
5041
0
            close(fd);
5042
0
            Py_END_ALLOW_THREADS
5043
0
        }
5044
4
#endif
5045
4
        goto exit;
5046
4
    }
5047
302
    if ((list = PyList_New(0)) == NULL) {
5048
0
        goto exit;
5049
0
    }
5050
15.9k
    for (;;) {
5051
15.9k
        errno = 0;
5052
15.9k
        Py_BEGIN_ALLOW_THREADS
5053
15.9k
        ep = readdir(dirp);
5054
15.9k
        Py_END_ALLOW_THREADS
5055
15.9k
        if (ep == NULL) {
5056
302
            if (errno == 0) {
5057
302
                break;
5058
302
            } else {
5059
0
                path_error(path);
5060
0
                Py_CLEAR(list);
5061
0
                goto exit;
5062
0
            }
5063
302
        }
5064
15.6k
        if (ep->d_name[0] == '.' &&
5065
604
            (NAMLEN(ep) == 1 ||
5066
302
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5067
604
            continue;
5068
15.0k
        if (return_str)
5069
15.0k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5070
0
        else
5071
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5072
15.0k
        if (v == NULL) {
5073
0
            Py_CLEAR(list);
5074
0
            break;
5075
0
        }
5076
15.0k
        if (PyList_Append(list, v) != 0) {
5077
0
            Py_DECREF(v);
5078
0
            Py_CLEAR(list);
5079
0
            break;
5080
0
        }
5081
15.0k
        Py_DECREF(v);
5082
15.0k
    }
5083
5084
306
exit:
5085
306
    if (dirp != NULL) {
5086
302
        Py_BEGIN_ALLOW_THREADS
5087
302
#ifdef HAVE_FDOPENDIR
5088
302
        if (fd > -1)
5089
0
            rewinddir(dirp);
5090
302
#endif
5091
302
        closedir(dirp);
5092
302
        Py_END_ALLOW_THREADS
5093
302
    }
5094
5095
306
    return list;
5096
302
}  /* end of _posix_listdir */
5097
#endif  /* which OS */
5098
5099
5100
/*[clinic input]
5101
@permit_long_docstring_body
5102
os.listdir
5103
5104
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5105
5106
Return a list containing the names of the files in the directory.
5107
5108
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
5109
  the filenames returned will also be bytes; in all other circumstances
5110
  the filenames returned will be str.
5111
If path is None, uses the path='.'.
5112
On some platforms, path may also be specified as an open file descriptor;\
5113
  the file descriptor must refer to a directory.
5114
  If this functionality is unavailable, using it raises NotImplementedError.
5115
5116
The list is in arbitrary order.  It does not include the special
5117
entries '.' and '..' even if they are present in the directory.
5118
5119
5120
[clinic start generated code]*/
5121
5122
static PyObject *
5123
os_listdir_impl(PyObject *module, path_t *path)
5124
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
5125
306
{
5126
306
    if (PySys_Audit("os.listdir", "O",
5127
306
                    path->object ? path->object : Py_None) < 0) {
5128
0
        return NULL;
5129
0
    }
5130
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5131
    return _listdir_windows_no_opendir(path, NULL);
5132
#else
5133
306
    return _posix_listdir(path, NULL);
5134
306
#endif
5135
306
}
5136
5137
5138
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5139
5140
/*[clinic input]
5141
os.listdrives
5142
5143
Return a list containing the names of drives in the system.
5144
5145
A drive name typically looks like 'C:\\'.
5146
5147
[clinic start generated code]*/
5148
5149
static PyObject *
5150
os_listdrives_impl(PyObject *module)
5151
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5152
{
5153
    /* Number of possible drives is limited, so 256 should always be enough.
5154
       On the day when it is not, listmounts() will have to be used. */
5155
    wchar_t buffer[256];
5156
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5157
    PyObject *result = NULL;
5158
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5159
        return NULL;
5160
    }
5161
5162
    Py_BEGIN_ALLOW_THREADS;
5163
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5164
    Py_END_ALLOW_THREADS;
5165
5166
    if (!buflen) {
5167
        PyErr_SetFromWindowsErr(0);
5168
        return NULL;
5169
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5170
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5171
        return NULL;
5172
    }
5173
5174
    /* buflen includes a null terminator, so remove it */
5175
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5176
    if (str) {
5177
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5178
        if (nullchar) {
5179
            result = PyUnicode_Split(str, nullchar, -1);
5180
            Py_DECREF(nullchar);
5181
        }
5182
        Py_DECREF(str);
5183
    }
5184
    return result;
5185
}
5186
5187
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5188
5189
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5190
5191
/*[clinic input]
5192
os.listvolumes
5193
5194
Return a list containing the volumes in the system.
5195
5196
Volumes are typically represented as a GUID path.
5197
5198
[clinic start generated code]*/
5199
5200
static PyObject *
5201
os_listvolumes_impl(PyObject *module)
5202
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5203
{
5204
    PyObject *result = PyList_New(0);
5205
    HANDLE find = INVALID_HANDLE_VALUE;
5206
    wchar_t buffer[MAX_PATH + 1];
5207
    if (!result) {
5208
        return NULL;
5209
    }
5210
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5211
        Py_DECREF(result);
5212
        return NULL;
5213
    }
5214
5215
    int err = 0;
5216
    Py_BEGIN_ALLOW_THREADS;
5217
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5218
    if (find == INVALID_HANDLE_VALUE) {
5219
        err = GetLastError();
5220
    }
5221
    Py_END_ALLOW_THREADS;
5222
5223
    while (!err) {
5224
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5225
        if (!s || PyList_Append(result, s) < 0) {
5226
            Py_XDECREF(s);
5227
            Py_CLEAR(result);
5228
            break;
5229
        }
5230
        Py_DECREF(s);
5231
5232
        Py_BEGIN_ALLOW_THREADS;
5233
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5234
            err = GetLastError();
5235
        }
5236
        Py_END_ALLOW_THREADS;
5237
    }
5238
5239
    if (find != INVALID_HANDLE_VALUE) {
5240
        Py_BEGIN_ALLOW_THREADS;
5241
        FindVolumeClose(find);
5242
        Py_END_ALLOW_THREADS;
5243
    }
5244
    if (err && err != ERROR_NO_MORE_FILES) {
5245
        PyErr_SetFromWindowsErr(err);
5246
        Py_XDECREF(result);
5247
        result = NULL;
5248
    }
5249
    return result;
5250
}
5251
5252
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5253
5254
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5255
5256
/*[clinic input]
5257
os.listmounts
5258
5259
    volume: path_t
5260
5261
Return a list containing mount points for a particular volume.
5262
5263
'volume' should be a GUID path as returned from os.listvolumes.
5264
5265
[clinic start generated code]*/
5266
5267
static PyObject *
5268
os_listmounts_impl(PyObject *module, path_t *volume)
5269
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5270
{
5271
    wchar_t default_buffer[MAX_PATH + 1];
5272
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5273
    LPWSTR buffer = default_buffer;
5274
    DWORD attributes;
5275
    PyObject *str = NULL;
5276
    PyObject *nullchar = NULL;
5277
    PyObject *result = NULL;
5278
5279
    /* Ensure we have a valid volume path before continuing */
5280
    Py_BEGIN_ALLOW_THREADS
5281
    attributes = GetFileAttributesW(volume->wide);
5282
    Py_END_ALLOW_THREADS
5283
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5284
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5285
    {
5286
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5287
    }
5288
5289
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5290
        return NULL;
5291
    }
5292
5293
    while (1) {
5294
        BOOL success;
5295
        Py_BEGIN_ALLOW_THREADS
5296
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5297
                                                   buflen, &buflen);
5298
        Py_END_ALLOW_THREADS
5299
        if (success) {
5300
            break;
5301
        }
5302
        if (GetLastError() != ERROR_MORE_DATA) {
5303
            PyErr_SetFromWindowsErr(0);
5304
            goto exit;
5305
        }
5306
        if (buffer != default_buffer) {
5307
            PyMem_Free((void *)buffer);
5308
        }
5309
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5310
        if (!buffer) {
5311
            PyErr_NoMemory();
5312
            goto exit;
5313
        }
5314
    }
5315
    if (buflen < 2) {
5316
        result = PyList_New(0);
5317
        goto exit;
5318
    }
5319
    // buflen includes two null terminators, one for the last string
5320
    // and one for the array of strings.
5321
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5322
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5323
    if (str && nullchar) {
5324
        result = PyUnicode_Split(str, nullchar, -1);
5325
    }
5326
exit:
5327
    if (buffer != default_buffer) {
5328
        PyMem_Free(buffer);
5329
    }
5330
    Py_XDECREF(nullchar);
5331
    Py_XDECREF(str);
5332
    return result;
5333
}
5334
5335
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5336
5337
#ifdef MS_WINDOWS
5338
5339
/*[clinic input]
5340
os._path_isdevdrive
5341
5342
    path: path_t
5343
5344
Determines whether the specified path is on a Windows Dev Drive.
5345
5346
[clinic start generated code]*/
5347
5348
static PyObject *
5349
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5350
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5351
{
5352
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5353
    /* This flag will be documented at
5354
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5355
       after release, and will be available in the latest WinSDK.
5356
       We include the flag to avoid a specific version dependency
5357
       on the latest WinSDK. */
5358
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5359
#endif
5360
    int err = 0;
5361
    PyObject *r = NULL;
5362
    wchar_t volume[MAX_PATH];
5363
5364
    Py_BEGIN_ALLOW_THREADS
5365
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5366
        /* invalid path of some kind */
5367
        /* Note that this also includes the case where a volume is mounted
5368
           in a path longer than 260 characters. This is likely to be rare
5369
           and problematic for other reasons, so a (soft) failure in this
5370
           check seems okay. */
5371
        err = GetLastError();
5372
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5373
        /* only care about local dev drives */
5374
        r = Py_False;
5375
    } else {
5376
        HANDLE hVolume = CreateFileW(
5377
            volume,
5378
            FILE_READ_ATTRIBUTES,
5379
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5380
            NULL,
5381
            OPEN_EXISTING,
5382
            FILE_FLAG_BACKUP_SEMANTICS,
5383
            NULL
5384
        );
5385
        if (hVolume == INVALID_HANDLE_VALUE) {
5386
            err = GetLastError();
5387
        } else {
5388
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5389
            volumeState.Version = 1;
5390
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5391
            if (!DeviceIoControl(
5392
                hVolume,
5393
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5394
                &volumeState,
5395
                sizeof(volumeState),
5396
                &volumeState,
5397
                sizeof(volumeState),
5398
                NULL,
5399
                NULL
5400
            )) {
5401
                err = GetLastError();
5402
            }
5403
            CloseHandle(hVolume);
5404
            if (err == ERROR_INVALID_PARAMETER) {
5405
                /* not supported on this platform */
5406
                r = Py_False;
5407
            } else if (!err) {
5408
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5409
                    ? Py_True : Py_False;
5410
            }
5411
        }
5412
    }
5413
    Py_END_ALLOW_THREADS
5414
5415
    if (err) {
5416
        PyErr_SetFromWindowsErr(err);
5417
        return NULL;
5418
    }
5419
5420
    if (r) {
5421
        return Py_NewRef(r);
5422
    }
5423
5424
    return NULL;
5425
}
5426
5427
5428
int
5429
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5430
{
5431
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5432
    DWORD result;
5433
5434
    result = GetFullPathNameW(path,
5435
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5436
                              NULL);
5437
    if (!result) {
5438
        return -1;
5439
    }
5440
5441
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5442
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5443
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5444
        }
5445
        else {
5446
            woutbufp = NULL;
5447
        }
5448
        if (!woutbufp) {
5449
            *abspath_p = NULL;
5450
            return 0;
5451
        }
5452
5453
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5454
        if (!result) {
5455
            PyMem_RawFree(woutbufp);
5456
            return -1;
5457
        }
5458
    }
5459
5460
    if (woutbufp != woutbuf) {
5461
        *abspath_p = woutbufp;
5462
        return 0;
5463
    }
5464
5465
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5466
    return 0;
5467
}
5468
5469
5470
/* A helper function for abspath on win32 */
5471
/*[clinic input]
5472
os._getfullpathname
5473
5474
    path: path_t
5475
    /
5476
5477
[clinic start generated code]*/
5478
5479
static PyObject *
5480
os__getfullpathname_impl(PyObject *module, path_t *path)
5481
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5482
{
5483
    wchar_t *abspath;
5484
5485
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5486
        return win32_error_object("GetFullPathNameW", path->object);
5487
    }
5488
    if (abspath == NULL) {
5489
        return PyErr_NoMemory();
5490
    }
5491
5492
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5493
    PyMem_RawFree(abspath);
5494
    if (str == NULL) {
5495
        return NULL;
5496
    }
5497
    if (PyBytes_Check(path->object)) {
5498
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5499
    }
5500
    return str;
5501
}
5502
5503
5504
/*[clinic input]
5505
os._getfinalpathname
5506
5507
    path: path_t
5508
    /
5509
5510
A helper function for samepath on windows.
5511
[clinic start generated code]*/
5512
5513
static PyObject *
5514
os__getfinalpathname_impl(PyObject *module, path_t *path)
5515
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5516
{
5517
    HANDLE hFile;
5518
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5519
    int buf_size = Py_ARRAY_LENGTH(buf);
5520
    int result_length;
5521
    PyObject *result;
5522
5523
    Py_BEGIN_ALLOW_THREADS
5524
    hFile = CreateFileW(
5525
        path->wide,
5526
        0, /* desired access */
5527
        0, /* share mode */
5528
        NULL, /* security attributes */
5529
        OPEN_EXISTING,
5530
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5531
        FILE_FLAG_BACKUP_SEMANTICS,
5532
        NULL);
5533
    Py_END_ALLOW_THREADS
5534
5535
    if (hFile == INVALID_HANDLE_VALUE) {
5536
        return win32_error_object("CreateFileW", path->object);
5537
    }
5538
5539
    /* We have a good handle to the target, use it to determine the
5540
       target path name. */
5541
    while (1) {
5542
        Py_BEGIN_ALLOW_THREADS
5543
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5544
                                                  buf_size, VOLUME_NAME_DOS);
5545
        Py_END_ALLOW_THREADS
5546
5547
        if (!result_length) {
5548
            result = win32_error_object("GetFinalPathNameByHandleW",
5549
                                         path->object);
5550
            goto cleanup;
5551
        }
5552
5553
        if (result_length < buf_size) {
5554
            break;
5555
        }
5556
5557
        wchar_t *tmp;
5558
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5559
                            result_length * sizeof(*tmp));
5560
        if (!tmp) {
5561
            result = PyErr_NoMemory();
5562
            goto cleanup;
5563
        }
5564
5565
        buf_size = result_length;
5566
        target_path = tmp;
5567
    }
5568
5569
    result = PyUnicode_FromWideChar(target_path, result_length);
5570
    if (result && PyBytes_Check(path->object)) {
5571
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5572
    }
5573
5574
cleanup:
5575
    if (target_path != buf) {
5576
        PyMem_Free(target_path);
5577
    }
5578
    CloseHandle(hFile);
5579
    return result;
5580
}
5581
5582
/*[clinic input]
5583
os._findfirstfile
5584
    path: path_t
5585
    /
5586
A function to get the real file name without accessing the file in Windows.
5587
[clinic start generated code]*/
5588
5589
static PyObject *
5590
os__findfirstfile_impl(PyObject *module, path_t *path)
5591
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5592
{
5593
    PyObject *result;
5594
    HANDLE hFindFile;
5595
    WIN32_FIND_DATAW wFileData;
5596
    WCHAR *wRealFileName;
5597
5598
    Py_BEGIN_ALLOW_THREADS
5599
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5600
    Py_END_ALLOW_THREADS
5601
5602
    if (hFindFile == INVALID_HANDLE_VALUE) {
5603
        path_error(path);
5604
        return NULL;
5605
    }
5606
5607
    wRealFileName = wFileData.cFileName;
5608
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5609
    FindClose(hFindFile);
5610
    return result;
5611
}
5612
5613
5614
/*[clinic input]
5615
os._getvolumepathname
5616
5617
    path: path_t
5618
5619
A helper function for ismount on Win32.
5620
[clinic start generated code]*/
5621
5622
static PyObject *
5623
os__getvolumepathname_impl(PyObject *module, path_t *path)
5624
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5625
{
5626
    PyObject *result;
5627
    wchar_t *mountpath=NULL;
5628
    size_t buflen;
5629
    BOOL ret;
5630
5631
    /* Volume path should be shorter than entire path */
5632
    buflen = Py_MAX(path->length, MAX_PATH);
5633
5634
    if (buflen > PY_DWORD_MAX) {
5635
        PyErr_SetString(PyExc_OverflowError, "path too long");
5636
        return NULL;
5637
    }
5638
5639
    mountpath = PyMem_New(wchar_t, buflen);
5640
    if (mountpath == NULL)
5641
        return PyErr_NoMemory();
5642
5643
    Py_BEGIN_ALLOW_THREADS
5644
    ret = GetVolumePathNameW(path->wide, mountpath,
5645
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5646
    Py_END_ALLOW_THREADS
5647
5648
    if (!ret) {
5649
        result = win32_error_object("_getvolumepathname", path->object);
5650
        goto exit;
5651
    }
5652
    result = PyUnicode_FromWideChar(mountpath, -1);
5653
    if (PyBytes_Check(path->object))
5654
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5655
5656
exit:
5657
    PyMem_Free(mountpath);
5658
    return result;
5659
}
5660
5661
5662
/*[clinic input]
5663
os._path_splitroot
5664
5665
    path: path_t,
5666
    /
5667
5668
Removes everything after the root on Win32.
5669
[clinic start generated code]*/
5670
5671
static PyObject *
5672
os__path_splitroot_impl(PyObject *module, path_t *path)
5673
/*[clinic end generated code: output=ab7f1a88b654581c input=42831e41f8458f6d]*/
5674
{
5675
    wchar_t *buffer;
5676
    wchar_t *end;
5677
    PyObject *result = NULL;
5678
    HRESULT ret;
5679
5680
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5681
    if (!buffer) {
5682
        return NULL;
5683
    }
5684
    wcscpy(buffer, path->wide);
5685
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5686
        *p = L'\\';
5687
    }
5688
5689
    Py_BEGIN_ALLOW_THREADS
5690
    ret = PathCchSkipRoot(buffer, &end);
5691
    Py_END_ALLOW_THREADS
5692
    if (FAILED(ret)) {
5693
        result = Py_BuildValue("sO", "", path->object);
5694
    } else if (end != buffer) {
5695
        size_t rootLen = (size_t)(end - buffer);
5696
        result = Py_BuildValue("NN",
5697
            PyUnicode_FromWideChar(path->wide, rootLen),
5698
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5699
        );
5700
    } else {
5701
        result = Py_BuildValue("Os", path->object, "");
5702
    }
5703
    PyMem_Free(buffer);
5704
5705
    return result;
5706
}
5707
5708
5709
#define PY_IFREG  1 // Regular file
5710
#define PY_IFDIR  2 // Directory
5711
#define PY_IFLNK  4 // Symlink
5712
#define PY_IFMNT  8 // Mount Point (junction)
5713
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5714
#define PY_IFRRP 32 // Regular Reparse Point
5715
5716
static inline BOOL
5717
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5718
{
5719
    switch (testedType) {
5720
    case PY_IFREG:
5721
        return diskDevice && attributes &&
5722
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5723
    case PY_IFDIR:
5724
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5725
    case PY_IFLNK:
5726
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5727
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5728
    case PY_IFMNT:
5729
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5730
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5731
    case PY_IFLRP:
5732
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5733
               IsReparseTagNameSurrogate(reparseTag);
5734
    case PY_IFRRP:
5735
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5736
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5737
    }
5738
5739
    return FALSE;
5740
}
5741
5742
static BOOL
5743
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5744
{
5745
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5746
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5747
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5748
5749
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5750
    if (diskOnly && !diskDevice) {
5751
        return FALSE;
5752
    }
5753
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5754
        FILE_ATTRIBUTE_TAG_INFO info;
5755
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5756
                                            sizeof(info)) &&
5757
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5758
                         testedType);
5759
    }
5760
    FILE_BASIC_INFO info;
5761
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5762
                                        sizeof(info)) &&
5763
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5764
}
5765
5766
static BOOL
5767
_testFileTypeByName(LPCWSTR path, int testedType)
5768
{
5769
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5770
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5771
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5772
5773
    FILE_STAT_BASIC_INFORMATION info;
5774
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5775
                                     sizeof(info)))
5776
    {
5777
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5778
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5779
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5780
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5781
                                diskDevice, testedType);
5782
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5783
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5784
        {
5785
            return result;
5786
        }
5787
    }
5788
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5789
                GetLastError()))
5790
    {
5791
        return FALSE;
5792
    }
5793
5794
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5795
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5796
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5797
    }
5798
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5799
                               OPEN_EXISTING, flags, NULL);
5800
    if (hfile != INVALID_HANDLE_VALUE) {
5801
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5802
        CloseHandle(hfile);
5803
        return result;
5804
    }
5805
5806
    switch (GetLastError()) {
5807
    case ERROR_ACCESS_DENIED:
5808
    case ERROR_SHARING_VIOLATION:
5809
    case ERROR_CANT_ACCESS_FILE:
5810
    case ERROR_INVALID_PARAMETER:
5811
        int rc;
5812
        STRUCT_STAT st;
5813
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5814
            rc = STAT(path, &st);
5815
        }
5816
        else {
5817
            // PY_IFRRP is not generally supported in this case, except for
5818
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5819
            rc = LSTAT(path, &st);
5820
        }
5821
        if (!rc) {
5822
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5823
                             st.st_mode & S_IFREG, testedType);
5824
        }
5825
    }
5826
5827
    return FALSE;
5828
}
5829
5830
5831
static BOOL
5832
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5833
{
5834
    FILE_STAT_BASIC_INFORMATION info;
5835
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5836
                                     sizeof(info)))
5837
    {
5838
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5839
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5840
        {
5841
            return TRUE;
5842
        }
5843
    }
5844
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5845
                    GetLastError()))
5846
    {
5847
        return FALSE;
5848
    }
5849
5850
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5851
    if (!followLinks) {
5852
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5853
    }
5854
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5855
                               OPEN_EXISTING, flags, NULL);
5856
    if (hfile != INVALID_HANDLE_VALUE) {
5857
        if (followLinks) {
5858
            CloseHandle(hfile);
5859
            return TRUE;
5860
        }
5861
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5862
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5863
        CloseHandle(hfile);
5864
        if (!result) {
5865
            return TRUE;
5866
        }
5867
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5868
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5869
        if (hfile != INVALID_HANDLE_VALUE) {
5870
            CloseHandle(hfile);
5871
            return TRUE;
5872
        }
5873
    }
5874
5875
    switch (GetLastError()) {
5876
    case ERROR_ACCESS_DENIED:
5877
    case ERROR_SHARING_VIOLATION:
5878
    case ERROR_CANT_ACCESS_FILE:
5879
    case ERROR_INVALID_PARAMETER:
5880
        STRUCT_STAT _st;
5881
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5882
    }
5883
5884
    return FALSE;
5885
}
5886
5887
5888
static BOOL
5889
_testFileExists(path_t *path, BOOL followLinks)
5890
{
5891
    BOOL result = FALSE;
5892
    if (path->value_error) {
5893
        return FALSE;
5894
    }
5895
5896
    Py_BEGIN_ALLOW_THREADS
5897
    if (path->fd != -1) {
5898
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5899
        if (hfile != INVALID_HANDLE_VALUE) {
5900
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5901
                result = TRUE;
5902
            }
5903
        }
5904
    }
5905
    else if (path->wide) {
5906
        result = _testFileExistsByName(path->wide, followLinks);
5907
    }
5908
    Py_END_ALLOW_THREADS
5909
5910
    return result;
5911
}
5912
5913
5914
static BOOL
5915
_testFileType(path_t *path, int testedType)
5916
{
5917
    BOOL result = FALSE;
5918
    if (path->value_error) {
5919
        return FALSE;
5920
    }
5921
5922
    Py_BEGIN_ALLOW_THREADS
5923
    if (path->fd != -1) {
5924
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5925
        if (hfile != INVALID_HANDLE_VALUE) {
5926
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5927
        }
5928
    }
5929
    else if (path->wide) {
5930
        result = _testFileTypeByName(path->wide, testedType);
5931
    }
5932
    Py_END_ALLOW_THREADS
5933
5934
    return result;
5935
}
5936
5937
5938
/*[clinic input]
5939
os._path_exists -> bool
5940
5941
    path: path_t(allow_fd=True, suppress_value_error=True)
5942
5943
Test whether a path exists.  Returns False for broken symbolic links.
5944
5945
[clinic start generated code]*/
5946
5947
static int
5948
os__path_exists_impl(PyObject *module, path_t *path)
5949
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5950
{
5951
    return _testFileExists(path, TRUE);
5952
}
5953
5954
5955
/*[clinic input]
5956
os._path_lexists -> bool
5957
5958
    path: path_t(allow_fd=True, suppress_value_error=True)
5959
5960
Test whether a path exists.  Returns True for broken symbolic links.
5961
5962
[clinic start generated code]*/
5963
5964
static int
5965
os__path_lexists_impl(PyObject *module, path_t *path)
5966
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5967
{
5968
    return _testFileExists(path, FALSE);
5969
}
5970
5971
5972
/*[clinic input]
5973
os._path_isdir -> bool
5974
5975
    path: path_t(allow_fd=True, suppress_value_error=True),
5976
    /
5977
5978
Return true if the pathname refers to an existing directory.
5979
5980
[clinic start generated code]*/
5981
5982
static int
5983
os__path_isdir_impl(PyObject *module, path_t *path)
5984
/*[clinic end generated code: output=d5786196f9e2fa7a input=0d3fd790564d244b]*/
5985
{
5986
    return _testFileType(path, PY_IFDIR);
5987
}
5988
5989
5990
/*[clinic input]
5991
os._path_isfile -> bool
5992
5993
    path: path_t(allow_fd=True, suppress_value_error=True)
5994
5995
Test whether a path is a regular file
5996
5997
[clinic start generated code]*/
5998
5999
static int
6000
os__path_isfile_impl(PyObject *module, path_t *path)
6001
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6002
{
6003
    return _testFileType(path, PY_IFREG);
6004
}
6005
6006
6007
/*[clinic input]
6008
os._path_islink -> bool
6009
6010
    path: path_t(allow_fd=True, suppress_value_error=True)
6011
6012
Test whether a path is a symbolic link
6013
6014
[clinic start generated code]*/
6015
6016
static int
6017
os__path_islink_impl(PyObject *module, path_t *path)
6018
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6019
{
6020
    return _testFileType(path, PY_IFLNK);
6021
}
6022
6023
6024
/*[clinic input]
6025
os._path_isjunction -> bool
6026
6027
    path: path_t(allow_fd=True, suppress_value_error=True)
6028
6029
Test whether a path is a junction
6030
6031
[clinic start generated code]*/
6032
6033
static int
6034
os__path_isjunction_impl(PyObject *module, path_t *path)
6035
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6036
{
6037
    return _testFileType(path, PY_IFMNT);
6038
}
6039
6040
#undef PY_IFREG
6041
#undef PY_IFDIR
6042
#undef PY_IFLNK
6043
#undef PY_IFMNT
6044
#undef PY_IFLRP
6045
#undef PY_IFRRP
6046
6047
#endif /* MS_WINDOWS */
6048
6049
6050
/*[clinic input]
6051
os._path_splitroot_ex
6052
6053
    path: path_t(make_wide=True, nonstrict=True),
6054
    /
6055
6056
Split a pathname into drive, root and tail.
6057
6058
The tail contains anything after the root.
6059
[clinic start generated code]*/
6060
6061
static PyObject *
6062
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6063
/*[clinic end generated code: output=4b0072b6cdf4b611 input=4ac47b394d68bd21]*/
6064
222k
{
6065
222k
    Py_ssize_t drvsize, rootsize;
6066
222k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6067
6068
222k
    const wchar_t *buffer = path->wide;
6069
222k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6070
222k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6071
222k
    if (drv == NULL) {
6072
0
        goto exit;
6073
0
    }
6074
222k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6075
222k
    if (root == NULL) {
6076
0
        goto exit;
6077
0
    }
6078
222k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6079
222k
                                  path->length - drvsize - rootsize);
6080
222k
    if (tail == NULL) {
6081
0
        goto exit;
6082
0
    }
6083
222k
    if (PyBytes_Check(path->object)) {
6084
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6085
0
        if (drv == NULL) {
6086
0
            goto exit;
6087
0
        }
6088
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6089
0
        if (root == NULL) {
6090
0
            goto exit;
6091
0
        }
6092
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6093
0
        if (tail == NULL) {
6094
0
            goto exit;
6095
0
        }
6096
0
    }
6097
222k
    result = PyTuple_Pack(3, drv, root, tail);
6098
222k
exit:
6099
222k
    Py_XDECREF(drv);
6100
222k
    Py_XDECREF(root);
6101
222k
    Py_XDECREF(tail);
6102
222k
    return result;
6103
222k
}
6104
6105
6106
/*[clinic input]
6107
os._path_normpath
6108
6109
    path: path_t(make_wide=True, nonstrict=True)
6110
6111
Normalize path, eliminating double slashes, etc.
6112
[clinic start generated code]*/
6113
6114
static PyObject *
6115
os__path_normpath_impl(PyObject *module, path_t *path)
6116
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6117
45.3k
{
6118
45.3k
    PyObject *result;
6119
45.3k
    Py_ssize_t norm_len;
6120
45.3k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6121
45.3k
                                               path->length, &norm_len);
6122
45.3k
    if (!norm_len) {
6123
0
        result = PyUnicode_FromOrdinal('.');
6124
0
    }
6125
45.3k
    else {
6126
45.3k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6127
45.3k
    }
6128
45.3k
    if (PyBytes_Check(path->object)) {
6129
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6130
0
    }
6131
45.3k
    return result;
6132
45.3k
}
6133
6134
/*[clinic input]
6135
os.mkdir
6136
6137
    path : path_t
6138
6139
    mode: int = 0o777
6140
6141
    *
6142
6143
    dir_fd : dir_fd(requires='mkdirat') = None
6144
6145
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
6146
6147
Create a directory.
6148
6149
If dir_fd is not None, it should be a file descriptor open to a directory,
6150
  and path should be relative; path will then be relative to that directory.
6151
dir_fd may not be implemented on your platform.
6152
  If it is unavailable, using it will raise a NotImplementedError.
6153
6154
The mode argument is ignored on Windows. Where it is used, the current umask
6155
value is first masked out.
6156
[clinic start generated code]*/
6157
6158
static PyObject *
6159
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6160
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
6161
185k
{
6162
185k
    int result;
6163
#ifdef MS_WINDOWS
6164
    int error = 0;
6165
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6166
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6167
#endif
6168
185k
#ifdef HAVE_MKDIRAT
6169
185k
    int mkdirat_unavailable = 0;
6170
185k
#endif
6171
6172
185k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6173
185k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6174
0
        return NULL;
6175
0
    }
6176
6177
#ifdef MS_WINDOWS
6178
    Py_BEGIN_ALLOW_THREADS
6179
    // For API sets that don't support these APIs, we have no choice
6180
    // but to silently create a directory with default ACL.
6181
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6182
    if (mode == 0700 /* 0o700 */) {
6183
        ULONG sdSize;
6184
        pSecAttr = &secAttr;
6185
        // Set a discretionary ACL (D) that is protected (P) and includes
6186
        // inheritable (OICI) entries that allow (A) full control (FA) to
6187
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6188
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6189
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6190
            SDDL_REVISION_1,
6191
            &secAttr.lpSecurityDescriptor,
6192
            &sdSize
6193
        )) {
6194
            error = GetLastError();
6195
        }
6196
    }
6197
#endif
6198
    if (!error) {
6199
        result = CreateDirectoryW(path->wide, pSecAttr);
6200
        if (secAttr.lpSecurityDescriptor &&
6201
            // uncommonly, LocalFree returns non-zero on error, but still uses
6202
            // GetLastError() to see what the error code is
6203
            LocalFree(secAttr.lpSecurityDescriptor)) {
6204
            error = GetLastError();
6205
        }
6206
    }
6207
    Py_END_ALLOW_THREADS
6208
6209
    if (error) {
6210
        return PyErr_SetFromWindowsErr(error);
6211
    }
6212
    if (!result) {
6213
        return path_error(path);
6214
    }
6215
#else
6216
185k
    Py_BEGIN_ALLOW_THREADS
6217
185k
#if HAVE_MKDIRAT
6218
185k
    if (dir_fd != DEFAULT_DIR_FD) {
6219
0
      if (HAVE_MKDIRAT_RUNTIME) {
6220
0
        result = mkdirat(dir_fd, path->narrow, mode);
6221
6222
0
      } else {
6223
0
        mkdirat_unavailable = 1;
6224
0
      }
6225
0
    } else
6226
185k
#endif
6227
#if defined(__WATCOMC__) && !defined(__QNX__)
6228
        result = mkdir(path->narrow);
6229
#else
6230
185k
        result = mkdir(path->narrow, mode);
6231
185k
#endif
6232
185k
    Py_END_ALLOW_THREADS
6233
6234
185k
#if HAVE_MKDIRAT
6235
185k
    if (mkdirat_unavailable) {
6236
0
        argument_unavailable_error(NULL, "dir_fd");
6237
0
        return NULL;
6238
0
    }
6239
185k
#endif
6240
6241
185k
    if (result < 0)
6242
392
        return path_error(path);
6243
184k
#endif /* MS_WINDOWS */
6244
185k
    Py_RETURN_NONE;
6245
185k
}
6246
6247
6248
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6249
#if defined(HAVE_SYS_RESOURCE_H)
6250
#include <sys/resource.h>
6251
#endif
6252
6253
6254
#ifdef HAVE_NICE
6255
/*[clinic input]
6256
os.nice
6257
6258
    increment: int
6259
    /
6260
6261
Add increment to the priority of process and return the new priority.
6262
[clinic start generated code]*/
6263
6264
static PyObject *
6265
os_nice_impl(PyObject *module, int increment)
6266
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6267
0
{
6268
0
    int value;
6269
6270
    /* There are two flavours of 'nice': one that returns the new
6271
       priority (as required by almost all standards out there) and the
6272
       Linux/FreeBSD one, which returns '0' on success and advices
6273
       the use of getpriority() to get the new priority.
6274
6275
       If we are of the nice family that returns the new priority, we
6276
       need to clear errno before the call, and check if errno is filled
6277
       before calling posix_error() on a returnvalue of -1, because the
6278
       -1 may be the actual new priority! */
6279
6280
0
    errno = 0;
6281
0
    value = nice(increment);
6282
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6283
    if (value == 0)
6284
        value = getpriority(PRIO_PROCESS, 0);
6285
#endif
6286
0
    if (value == -1 && errno != 0)
6287
        /* either nice() or getpriority() returned an error */
6288
0
        return posix_error();
6289
0
    return PyLong_FromLong((long) value);
6290
0
}
6291
#endif /* HAVE_NICE */
6292
6293
6294
#ifdef HAVE_GETPRIORITY
6295
/*[clinic input]
6296
os.getpriority
6297
6298
    which: int
6299
    who: int
6300
6301
Return program scheduling priority.
6302
[clinic start generated code]*/
6303
6304
static PyObject *
6305
os_getpriority_impl(PyObject *module, int which, int who)
6306
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6307
0
{
6308
0
    int retval;
6309
6310
0
    errno = 0;
6311
0
    retval = getpriority(which, who);
6312
0
    if (errno != 0)
6313
0
        return posix_error();
6314
0
    return PyLong_FromLong((long)retval);
6315
0
}
6316
#endif /* HAVE_GETPRIORITY */
6317
6318
6319
#ifdef HAVE_SETPRIORITY
6320
/*[clinic input]
6321
os.setpriority
6322
6323
    which: int
6324
    who: int
6325
    priority: int
6326
6327
Set program scheduling priority.
6328
[clinic start generated code]*/
6329
6330
static PyObject *
6331
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6332
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6333
0
{
6334
0
    int retval;
6335
6336
0
    retval = setpriority(which, who, priority);
6337
0
    if (retval == -1)
6338
0
        return posix_error();
6339
0
    Py_RETURN_NONE;
6340
0
}
6341
#endif /* HAVE_SETPRIORITY */
6342
6343
6344
static PyObject *
6345
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6346
167
{
6347
167
    const char *function_name = is_replace ? "replace" : "rename";
6348
167
    int dir_fd_specified;
6349
6350
167
#ifdef HAVE_RENAMEAT
6351
167
    int renameat_unavailable = 0;
6352
167
#endif
6353
6354
#ifdef MS_WINDOWS
6355
    BOOL result;
6356
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6357
#else
6358
167
    int result;
6359
167
#endif
6360
6361
167
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6362
167
                       (dst_dir_fd != DEFAULT_DIR_FD);
6363
#ifndef HAVE_RENAMEAT
6364
    if (dir_fd_specified) {
6365
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6366
        return NULL;
6367
    }
6368
#endif
6369
6370
167
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6371
167
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6372
167
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6373
0
        return NULL;
6374
0
    }
6375
6376
#ifdef MS_WINDOWS
6377
    Py_BEGIN_ALLOW_THREADS
6378
    result = MoveFileExW(src->wide, dst->wide, flags);
6379
    Py_END_ALLOW_THREADS
6380
6381
    if (!result)
6382
        return path_error2(src, dst);
6383
6384
#else
6385
167
    Py_BEGIN_ALLOW_THREADS
6386
167
#ifdef HAVE_RENAMEAT
6387
167
    if (dir_fd_specified) {
6388
0
        if (HAVE_RENAMEAT_RUNTIME) {
6389
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6390
0
        } else {
6391
0
            renameat_unavailable = 1;
6392
0
        }
6393
0
    } else
6394
167
#endif
6395
167
    result = rename(src->narrow, dst->narrow);
6396
167
    Py_END_ALLOW_THREADS
6397
6398
6399
167
#ifdef HAVE_RENAMEAT
6400
167
    if (renameat_unavailable) {
6401
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6402
0
        return NULL;
6403
0
    }
6404
167
#endif
6405
6406
167
    if (result)
6407
0
        return path_error2(src, dst);
6408
167
#endif
6409
167
    Py_RETURN_NONE;
6410
167
}
6411
6412
6413
/*[clinic input]
6414
@permit_long_docstring_body
6415
os.rename
6416
6417
    src : path_t
6418
    dst : path_t
6419
    *
6420
    src_dir_fd : dir_fd = None
6421
    dst_dir_fd : dir_fd = None
6422
6423
Rename a file or directory.
6424
6425
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6426
  descriptor open to a directory, and the respective path string (src or dst)
6427
  should be relative; the path will then be relative to that directory.
6428
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6429
  If they are unavailable, using them will raise a NotImplementedError.
6430
[clinic start generated code]*/
6431
6432
static PyObject *
6433
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6434
               int dst_dir_fd)
6435
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6436
3
{
6437
3
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6438
3
}
6439
6440
6441
/*[clinic input]
6442
@permit_long_docstring_body
6443
os.replace = os.rename
6444
6445
Rename a file or directory, overwriting the destination.
6446
6447
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6448
  descriptor open to a directory, and the respective path string (src or dst)
6449
  should be relative; the path will then be relative to that directory.
6450
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6451
  If they are unavailable, using them will raise a NotImplementedError.
6452
[clinic start generated code]*/
6453
6454
static PyObject *
6455
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6456
                int dst_dir_fd)
6457
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6458
164
{
6459
164
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6460
164
}
6461
6462
6463
/*[clinic input]
6464
os.rmdir
6465
6466
    path: path_t
6467
    *
6468
    dir_fd: dir_fd(requires='unlinkat') = None
6469
6470
Remove a directory.
6471
6472
If dir_fd is not None, it should be a file descriptor open to a directory,
6473
  and path should be relative; path will then be relative to that directory.
6474
dir_fd may not be implemented on your platform.
6475
  If it is unavailable, using it will raise a NotImplementedError.
6476
[clinic start generated code]*/
6477
6478
static PyObject *
6479
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6480
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6481
184k
{
6482
184k
    int result;
6483
184k
#ifdef HAVE_UNLINKAT
6484
184k
    int unlinkat_unavailable = 0;
6485
184k
#endif
6486
6487
184k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6488
184k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6489
0
        return NULL;
6490
0
    }
6491
6492
184k
    Py_BEGIN_ALLOW_THREADS
6493
#ifdef MS_WINDOWS
6494
    /* Windows, success=1, UNIX, success=0 */
6495
    result = !RemoveDirectoryW(path->wide);
6496
#else
6497
184k
#ifdef HAVE_UNLINKAT
6498
184k
    if (dir_fd != DEFAULT_DIR_FD) {
6499
180k
      if (HAVE_UNLINKAT_RUNTIME) {
6500
180k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6501
180k
      } else {
6502
0
        unlinkat_unavailable = 1;
6503
0
        result = -1;
6504
0
      }
6505
180k
    } else
6506
4.74k
#endif
6507
4.74k
        result = rmdir(path->narrow);
6508
184k
#endif
6509
184k
    Py_END_ALLOW_THREADS
6510
6511
184k
#ifdef HAVE_UNLINKAT
6512
184k
    if (unlinkat_unavailable) {
6513
0
        argument_unavailable_error("rmdir", "dir_fd");
6514
0
        return NULL;
6515
0
    }
6516
184k
#endif
6517
6518
184k
    if (result)
6519
3
        return path_error(path);
6520
6521
184k
    Py_RETURN_NONE;
6522
184k
}
6523
6524
6525
#ifdef HAVE_SYSTEM
6526
#ifdef MS_WINDOWS
6527
/*[clinic input]
6528
os.system -> long
6529
6530
    command: Py_UNICODE
6531
6532
Execute the command in a subshell.
6533
[clinic start generated code]*/
6534
6535
static long
6536
os_system_impl(PyObject *module, const wchar_t *command)
6537
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6538
{
6539
    long result;
6540
6541
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6542
        return -1;
6543
    }
6544
6545
    Py_BEGIN_ALLOW_THREADS
6546
    _Py_BEGIN_SUPPRESS_IPH
6547
    result = _wsystem(command);
6548
    _Py_END_SUPPRESS_IPH
6549
    Py_END_ALLOW_THREADS
6550
    return result;
6551
}
6552
#else /* MS_WINDOWS */
6553
/*[clinic input]
6554
os.system -> long
6555
6556
    command: unicode_fs_encoded
6557
6558
Execute the command in a subshell.
6559
[clinic start generated code]*/
6560
6561
static long
6562
os_system_impl(PyObject *module, PyObject *command)
6563
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6564
0
{
6565
0
    long result;
6566
0
    const char *bytes = PyBytes_AsString(command);
6567
6568
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6569
0
        return -1;
6570
0
    }
6571
6572
0
    Py_BEGIN_ALLOW_THREADS
6573
0
    result = system(bytes);
6574
0
    Py_END_ALLOW_THREADS
6575
0
    return result;
6576
0
}
6577
#endif
6578
#endif /* HAVE_SYSTEM */
6579
6580
6581
#ifdef HAVE_UMASK
6582
/*[clinic input]
6583
os.umask
6584
6585
    mask: int
6586
    /
6587
6588
Set the current numeric umask and return the previous umask.
6589
[clinic start generated code]*/
6590
6591
static PyObject *
6592
os_umask_impl(PyObject *module, int mask)
6593
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6594
0
{
6595
0
    int i = (int)umask(mask);
6596
0
    if (i < 0)
6597
0
        return posix_error();
6598
0
    return PyLong_FromLong((long)i);
6599
0
}
6600
#endif
6601
6602
#ifdef MS_WINDOWS
6603
6604
/* override the default DeleteFileW behavior so that directory
6605
symlinks can be removed with this function, the same as with
6606
Unix symlinks */
6607
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6608
{
6609
    WIN32_FILE_ATTRIBUTE_DATA info;
6610
    WIN32_FIND_DATAW find_data;
6611
    HANDLE find_data_handle;
6612
    int is_directory = 0;
6613
    int is_link = 0;
6614
6615
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6616
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6617
6618
        /* Get WIN32_FIND_DATA structure for the path to determine if
6619
           it is a symlink */
6620
        if(is_directory &&
6621
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6622
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6623
6624
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6625
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6626
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6627
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6628
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6629
                FindClose(find_data_handle);
6630
            }
6631
        }
6632
    }
6633
6634
    if (is_directory && is_link)
6635
        return RemoveDirectoryW(lpFileName);
6636
6637
    return DeleteFileW(lpFileName);
6638
}
6639
#endif /* MS_WINDOWS */
6640
6641
6642
/*[clinic input]
6643
os.unlink
6644
6645
    path: path_t
6646
    *
6647
    dir_fd: dir_fd(requires='unlinkat')=None
6648
6649
Remove a file (same as remove()).
6650
6651
If dir_fd is not None, it should be a file descriptor open to a directory,
6652
  and path should be relative; path will then be relative to that directory.
6653
dir_fd may not be implemented on your platform.
6654
  If it is unavailable, using it will raise a NotImplementedError.
6655
6656
[clinic start generated code]*/
6657
6658
static PyObject *
6659
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6660
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6661
36.4k
{
6662
36.4k
    int result;
6663
36.4k
#ifdef HAVE_UNLINKAT
6664
36.4k
    int unlinkat_unavailable = 0;
6665
36.4k
#endif
6666
6667
36.4k
    if (PySys_Audit("os.remove", "Oi", path->object,
6668
36.4k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6669
0
        return NULL;
6670
0
    }
6671
6672
36.4k
    Py_BEGIN_ALLOW_THREADS
6673
36.4k
    _Py_BEGIN_SUPPRESS_IPH
6674
#ifdef MS_WINDOWS
6675
    /* Windows, success=1, UNIX, success=0 */
6676
    result = !Py_DeleteFileW(path->wide);
6677
#else
6678
36.4k
#ifdef HAVE_UNLINKAT
6679
36.4k
    if (dir_fd != DEFAULT_DIR_FD) {
6680
36.4k
      if (HAVE_UNLINKAT_RUNTIME) {
6681
6682
36.4k
        result = unlinkat(dir_fd, path->narrow, 0);
6683
36.4k
      } else {
6684
0
        unlinkat_unavailable = 1;
6685
0
      }
6686
36.4k
    } else
6687
2
#endif /* HAVE_UNLINKAT */
6688
2
        result = unlink(path->narrow);
6689
36.4k
#endif
6690
36.4k
    _Py_END_SUPPRESS_IPH
6691
36.4k
    Py_END_ALLOW_THREADS
6692
6693
36.4k
#ifdef HAVE_UNLINKAT
6694
36.4k
    if (unlinkat_unavailable) {
6695
0
        argument_unavailable_error(NULL, "dir_fd");
6696
0
        return NULL;
6697
0
    }
6698
36.4k
#endif
6699
6700
36.4k
    if (result)
6701
0
        return path_error(path);
6702
6703
36.4k
    Py_RETURN_NONE;
6704
36.4k
}
6705
6706
6707
/*[clinic input]
6708
os.remove = os.unlink
6709
6710
Remove a file (same as unlink()).
6711
6712
If dir_fd is not None, it should be a file descriptor open to a directory,
6713
  and path should be relative; path will then be relative to that directory.
6714
dir_fd may not be implemented on your platform.
6715
  If it is unavailable, using it will raise a NotImplementedError.
6716
[clinic start generated code]*/
6717
6718
static PyObject *
6719
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6720
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6721
0
{
6722
0
    return os_unlink_impl(module, path, dir_fd);
6723
0
}
6724
6725
6726
static PyStructSequence_Field uname_result_fields[] = {
6727
    {"sysname",    "operating system name"},
6728
    {"nodename",   "name of machine on network (implementation-defined)"},
6729
    {"release",    "operating system release"},
6730
    {"version",    "operating system version"},
6731
    {"machine",    "hardware identifier"},
6732
    {NULL}
6733
};
6734
6735
PyDoc_STRVAR(uname_result__doc__,
6736
"uname_result: Result from os.uname().\n\n\
6737
This object may be accessed either as a tuple of\n\
6738
  (sysname, nodename, release, version, machine),\n\
6739
or via the attributes sysname, nodename, release, version, and machine.\n\
6740
\n\
6741
See os.uname for more information.");
6742
6743
static PyStructSequence_Desc uname_result_desc = {
6744
    MODNAME ".uname_result", /* name */
6745
    uname_result__doc__, /* doc */
6746
    uname_result_fields,
6747
    5
6748
};
6749
6750
#ifdef HAVE_UNAME
6751
/*[clinic input]
6752
os.uname
6753
6754
Return an object identifying the current operating system.
6755
6756
The object behaves like a named tuple with the following fields:
6757
  (sysname, nodename, release, version, machine)
6758
6759
[clinic start generated code]*/
6760
6761
static PyObject *
6762
os_uname_impl(PyObject *module)
6763
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6764
2
{
6765
2
    struct utsname u;
6766
2
    int res;
6767
2
    PyObject *value;
6768
6769
2
    Py_BEGIN_ALLOW_THREADS
6770
2
    res = uname(&u);
6771
2
    Py_END_ALLOW_THREADS
6772
2
    if (res < 0)
6773
0
        return posix_error();
6774
6775
2
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6776
2
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6777
2
    if (value == NULL)
6778
0
        return NULL;
6779
6780
2
#define SET(i, field) \
6781
10
    { \
6782
10
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6783
10
    if (!o) { \
6784
0
        Py_DECREF(value); \
6785
0
        return NULL; \
6786
0
    } \
6787
10
    PyStructSequence_SET_ITEM(value, i, o); \
6788
10
    } \
6789
2
6790
4
    SET(0, u.sysname);
6791
4
    SET(1, u.nodename);
6792
2
    SET(2, u.release);
6793
2
    SET(3, u.version);
6794
2
    SET(4, u.machine);
6795
6796
2
#undef SET
6797
6798
2
    return value;
6799
2
}
6800
#endif /* HAVE_UNAME */
6801
6802
6803
6804
typedef struct {
6805
    int    now;
6806
    time_t atime_s;
6807
    long   atime_ns;
6808
    time_t mtime_s;
6809
    long   mtime_ns;
6810
} utime_t;
6811
6812
/*
6813
 * these macros assume that "ut" is a pointer to a utime_t
6814
 * they also intentionally leak the declaration of a pointer named "time"
6815
 */
6816
#define UTIME_TO_TIMESPEC \
6817
0
    struct timespec ts[2]; \
6818
0
    struct timespec *time; \
6819
0
    if (ut->now) \
6820
0
        time = NULL; \
6821
0
    else { \
6822
0
        ts[0].tv_sec = ut->atime_s; \
6823
0
        ts[0].tv_nsec = ut->atime_ns; \
6824
0
        ts[1].tv_sec = ut->mtime_s; \
6825
0
        ts[1].tv_nsec = ut->mtime_ns; \
6826
0
        time = ts; \
6827
0
    } \
6828
6829
#define UTIME_TO_TIMEVAL \
6830
0
    struct timeval tv[2]; \
6831
0
    struct timeval *time; \
6832
0
    if (ut->now) \
6833
0
        time = NULL; \
6834
0
    else { \
6835
0
        tv[0].tv_sec = ut->atime_s; \
6836
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6837
0
        tv[1].tv_sec = ut->mtime_s; \
6838
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6839
0
        time = tv; \
6840
0
    } \
6841
6842
#define UTIME_TO_UTIMBUF \
6843
    struct utimbuf u; \
6844
    struct utimbuf *time; \
6845
    if (ut->now) \
6846
        time = NULL; \
6847
    else { \
6848
        u.actime = ut->atime_s; \
6849
        u.modtime = ut->mtime_s; \
6850
        time = &u; \
6851
    }
6852
6853
#define UTIME_TO_TIME_T \
6854
    time_t timet[2]; \
6855
    time_t *time; \
6856
    if (ut->now) \
6857
        time = NULL; \
6858
    else { \
6859
        timet[0] = ut->atime_s; \
6860
        timet[1] = ut->mtime_s; \
6861
        time = timet; \
6862
    } \
6863
6864
6865
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6866
6867
static int
6868
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6869
0
{
6870
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6871
    if (HAVE_UTIMENSAT_RUNTIME) {
6872
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6873
        UTIME_TO_TIMESPEC;
6874
        return utimensat(dir_fd, path, time, flags);
6875
    }  else {
6876
        errno = ENOSYS;
6877
        return -1;
6878
    }
6879
#elif defined(HAVE_UTIMENSAT)
6880
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6881
0
    UTIME_TO_TIMESPEC;
6882
0
    return utimensat(dir_fd, path, time, flags);
6883
#elif defined(HAVE_FUTIMESAT)
6884
    UTIME_TO_TIMEVAL;
6885
    /*
6886
     * follow_symlinks will never be false here;
6887
     * we only allow !follow_symlinks and dir_fd together
6888
     * if we have utimensat()
6889
     */
6890
    assert(follow_symlinks);
6891
    return futimesat(dir_fd, path, time);
6892
#endif
6893
0
}
6894
6895
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6896
#else
6897
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6898
#endif
6899
6900
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6901
6902
static int
6903
utime_fd(utime_t *ut, int fd)
6904
0
{
6905
0
#ifdef HAVE_FUTIMENS
6906
6907
0
    if (HAVE_FUTIMENS_RUNTIME) {
6908
6909
0
    UTIME_TO_TIMESPEC;
6910
0
    return futimens(fd, time);
6911
6912
0
    } else
6913
#ifndef HAVE_FUTIMES
6914
    {
6915
        /* Not sure if this can happen */
6916
        PyErr_SetString(
6917
            PyExc_RuntimeError,
6918
            "neither futimens nor futimes are supported"
6919
            " on this system");
6920
        return -1;
6921
    }
6922
#endif
6923
6924
0
#endif
6925
0
#ifdef HAVE_FUTIMES
6926
0
    {
6927
0
    UTIME_TO_TIMEVAL;
6928
0
    return futimes(fd, time);
6929
0
    }
6930
0
#endif
6931
0
}
6932
6933
    #define PATH_UTIME_HAVE_FD 1
6934
#else
6935
    #define PATH_UTIME_HAVE_FD 0
6936
#endif
6937
6938
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6939
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6940
#endif
6941
6942
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6943
6944
static int
6945
utime_nofollow_symlinks(utime_t *ut, const char *path)
6946
0
{
6947
0
#ifdef HAVE_UTIMENSAT
6948
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6949
0
        UTIME_TO_TIMESPEC;
6950
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6951
0
    } else
6952
#ifndef HAVE_LUTIMES
6953
    {
6954
        /* Not sure if this can happen */
6955
        PyErr_SetString(
6956
            PyExc_RuntimeError,
6957
            "neither utimensat nor lutimes are supported"
6958
            " on this system");
6959
        return -1;
6960
    }
6961
#endif
6962
0
#endif
6963
6964
0
#ifdef HAVE_LUTIMES
6965
0
    {
6966
0
    UTIME_TO_TIMEVAL;
6967
0
    return lutimes(path, time);
6968
0
    }
6969
0
#endif
6970
0
}
6971
6972
#endif
6973
6974
#ifndef MS_WINDOWS
6975
6976
static int
6977
utime_default(utime_t *ut, const char *path)
6978
0
{
6979
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6980
    if (HAVE_UTIMENSAT_RUNTIME) {
6981
        UTIME_TO_TIMESPEC;
6982
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6983
    } else {
6984
        UTIME_TO_TIMEVAL;
6985
        return utimes(path, time);
6986
    }
6987
#elif defined(HAVE_UTIMENSAT)
6988
0
    UTIME_TO_TIMESPEC;
6989
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6990
#elif defined(HAVE_UTIMES)
6991
    UTIME_TO_TIMEVAL;
6992
    return utimes(path, time);
6993
#elif defined(HAVE_UTIME_H)
6994
    UTIME_TO_UTIMBUF;
6995
    return utime(path, time);
6996
#else
6997
    UTIME_TO_TIME_T;
6998
    return utime(path, time);
6999
#endif
7000
0
}
7001
7002
#endif
7003
7004
static int
7005
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7006
0
{
7007
0
    int result = 0;
7008
0
    PyObject *divmod;
7009
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7010
0
    if (!divmod)
7011
0
        goto exit;
7012
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7013
0
        PyErr_Format(PyExc_TypeError,
7014
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7015
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7016
0
        goto exit;
7017
0
    }
7018
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7019
0
    if ((*s == -1) && PyErr_Occurred())
7020
0
        goto exit;
7021
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7022
0
    if ((*ns == -1) && PyErr_Occurred())
7023
0
        goto exit;
7024
7025
0
    result = 1;
7026
0
exit:
7027
0
    Py_XDECREF(divmod);
7028
0
    return result;
7029
0
}
7030
7031
7032
/*[clinic input]
7033
os.utime
7034
7035
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7036
    times: object = None
7037
    *
7038
    ns: object = NULL
7039
    dir_fd: dir_fd(requires='futimensat') = None
7040
    follow_symlinks: bool=True
7041
7042
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
7043
7044
Set the access and modified time of path.
7045
7046
path may always be specified as a string.
7047
On some platforms, path may also be specified as an open file descriptor.
7048
  If this functionality is unavailable, using it raises an exception.
7049
7050
If times is not None, it must be a tuple (atime, mtime);
7051
    atime and mtime should be expressed as float seconds since the epoch.
7052
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7053
    atime_ns and mtime_ns should be expressed as integer nanoseconds
7054
    since the epoch.
7055
If times is None and ns is unspecified, utime uses the current time.
7056
Specifying tuples for both times and ns is an error.
7057
7058
If dir_fd is not None, it should be a file descriptor open to a directory,
7059
  and path should be relative; path will then be relative to that directory.
7060
If follow_symlinks is False, and the last element of the path is a symbolic
7061
  link, utime will modify the symbolic link itself instead of the file the
7062
  link points to.
7063
It is an error to use dir_fd or follow_symlinks when specifying path
7064
  as an open file descriptor.
7065
dir_fd and follow_symlinks may not be available on your platform.
7066
  If they are unavailable, using them will raise a NotImplementedError.
7067
7068
[clinic start generated code]*/
7069
7070
static PyObject *
7071
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7072
              int dir_fd, int follow_symlinks)
7073
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
7074
0
{
7075
#ifdef MS_WINDOWS
7076
    HANDLE hFile;
7077
    FILETIME atime, mtime;
7078
#else
7079
0
    int result;
7080
0
#endif
7081
7082
0
    utime_t utime;
7083
7084
0
    memset(&utime, 0, sizeof(utime_t));
7085
7086
0
    if (times != Py_None && ns) {
7087
0
        PyErr_SetString(PyExc_ValueError,
7088
0
                     "utime: you may specify either 'times'"
7089
0
                     " or 'ns' but not both");
7090
0
        return NULL;
7091
0
    }
7092
7093
0
    if (times != Py_None) {
7094
0
        time_t a_sec, m_sec;
7095
0
        long a_nsec, m_nsec;
7096
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7097
0
            PyErr_SetString(PyExc_TypeError,
7098
0
                         "utime: 'times' must be either"
7099
0
                         " a tuple of two numbers or None");
7100
0
            return NULL;
7101
0
        }
7102
0
        utime.now = 0;
7103
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7104
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7105
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7106
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7107
0
            return NULL;
7108
0
        }
7109
0
        utime.atime_s = a_sec;
7110
0
        utime.atime_ns = a_nsec;
7111
0
        utime.mtime_s = m_sec;
7112
0
        utime.mtime_ns = m_nsec;
7113
0
    }
7114
0
    else if (ns) {
7115
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7116
0
            PyErr_SetString(PyExc_TypeError,
7117
0
                         "utime: 'ns' must be a tuple of two ints");
7118
0
            return NULL;
7119
0
        }
7120
0
        utime.now = 0;
7121
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7122
0
                                      &utime.atime_s, &utime.atime_ns) ||
7123
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7124
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7125
0
            return NULL;
7126
0
        }
7127
0
    }
7128
0
    else {
7129
        /* times and ns are both None/unspecified. use "now". */
7130
0
        utime.now = 1;
7131
0
    }
7132
7133
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7134
    if (follow_symlinks_specified("utime", follow_symlinks))
7135
        return NULL;
7136
#endif
7137
7138
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7139
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7140
0
        fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
7141
0
        return NULL;
7142
7143
#if !defined(HAVE_UTIMENSAT)
7144
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7145
        PyErr_SetString(PyExc_ValueError,
7146
                     "utime: cannot use dir_fd and follow_symlinks "
7147
                     "together on this platform");
7148
        return NULL;
7149
    }
7150
#endif
7151
7152
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7153
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7154
0
        return NULL;
7155
0
    }
7156
7157
#ifdef MS_WINDOWS
7158
    Py_BEGIN_ALLOW_THREADS
7159
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7160
                        NULL, OPEN_EXISTING,
7161
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7162
    Py_END_ALLOW_THREADS
7163
    if (hFile == INVALID_HANDLE_VALUE) {
7164
        path_error(path);
7165
        return NULL;
7166
    }
7167
7168
    if (utime.now) {
7169
        GetSystemTimeAsFileTime(&mtime);
7170
        atime = mtime;
7171
    }
7172
    else {
7173
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7174
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7175
    }
7176
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7177
        path_error(path);
7178
        CloseHandle(hFile);
7179
        return NULL;
7180
    }
7181
    CloseHandle(hFile);
7182
#else /* MS_WINDOWS */
7183
0
    Py_BEGIN_ALLOW_THREADS
7184
7185
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7186
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7187
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7188
0
    else
7189
0
#endif
7190
7191
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7192
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7193
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7194
7195
0
    } else
7196
0
#endif
7197
7198
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7199
0
    if (path->fd != -1)
7200
0
        result = utime_fd(&utime, path->fd);
7201
0
    else
7202
0
#endif
7203
7204
0
    result = utime_default(&utime, path->narrow);
7205
7206
0
    Py_END_ALLOW_THREADS
7207
7208
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7209
    /* See utime_dir_fd implementation */
7210
    if (result == -1 && errno == ENOSYS) {
7211
        argument_unavailable_error(NULL, "dir_fd");
7212
        return NULL;
7213
    }
7214
#endif
7215
7216
0
    if (result < 0) {
7217
0
        path_error(path);
7218
0
        return NULL;
7219
0
    }
7220
7221
0
#endif /* MS_WINDOWS */
7222
7223
0
    Py_RETURN_NONE;
7224
0
}
7225
7226
/* Process operations */
7227
7228
7229
/*[clinic input]
7230
os._exit
7231
7232
    status: int
7233
7234
Exit to the system with specified status, without normal exit processing.
7235
[clinic start generated code]*/
7236
7237
static PyObject *
7238
os__exit_impl(PyObject *module, int status)
7239
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
7240
0
{
7241
0
    _exit(status);
7242
0
    return NULL; /* Make gcc -Wall happy */
7243
0
}
7244
7245
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7246
#define EXECV_CHAR wchar_t
7247
#else
7248
0
#define EXECV_CHAR char
7249
#endif
7250
7251
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7252
static void
7253
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7254
0
{
7255
0
    Py_ssize_t i;
7256
0
    for (i = 0; i < count; i++)
7257
0
        PyMem_Free(array[i]);
7258
0
    PyMem_Free(array);
7259
0
}
7260
7261
static int
7262
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7263
0
{
7264
0
    Py_ssize_t size;
7265
0
    PyObject *ub;
7266
0
    int result = 0;
7267
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7268
    if (!PyUnicode_FSDecoder(o, &ub))
7269
        return 0;
7270
    *out = PyUnicode_AsWideCharString(ub, &size);
7271
    if (*out)
7272
        result = 1;
7273
#else
7274
0
    if (!PyUnicode_FSConverter(o, &ub))
7275
0
        return 0;
7276
0
    size = PyBytes_GET_SIZE(ub);
7277
0
    *out = PyMem_Malloc(size + 1);
7278
0
    if (*out) {
7279
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7280
0
        result = 1;
7281
0
    } else
7282
0
        PyErr_NoMemory();
7283
0
#endif
7284
0
    Py_DECREF(ub);
7285
0
    return result;
7286
0
}
7287
#endif
7288
7289
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7290
static EXECV_CHAR**
7291
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7292
0
{
7293
0
    Py_ssize_t i, pos, envc;
7294
0
    PyObject *keys = NULL, *vals = NULL;
7295
0
    PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
7296
0
    EXECV_CHAR **envlist;
7297
7298
0
    i = PyMapping_Size(env);
7299
0
    if (i < 0)
7300
0
        return NULL;
7301
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7302
0
    if (envlist == NULL) {
7303
0
        PyErr_NoMemory();
7304
0
        return NULL;
7305
0
    }
7306
0
    envc = 0;
7307
0
    keys = PyMapping_Keys(env);
7308
0
    if (!keys)
7309
0
        goto error;
7310
0
    vals = PyMapping_Values(env);
7311
0
    if (!vals)
7312
0
        goto error;
7313
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7314
0
        PyErr_Format(PyExc_TypeError,
7315
0
                     "env.keys() or env.values() is not a list");
7316
0
        goto error;
7317
0
    }
7318
7319
0
    for (pos = 0; pos < i; pos++) {
7320
        // The 'key' and 'val' must be strong references because of
7321
        // possible side-effects by PyUnicode_FS{Converter,Decoder}().
7322
0
        key = PyList_GetItemRef(keys, pos);
7323
0
        if (key == NULL) {
7324
0
            goto error;
7325
0
        }
7326
0
        val = PyList_GetItemRef(vals, pos);
7327
0
        if (val == NULL) {
7328
0
            goto error;
7329
0
        }
7330
7331
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7332
        if (!PyUnicode_FSDecoder(key, &key2)) {
7333
            goto error;
7334
        }
7335
        if (!PyUnicode_FSDecoder(val, &val2)) {
7336
            goto error;
7337
        }
7338
        /* Search from index 1 because on Windows starting '=' is allowed for
7339
           defining hidden environment variables. */
7340
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7341
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7342
        {
7343
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7344
            goto error;
7345
        }
7346
        PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7347
#else
7348
0
        if (!PyUnicode_FSConverter(key, &key2)) {
7349
0
            goto error;
7350
0
        }
7351
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7352
0
            goto error;
7353
0
        }
7354
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7355
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7356
0
        {
7357
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7358
0
            goto error;
7359
0
        }
7360
0
        PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7361
0
                                              PyBytes_AS_STRING(val2));
7362
0
#endif
7363
0
        if (!keyval) {
7364
0
            goto error;
7365
0
        }
7366
7367
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7368
0
            Py_DECREF(keyval);
7369
0
            goto error;
7370
0
        }
7371
7372
0
        Py_CLEAR(key);
7373
0
        Py_CLEAR(val);
7374
0
        Py_CLEAR(key2);
7375
0
        Py_CLEAR(val2);
7376
0
        Py_DECREF(keyval);
7377
0
    }
7378
0
    Py_DECREF(vals);
7379
0
    Py_DECREF(keys);
7380
7381
0
    envlist[envc] = 0;
7382
0
    *envc_ptr = envc;
7383
0
    return envlist;
7384
7385
0
error:
7386
0
    Py_XDECREF(key);
7387
0
    Py_XDECREF(val);
7388
0
    Py_XDECREF(key2);
7389
0
    Py_XDECREF(val2);
7390
0
    Py_XDECREF(keys);
7391
0
    Py_XDECREF(vals);
7392
0
    free_string_array(envlist, envc);
7393
0
    return NULL;
7394
0
}
7395
7396
static EXECV_CHAR**
7397
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7398
0
{
7399
0
    int i;
7400
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7401
0
    if (argvlist == NULL) {
7402
0
        PyErr_NoMemory();
7403
0
        return NULL;
7404
0
    }
7405
0
    for (i = 0; i < *argc; i++) {
7406
0
        PyObject* item = PySequence_ITEM(argv, i);
7407
0
        if (item == NULL)
7408
0
            goto fail;
7409
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7410
0
            Py_DECREF(item);
7411
0
            goto fail;
7412
0
        }
7413
0
        Py_DECREF(item);
7414
0
    }
7415
0
    argvlist[*argc] = NULL;
7416
0
    return argvlist;
7417
0
fail:
7418
0
    *argc = i;
7419
0
    free_string_array(argvlist, *argc);
7420
0
    return NULL;
7421
0
}
7422
7423
#endif
7424
7425
7426
#ifdef HAVE_EXECV
7427
/*[clinic input]
7428
os.execv
7429
7430
    path: path_t
7431
        Path of executable file.
7432
    argv: object
7433
        Tuple or list of strings.
7434
    /
7435
7436
Execute an executable path with arguments, replacing current process.
7437
[clinic start generated code]*/
7438
7439
static PyObject *
7440
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7441
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7442
0
{
7443
0
    EXECV_CHAR **argvlist;
7444
0
    Py_ssize_t argc;
7445
7446
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7447
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7448
0
        PyErr_SetString(PyExc_RuntimeError,
7449
0
                        "exec not supported for isolated subinterpreters");
7450
0
        return NULL;
7451
0
    }
7452
7453
    /* execv has two arguments: (path, argv), where
7454
       argv is a list or tuple of strings. */
7455
7456
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7457
0
        PyErr_SetString(PyExc_TypeError,
7458
0
                        "execv() arg 2 must be a tuple or list");
7459
0
        return NULL;
7460
0
    }
7461
0
    argc = PySequence_Size(argv);
7462
0
    if (argc < 1) {
7463
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7464
0
        return NULL;
7465
0
    }
7466
7467
0
    argvlist = parse_arglist(argv, &argc);
7468
0
    if (argvlist == NULL) {
7469
0
        return NULL;
7470
0
    }
7471
0
    if (!argvlist[0][0]) {
7472
0
        PyErr_SetString(PyExc_ValueError,
7473
0
            "execv() arg 2 first element cannot be empty");
7474
0
        free_string_array(argvlist, argc);
7475
0
        return NULL;
7476
0
    }
7477
7478
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7479
0
        free_string_array(argvlist, argc);
7480
0
        return NULL;
7481
0
    }
7482
7483
0
    _Py_BEGIN_SUPPRESS_IPH
7484
#ifdef HAVE_WEXECV
7485
    _wexecv(path->wide, argvlist);
7486
#else
7487
0
    execv(path->narrow, argvlist);
7488
0
#endif
7489
0
    _Py_END_SUPPRESS_IPH
7490
7491
    /* If we get here it's definitely an error */
7492
7493
0
    posix_error();
7494
0
    free_string_array(argvlist, argc);
7495
0
    return NULL;
7496
0
}
7497
7498
7499
/*[clinic input]
7500
os.execve
7501
7502
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7503
        Path of executable file.
7504
    argv: object
7505
        Tuple or list of strings.
7506
    env: object
7507
        Dictionary of strings mapping to strings.
7508
7509
Execute an executable path with arguments, replacing current process.
7510
[clinic start generated code]*/
7511
7512
static PyObject *
7513
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7514
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7515
0
{
7516
0
    EXECV_CHAR **argvlist = NULL;
7517
0
    EXECV_CHAR **envlist;
7518
0
    Py_ssize_t argc, envc;
7519
7520
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7521
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7522
0
        PyErr_SetString(PyExc_RuntimeError,
7523
0
                        "exec not supported for isolated subinterpreters");
7524
0
        return NULL;
7525
0
    }
7526
7527
    /* execve has three arguments: (path, argv, env), where
7528
       argv is a list or tuple of strings and env is a dictionary
7529
       like posix.environ. */
7530
7531
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7532
0
        PyErr_SetString(PyExc_TypeError,
7533
0
                        "execve: argv must be a tuple or list");
7534
0
        goto fail_0;
7535
0
    }
7536
0
    argc = PySequence_Size(argv);
7537
0
    if (argc < 1) {
7538
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7539
0
        return NULL;
7540
0
    }
7541
7542
0
    if (!PyMapping_Check(env)) {
7543
0
        PyErr_SetString(PyExc_TypeError,
7544
0
                        "execve: environment must be a mapping object");
7545
0
        goto fail_0;
7546
0
    }
7547
7548
0
    argvlist = parse_arglist(argv, &argc);
7549
0
    if (argvlist == NULL) {
7550
0
        goto fail_0;
7551
0
    }
7552
0
    if (!argvlist[0][0]) {
7553
0
        PyErr_SetString(PyExc_ValueError,
7554
0
            "execve: argv first element cannot be empty");
7555
0
        goto fail_0;
7556
0
    }
7557
7558
0
    envlist = parse_envlist(env, &envc);
7559
0
    if (envlist == NULL)
7560
0
        goto fail_0;
7561
7562
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7563
0
        goto fail_1;
7564
0
    }
7565
7566
0
    _Py_BEGIN_SUPPRESS_IPH
7567
0
#ifdef HAVE_FEXECVE
7568
0
    if (path->fd > -1)
7569
0
        fexecve(path->fd, argvlist, envlist);
7570
0
    else
7571
0
#endif
7572
#ifdef HAVE_WEXECV
7573
        _wexecve(path->wide, argvlist, envlist);
7574
#else
7575
0
        execve(path->narrow, argvlist, envlist);
7576
0
#endif
7577
0
    _Py_END_SUPPRESS_IPH
7578
7579
    /* If we get here it's definitely an error */
7580
7581
0
    posix_path_error(path);
7582
0
  fail_1:
7583
0
    free_string_array(envlist, envc);
7584
0
  fail_0:
7585
0
    if (argvlist)
7586
0
        free_string_array(argvlist, argc);
7587
0
    return NULL;
7588
0
}
7589
7590
#endif /* HAVE_EXECV */
7591
7592
#ifdef HAVE_POSIX_SPAWN
7593
7594
enum posix_spawn_file_actions_identifier {
7595
    POSIX_SPAWN_OPEN,
7596
    POSIX_SPAWN_CLOSE,
7597
    POSIX_SPAWN_DUP2
7598
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7599
    ,POSIX_SPAWN_CLOSEFROM
7600
#endif
7601
};
7602
7603
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7604
static int
7605
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7606
#endif
7607
7608
static int
7609
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7610
                        int resetids, int setsid, PyObject *setsigmask,
7611
                        PyObject *setsigdef, PyObject *scheduler,
7612
                        posix_spawnattr_t *attrp)
7613
0
{
7614
0
    assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
7615
0
    long all_flags = 0;
7616
7617
0
    errno = posix_spawnattr_init(attrp);
7618
0
    if (errno) {
7619
0
        posix_error();
7620
0
        return -1;
7621
0
    }
7622
7623
0
    if (setpgroup && setpgroup != Py_None) {
7624
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7625
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7626
0
            goto fail;
7627
0
        }
7628
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7629
0
        if (errno) {
7630
0
            posix_error();
7631
0
            goto fail;
7632
0
        }
7633
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7634
0
    }
7635
7636
0
    if (resetids) {
7637
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7638
0
    }
7639
7640
0
    if (setsid) {
7641
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7642
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7643
#endif
7644
0
#ifdef POSIX_SPAWN_SETSID
7645
0
        all_flags |= POSIX_SPAWN_SETSID;
7646
#elif defined(POSIX_SPAWN_SETSID_NP)
7647
        all_flags |= POSIX_SPAWN_SETSID_NP;
7648
#else
7649
        argument_unavailable_error(func_name, "setsid");
7650
        return -1;
7651
#endif
7652
7653
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7654
        } else {
7655
            argument_unavailable_error(func_name, "setsid");
7656
            return -1;
7657
        }
7658
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7659
7660
0
    }
7661
7662
0
#ifdef HAVE_SIGSET_T
7663
0
   if (setsigmask) {
7664
0
        sigset_t set;
7665
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7666
0
            goto fail;
7667
0
        }
7668
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7669
0
        if (errno) {
7670
0
            posix_error();
7671
0
            goto fail;
7672
0
        }
7673
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7674
0
    }
7675
7676
0
    if (setsigdef) {
7677
0
        sigset_t set;
7678
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7679
0
            goto fail;
7680
0
        }
7681
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7682
0
        if (errno) {
7683
0
            posix_error();
7684
0
            goto fail;
7685
0
        }
7686
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7687
0
    }
7688
#else
7689
    if (setsigmask || setsigdef) {
7690
        PyErr_SetString(PyExc_NotImplementedError,
7691
                        "sigset is not supported on this platform");
7692
        goto fail;
7693
    }
7694
#endif
7695
7696
0
    if (scheduler && scheduler != Py_None) {
7697
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7698
0
        PyObject *py_schedpolicy;
7699
0
        PyObject *schedparam_obj;
7700
0
        struct sched_param schedparam;
7701
7702
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7703
0
                        ";A scheduler tuple must have two elements",
7704
0
                        &py_schedpolicy, &schedparam_obj)) {
7705
0
            goto fail;
7706
0
        }
7707
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7708
0
            goto fail;
7709
0
        }
7710
0
        if (py_schedpolicy != Py_None) {
7711
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7712
7713
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7714
0
                goto fail;
7715
0
            }
7716
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7717
0
            if (errno) {
7718
0
                posix_error();
7719
0
                goto fail;
7720
0
            }
7721
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7722
0
        }
7723
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7724
0
        if (errno) {
7725
0
            posix_error();
7726
0
            goto fail;
7727
0
        }
7728
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7729
#else
7730
        PyErr_SetString(PyExc_NotImplementedError,
7731
                "The scheduler option is not supported in this system.");
7732
        goto fail;
7733
#endif
7734
0
    }
7735
7736
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7737
0
    if (errno) {
7738
0
        posix_error();
7739
0
        goto fail;
7740
0
    }
7741
7742
0
    return 0;
7743
7744
0
fail:
7745
0
    (void)posix_spawnattr_destroy(attrp);
7746
0
    return -1;
7747
0
}
7748
7749
static int
7750
parse_file_actions(PyObject *file_actions,
7751
                   posix_spawn_file_actions_t *file_actionsp,
7752
                   PyObject *temp_buffer)
7753
0
{
7754
0
    PyObject *seq;
7755
0
    PyObject *file_action = NULL;
7756
0
    PyObject *tag_obj;
7757
7758
0
    seq = PySequence_Fast(file_actions,
7759
0
                          "file_actions must be a sequence or None");
7760
0
    if (seq == NULL) {
7761
0
        return -1;
7762
0
    }
7763
7764
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7765
0
    if (errno) {
7766
0
        posix_error();
7767
0
        Py_DECREF(seq);
7768
0
        return -1;
7769
0
    }
7770
7771
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7772
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7773
0
        Py_INCREF(file_action);
7774
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7775
0
            PyErr_SetString(PyExc_TypeError,
7776
0
                "Each file_actions element must be a non-empty tuple");
7777
0
            goto fail;
7778
0
        }
7779
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7780
0
        if (tag == -1 && PyErr_Occurred()) {
7781
0
            goto fail;
7782
0
        }
7783
7784
        /* Populate the file_actions object */
7785
0
        switch (tag) {
7786
0
            case POSIX_SPAWN_OPEN: {
7787
0
                int fd, oflag;
7788
0
                PyObject *path;
7789
0
                unsigned long mode;
7790
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7791
0
                        ";A open file_action tuple must have 5 elements",
7792
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7793
0
                        &oflag, &mode))
7794
0
                {
7795
0
                    goto fail;
7796
0
                }
7797
0
                if (PyList_Append(temp_buffer, path)) {
7798
0
                    Py_DECREF(path);
7799
0
                    goto fail;
7800
0
                }
7801
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7802
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7803
0
                if (errno) {
7804
0
                    posix_error();
7805
0
                    Py_DECREF(path);
7806
0
                    goto fail;
7807
0
                }
7808
0
                Py_DECREF(path);
7809
0
                break;
7810
0
            }
7811
0
            case POSIX_SPAWN_CLOSE: {
7812
0
                int fd;
7813
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7814
0
                        ";A close file_action tuple must have 2 elements",
7815
0
                        &tag_obj, &fd))
7816
0
                {
7817
0
                    goto fail;
7818
0
                }
7819
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7820
0
                if (errno) {
7821
0
                    posix_error();
7822
0
                    goto fail;
7823
0
                }
7824
0
                break;
7825
0
            }
7826
0
            case POSIX_SPAWN_DUP2: {
7827
0
                int fd1, fd2;
7828
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7829
0
                        ";A dup2 file_action tuple must have 3 elements",
7830
0
                        &tag_obj, &fd1, &fd2))
7831
0
                {
7832
0
                    goto fail;
7833
0
                }
7834
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7835
0
                                                         fd1, fd2);
7836
0
                if (errno) {
7837
0
                    posix_error();
7838
0
                    goto fail;
7839
0
                }
7840
0
                break;
7841
0
            }
7842
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7843
            case POSIX_SPAWN_CLOSEFROM: {
7844
                int fd;
7845
                if (!PyArg_ParseTuple(file_action, "Oi"
7846
                        ";A closefrom file_action tuple must have 2 elements",
7847
                        &tag_obj, &fd))
7848
                {
7849
                    goto fail;
7850
                }
7851
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7852
                                                                 fd);
7853
                if (errno) {
7854
                    posix_error();
7855
                    goto fail;
7856
                }
7857
                break;
7858
            }
7859
#endif
7860
0
            default: {
7861
0
                PyErr_SetString(PyExc_TypeError,
7862
0
                                "Unknown file_actions identifier");
7863
0
                goto fail;
7864
0
            }
7865
0
        }
7866
0
        Py_DECREF(file_action);
7867
0
    }
7868
7869
0
    Py_DECREF(seq);
7870
0
    return 0;
7871
7872
0
fail:
7873
0
    Py_DECREF(seq);
7874
0
    Py_DECREF(file_action);
7875
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7876
0
    return -1;
7877
0
}
7878
7879
7880
static PyObject *
7881
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7882
               PyObject *env, PyObject *file_actions,
7883
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7884
               PyObject *setsigdef, PyObject *scheduler)
7885
0
{
7886
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7887
0
    EXECV_CHAR **argvlist = NULL;
7888
0
    EXECV_CHAR **envlist = NULL;
7889
0
    posix_spawn_file_actions_t file_actions_buf;
7890
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7891
0
    posix_spawnattr_t attr;
7892
0
    posix_spawnattr_t *attrp = NULL;
7893
0
    Py_ssize_t argc, envc;
7894
0
    PyObject *result = NULL;
7895
0
    PyObject *temp_buffer = NULL;
7896
0
    pid_t pid;
7897
0
    int err_code;
7898
7899
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7900
       argv is a list or tuple of strings and env is a dictionary
7901
       like posix.environ. */
7902
7903
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7904
0
        PyErr_Format(PyExc_TypeError,
7905
0
                     "%s: argv must be a tuple or list", func_name);
7906
0
        goto exit;
7907
0
    }
7908
0
    argc = PySequence_Size(argv);
7909
0
    if (argc < 1) {
7910
0
        PyErr_Format(PyExc_ValueError,
7911
0
                     "%s: argv must not be empty", func_name);
7912
0
        goto exit;
7913
0
    }
7914
7915
0
    if (!PyMapping_Check(env) && env != Py_None) {
7916
0
        PyErr_Format(PyExc_TypeError,
7917
0
                     "%s: environment must be a mapping object or None", func_name);
7918
0
        goto exit;
7919
0
    }
7920
7921
0
    if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7922
0
        PyErr_Format(PyExc_TypeError,
7923
0
                     "%s: scheduler must be a tuple or None", func_name);
7924
0
        goto exit;
7925
0
    }
7926
7927
0
    argvlist = parse_arglist(argv, &argc);
7928
0
    if (argvlist == NULL) {
7929
0
        goto exit;
7930
0
    }
7931
0
    if (!argvlist[0][0]) {
7932
0
        PyErr_Format(PyExc_ValueError,
7933
0
                     "%s: argv first element cannot be empty", func_name);
7934
0
        goto exit;
7935
0
    }
7936
7937
#ifdef USE_DARWIN_NS_GET_ENVIRON
7938
    // There is no environ global in this situation.
7939
    char **environ = NULL;
7940
#endif
7941
7942
0
    if (env == Py_None) {
7943
#ifdef USE_DARWIN_NS_GET_ENVIRON
7944
        environ = *_NSGetEnviron();
7945
#endif
7946
0
        envlist = environ;
7947
0
    } else {
7948
0
        envlist = parse_envlist(env, &envc);
7949
0
        if (envlist == NULL) {
7950
0
            goto exit;
7951
0
        }
7952
0
    }
7953
7954
0
    if (file_actions != NULL && file_actions != Py_None) {
7955
        /* There is a bug in old versions of glibc that makes some of the
7956
         * helper functions for manipulating file actions not copy the provided
7957
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7958
         * copy the value of path for some old versions of glibc (<2.20).
7959
         * The use of temp_buffer here is a workaround that keeps the
7960
         * python objects that own the buffers alive until posix_spawn gets called.
7961
         * Check https://bugs.python.org/issue33630 and
7962
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7963
0
        temp_buffer = PyList_New(0);
7964
0
        if (!temp_buffer) {
7965
0
            goto exit;
7966
0
        }
7967
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7968
0
            goto exit;
7969
0
        }
7970
0
        file_actionsp = &file_actions_buf;
7971
0
    }
7972
7973
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7974
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7975
0
        goto exit;
7976
0
    }
7977
0
    attrp = &attr;
7978
7979
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7980
0
        goto exit;
7981
0
    }
7982
7983
0
    _Py_BEGIN_SUPPRESS_IPH
7984
0
#ifdef HAVE_POSIX_SPAWNP
7985
0
    if (use_posix_spawnp) {
7986
0
        err_code = posix_spawnp(&pid, path->narrow,
7987
0
                                file_actionsp, attrp, argvlist, envlist);
7988
0
    }
7989
0
    else
7990
0
#endif /* HAVE_POSIX_SPAWNP */
7991
0
    {
7992
0
        err_code = posix_spawn(&pid, path->narrow,
7993
0
                               file_actionsp, attrp, argvlist, envlist);
7994
0
    }
7995
0
    _Py_END_SUPPRESS_IPH
7996
7997
0
    if (err_code) {
7998
0
        errno = err_code;
7999
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8000
0
        goto exit;
8001
0
    }
8002
#ifdef _Py_MEMORY_SANITIZER
8003
    __msan_unpoison(&pid, sizeof(pid));
8004
#endif
8005
0
    result = PyLong_FromPid(pid);
8006
8007
0
exit:
8008
0
    if (file_actionsp) {
8009
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
8010
0
    }
8011
0
    if (attrp) {
8012
0
        (void)posix_spawnattr_destroy(attrp);
8013
0
    }
8014
0
    if (envlist && envlist != environ) {
8015
0
        free_string_array(envlist, envc);
8016
0
    }
8017
0
    if (argvlist) {
8018
0
        free_string_array(argvlist, argc);
8019
0
    }
8020
0
    Py_XDECREF(temp_buffer);
8021
0
    return result;
8022
0
}
8023
8024
8025
/*[clinic input]
8026
8027
os.posix_spawn
8028
    path: path_t
8029
        Path of executable file.
8030
    argv: object
8031
        Tuple or list of strings.
8032
    env: object
8033
        Dictionary of strings mapping to strings.
8034
    /
8035
    *
8036
    file_actions: object(c_default='NULL') = ()
8037
        A sequence of file action tuples.
8038
    setpgroup: object(c_default='NULL') = None
8039
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8040
    resetids: bool = False
8041
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8042
    setsid: bool = False
8043
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8044
    setsigmask: object(c_default='NULL') = ()
8045
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8046
    setsigdef: object(c_default='NULL') = ()
8047
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8048
    scheduler: object(c_default='NULL') = None
8049
        A tuple with the scheduler policy (optional) and parameters.
8050
8051
Execute the program specified by path in a new process.
8052
[clinic start generated code]*/
8053
8054
static PyObject *
8055
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8056
                    PyObject *env, PyObject *file_actions,
8057
                    PyObject *setpgroup, int resetids, int setsid,
8058
                    PyObject *setsigmask, PyObject *setsigdef,
8059
                    PyObject *scheduler)
8060
/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/
8061
0
{
8062
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8063
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8064
0
                          scheduler);
8065
0
}
8066
 #endif /* HAVE_POSIX_SPAWN */
8067
8068
8069
8070
#ifdef HAVE_POSIX_SPAWNP
8071
/*[clinic input]
8072
8073
os.posix_spawnp
8074
    path: path_t
8075
        Path of executable file.
8076
    argv: object
8077
        Tuple or list of strings.
8078
    env: object
8079
        Dictionary of strings mapping to strings.
8080
    /
8081
    *
8082
    file_actions: object(c_default='NULL') = ()
8083
        A sequence of file action tuples.
8084
    setpgroup: object(c_default='NULL') = None
8085
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8086
    resetids: bool = False
8087
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8088
    setsid: bool = False
8089
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8090
    setsigmask: object(c_default='NULL') = ()
8091
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8092
    setsigdef: object(c_default='NULL') = ()
8093
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8094
    scheduler: object(c_default='NULL') = None
8095
        A tuple with the scheduler policy (optional) and parameters.
8096
8097
Execute the program specified by path in a new process.
8098
[clinic start generated code]*/
8099
8100
static PyObject *
8101
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8102
                     PyObject *env, PyObject *file_actions,
8103
                     PyObject *setpgroup, int resetids, int setsid,
8104
                     PyObject *setsigmask, PyObject *setsigdef,
8105
                     PyObject *scheduler)
8106
/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/
8107
0
{
8108
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8109
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8110
0
                          scheduler);
8111
0
}
8112
#endif /* HAVE_POSIX_SPAWNP */
8113
8114
#ifdef HAVE_RTPSPAWN
8115
static intptr_t
8116
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8117
               const char  *envp[])
8118
{
8119
     RTP_ID rtpid;
8120
     int status;
8121
     pid_t res;
8122
     int async_err = 0;
8123
8124
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8125
        uStackSize=0 cannot be used, the default stack size is too small for
8126
        Python. */
8127
     if (envp) {
8128
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8129
                          100, 0x1000000, 0, VX_FP_TASK);
8130
     }
8131
     else {
8132
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8133
                          100, 0x1000000, 0, VX_FP_TASK);
8134
     }
8135
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8136
         do {
8137
             res = waitpid((pid_t)rtpid, &status, 0);
8138
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8139
8140
         if (res < 0)
8141
             return RTP_ID_ERROR;
8142
         return ((intptr_t)status);
8143
     }
8144
     return ((intptr_t)rtpid);
8145
}
8146
#endif
8147
8148
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8149
/*[clinic input]
8150
os.spawnv
8151
8152
    mode: int
8153
        Mode of process creation.
8154
    path: path_t
8155
        Path of executable file.
8156
    argv: object
8157
        Tuple or list of strings.
8158
    /
8159
8160
Execute the program specified by path in a new process.
8161
[clinic start generated code]*/
8162
8163
static PyObject *
8164
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8165
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8166
{
8167
    EXECV_CHAR **argvlist;
8168
    int i;
8169
    Py_ssize_t argc;
8170
    intptr_t spawnval;
8171
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8172
8173
    /* spawnv has three arguments: (mode, path, argv), where
8174
       argv is a list or tuple of strings. */
8175
8176
    if (PyList_Check(argv)) {
8177
        argc = PyList_Size(argv);
8178
        getitem = PyList_GetItem;
8179
    }
8180
    else if (PyTuple_Check(argv)) {
8181
        argc = PyTuple_Size(argv);
8182
        getitem = PyTuple_GetItem;
8183
    }
8184
    else {
8185
        PyErr_SetString(PyExc_TypeError,
8186
                        "spawnv() arg 2 must be a tuple or list");
8187
        return NULL;
8188
    }
8189
    if (argc == 0) {
8190
        PyErr_SetString(PyExc_ValueError,
8191
            "spawnv() arg 2 cannot be empty");
8192
        return NULL;
8193
    }
8194
8195
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8196
    if (argvlist == NULL) {
8197
        return PyErr_NoMemory();
8198
    }
8199
    for (i = 0; i < argc; i++) {
8200
        if (!fsconvert_strdup((*getitem)(argv, i),
8201
                              &argvlist[i])) {
8202
            free_string_array(argvlist, i);
8203
            PyErr_SetString(
8204
                PyExc_TypeError,
8205
                "spawnv() arg 2 must contain only strings");
8206
            return NULL;
8207
        }
8208
        if (i == 0 && !argvlist[0][0]) {
8209
            free_string_array(argvlist, i + 1);
8210
            PyErr_SetString(
8211
                PyExc_ValueError,
8212
                "spawnv() arg 2 first element cannot be empty");
8213
            return NULL;
8214
        }
8215
    }
8216
    argvlist[argc] = NULL;
8217
8218
#if !defined(HAVE_RTPSPAWN)
8219
    if (mode == _OLD_P_OVERLAY)
8220
        mode = _P_OVERLAY;
8221
#endif
8222
8223
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8224
                    Py_None) < 0) {
8225
        free_string_array(argvlist, argc);
8226
        return NULL;
8227
    }
8228
8229
    Py_BEGIN_ALLOW_THREADS
8230
    _Py_BEGIN_SUPPRESS_IPH
8231
#ifdef HAVE_WSPAWNV
8232
    spawnval = _wspawnv(mode, path->wide, argvlist);
8233
#elif defined(HAVE_RTPSPAWN)
8234
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8235
#else
8236
    spawnval = _spawnv(mode, path->narrow, argvlist);
8237
#endif
8238
    _Py_END_SUPPRESS_IPH
8239
    Py_END_ALLOW_THREADS
8240
8241
    int saved_errno = errno;
8242
    free_string_array(argvlist, argc);
8243
8244
    if (spawnval == -1) {
8245
        errno = saved_errno;
8246
        posix_error();
8247
        return NULL;
8248
    }
8249
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8250
}
8251
8252
/*[clinic input]
8253
os.spawnve
8254
8255
    mode: int
8256
        Mode of process creation.
8257
    path: path_t
8258
        Path of executable file.
8259
    argv: object
8260
        Tuple or list of strings.
8261
    env: object
8262
        Dictionary of strings mapping to strings.
8263
    /
8264
8265
Execute the program specified by path in a new process.
8266
[clinic start generated code]*/
8267
8268
static PyObject *
8269
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8270
                PyObject *env)
8271
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8272
{
8273
    EXECV_CHAR **argvlist;
8274
    EXECV_CHAR **envlist;
8275
    PyObject *res = NULL;
8276
    Py_ssize_t argc, i, envc;
8277
    intptr_t spawnval;
8278
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8279
    Py_ssize_t lastarg = 0;
8280
8281
    /* spawnve has four arguments: (mode, path, argv, env), where
8282
       argv is a list or tuple of strings and env is a dictionary
8283
       like posix.environ. */
8284
8285
    if (PyList_Check(argv)) {
8286
        argc = PyList_Size(argv);
8287
        getitem = PyList_GetItem;
8288
    }
8289
    else if (PyTuple_Check(argv)) {
8290
        argc = PyTuple_Size(argv);
8291
        getitem = PyTuple_GetItem;
8292
    }
8293
    else {
8294
        PyErr_SetString(PyExc_TypeError,
8295
                        "spawnve() arg 2 must be a tuple or list");
8296
        goto fail_0;
8297
    }
8298
    if (argc == 0) {
8299
        PyErr_SetString(PyExc_ValueError,
8300
            "spawnve() arg 2 cannot be empty");
8301
        goto fail_0;
8302
    }
8303
    if (!PyMapping_Check(env)) {
8304
        PyErr_SetString(PyExc_TypeError,
8305
                        "spawnve() arg 3 must be a mapping object");
8306
        goto fail_0;
8307
    }
8308
8309
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8310
    if (argvlist == NULL) {
8311
        PyErr_NoMemory();
8312
        goto fail_0;
8313
    }
8314
    for (i = 0; i < argc; i++) {
8315
        if (!fsconvert_strdup((*getitem)(argv, i),
8316
                              &argvlist[i]))
8317
        {
8318
            lastarg = i;
8319
            goto fail_1;
8320
        }
8321
        if (i == 0 && !argvlist[0][0]) {
8322
            lastarg = i + 1;
8323
            PyErr_SetString(
8324
                PyExc_ValueError,
8325
                "spawnv() arg 2 first element cannot be empty");
8326
            goto fail_1;
8327
        }
8328
    }
8329
    lastarg = argc;
8330
    argvlist[argc] = NULL;
8331
8332
    envlist = parse_envlist(env, &envc);
8333
    if (envlist == NULL)
8334
        goto fail_1;
8335
8336
#if !defined(HAVE_RTPSPAWN)
8337
    if (mode == _OLD_P_OVERLAY)
8338
        mode = _P_OVERLAY;
8339
#endif
8340
8341
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8342
        goto fail_2;
8343
    }
8344
8345
    Py_BEGIN_ALLOW_THREADS
8346
    _Py_BEGIN_SUPPRESS_IPH
8347
#ifdef HAVE_WSPAWNV
8348
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8349
#elif defined(HAVE_RTPSPAWN)
8350
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8351
                           (const char **)envlist);
8352
#else
8353
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8354
#endif
8355
    _Py_END_SUPPRESS_IPH
8356
    Py_END_ALLOW_THREADS
8357
8358
    if (spawnval == -1)
8359
        (void) posix_error();
8360
    else
8361
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8362
8363
  fail_2:
8364
    while (--envc >= 0) {
8365
        PyMem_Free(envlist[envc]);
8366
    }
8367
    PyMem_Free(envlist);
8368
  fail_1:
8369
    free_string_array(argvlist, lastarg);
8370
  fail_0:
8371
    return res;
8372
}
8373
8374
#endif /* HAVE_SPAWNV */
8375
8376
#ifdef HAVE_FORK
8377
8378
/* Helper function to validate arguments.
8379
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8380
   If obj is non-NULL it must be callable.  */
8381
static int
8382
check_null_or_callable(PyObject *obj, const char* obj_name)
8383
48
{
8384
48
    if (obj && !PyCallable_Check(obj)) {
8385
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8386
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8387
0
        return -1;
8388
0
    }
8389
48
    return 0;
8390
48
}
8391
8392
/*[clinic input]
8393
os.register_at_fork
8394
8395
    *
8396
    before: object=NULL
8397
        A callable to be called in the parent before the fork() syscall.
8398
    after_in_child: object=NULL
8399
        A callable to be called in the child after fork().
8400
    after_in_parent: object=NULL
8401
        A callable to be called in the parent after fork().
8402
8403
Register callables to be called when forking a new process.
8404
8405
'before' callbacks are called in reverse order.
8406
'after_in_child' and 'after_in_parent' callbacks are called in order.
8407
8408
[clinic start generated code]*/
8409
8410
static PyObject *
8411
os_register_at_fork_impl(PyObject *module, PyObject *before,
8412
                         PyObject *after_in_child, PyObject *after_in_parent)
8413
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8414
16
{
8415
16
    PyInterpreterState *interp;
8416
8417
16
    if (!before && !after_in_child && !after_in_parent) {
8418
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8419
0
        return NULL;
8420
0
    }
8421
16
    if (check_null_or_callable(before, "before") ||
8422
16
        check_null_or_callable(after_in_child, "after_in_child") ||
8423
16
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8424
0
        return NULL;
8425
0
    }
8426
16
    interp = _PyInterpreterState_GET();
8427
8428
16
    if (register_at_forker(&interp->before_forkers, before)) {
8429
0
        return NULL;
8430
0
    }
8431
16
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8432
0
        return NULL;
8433
0
    }
8434
16
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8435
0
        return NULL;
8436
0
    }
8437
16
    Py_RETURN_NONE;
8438
16
}
8439
#endif /* HAVE_FORK */
8440
8441
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8442
// Common code to raise a warning if we detect there is more than one thread
8443
// running in the process. Best effort, silent if unable to count threads.
8444
// Constraint: Quick. Never overcounts. Never leaves an error set.
8445
//
8446
// This MUST only be called from the parent process after
8447
// PyOS_AfterFork_Parent().
8448
static int
8449
warn_about_fork_with_threads(
8450
    const char* name,  // Name of the API to use in the warning message.
8451
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8452
)
8453
0
{
8454
    // It's not safe to issue the warning while the world is stopped, because
8455
    // other threads might be holding locks that we need, which would deadlock.
8456
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8457
8458
0
    Py_ssize_t num_python_threads = num_os_threads;
8459
0
    if (num_python_threads <= 0) {
8460
        // Fall back to just the number our threading module knows about.
8461
        // An incomplete view of the world, but better than nothing.
8462
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8463
0
        if (!threading) {
8464
0
            PyErr_Clear();
8465
0
            return 0;
8466
0
        }
8467
0
        PyObject *threading_active =
8468
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8469
0
        if (!threading_active) {
8470
0
            PyErr_Clear();
8471
0
            Py_DECREF(threading);
8472
0
            return 0;
8473
0
        }
8474
0
        PyObject *threading_limbo =
8475
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8476
0
        if (!threading_limbo) {
8477
0
            PyErr_Clear();
8478
0
            Py_DECREF(threading);
8479
0
            Py_DECREF(threading_active);
8480
0
            return 0;
8481
0
        }
8482
0
        Py_DECREF(threading);
8483
        // Duplicating what threading.active_count() does but without holding
8484
        // threading._active_limbo_lock so our count could be inaccurate if
8485
        // these dicts are mid-update from another thread.  Not a big deal.
8486
        // Worst case if someone replaced threading._active or threading._limbo
8487
        // with non-dicts, we get -1 from *Length() below and undercount.
8488
        // Nobody should, but we're best effort so we clear errors and move on.
8489
0
        num_python_threads = (PyMapping_Length(threading_active)
8490
0
                              + PyMapping_Length(threading_limbo));
8491
0
        PyErr_Clear();
8492
0
        Py_DECREF(threading_active);
8493
0
        Py_DECREF(threading_limbo);
8494
0
    }
8495
0
    if (num_python_threads > 1) {
8496
0
        return PyErr_WarnFormat(
8497
0
                PyExc_DeprecationWarning, 1,
8498
0
#ifdef HAVE_GETPID
8499
0
                "This process (pid=%d) is multi-threaded, "
8500
#else
8501
                "This process is multi-threaded, "
8502
#endif
8503
0
                "use of %s() may lead to deadlocks in the child.",
8504
0
#ifdef HAVE_GETPID
8505
0
                getpid(),
8506
0
#endif
8507
0
                name);
8508
0
    }
8509
0
    return 0;
8510
0
}
8511
8512
// If this returns <= 0, we were unable to successfully use any OS APIs.
8513
// Returns a positive number of threads otherwise.
8514
static Py_ssize_t get_number_of_os_threads(void)
8515
0
{
8516
    // TODO: Consider making an `os` module API to return the current number
8517
    // of threads in the process. That'd presumably use this platform code but
8518
    // raise an error rather than using the inaccurate fallback.
8519
0
    Py_ssize_t num_python_threads = 0;
8520
#if defined(__APPLE__) && defined(HAVE_GETPID)
8521
    mach_port_t macos_self = mach_task_self();
8522
    mach_port_t macos_task;
8523
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8524
        thread_array_t macos_threads;
8525
        mach_msg_type_number_t macos_n_threads;
8526
        if (task_threads(macos_task, &macos_threads,
8527
                         &macos_n_threads) == KERN_SUCCESS) {
8528
            num_python_threads = macos_n_threads;
8529
        }
8530
    }
8531
#elif defined(__linux__)
8532
    // Linux /proc/self/stat 20th field is the number of threads.
8533
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8534
0
    if (proc_stat) {
8535
0
        size_t n;
8536
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8537
        // observed on the author's workstation.
8538
0
        char stat_line[160];
8539
0
        n = fread(&stat_line, 1, 159, proc_stat);
8540
0
        stat_line[n] = '\0';
8541
0
        fclose(proc_stat);
8542
8543
0
        char *saveptr = NULL;
8544
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8545
0
        unsigned int idx;
8546
0
        for (idx = 19; idx && field; --idx) {
8547
0
            field = strtok_r(NULL, " ", &saveptr);
8548
0
        }
8549
0
        if (idx == 0 && field) {  // found the 20th field
8550
0
            num_python_threads = atoi(field);  // 0 on error
8551
0
        }
8552
0
    }
8553
0
#endif
8554
0
    return num_python_threads;
8555
0
}
8556
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8557
8558
#ifdef HAVE_FORK1
8559
/*[clinic input]
8560
os.fork1
8561
8562
Fork a child process with a single multiplexed (i.e., not bound) thread.
8563
8564
Return 0 to child process and PID of child to parent process.
8565
[clinic start generated code]*/
8566
8567
static PyObject *
8568
os_fork1_impl(PyObject *module)
8569
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8570
{
8571
    pid_t pid;
8572
8573
    PyInterpreterState *interp = _PyInterpreterState_GET();
8574
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8575
        PyErr_SetString(PyExc_PythonFinalizationError,
8576
                        "can't fork at interpreter shutdown");
8577
        return NULL;
8578
    }
8579
    if (!_Py_IsMainInterpreter(interp)) {
8580
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8581
        return NULL;
8582
    }
8583
    PyOS_BeforeFork();
8584
    pid = fork1();
8585
    int saved_errno = errno;
8586
    if (pid == 0) {
8587
        /* child: this clobbers and resets the import lock. */
8588
        PyOS_AfterFork_Child();
8589
    } else {
8590
        // Called before AfterFork_Parent in case those hooks start threads.
8591
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8592
        /* parent: release the import lock. */
8593
        PyOS_AfterFork_Parent();
8594
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8595
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8596
            return NULL;
8597
        }
8598
    }
8599
    if (pid == -1) {
8600
        errno = saved_errno;
8601
        return posix_error();
8602
    }
8603
    return PyLong_FromPid(pid);
8604
}
8605
#endif /* HAVE_FORK1 */
8606
8607
8608
#ifdef HAVE_FORK
8609
/*[clinic input]
8610
os.fork
8611
8612
Fork a child process.
8613
8614
Return 0 to child process and PID of child to parent process.
8615
[clinic start generated code]*/
8616
8617
static PyObject *
8618
os_fork_impl(PyObject *module)
8619
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8620
0
{
8621
0
    pid_t pid;
8622
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8623
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8624
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8625
0
                        "can't fork at interpreter shutdown");
8626
0
        return NULL;
8627
0
    }
8628
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8629
0
        PyErr_SetString(PyExc_RuntimeError,
8630
0
                        "fork not supported for isolated subinterpreters");
8631
0
        return NULL;
8632
0
    }
8633
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8634
0
        return NULL;
8635
0
    }
8636
0
    PyOS_BeforeFork();
8637
0
    pid = fork();
8638
0
    int saved_errno = errno;
8639
0
    if (pid == 0) {
8640
        /* child: this clobbers and resets the import lock. */
8641
0
        PyOS_AfterFork_Child();
8642
0
    } else {
8643
        // Called before AfterFork_Parent in case those hooks start threads.
8644
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8645
        /* parent: release the import lock. */
8646
0
        PyOS_AfterFork_Parent();
8647
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8648
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8649
0
            return NULL;
8650
0
    }
8651
0
    if (pid == -1) {
8652
0
        errno = saved_errno;
8653
0
        return posix_error();
8654
0
    }
8655
0
    return PyLong_FromPid(pid);
8656
0
}
8657
#endif /* HAVE_FORK */
8658
8659
8660
#ifdef HAVE_SCHED_H
8661
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8662
/*[clinic input]
8663
os.sched_get_priority_max
8664
8665
    policy: int
8666
8667
Get the maximum scheduling priority for policy.
8668
[clinic start generated code]*/
8669
8670
static PyObject *
8671
os_sched_get_priority_max_impl(PyObject *module, int policy)
8672
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8673
0
{
8674
    /* make sure that errno is cleared before the call */
8675
0
    errno = 0;
8676
0
    int max = sched_get_priority_max(policy);
8677
0
    if (max == -1 && errno)
8678
0
        return posix_error();
8679
0
    return PyLong_FromLong(max);
8680
0
}
8681
8682
8683
/*[clinic input]
8684
os.sched_get_priority_min
8685
8686
    policy: int
8687
8688
Get the minimum scheduling priority for policy.
8689
[clinic start generated code]*/
8690
8691
static PyObject *
8692
os_sched_get_priority_min_impl(PyObject *module, int policy)
8693
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8694
0
{
8695
    /* make sure that errno is cleared before the call */
8696
0
    errno = 0;
8697
0
    int min = sched_get_priority_min(policy);
8698
0
    if (min == -1 && errno)
8699
0
        return posix_error();
8700
0
    return PyLong_FromLong(min);
8701
0
}
8702
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8703
8704
8705
#ifdef HAVE_SCHED_SETSCHEDULER
8706
/*[clinic input]
8707
os.sched_getscheduler
8708
    pid: pid_t
8709
    /
8710
8711
Get the scheduling policy for the process identified by pid.
8712
8713
Passing 0 for pid returns the scheduling policy for the calling process.
8714
[clinic start generated code]*/
8715
8716
static PyObject *
8717
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8718
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8719
0
{
8720
0
    int policy;
8721
8722
0
    policy = sched_getscheduler(pid);
8723
0
    if (policy < 0)
8724
0
        return posix_error();
8725
0
    return PyLong_FromLong(policy);
8726
0
}
8727
#endif /* HAVE_SCHED_SETSCHEDULER */
8728
8729
8730
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8731
/*[clinic input]
8732
class os.sched_param "PyObject *" "SchedParamType"
8733
8734
@classmethod
8735
os.sched_param.__new__
8736
8737
    sched_priority: object
8738
        A scheduling parameter.
8739
8740
Currently has only one field: sched_priority
8741
[clinic start generated code]*/
8742
8743
static PyObject *
8744
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8745
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8746
0
{
8747
0
    PyObject *res;
8748
8749
0
    res = PyStructSequence_New(type);
8750
0
    if (!res)
8751
0
        return NULL;
8752
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8753
0
    return res;
8754
0
}
8755
8756
static PyObject *
8757
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8758
0
{
8759
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8760
0
}
8761
8762
static PyMethodDef os_sched_param_reduce_method = {
8763
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8764
};
8765
8766
PyDoc_VAR(os_sched_param__doc__);
8767
8768
static PyStructSequence_Field sched_param_fields[] = {
8769
    {"sched_priority", "the scheduling priority"},
8770
    {0}
8771
};
8772
8773
static PyStructSequence_Desc sched_param_desc = {
8774
    MODNAME ".sched_param", /* name */
8775
    os_sched_param__doc__, /* doc */
8776
    sched_param_fields,
8777
    1
8778
};
8779
8780
static int
8781
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8782
0
{
8783
0
    long priority;
8784
8785
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8786
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8787
0
        return 0;
8788
0
    }
8789
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8790
0
    if (priority == -1 && PyErr_Occurred())
8791
0
        return 0;
8792
0
    if (priority > INT_MAX || priority < INT_MIN) {
8793
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8794
0
        return 0;
8795
0
    }
8796
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8797
0
    return 1;
8798
0
}
8799
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8800
8801
8802
#ifdef HAVE_SCHED_SETSCHEDULER
8803
/*[clinic input]
8804
os.sched_setscheduler
8805
8806
    pid: pid_t
8807
    policy: int
8808
    param as param_obj: object
8809
    /
8810
8811
Set the scheduling policy for the process identified by pid.
8812
8813
If pid is 0, the calling process is changed.
8814
param is an instance of sched_param.
8815
[clinic start generated code]*/
8816
8817
static PyObject *
8818
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8819
                           PyObject *param_obj)
8820
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8821
0
{
8822
0
    struct sched_param param;
8823
0
    if (!convert_sched_param(module, param_obj, &param)) {
8824
0
        return NULL;
8825
0
    }
8826
8827
    /*
8828
    ** sched_setscheduler() returns 0 in Linux, but the previous
8829
    ** scheduling policy under Solaris/Illumos, and others.
8830
    ** On error, -1 is returned in all Operating Systems.
8831
    */
8832
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8833
0
        return posix_error();
8834
0
    Py_RETURN_NONE;
8835
0
}
8836
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8837
8838
8839
#ifdef HAVE_SCHED_SETPARAM
8840
/*[clinic input]
8841
os.sched_getparam
8842
    pid: pid_t
8843
    /
8844
8845
Returns scheduling parameters for the process identified by pid.
8846
8847
If pid is 0, returns parameters for the calling process.
8848
Return value is an instance of sched_param.
8849
[clinic start generated code]*/
8850
8851
static PyObject *
8852
os_sched_getparam_impl(PyObject *module, pid_t pid)
8853
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8854
0
{
8855
0
    struct sched_param param;
8856
0
    PyObject *result;
8857
0
    PyObject *priority;
8858
8859
0
    if (sched_getparam(pid, &param))
8860
0
        return posix_error();
8861
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8862
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8863
0
    if (!result)
8864
0
        return NULL;
8865
0
    priority = PyLong_FromLong(param.sched_priority);
8866
0
    if (!priority) {
8867
0
        Py_DECREF(result);
8868
0
        return NULL;
8869
0
    }
8870
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8871
0
    return result;
8872
0
}
8873
8874
8875
/*[clinic input]
8876
os.sched_setparam
8877
    pid: pid_t
8878
    param as param_obj: object
8879
    /
8880
8881
Set scheduling parameters for the process identified by pid.
8882
8883
If pid is 0, sets parameters for the calling process.
8884
param should be an instance of sched_param.
8885
[clinic start generated code]*/
8886
8887
static PyObject *
8888
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8889
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8890
0
{
8891
0
    struct sched_param param;
8892
0
    if (!convert_sched_param(module, param_obj, &param)) {
8893
0
        return NULL;
8894
0
    }
8895
8896
0
    if (sched_setparam(pid, &param))
8897
0
        return posix_error();
8898
0
    Py_RETURN_NONE;
8899
0
}
8900
#endif /* HAVE_SCHED_SETPARAM */
8901
8902
8903
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8904
/*[clinic input]
8905
@permit_long_summary
8906
os.sched_rr_get_interval -> double
8907
    pid: pid_t
8908
    /
8909
8910
Return the round-robin quantum for the process identified by pid, in seconds.
8911
8912
Value returned is a float.
8913
[clinic start generated code]*/
8914
8915
static double
8916
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8917
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8918
0
{
8919
0
    struct timespec interval;
8920
0
    if (sched_rr_get_interval(pid, &interval)) {
8921
0
        posix_error();
8922
0
        return -1.0;
8923
0
    }
8924
#ifdef _Py_MEMORY_SANITIZER
8925
    __msan_unpoison(&interval, sizeof(interval));
8926
#endif
8927
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8928
0
}
8929
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8930
8931
8932
/*[clinic input]
8933
os.sched_yield
8934
8935
Voluntarily relinquish the CPU.
8936
[clinic start generated code]*/
8937
8938
static PyObject *
8939
os_sched_yield_impl(PyObject *module)
8940
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8941
0
{
8942
0
    int result;
8943
0
    Py_BEGIN_ALLOW_THREADS
8944
0
    result = sched_yield();
8945
0
    Py_END_ALLOW_THREADS
8946
0
    if (result < 0) {
8947
0
        return posix_error();
8948
0
    }
8949
0
    Py_RETURN_NONE;
8950
0
}
8951
8952
#ifdef HAVE_SCHED_SETAFFINITY
8953
/* The minimum number of CPUs allocated in a cpu_set_t */
8954
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8955
8956
/*[clinic input]
8957
os.sched_setaffinity
8958
    pid: pid_t
8959
    mask : object
8960
    /
8961
8962
Set the CPU affinity of the process identified by pid to mask.
8963
8964
mask should be an iterable of integers identifying CPUs.
8965
[clinic start generated code]*/
8966
8967
static PyObject *
8968
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8969
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8970
0
{
8971
0
    int ncpus;
8972
0
    size_t setsize;
8973
0
    cpu_set_t *cpu_set = NULL;
8974
0
    PyObject *iterator = NULL, *item;
8975
8976
0
    iterator = PyObject_GetIter(mask);
8977
0
    if (iterator == NULL)
8978
0
        return NULL;
8979
8980
0
    ncpus = NCPUS_START;
8981
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8982
0
    cpu_set = CPU_ALLOC(ncpus);
8983
0
    if (cpu_set == NULL) {
8984
0
        PyErr_NoMemory();
8985
0
        goto error;
8986
0
    }
8987
0
    CPU_ZERO_S(setsize, cpu_set);
8988
8989
0
    while ((item = PyIter_Next(iterator))) {
8990
0
        long cpu;
8991
0
        if (!PyIndex_Check(item)) {
8992
0
            PyErr_Format(PyExc_TypeError,
8993
0
                        "expected an iterator of ints, "
8994
0
                        "but iterator yielded %R",
8995
0
                        Py_TYPE(item));
8996
0
            Py_DECREF(item);
8997
0
            goto error;
8998
0
        }
8999
0
        cpu = PyLong_AsLong(item);
9000
0
        Py_DECREF(item);
9001
0
        if (cpu < 0) {
9002
0
            if (!PyErr_Occurred())
9003
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9004
0
            goto error;
9005
0
        }
9006
0
        if (cpu > INT_MAX - 1) {
9007
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9008
0
            goto error;
9009
0
        }
9010
0
        if (cpu >= ncpus) {
9011
            /* Grow CPU mask to fit the CPU number */
9012
0
            int newncpus = ncpus;
9013
0
            cpu_set_t *newmask;
9014
0
            size_t newsetsize;
9015
0
            while (newncpus <= cpu) {
9016
0
                if (newncpus > INT_MAX / 2)
9017
0
                    newncpus = cpu + 1;
9018
0
                else
9019
0
                    newncpus = newncpus * 2;
9020
0
            }
9021
0
            newmask = CPU_ALLOC(newncpus);
9022
0
            if (newmask == NULL) {
9023
0
                PyErr_NoMemory();
9024
0
                goto error;
9025
0
            }
9026
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9027
0
            CPU_ZERO_S(newsetsize, newmask);
9028
0
            memcpy(newmask, cpu_set, setsize);
9029
0
            CPU_FREE(cpu_set);
9030
0
            setsize = newsetsize;
9031
0
            cpu_set = newmask;
9032
0
            ncpus = newncpus;
9033
0
        }
9034
0
        CPU_SET_S(cpu, setsize, cpu_set);
9035
0
    }
9036
0
    if (PyErr_Occurred()) {
9037
0
        goto error;
9038
0
    }
9039
0
    Py_CLEAR(iterator);
9040
9041
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9042
0
        posix_error();
9043
0
        goto error;
9044
0
    }
9045
0
    CPU_FREE(cpu_set);
9046
0
    Py_RETURN_NONE;
9047
9048
0
error:
9049
0
    if (cpu_set)
9050
0
        CPU_FREE(cpu_set);
9051
0
    Py_XDECREF(iterator);
9052
0
    return NULL;
9053
0
}
9054
9055
9056
/*[clinic input]
9057
@permit_long_summary
9058
os.sched_getaffinity
9059
    pid: pid_t
9060
    /
9061
9062
Return the affinity of the process identified by pid (or the current process if zero).
9063
9064
The affinity is returned as a set of CPU identifiers.
9065
[clinic start generated code]*/
9066
9067
static PyObject *
9068
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9069
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9070
0
{
9071
0
    int ncpus = NCPUS_START;
9072
0
    size_t setsize;
9073
0
    cpu_set_t *mask;
9074
9075
0
    while (1) {
9076
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9077
0
        mask = CPU_ALLOC(ncpus);
9078
0
        if (mask == NULL) {
9079
0
            return PyErr_NoMemory();
9080
0
        }
9081
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9082
0
            break;
9083
0
        }
9084
0
        CPU_FREE(mask);
9085
0
        if (errno != EINVAL) {
9086
0
            return posix_error();
9087
0
        }
9088
0
        if (ncpus > INT_MAX / 2) {
9089
0
            PyErr_SetString(PyExc_OverflowError,
9090
0
                            "could not allocate a large enough CPU set");
9091
0
            return NULL;
9092
0
        }
9093
0
        ncpus *= 2;
9094
0
    }
9095
9096
0
    PyObject *res = PySet_New(NULL);
9097
0
    if (res == NULL) {
9098
0
        goto error;
9099
0
    }
9100
9101
0
    int cpu = 0;
9102
0
    int count = CPU_COUNT_S(setsize, mask);
9103
0
    for (; count; cpu++) {
9104
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9105
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9106
0
            --count;
9107
0
            if (cpu_num == NULL) {
9108
0
                goto error;
9109
0
            }
9110
0
            if (PySet_Add(res, cpu_num)) {
9111
0
                Py_DECREF(cpu_num);
9112
0
                goto error;
9113
0
            }
9114
0
            Py_DECREF(cpu_num);
9115
0
        }
9116
0
    }
9117
0
    CPU_FREE(mask);
9118
0
    return res;
9119
9120
0
error:
9121
0
    if (mask) {
9122
0
        CPU_FREE(mask);
9123
0
    }
9124
0
    Py_XDECREF(res);
9125
0
    return NULL;
9126
0
}
9127
#endif /* HAVE_SCHED_SETAFFINITY */
9128
9129
#endif /* HAVE_SCHED_H */
9130
9131
9132
#ifdef HAVE_POSIX_OPENPT
9133
/*[clinic input]
9134
os.posix_openpt -> int
9135
9136
    oflag: int
9137
    /
9138
9139
Open and return a file descriptor for a master pseudo-terminal device.
9140
9141
Performs a posix_openpt() C function call. The oflag argument is used to
9142
set file status flags and file access modes as specified in the manual page
9143
of posix_openpt() of your system.
9144
[clinic start generated code]*/
9145
9146
static int
9147
os_posix_openpt_impl(PyObject *module, int oflag)
9148
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
9149
0
{
9150
0
    int fd;
9151
9152
0
#if defined(O_CLOEXEC)
9153
0
    oflag |= O_CLOEXEC;
9154
0
#endif
9155
9156
0
    fd = posix_openpt(oflag);
9157
0
    if (fd == -1) {
9158
0
        posix_error();
9159
0
        return -1;
9160
0
    }
9161
9162
    // Just in case, likely a no-op given O_CLOEXEC above.
9163
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9164
0
        close(fd);
9165
0
        return -1;
9166
0
    }
9167
9168
0
    return fd;
9169
0
}
9170
#endif /* HAVE_POSIX_OPENPT */
9171
9172
#ifdef HAVE_GRANTPT
9173
/*[clinic input]
9174
os.grantpt
9175
9176
    fd: fildes
9177
        File descriptor of a master pseudo-terminal device.
9178
    /
9179
9180
Grant access to the slave pseudo-terminal device.
9181
9182
Performs a grantpt() C function call.
9183
[clinic start generated code]*/
9184
9185
static PyObject *
9186
os_grantpt_impl(PyObject *module, int fd)
9187
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9188
0
{
9189
0
    int ret;
9190
0
    int saved_errno;
9191
0
    PyOS_sighandler_t sig_saved;
9192
9193
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9194
9195
0
    ret = grantpt(fd);
9196
0
    if (ret == -1)
9197
0
        saved_errno = errno;
9198
9199
0
    PyOS_setsig(SIGCHLD, sig_saved);
9200
9201
0
    if (ret == -1) {
9202
0
        errno = saved_errno;
9203
0
        return posix_error();
9204
0
    }
9205
9206
0
    Py_RETURN_NONE;
9207
0
}
9208
#endif /* HAVE_GRANTPT */
9209
9210
#ifdef HAVE_UNLOCKPT
9211
/*[clinic input]
9212
os.unlockpt
9213
9214
    fd: fildes
9215
        File descriptor of a master pseudo-terminal device.
9216
    /
9217
9218
Unlock a pseudo-terminal master/slave pair.
9219
9220
Performs an unlockpt() C function call.
9221
[clinic start generated code]*/
9222
9223
static PyObject *
9224
os_unlockpt_impl(PyObject *module, int fd)
9225
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9226
0
{
9227
0
    if (unlockpt(fd) == -1)
9228
0
        return posix_error();
9229
9230
0
    Py_RETURN_NONE;
9231
0
}
9232
#endif /* HAVE_UNLOCKPT */
9233
9234
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9235
static PyObject *
9236
py_ptsname(int fd)
9237
0
{
9238
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9239
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9240
0
    errno = 0;
9241
0
    char *name = ptsname(fd);
9242
0
    if (name == NULL) {
9243
0
        return posix_error();
9244
0
    }
9245
0
    return PyUnicode_DecodeFSDefault(name);
9246
0
}
9247
9248
/*[clinic input]
9249
os.ptsname
9250
9251
    fd: fildes
9252
        File descriptor of a master pseudo-terminal device.
9253
    /
9254
9255
Return the name of the slave pseudo-terminal device.
9256
9257
If the ptsname_r() C function is available, it is called;
9258
otherwise, performs a ptsname() C function call.
9259
[clinic start generated code]*/
9260
9261
static PyObject *
9262
os_ptsname_impl(PyObject *module, int fd)
9263
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9264
0
{
9265
0
#ifdef HAVE_PTSNAME_R
9266
0
    int ret;
9267
0
    char name[MAXPATHLEN+1];
9268
9269
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9270
0
        ret = ptsname_r(fd, name, sizeof(name));
9271
0
    }
9272
0
    else {
9273
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9274
0
        return py_ptsname(fd);
9275
0
    }
9276
0
    if (ret != 0) {
9277
0
        errno = ret;
9278
0
        return posix_error();
9279
0
    }
9280
9281
0
    return PyUnicode_DecodeFSDefault(name);
9282
#else
9283
    return py_ptsname(fd);
9284
#endif /* HAVE_PTSNAME_R */
9285
0
}
9286
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9287
9288
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9289
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9290
#  define DEV_PTY_FILE "/dev/ptc"
9291
#  define HAVE_DEV_PTMX
9292
#else
9293
#  define DEV_PTY_FILE "/dev/ptmx"
9294
#endif
9295
9296
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9297
#ifdef HAVE_PTY_H
9298
#include <pty.h>
9299
#elif defined(HAVE_LIBUTIL_H)
9300
#include <libutil.h>
9301
#elif defined(HAVE_UTIL_H)
9302
#include <util.h>
9303
#endif /* HAVE_PTY_H */
9304
#ifdef HAVE_UTMP_H
9305
#include <utmp.h>
9306
#endif /* HAVE_UTMP_H */
9307
#ifdef HAVE_STROPTS_H
9308
#include <stropts.h>
9309
#endif
9310
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9311
9312
9313
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9314
/*[clinic input]
9315
os.openpty
9316
9317
Open a pseudo-terminal.
9318
9319
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9320
for both the master and slave ends.
9321
[clinic start generated code]*/
9322
9323
static PyObject *
9324
os_openpty_impl(PyObject *module)
9325
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9326
0
{
9327
0
    int master_fd = -1, slave_fd = -1;
9328
#ifndef HAVE_OPENPTY
9329
    char * slave_name;
9330
#endif
9331
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9332
    PyOS_sighandler_t sig_saved;
9333
#if defined(__sun) && defined(__SVR4)
9334
    extern char *ptsname(int fildes);
9335
#endif
9336
#endif
9337
9338
0
#ifdef HAVE_OPENPTY
9339
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9340
0
        goto posix_error;
9341
9342
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9343
0
        goto error;
9344
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9345
0
        goto error;
9346
9347
#elif defined(HAVE__GETPTY)
9348
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9349
    if (slave_name == NULL)
9350
        goto posix_error;
9351
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9352
        goto error;
9353
9354
    slave_fd = _Py_open(slave_name, O_RDWR);
9355
    if (slave_fd < 0)
9356
        goto error;
9357
9358
#else
9359
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9360
    if (master_fd < 0)
9361
        goto posix_error;
9362
9363
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9364
9365
    /* change permission of slave */
9366
    if (grantpt(master_fd) < 0) {
9367
        int saved_errno = errno;
9368
        PyOS_setsig(SIGCHLD, sig_saved);
9369
        errno = saved_errno;
9370
        goto posix_error;
9371
    }
9372
9373
    /* unlock slave */
9374
    if (unlockpt(master_fd) < 0) {
9375
        int saved_errno = errno;
9376
        PyOS_setsig(SIGCHLD, sig_saved);
9377
        errno = saved_errno;
9378
        goto posix_error;
9379
    }
9380
9381
    PyOS_setsig(SIGCHLD, sig_saved);
9382
9383
    slave_name = ptsname(master_fd); /* get name of slave */
9384
    if (slave_name == NULL)
9385
        goto posix_error;
9386
9387
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9388
    if (slave_fd == -1)
9389
        goto error;
9390
9391
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9392
        goto posix_error;
9393
9394
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
9395
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9396
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9397
#ifndef __hpux
9398
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9399
#endif /* __hpux */
9400
#endif /* HAVE_CYGWIN */
9401
#endif /* HAVE_OPENPTY */
9402
9403
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9404
9405
0
posix_error:
9406
0
    posix_error();
9407
0
error:
9408
0
    if (master_fd != -1)
9409
0
        close(master_fd);
9410
0
    if (slave_fd != -1)
9411
0
        close(slave_fd);
9412
0
    return NULL;
9413
0
}
9414
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9415
9416
9417
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9418
#define HAVE_FALLBACK_LOGIN_TTY 1
9419
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9420
9421
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9422
/*[clinic input]
9423
os.login_tty
9424
9425
    fd: fildes
9426
    /
9427
9428
Prepare the tty of which fd is a file descriptor for a new login session.
9429
9430
Make the calling process a session leader; make the tty the
9431
controlling tty, the stdin, the stdout, and the stderr of the
9432
calling process; close fd.
9433
[clinic start generated code]*/
9434
9435
static PyObject *
9436
os_login_tty_impl(PyObject *module, int fd)
9437
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
9438
0
{
9439
0
#ifdef HAVE_LOGIN_TTY
9440
0
    if (login_tty(fd) == -1) {
9441
0
        return posix_error();
9442
0
    }
9443
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9444
    /* Establish a new session. */
9445
    if (setsid() == -1) {
9446
        return posix_error();
9447
    }
9448
9449
    /* The tty becomes the controlling terminal. */
9450
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9451
        return posix_error();
9452
    }
9453
9454
    /* The tty becomes stdin/stdout/stderr */
9455
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9456
        return posix_error();
9457
    }
9458
    if (fd > 2) {
9459
        close(fd);
9460
    }
9461
#endif /* HAVE_LOGIN_TTY */
9462
0
    Py_RETURN_NONE;
9463
0
}
9464
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9465
9466
9467
#ifdef HAVE_FORKPTY
9468
/*[clinic input]
9469
os.forkpty
9470
9471
Fork a new process with a new pseudo-terminal as controlling tty.
9472
9473
Returns a tuple of (pid, master_fd).
9474
Like fork(), return pid of 0 to the child process,
9475
and pid of child to the parent process.
9476
To both, return fd of newly opened pseudo-terminal.
9477
The master_fd is non-inheritable.
9478
[clinic start generated code]*/
9479
9480
static PyObject *
9481
os_forkpty_impl(PyObject *module)
9482
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9483
0
{
9484
0
    int master_fd = -1;
9485
0
    pid_t pid;
9486
9487
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9488
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9489
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9490
0
                        "can't fork at interpreter shutdown");
9491
0
        return NULL;
9492
0
    }
9493
0
    if (!_Py_IsMainInterpreter(interp)) {
9494
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9495
0
        return NULL;
9496
0
    }
9497
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9498
0
        return NULL;
9499
0
    }
9500
0
    PyOS_BeforeFork();
9501
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9502
0
    if (pid == 0) {
9503
        /* child: this clobbers and resets the import lock. */
9504
0
        PyOS_AfterFork_Child();
9505
0
    } else {
9506
        // Called before AfterFork_Parent in case those hooks start threads.
9507
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9508
        /* parent: release the import lock. */
9509
0
        PyOS_AfterFork_Parent();
9510
        /* set O_CLOEXEC on master_fd */
9511
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9512
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9513
0
                                   "non-inheritable in forkpty()");
9514
0
        }
9515
9516
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9517
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9518
0
            return NULL;
9519
0
    }
9520
0
    if (pid == -1) {
9521
0
        return posix_error();
9522
0
    }
9523
9524
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9525
0
}
9526
#endif /* HAVE_FORKPTY */
9527
9528
9529
#ifdef HAVE_GETEGID
9530
/*[clinic input]
9531
os.getegid
9532
9533
Return the current process's effective group id.
9534
[clinic start generated code]*/
9535
9536
static PyObject *
9537
os_getegid_impl(PyObject *module)
9538
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9539
32
{
9540
32
    return _PyLong_FromGid(getegid());
9541
32
}
9542
#endif /* HAVE_GETEGID */
9543
9544
9545
#ifdef HAVE_GETEUID
9546
/*[clinic input]
9547
os.geteuid
9548
9549
Return the current process's effective user id.
9550
[clinic start generated code]*/
9551
9552
static PyObject *
9553
os_geteuid_impl(PyObject *module)
9554
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9555
32
{
9556
32
    return _PyLong_FromUid(geteuid());
9557
32
}
9558
#endif /* HAVE_GETEUID */
9559
9560
9561
#ifdef HAVE_GETGID
9562
/*[clinic input]
9563
os.getgid
9564
9565
Return the current process's group id.
9566
[clinic start generated code]*/
9567
9568
static PyObject *
9569
os_getgid_impl(PyObject *module)
9570
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9571
32
{
9572
32
    return _PyLong_FromGid(getgid());
9573
32
}
9574
#endif /* HAVE_GETGID */
9575
9576
9577
#if defined(HAVE_GETPID)
9578
/*[clinic input]
9579
os.getpid
9580
9581
Return the current process id.
9582
[clinic start generated code]*/
9583
9584
static PyObject *
9585
os_getpid_impl(PyObject *module)
9586
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9587
4.74k
{
9588
4.74k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9589
4.74k
    return PyLong_FromPid(getpid());
9590
#else
9591
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9592
#endif
9593
4.74k
}
9594
#endif /* defined(HAVE_GETPID) */
9595
9596
#ifdef NGROUPS_MAX
9597
0
#define MAX_GROUPS NGROUPS_MAX
9598
#else
9599
    /* defined to be 16 on Solaris7, so this should be a small number */
9600
#define MAX_GROUPS 64
9601
#endif
9602
9603
#ifdef HAVE_GETGROUPLIST
9604
9605
#ifdef __APPLE__
9606
/*[clinic input]
9607
os.getgrouplist
9608
9609
    user: str
9610
        username to lookup
9611
    group as basegid: int
9612
        base group id of the user
9613
    /
9614
9615
Returns a list of groups to which a user belongs.
9616
[clinic start generated code]*/
9617
9618
static PyObject *
9619
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9620
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9621
#else
9622
/*[clinic input]
9623
os.getgrouplist
9624
9625
    user: str
9626
        username to lookup
9627
    group as basegid: gid_t
9628
        base group id of the user
9629
    /
9630
9631
Returns a list of groups to which a user belongs.
9632
[clinic start generated code]*/
9633
9634
static PyObject *
9635
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9636
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9637
#endif
9638
0
{
9639
0
    int i, ngroups;
9640
0
    PyObject *list;
9641
#ifdef __APPLE__
9642
    int *groups;
9643
#else
9644
0
    gid_t *groups;
9645
0
#endif
9646
9647
    /*
9648
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9649
     * number of supplemental groups a users can belong to.
9650
     * We have to increment it by one because
9651
     * getgrouplist() returns both the supplemental groups
9652
     * and the primary group, i.e. all of the groups the
9653
     * user belongs to.
9654
     */
9655
0
    ngroups = 1 + MAX_GROUPS;
9656
9657
0
    while (1) {
9658
#ifdef __APPLE__
9659
        groups = PyMem_New(int, ngroups);
9660
#else
9661
0
        groups = PyMem_New(gid_t, ngroups);
9662
0
#endif
9663
0
        if (groups == NULL) {
9664
0
            return PyErr_NoMemory();
9665
0
        }
9666
9667
0
        int old_ngroups = ngroups;
9668
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9669
            /* Success */
9670
0
            break;
9671
0
        }
9672
9673
        /* getgrouplist() fails if the group list is too small */
9674
0
        PyMem_Free(groups);
9675
9676
0
        if (ngroups > old_ngroups) {
9677
            /* If the group list is too small, the glibc implementation of
9678
               getgrouplist() sets ngroups to the total number of groups and
9679
               returns -1. */
9680
0
        }
9681
0
        else {
9682
            /* Double the group list size */
9683
0
            if (ngroups > INT_MAX / 2) {
9684
0
                return PyErr_NoMemory();
9685
0
            }
9686
0
            ngroups *= 2;
9687
0
        }
9688
9689
        /* Retry getgrouplist() with a larger group list */
9690
0
    }
9691
9692
#ifdef _Py_MEMORY_SANITIZER
9693
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9694
    __msan_unpoison(&ngroups, sizeof(ngroups));
9695
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9696
#endif
9697
9698
0
    list = PyList_New(ngroups);
9699
0
    if (list == NULL) {
9700
0
        PyMem_Free(groups);
9701
0
        return NULL;
9702
0
    }
9703
9704
0
    for (i = 0; i < ngroups; i++) {
9705
#ifdef __APPLE__
9706
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9707
#else
9708
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9709
0
#endif
9710
0
        if (o == NULL) {
9711
0
            Py_DECREF(list);
9712
0
            PyMem_Free(groups);
9713
0
            return NULL;
9714
0
        }
9715
0
        PyList_SET_ITEM(list, i, o);
9716
0
    }
9717
9718
0
    PyMem_Free(groups);
9719
9720
0
    return list;
9721
0
}
9722
#endif /* HAVE_GETGROUPLIST */
9723
9724
9725
#ifdef HAVE_GETGROUPS
9726
/*[clinic input]
9727
os.getgroups
9728
9729
Return list of supplemental group IDs for the process.
9730
[clinic start generated code]*/
9731
9732
static PyObject *
9733
os_getgroups_impl(PyObject *module)
9734
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9735
0
{
9736
    // Call getgroups with length 0 to get the actual number of groups
9737
0
    int n = getgroups(0, NULL);
9738
0
    if (n < 0) {
9739
0
        return posix_error();
9740
0
    }
9741
9742
0
    if (n == 0) {
9743
0
        return PyList_New(0);
9744
0
    }
9745
9746
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9747
0
    if (grouplist == NULL) {
9748
0
        return PyErr_NoMemory();
9749
0
    }
9750
9751
0
    n = getgroups(n, grouplist);
9752
0
    if (n == -1) {
9753
0
        posix_error();
9754
0
        PyMem_Free(grouplist);
9755
0
        return NULL;
9756
0
    }
9757
9758
0
    PyObject *result = PyList_New(n);
9759
0
    if (result == NULL) {
9760
0
        goto error;
9761
0
    }
9762
9763
0
    for (int i = 0; i < n; ++i) {
9764
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9765
0
        if (group == NULL) {
9766
0
            goto error;
9767
0
        }
9768
0
        PyList_SET_ITEM(result, i, group);
9769
0
    }
9770
0
    PyMem_Free(grouplist);
9771
9772
0
    return result;
9773
9774
0
error:
9775
0
    PyMem_Free(grouplist);
9776
0
    Py_XDECREF(result);
9777
0
    return NULL;
9778
0
}
9779
#endif /* HAVE_GETGROUPS */
9780
9781
#ifdef HAVE_INITGROUPS
9782
#ifdef __APPLE__
9783
/*[clinic input]
9784
os.initgroups
9785
9786
    username as oname: unicode_fs_encoded
9787
    gid: int
9788
    /
9789
9790
Initialize the group access list.
9791
9792
Call the system initgroups() to initialize the group access list with all of
9793
the groups of which the specified username is a member, plus the specified
9794
group id.
9795
[clinic start generated code]*/
9796
9797
static PyObject *
9798
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9799
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9800
#else
9801
/*[clinic input]
9802
os.initgroups
9803
9804
    username as oname: unicode_fs_encoded
9805
    gid: gid_t
9806
    /
9807
9808
Initialize the group access list.
9809
9810
Call the system initgroups() to initialize the group access list with all of
9811
the groups of which the specified username is a member, plus the specified
9812
group id.
9813
[clinic start generated code]*/
9814
9815
static PyObject *
9816
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9817
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9818
#endif
9819
0
{
9820
0
    const char *username = PyBytes_AS_STRING(oname);
9821
9822
0
    if (initgroups(username, gid) == -1)
9823
0
        return PyErr_SetFromErrno(PyExc_OSError);
9824
9825
0
    Py_RETURN_NONE;
9826
0
}
9827
#endif /* HAVE_INITGROUPS */
9828
9829
9830
#ifdef HAVE_GETPGID
9831
/*[clinic input]
9832
os.getpgid
9833
9834
    pid: pid_t
9835
9836
Call the system call getpgid(), and return the result.
9837
[clinic start generated code]*/
9838
9839
static PyObject *
9840
os_getpgid_impl(PyObject *module, pid_t pid)
9841
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9842
0
{
9843
0
    pid_t pgid = getpgid(pid);
9844
0
    if (pgid < 0)
9845
0
        return posix_error();
9846
0
    return PyLong_FromPid(pgid);
9847
0
}
9848
#endif /* HAVE_GETPGID */
9849
9850
9851
#ifdef HAVE_GETPGRP
9852
/*[clinic input]
9853
os.getpgrp
9854
9855
Return the current process group id.
9856
[clinic start generated code]*/
9857
9858
static PyObject *
9859
os_getpgrp_impl(PyObject *module)
9860
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9861
0
{
9862
#ifdef GETPGRP_HAVE_ARG
9863
    return PyLong_FromPid(getpgrp(0));
9864
#else /* GETPGRP_HAVE_ARG */
9865
0
    return PyLong_FromPid(getpgrp());
9866
0
#endif /* GETPGRP_HAVE_ARG */
9867
0
}
9868
#endif /* HAVE_GETPGRP */
9869
9870
9871
#ifdef HAVE_SETPGRP
9872
/*[clinic input]
9873
os.setpgrp
9874
9875
Make the current process the leader of its process group.
9876
[clinic start generated code]*/
9877
9878
static PyObject *
9879
os_setpgrp_impl(PyObject *module)
9880
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9881
0
{
9882
#ifdef SETPGRP_HAVE_ARG
9883
    if (setpgrp(0, 0) < 0)
9884
#else /* SETPGRP_HAVE_ARG */
9885
0
    if (setpgrp() < 0)
9886
0
#endif /* SETPGRP_HAVE_ARG */
9887
0
        return posix_error();
9888
0
    Py_RETURN_NONE;
9889
0
}
9890
#endif /* HAVE_SETPGRP */
9891
9892
#ifdef HAVE_GETPPID
9893
9894
#ifdef MS_WINDOWS
9895
#include <winternl.h>
9896
#include <ProcessSnapshot.h>
9897
9898
// The structure definition in winternl.h may be incomplete.
9899
// This structure is the full version from the MSDN documentation.
9900
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9901
    NTSTATUS ExitStatus;
9902
    PVOID PebBaseAddress;
9903
    ULONG_PTR AffinityMask;
9904
    LONG BasePriority;
9905
    ULONG_PTR UniqueProcessId;
9906
    ULONG_PTR InheritedFromUniqueProcessId;
9907
} PROCESS_BASIC_INFORMATION_FULL;
9908
9909
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9910
    IN    HANDLE           ProcessHandle,
9911
    IN    PROCESSINFOCLASS ProcessInformationClass,
9912
    OUT   PVOID            ProcessInformation,
9913
    IN    ULONG            ProcessInformationLength,
9914
    OUT   PULONG           ReturnLength OPTIONAL);
9915
9916
// This function returns the process ID of the parent process.
9917
// Returns 0 on failure.
9918
static ULONG
9919
win32_getppid_fast(void)
9920
{
9921
    NTSTATUS status;
9922
    HMODULE ntdll;
9923
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9924
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9925
    static ULONG cached_ppid = 0;
9926
9927
    if (cached_ppid) {
9928
        // No need to query the kernel again.
9929
        return cached_ppid;
9930
    }
9931
9932
    ntdll = GetModuleHandleW(L"ntdll.dll");
9933
    if (!ntdll) {
9934
        return 0;
9935
    }
9936
9937
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9938
    if (!pNtQueryInformationProcess) {
9939
        return 0;
9940
    }
9941
9942
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9943
                                        ProcessBasicInformation,
9944
                                        &basic_information,
9945
                                        sizeof(basic_information),
9946
                                        NULL);
9947
9948
    if (!NT_SUCCESS(status)) {
9949
        return 0;
9950
    }
9951
9952
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9953
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9954
    // zero and (ULONG) -1.
9955
9956
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9957
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9958
    {
9959
        return 0;
9960
    }
9961
9962
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9963
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9964
    // process. This process ID will be correctly returned even if the parent process has
9965
    // exited or been terminated.
9966
9967
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9968
    return cached_ppid;
9969
}
9970
9971
static PyObject*
9972
win32_getppid(void)
9973
{
9974
    DWORD error;
9975
    PyObject* result = NULL;
9976
    HANDLE process = GetCurrentProcess();
9977
    HPSS snapshot = NULL;
9978
    ULONG pid;
9979
9980
    pid = win32_getppid_fast();
9981
    if (pid != 0) {
9982
        return PyLong_FromUnsignedLong(pid);
9983
    }
9984
9985
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9986
9987
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9988
    if (error != ERROR_SUCCESS) {
9989
        return PyErr_SetFromWindowsErr(error);
9990
    }
9991
9992
    PSS_PROCESS_INFORMATION info;
9993
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
9994
                             sizeof(info));
9995
    if (error == ERROR_SUCCESS) {
9996
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
9997
    }
9998
    else {
9999
        result = PyErr_SetFromWindowsErr(error);
10000
    }
10001
10002
    PssFreeSnapshot(process, snapshot);
10003
    return result;
10004
}
10005
#endif /*MS_WINDOWS*/
10006
10007
10008
/*[clinic input]
10009
os.getppid
10010
10011
Return the parent's process id.
10012
10013
If the parent process has already exited, Windows machines will still
10014
return its id; others systems will return the id of the 'init' process (1).
10015
[clinic start generated code]*/
10016
10017
static PyObject *
10018
os_getppid_impl(PyObject *module)
10019
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
10020
0
{
10021
#ifdef MS_WINDOWS
10022
    return win32_getppid();
10023
#else
10024
0
    return PyLong_FromPid(getppid());
10025
0
#endif
10026
0
}
10027
#endif /* HAVE_GETPPID */
10028
10029
10030
#ifdef HAVE_GETLOGIN
10031
/*[clinic input]
10032
os.getlogin
10033
10034
Return the actual login name.
10035
[clinic start generated code]*/
10036
10037
static PyObject *
10038
os_getlogin_impl(PyObject *module)
10039
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10040
0
{
10041
0
    PyObject *result = NULL;
10042
#ifdef MS_WINDOWS
10043
    wchar_t user_name[UNLEN + 1];
10044
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10045
10046
    if (GetUserNameW(user_name, &num_chars)) {
10047
        /* num_chars is the number of unicode chars plus null terminator */
10048
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10049
    }
10050
    else
10051
        result = PyErr_SetFromWindowsErr(GetLastError());
10052
#elif defined (HAVE_GETLOGIN_R)
10053
# if defined (HAVE_MAXLOGNAME)
10054
    char name[MAXLOGNAME + 1];
10055
# elif defined (HAVE_UT_NAMESIZE)
10056
    char name[UT_NAMESIZE + 1];
10057
# else
10058
    char name[256];
10059
# endif
10060
0
    int err = getlogin_r(name, sizeof(name));
10061
0
    if (err) {
10062
0
        int old_errno = errno;
10063
0
        errno = err;
10064
0
        posix_error();
10065
0
        errno = old_errno;
10066
0
    }
10067
0
    else {
10068
0
        result = PyUnicode_DecodeFSDefault(name);
10069
0
    }
10070
#else
10071
    char *name;
10072
    int old_errno = errno;
10073
10074
    errno = 0;
10075
    name = getlogin();
10076
    if (name == NULL) {
10077
        if (errno)
10078
            posix_error();
10079
        else
10080
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10081
    }
10082
    else
10083
        result = PyUnicode_DecodeFSDefault(name);
10084
    errno = old_errno;
10085
#endif
10086
0
    return result;
10087
0
}
10088
#endif /* HAVE_GETLOGIN */
10089
10090
10091
#ifdef HAVE_GETUID
10092
/*[clinic input]
10093
os.getuid
10094
10095
Return the current process's user id.
10096
[clinic start generated code]*/
10097
10098
static PyObject *
10099
os_getuid_impl(PyObject *module)
10100
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10101
32
{
10102
32
    return _PyLong_FromUid(getuid());
10103
32
}
10104
#endif /* HAVE_GETUID */
10105
10106
10107
#ifdef MS_WINDOWS
10108
#define HAVE_KILL
10109
#endif /* MS_WINDOWS */
10110
10111
#ifdef HAVE_KILL
10112
/*[clinic input]
10113
os.kill
10114
10115
    pid: pid_t
10116
    signal: Py_ssize_t
10117
    /
10118
10119
Kill a process with a signal.
10120
[clinic start generated code]*/
10121
10122
static PyObject *
10123
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10124
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10125
0
{
10126
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10127
0
        return NULL;
10128
0
    }
10129
0
#ifndef MS_WINDOWS
10130
0
    if (kill(pid, (int)signal) == -1) {
10131
0
        return posix_error();
10132
0
    }
10133
10134
    // Check immediately if the signal was sent to the current process.
10135
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10136
    // is cheap.
10137
0
    if (PyErr_CheckSignals()) {
10138
0
        return NULL;
10139
0
    }
10140
10141
0
    Py_RETURN_NONE;
10142
#else /* !MS_WINDOWS */
10143
    DWORD sig = (DWORD)signal;
10144
10145
#ifdef HAVE_WINDOWS_CONSOLE_IO
10146
    /* Console processes which share a common console can be sent CTRL+C or
10147
       CTRL+BREAK events, provided they handle said events. */
10148
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10149
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10150
            return PyErr_SetFromWindowsErr(0);
10151
        }
10152
        Py_RETURN_NONE;
10153
    }
10154
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10155
10156
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10157
       attempt to open and terminate the process. */
10158
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10159
    if (handle == NULL) {
10160
        return PyErr_SetFromWindowsErr(0);
10161
    }
10162
10163
    BOOL res = TerminateProcess(handle, sig);
10164
    CloseHandle(handle);
10165
    if (res == 0) {
10166
        return PyErr_SetFromWindowsErr(0);
10167
    }
10168
10169
    Py_RETURN_NONE;
10170
#endif /* !MS_WINDOWS */
10171
0
}
10172
#endif /* HAVE_KILL */
10173
10174
10175
#ifdef HAVE_KILLPG
10176
/*[clinic input]
10177
os.killpg
10178
10179
    pgid: pid_t
10180
    signal: int
10181
    /
10182
10183
Kill a process group with a signal.
10184
[clinic start generated code]*/
10185
10186
static PyObject *
10187
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10188
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10189
0
{
10190
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10191
0
        return NULL;
10192
0
    }
10193
    /* XXX some man pages make the `pgid` parameter an int, others
10194
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10195
       take the same type. Moreover, pid_t is always at least as wide as
10196
       int (else compilation of this module fails), which is safe. */
10197
0
    if (killpg(pgid, signal) == -1)
10198
0
        return posix_error();
10199
0
    Py_RETURN_NONE;
10200
0
}
10201
#endif /* HAVE_KILLPG */
10202
10203
10204
#ifdef HAVE_PLOCK
10205
#ifdef HAVE_SYS_LOCK_H
10206
#include <sys/lock.h>
10207
#endif
10208
10209
/*[clinic input]
10210
os.plock
10211
    op: int
10212
    /
10213
10214
Lock program segments into memory.");
10215
[clinic start generated code]*/
10216
10217
static PyObject *
10218
os_plock_impl(PyObject *module, int op)
10219
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10220
{
10221
    if (plock(op) == -1)
10222
        return posix_error();
10223
    Py_RETURN_NONE;
10224
}
10225
#endif /* HAVE_PLOCK */
10226
10227
10228
#ifdef HAVE_SETUID
10229
/*[clinic input]
10230
os.setuid
10231
10232
    uid: uid_t
10233
    /
10234
10235
Set the current process's user id.
10236
[clinic start generated code]*/
10237
10238
static PyObject *
10239
os_setuid_impl(PyObject *module, uid_t uid)
10240
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10241
0
{
10242
0
    if (setuid(uid) < 0)
10243
0
        return posix_error();
10244
0
    Py_RETURN_NONE;
10245
0
}
10246
#endif /* HAVE_SETUID */
10247
10248
10249
#ifdef HAVE_SETEUID
10250
/*[clinic input]
10251
os.seteuid
10252
10253
    euid: uid_t
10254
    /
10255
10256
Set the current process's effective user id.
10257
[clinic start generated code]*/
10258
10259
static PyObject *
10260
os_seteuid_impl(PyObject *module, uid_t euid)
10261
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10262
0
{
10263
0
    if (seteuid(euid) < 0)
10264
0
        return posix_error();
10265
0
    Py_RETURN_NONE;
10266
0
}
10267
#endif /* HAVE_SETEUID */
10268
10269
10270
#ifdef HAVE_SETEGID
10271
/*[clinic input]
10272
os.setegid
10273
10274
    egid: gid_t
10275
    /
10276
10277
Set the current process's effective group id.
10278
[clinic start generated code]*/
10279
10280
static PyObject *
10281
os_setegid_impl(PyObject *module, gid_t egid)
10282
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10283
0
{
10284
0
    if (setegid(egid) < 0)
10285
0
        return posix_error();
10286
0
    Py_RETURN_NONE;
10287
0
}
10288
#endif /* HAVE_SETEGID */
10289
10290
10291
#ifdef HAVE_SETREUID
10292
/*[clinic input]
10293
os.setreuid
10294
10295
    ruid: uid_t
10296
    euid: uid_t
10297
    /
10298
10299
Set the current process's real and effective user ids.
10300
[clinic start generated code]*/
10301
10302
static PyObject *
10303
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10304
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10305
0
{
10306
0
    if (setreuid(ruid, euid) < 0) {
10307
0
        return posix_error();
10308
0
    } else {
10309
0
        Py_RETURN_NONE;
10310
0
    }
10311
0
}
10312
#endif /* HAVE_SETREUID */
10313
10314
10315
#ifdef HAVE_SETREGID
10316
/*[clinic input]
10317
os.setregid
10318
10319
    rgid: gid_t
10320
    egid: gid_t
10321
    /
10322
10323
Set the current process's real and effective group ids.
10324
[clinic start generated code]*/
10325
10326
static PyObject *
10327
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10328
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10329
0
{
10330
0
    if (setregid(rgid, egid) < 0)
10331
0
        return posix_error();
10332
0
    Py_RETURN_NONE;
10333
0
}
10334
#endif /* HAVE_SETREGID */
10335
10336
10337
#ifdef HAVE_SETGID
10338
/*[clinic input]
10339
os.setgid
10340
    gid: gid_t
10341
    /
10342
10343
Set the current process's group id.
10344
[clinic start generated code]*/
10345
10346
static PyObject *
10347
os_setgid_impl(PyObject *module, gid_t gid)
10348
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10349
0
{
10350
0
    if (setgid(gid) < 0)
10351
0
        return posix_error();
10352
0
    Py_RETURN_NONE;
10353
0
}
10354
#endif /* HAVE_SETGID */
10355
10356
10357
#ifdef HAVE_SETGROUPS
10358
/*[clinic input]
10359
os.setgroups
10360
10361
    groups: object
10362
    /
10363
10364
Set the groups of the current process to list.
10365
[clinic start generated code]*/
10366
10367
static PyObject *
10368
os_setgroups(PyObject *module, PyObject *groups)
10369
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10370
0
{
10371
0
    if (!PySequence_Check(groups)) {
10372
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10373
0
        return NULL;
10374
0
    }
10375
0
    Py_ssize_t len = PySequence_Size(groups);
10376
0
    if (len < 0) {
10377
0
        return NULL;
10378
0
    }
10379
0
    if (len > MAX_GROUPS) {
10380
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10381
0
        return NULL;
10382
0
    }
10383
10384
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10385
0
    if (grouplist == NULL) {
10386
0
        PyErr_NoMemory();
10387
0
        return NULL;
10388
0
    }
10389
0
    for (Py_ssize_t i = 0; i < len; i++) {
10390
0
        PyObject *elem;
10391
0
        elem = PySequence_GetItem(groups, i);
10392
0
        if (!elem) {
10393
0
            PyMem_Free(grouplist);
10394
0
            return NULL;
10395
0
        }
10396
0
        if (!PyIndex_Check(elem)) {
10397
0
            PyErr_SetString(PyExc_TypeError,
10398
0
                            "groups must be integers");
10399
0
            Py_DECREF(elem);
10400
0
            PyMem_Free(grouplist);
10401
0
            return NULL;
10402
0
        } else {
10403
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10404
0
                Py_DECREF(elem);
10405
0
                PyMem_Free(grouplist);
10406
0
                return NULL;
10407
0
            }
10408
0
        }
10409
0
        Py_DECREF(elem);
10410
0
    }
10411
10412
0
    if (setgroups(len, grouplist) < 0) {
10413
0
        posix_error();
10414
0
        PyMem_Free(grouplist);
10415
0
        return NULL;
10416
0
    }
10417
0
    PyMem_Free(grouplist);
10418
0
    Py_RETURN_NONE;
10419
0
}
10420
#endif /* HAVE_SETGROUPS */
10421
10422
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10423
static PyObject *
10424
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10425
0
{
10426
0
    PyObject *result;
10427
0
    PyObject *struct_rusage;
10428
10429
0
    if (pid == -1)
10430
0
        return posix_error();
10431
10432
    // If wait succeeded but no child was ready to report status, ru will not
10433
    // have been populated.
10434
0
    if (pid == 0) {
10435
0
        memset(ru, 0, sizeof(*ru));
10436
0
    }
10437
10438
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10439
0
    if (struct_rusage == NULL)
10440
0
        return NULL;
10441
10442
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10443
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10444
0
    Py_DECREF(struct_rusage);
10445
0
    if (!result)
10446
0
        return NULL;
10447
10448
0
    int pos = 0;
10449
10450
0
#ifndef doubletime
10451
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10452
0
#endif
10453
10454
0
#define SET_RESULT(CALL)                                     \
10455
0
    do {                                                     \
10456
0
        PyObject *item = (CALL);                             \
10457
0
        if (item == NULL) {                                  \
10458
0
            Py_DECREF(result);                               \
10459
0
            return NULL;                                     \
10460
0
        }                                                    \
10461
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10462
0
    } while(0)
10463
10464
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10465
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10466
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10467
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10468
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10469
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10470
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10471
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10472
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10473
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10474
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10475
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10476
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10477
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10478
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10479
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10480
0
#undef SET_RESULT
10481
10482
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10483
0
}
10484
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10485
10486
10487
#ifdef HAVE_WAIT3
10488
/*[clinic input]
10489
os.wait3
10490
10491
    options: int
10492
Wait for completion of a child process.
10493
10494
Returns a tuple of information about the child process:
10495
  (pid, status, rusage)
10496
[clinic start generated code]*/
10497
10498
static PyObject *
10499
os_wait3_impl(PyObject *module, int options)
10500
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10501
0
{
10502
0
    pid_t pid;
10503
0
    struct rusage ru;
10504
0
    int async_err = 0;
10505
0
    WAIT_TYPE status;
10506
0
    WAIT_STATUS_INT(status) = 0;
10507
10508
0
    do {
10509
0
        Py_BEGIN_ALLOW_THREADS
10510
0
        pid = wait3(&status, options, &ru);
10511
0
        Py_END_ALLOW_THREADS
10512
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10513
0
    if (pid < 0)
10514
0
        return (!async_err) ? posix_error() : NULL;
10515
10516
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10517
0
}
10518
#endif /* HAVE_WAIT3 */
10519
10520
10521
#ifdef HAVE_WAIT4
10522
/*[clinic input]
10523
10524
os.wait4
10525
10526
    pid: pid_t
10527
    options: int
10528
10529
Wait for completion of a specific child process.
10530
10531
Returns a tuple of information about the child process:
10532
  (pid, status, rusage)
10533
[clinic start generated code]*/
10534
10535
static PyObject *
10536
os_wait4_impl(PyObject *module, pid_t pid, int options)
10537
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10538
0
{
10539
0
    pid_t res;
10540
0
    struct rusage ru;
10541
0
    int async_err = 0;
10542
0
    WAIT_TYPE status;
10543
0
    WAIT_STATUS_INT(status) = 0;
10544
10545
0
    do {
10546
0
        Py_BEGIN_ALLOW_THREADS
10547
0
        res = wait4(pid, &status, options, &ru);
10548
0
        Py_END_ALLOW_THREADS
10549
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10550
0
    if (res < 0)
10551
0
        return (!async_err) ? posix_error() : NULL;
10552
10553
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10554
0
}
10555
#endif /* HAVE_WAIT4 */
10556
10557
10558
#if defined(HAVE_WAITID)
10559
/*[clinic input]
10560
os.waitid
10561
10562
    idtype: idtype_t
10563
        Must be one of be P_PID, P_PGID or P_ALL.
10564
    id: id_t
10565
        The id to wait on.
10566
    options: int
10567
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10568
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10569
    /
10570
10571
Returns the result of waiting for a process or processes.
10572
10573
Returns either waitid_result or None if WNOHANG is specified and there are
10574
no children in a waitable state.
10575
[clinic start generated code]*/
10576
10577
static PyObject *
10578
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10579
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10580
0
{
10581
0
    PyObject *result;
10582
0
    int res;
10583
0
    int async_err = 0;
10584
0
    siginfo_t si;
10585
0
    si.si_pid = 0;
10586
10587
0
    do {
10588
0
        Py_BEGIN_ALLOW_THREADS
10589
0
        res = waitid(idtype, id, &si, options);
10590
0
        Py_END_ALLOW_THREADS
10591
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10592
0
    if (res < 0)
10593
0
        return (!async_err) ? posix_error() : NULL;
10594
10595
0
    if (si.si_pid == 0)
10596
0
        Py_RETURN_NONE;
10597
10598
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10599
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10600
0
    if (!result)
10601
0
        return NULL;
10602
10603
0
    int pos = 0;
10604
10605
0
#define SET_RESULT(CALL)                                     \
10606
0
    do {                                                     \
10607
0
        PyObject *item = (CALL);                             \
10608
0
        if (item == NULL) {                                  \
10609
0
            Py_DECREF(result);                               \
10610
0
            return NULL;                                     \
10611
0
        }                                                    \
10612
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10613
0
    } while(0)
10614
10615
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10616
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10617
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10618
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10619
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10620
10621
0
#undef SET_RESULT
10622
10623
0
    return result;
10624
0
}
10625
#endif /* defined(HAVE_WAITID) */
10626
10627
10628
#if defined(HAVE_WAITPID)
10629
/*[clinic input]
10630
os.waitpid
10631
    pid: pid_t
10632
    options: int
10633
    /
10634
10635
Wait for completion of a given child process.
10636
10637
Returns a tuple of information regarding the child process:
10638
    (pid, status)
10639
10640
The options argument is ignored on Windows.
10641
[clinic start generated code]*/
10642
10643
static PyObject *
10644
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10645
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10646
0
{
10647
0
    pid_t res;
10648
0
    int async_err = 0;
10649
0
    WAIT_TYPE status;
10650
0
    WAIT_STATUS_INT(status) = 0;
10651
10652
0
    do {
10653
0
        Py_BEGIN_ALLOW_THREADS
10654
0
        res = waitpid(pid, &status, options);
10655
0
        Py_END_ALLOW_THREADS
10656
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10657
0
    if (res < 0)
10658
0
        return (!async_err) ? posix_error() : NULL;
10659
10660
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10661
0
}
10662
#elif defined(HAVE_CWAIT)
10663
/* MS C has a variant of waitpid() that's usable for most purposes. */
10664
/*[clinic input]
10665
os.waitpid
10666
    pid: intptr_t
10667
    options: int
10668
    /
10669
10670
Wait for completion of a given process.
10671
10672
Returns a tuple of information regarding the process:
10673
    (pid, status << 8)
10674
10675
The options argument is ignored on Windows.
10676
[clinic start generated code]*/
10677
10678
static PyObject *
10679
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10680
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10681
{
10682
    int status;
10683
    intptr_t res;
10684
    int async_err = 0;
10685
10686
    do {
10687
        Py_BEGIN_ALLOW_THREADS
10688
        _Py_BEGIN_SUPPRESS_IPH
10689
        res = _cwait(&status, pid, options);
10690
        _Py_END_SUPPRESS_IPH
10691
        Py_END_ALLOW_THREADS
10692
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10693
    if (res < 0)
10694
        return (!async_err) ? posix_error() : NULL;
10695
10696
    unsigned long long ustatus = (unsigned int)status;
10697
10698
    /* shift the status left a byte so this is more like the POSIX waitpid */
10699
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10700
}
10701
#endif
10702
10703
10704
#ifdef HAVE_WAIT
10705
/*[clinic input]
10706
os.wait
10707
10708
Wait for completion of a child process.
10709
10710
Returns a tuple of information about the child process:
10711
    (pid, status)
10712
[clinic start generated code]*/
10713
10714
static PyObject *
10715
os_wait_impl(PyObject *module)
10716
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10717
0
{
10718
0
    pid_t pid;
10719
0
    int async_err = 0;
10720
0
    WAIT_TYPE status;
10721
0
    WAIT_STATUS_INT(status) = 0;
10722
10723
0
    do {
10724
0
        Py_BEGIN_ALLOW_THREADS
10725
0
        pid = wait(&status);
10726
0
        Py_END_ALLOW_THREADS
10727
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10728
0
    if (pid < 0)
10729
0
        return (!async_err) ? posix_error() : NULL;
10730
10731
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10732
0
}
10733
#endif /* HAVE_WAIT */
10734
10735
10736
// This system call always crashes on older Android versions.
10737
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10738
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10739
/*[clinic input]
10740
os.pidfd_open
10741
  pid: pid_t
10742
  flags: unsigned_int = 0
10743
10744
Return a file descriptor referring to the process *pid*.
10745
10746
The descriptor can be used to perform process management without races and
10747
signals.
10748
[clinic start generated code]*/
10749
10750
static PyObject *
10751
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10752
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10753
2
{
10754
2
    int fd = syscall(__NR_pidfd_open, pid, flags);
10755
2
    if (fd < 0) {
10756
0
        return posix_error();
10757
0
    }
10758
2
    return PyLong_FromLong(fd);
10759
2
}
10760
#endif
10761
10762
10763
#ifdef HAVE_SETNS
10764
/*[clinic input]
10765
os.setns
10766
  fd: fildes
10767
    A file descriptor to a namespace.
10768
  nstype: int = 0
10769
    Type of namespace.
10770
10771
Move the calling thread into different namespaces.
10772
[clinic start generated code]*/
10773
10774
static PyObject *
10775
os_setns_impl(PyObject *module, int fd, int nstype)
10776
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10777
0
{
10778
0
    int res;
10779
10780
0
    Py_BEGIN_ALLOW_THREADS
10781
0
    res = setns(fd, nstype);
10782
0
    Py_END_ALLOW_THREADS
10783
10784
0
    if (res != 0) {
10785
0
        return posix_error();
10786
0
    }
10787
10788
0
    Py_RETURN_NONE;
10789
0
}
10790
#endif
10791
10792
10793
#ifdef HAVE_UNSHARE
10794
/*[clinic input]
10795
os.unshare
10796
  flags: int
10797
    Namespaces to be unshared.
10798
10799
Disassociate parts of a process (or thread) execution context.
10800
[clinic start generated code]*/
10801
10802
static PyObject *
10803
os_unshare_impl(PyObject *module, int flags)
10804
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10805
0
{
10806
0
    int res;
10807
10808
0
    Py_BEGIN_ALLOW_THREADS
10809
0
    res = unshare(flags);
10810
0
    Py_END_ALLOW_THREADS
10811
10812
0
    if (res != 0) {
10813
0
        return posix_error();
10814
0
    }
10815
10816
0
    Py_RETURN_NONE;
10817
0
}
10818
#endif
10819
10820
10821
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10822
/*[clinic input]
10823
os.readlink
10824
10825
    path: path_t
10826
    *
10827
    dir_fd: dir_fd(requires='readlinkat') = None
10828
10829
Return a string representing the path to which the symbolic link points.
10830
10831
If dir_fd is not None, it should be a file descriptor open to a directory,
10832
and path should be relative; path will then be relative to that directory.
10833
10834
dir_fd may not be implemented on your platform.  If it is unavailable,
10835
using it will raise a NotImplementedError.
10836
[clinic start generated code]*/
10837
10838
static PyObject *
10839
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10840
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10841
2
{
10842
2
#if defined(HAVE_READLINK)
10843
2
    char buffer[MAXPATHLEN+1];
10844
2
    ssize_t length;
10845
2
#ifdef HAVE_READLINKAT
10846
2
    int readlinkat_unavailable = 0;
10847
2
#endif
10848
10849
2
    Py_BEGIN_ALLOW_THREADS
10850
2
#ifdef HAVE_READLINKAT
10851
2
    if (dir_fd != DEFAULT_DIR_FD) {
10852
0
        if (HAVE_READLINKAT_RUNTIME) {
10853
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10854
0
        } else {
10855
0
            readlinkat_unavailable = 1;
10856
0
        }
10857
0
    } else
10858
2
#endif
10859
2
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10860
2
    Py_END_ALLOW_THREADS
10861
10862
2
#ifdef HAVE_READLINKAT
10863
2
    if (readlinkat_unavailable) {
10864
0
        argument_unavailable_error(NULL, "dir_fd");
10865
0
        return NULL;
10866
0
    }
10867
2
#endif
10868
10869
2
    if (length < 0) {
10870
0
        return path_error(path);
10871
0
    }
10872
2
    buffer[length] = '\0';
10873
10874
2
    if (PyUnicode_Check(path->object))
10875
2
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10876
0
    else
10877
0
        return PyBytes_FromStringAndSize(buffer, length);
10878
#elif defined(MS_WINDOWS)
10879
    DWORD n_bytes_returned;
10880
    DWORD io_result = 0;
10881
    HANDLE reparse_point_handle;
10882
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10883
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10884
    PyObject *result = NULL;
10885
10886
    /* First get a handle to the reparse point */
10887
    Py_BEGIN_ALLOW_THREADS
10888
    reparse_point_handle = CreateFileW(
10889
        path->wide,
10890
        0,
10891
        0,
10892
        0,
10893
        OPEN_EXISTING,
10894
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10895
        0);
10896
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10897
        /* New call DeviceIoControl to read the reparse point */
10898
        io_result = DeviceIoControl(
10899
            reparse_point_handle,
10900
            FSCTL_GET_REPARSE_POINT,
10901
            0, 0, /* in buffer */
10902
            target_buffer, sizeof(target_buffer),
10903
            &n_bytes_returned,
10904
            0 /* we're not using OVERLAPPED_IO */
10905
            );
10906
        CloseHandle(reparse_point_handle);
10907
    }
10908
    Py_END_ALLOW_THREADS
10909
10910
    if (io_result == 0) {
10911
        return path_error(path);
10912
    }
10913
10914
    wchar_t *name = NULL;
10915
    Py_ssize_t nameLen = 0;
10916
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10917
    {
10918
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10919
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10920
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10921
    }
10922
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10923
    {
10924
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10925
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10926
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10927
    }
10928
    else
10929
    {
10930
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10931
    }
10932
    if (name) {
10933
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10934
            /* Our buffer is mutable, so this is okay */
10935
            name[1] = L'\\';
10936
        }
10937
        result = PyUnicode_FromWideChar(name, nameLen);
10938
        if (result && PyBytes_Check(path->object)) {
10939
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10940
        }
10941
    }
10942
    return result;
10943
#endif
10944
2
}
10945
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10946
10947
#if defined(MS_WINDOWS)
10948
10949
/* Remove the last portion of the path - return 0 on success */
10950
static int
10951
_dirnameW(WCHAR *path)
10952
{
10953
    WCHAR *ptr;
10954
    size_t length = wcsnlen_s(path, MAX_PATH);
10955
    if (length == MAX_PATH) {
10956
        return -1;
10957
    }
10958
10959
    /* walk the path from the end until a backslash is encountered */
10960
    for(ptr = path + length; ptr != path; ptr--) {
10961
        if (*ptr == L'\\' || *ptr == L'/') {
10962
            break;
10963
        }
10964
    }
10965
    *ptr = 0;
10966
    return 0;
10967
}
10968
10969
#endif
10970
10971
#ifdef HAVE_SYMLINK
10972
10973
#if defined(MS_WINDOWS)
10974
10975
/* Is this path absolute? */
10976
static int
10977
_is_absW(const WCHAR *path)
10978
{
10979
    return path[0] == L'\\' || path[0] == L'/' ||
10980
        (path[0] && path[1] == L':');
10981
}
10982
10983
/* join root and rest with a backslash - return 0 on success */
10984
static int
10985
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10986
{
10987
    if (_is_absW(rest)) {
10988
        return wcscpy_s(dest_path, MAX_PATH, rest);
10989
    }
10990
10991
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
10992
        return -1;
10993
    }
10994
10995
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
10996
        return -1;
10997
    }
10998
10999
    return wcscat_s(dest_path, MAX_PATH, rest);
11000
}
11001
11002
/* Return True if the path at src relative to dest is a directory */
11003
static int
11004
_check_dirW(LPCWSTR src, LPCWSTR dest)
11005
{
11006
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11007
    WCHAR dest_parent[MAX_PATH];
11008
    WCHAR src_resolved[MAX_PATH] = L"";
11009
11010
    /* dest_parent = os.path.dirname(dest) */
11011
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11012
        _dirnameW(dest_parent)) {
11013
        return 0;
11014
    }
11015
    /* src_resolved = os.path.join(dest_parent, src) */
11016
    if (_joinW(src_resolved, dest_parent, src)) {
11017
        return 0;
11018
    }
11019
    return (
11020
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11021
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11022
    );
11023
}
11024
#endif
11025
11026
11027
/*[clinic input]
11028
os.symlink
11029
    src: path_t
11030
    dst: path_t
11031
    target_is_directory: bool = False
11032
    *
11033
    dir_fd: dir_fd(requires='symlinkat')=None
11034
11035
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
11036
11037
Create a symbolic link pointing to src named dst.
11038
11039
target_is_directory is required on Windows if the target is to be
11040
  interpreted as a directory.  (On Windows, symlink requires
11041
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
11042
  target_is_directory is ignored on non-Windows platforms.
11043
11044
If dir_fd is not None, it should be a file descriptor open to a directory,
11045
  and path should be relative; path will then be relative to that directory.
11046
dir_fd may not be implemented on your platform.
11047
  If it is unavailable, using it will raise a NotImplementedError.
11048
11049
[clinic start generated code]*/
11050
11051
static PyObject *
11052
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11053
                int target_is_directory, int dir_fd)
11054
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
11055
0
{
11056
#ifdef MS_WINDOWS
11057
    DWORD result;
11058
    DWORD flags = 0;
11059
11060
    /* Assumed true, set to false if detected to not be available. */
11061
    static int windows_has_symlink_unprivileged_flag = TRUE;
11062
#else
11063
0
    int result;
11064
0
#ifdef HAVE_SYMLINKAT
11065
0
    int symlinkat_unavailable = 0;
11066
0
#endif
11067
0
#endif
11068
11069
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11070
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11071
0
        return NULL;
11072
0
    }
11073
11074
#ifdef MS_WINDOWS
11075
11076
    if (windows_has_symlink_unprivileged_flag) {
11077
        /* Allow non-admin symlinks if system allows it. */
11078
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11079
    }
11080
11081
    Py_BEGIN_ALLOW_THREADS
11082
    _Py_BEGIN_SUPPRESS_IPH
11083
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11084
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11085
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11086
    }
11087
11088
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11089
    _Py_END_SUPPRESS_IPH
11090
    Py_END_ALLOW_THREADS
11091
11092
    if (windows_has_symlink_unprivileged_flag && !result &&
11093
        ERROR_INVALID_PARAMETER == GetLastError()) {
11094
11095
        Py_BEGIN_ALLOW_THREADS
11096
        _Py_BEGIN_SUPPRESS_IPH
11097
        /* This error might be caused by
11098
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11099
        Try again, and update windows_has_symlink_unprivileged_flag if we
11100
        are successful this time.
11101
11102
        NOTE: There is a risk of a race condition here if there are other
11103
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11104
        another process (or thread) changes that condition in between our
11105
        calls to CreateSymbolicLink.
11106
        */
11107
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11108
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11109
        _Py_END_SUPPRESS_IPH
11110
        Py_END_ALLOW_THREADS
11111
11112
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11113
            windows_has_symlink_unprivileged_flag = FALSE;
11114
        }
11115
    }
11116
11117
    if (!result)
11118
        return path_error2(src, dst);
11119
11120
#else
11121
11122
0
    Py_BEGIN_ALLOW_THREADS
11123
0
#ifdef HAVE_SYMLINKAT
11124
0
    if (dir_fd != DEFAULT_DIR_FD) {
11125
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11126
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11127
0
        } else {
11128
0
            symlinkat_unavailable = 1;
11129
0
        }
11130
0
    } else
11131
0
#endif
11132
0
        result = symlink(src->narrow, dst->narrow);
11133
0
    Py_END_ALLOW_THREADS
11134
11135
0
#ifdef HAVE_SYMLINKAT
11136
0
    if (symlinkat_unavailable) {
11137
0
          argument_unavailable_error(NULL, "dir_fd");
11138
0
          return NULL;
11139
0
    }
11140
0
#endif
11141
11142
0
    if (result)
11143
0
        return path_error2(src, dst);
11144
0
#endif
11145
11146
0
    Py_RETURN_NONE;
11147
0
}
11148
#endif /* HAVE_SYMLINK */
11149
11150
11151
static PyStructSequence_Field times_result_fields[] = {
11152
    {"user",    "user time"},
11153
    {"system",   "system time"},
11154
    {"children_user",    "user time of children"},
11155
    {"children_system",    "system time of children"},
11156
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11157
    {NULL}
11158
};
11159
11160
PyDoc_STRVAR(times_result__doc__,
11161
"times_result: Result from os.times().\n\n\
11162
This object may be accessed either as a tuple of\n\
11163
  (user, system, children_user, children_system, elapsed),\n\
11164
or via the attributes user, system, children_user, children_system,\n\
11165
and elapsed.\n\
11166
\n\
11167
See os.times for more information.");
11168
11169
static PyStructSequence_Desc times_result_desc = {
11170
    MODNAME ".times_result", /* name */
11171
    times_result__doc__, /* doc */
11172
    times_result_fields,
11173
    5
11174
};
11175
11176
static PyObject *
11177
build_times_result(PyObject *module, double user, double system,
11178
    double children_user, double children_system,
11179
    double elapsed)
11180
0
{
11181
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11182
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11183
0
    if (value == NULL)
11184
0
        return NULL;
11185
11186
0
#define SET(i, field) \
11187
0
    { \
11188
0
    PyObject *o = PyFloat_FromDouble(field); \
11189
0
    if (!o) { \
11190
0
        Py_DECREF(value); \
11191
0
        return NULL; \
11192
0
    } \
11193
0
    PyStructSequence_SET_ITEM(value, i, o); \
11194
0
    } \
11195
0
11196
0
    SET(0, user);
11197
0
    SET(1, system);
11198
0
    SET(2, children_user);
11199
0
    SET(3, children_system);
11200
0
    SET(4, elapsed);
11201
11202
0
#undef SET
11203
11204
0
    return value;
11205
0
}
11206
11207
11208
/*[clinic input]
11209
os.times
11210
11211
Return a collection containing process timing information.
11212
11213
The object returned behaves like a named tuple with these fields:
11214
  (utime, stime, cutime, cstime, elapsed_time)
11215
All fields are floating-point numbers.
11216
[clinic start generated code]*/
11217
11218
static PyObject *
11219
os_times_impl(PyObject *module)
11220
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11221
0
{
11222
#ifdef MS_WINDOWS
11223
    FILETIME create, exit, kernel, user;
11224
    HANDLE hProc;
11225
    hProc = GetCurrentProcess();
11226
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11227
    /* The fields of a FILETIME structure are the hi and lo part
11228
       of a 64-bit value expressed in 100 nanosecond units.
11229
       1e7 is one second in such units; 1e-7 the inverse.
11230
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11231
    */
11232
    return build_times_result(module,
11233
        (double)(user.dwHighDateTime*429.4967296 +
11234
                 user.dwLowDateTime*1e-7),
11235
        (double)(kernel.dwHighDateTime*429.4967296 +
11236
                 kernel.dwLowDateTime*1e-7),
11237
        (double)0,
11238
        (double)0,
11239
        (double)0);
11240
#else /* MS_WINDOWS */
11241
0
    _posixstate *state = get_posix_state(module);
11242
0
    long ticks_per_second = state->ticks_per_second;
11243
11244
0
    struct tms process;
11245
0
    clock_t elapsed;
11246
0
    errno = 0;
11247
0
    elapsed = times(&process);
11248
0
    if (elapsed == (clock_t) -1) {
11249
0
        return posix_error();
11250
0
    }
11251
11252
0
    return build_times_result(module,
11253
0
        (double)process.tms_utime / ticks_per_second,
11254
0
        (double)process.tms_stime / ticks_per_second,
11255
0
        (double)process.tms_cutime / ticks_per_second,
11256
0
        (double)process.tms_cstime / ticks_per_second,
11257
0
        (double)elapsed / ticks_per_second);
11258
0
#endif /* MS_WINDOWS */
11259
0
}
11260
11261
11262
#if defined(HAVE_TIMERFD_CREATE)
11263
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11264
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11265
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11266
11267
static PyObject *
11268
build_itimerspec(const struct itimerspec* curr_value)
11269
0
{
11270
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11271
0
                                                          curr_value->it_value.tv_nsec);
11272
0
    PyObject *value = PyFloat_FromDouble(_value);
11273
0
    if (value == NULL) {
11274
0
        return NULL;
11275
0
    }
11276
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11277
0
                                                   curr_value->it_interval.tv_nsec);
11278
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11279
0
    if (interval == NULL) {
11280
0
        Py_DECREF(value);
11281
0
        return NULL;
11282
0
    }
11283
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
11284
0
    Py_DECREF(interval);
11285
0
    Py_DECREF(value);
11286
0
    return tuple;
11287
0
}
11288
11289
static PyObject *
11290
build_itimerspec_ns(const struct itimerspec* curr_value)
11291
0
{
11292
0
    PyTime_t value, interval;
11293
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11294
0
        return NULL;
11295
0
    }
11296
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11297
0
        return NULL;
11298
0
    }
11299
0
    return Py_BuildValue("LL", value, interval);
11300
0
}
11301
11302
/*[clinic input]
11303
os.timerfd_create
11304
11305
    clockid: int
11306
        A valid clock ID constant as timer file descriptor.
11307
11308
        time.CLOCK_REALTIME
11309
        time.CLOCK_MONOTONIC
11310
        time.CLOCK_BOOTTIME
11311
    /
11312
    *
11313
    flags: int = 0
11314
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11315
11316
        os.TFD_NONBLOCK
11317
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11318
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11319
11320
        os.TFD_CLOEXEC
11321
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11322
11323
Create and return a timer file descriptor.
11324
[clinic start generated code]*/
11325
11326
static PyObject *
11327
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11328
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11329
11330
0
{
11331
0
    int fd;
11332
0
    Py_BEGIN_ALLOW_THREADS
11333
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11334
0
    fd = timerfd_create(clockid, flags);
11335
0
    Py_END_ALLOW_THREADS
11336
0
    if (fd == -1) {
11337
0
        return PyErr_SetFromErrno(PyExc_OSError);
11338
0
    }
11339
0
    return PyLong_FromLong(fd);
11340
0
}
11341
11342
/*[clinic input]
11343
os.timerfd_settime
11344
11345
    fd: fildes
11346
        A timer file descriptor.
11347
    /
11348
    *
11349
    flags: int = 0
11350
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11351
    initial as initial_double: double = 0.0
11352
        The initial expiration time, in seconds.
11353
    interval as interval_double: double = 0.0
11354
        The timer's interval, in seconds.
11355
11356
Alter a timer file descriptor's internal timer in seconds.
11357
[clinic start generated code]*/
11358
11359
static PyObject *
11360
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11361
                        double initial_double, double interval_double)
11362
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11363
0
{
11364
0
    PyTime_t initial, interval;
11365
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11366
0
                                  &initial) < 0) {
11367
0
        return NULL;
11368
0
    }
11369
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11370
0
                                  &interval) < 0) {
11371
0
        return NULL;
11372
0
    }
11373
11374
0
    struct itimerspec new_value, old_value;
11375
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11376
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11377
0
        return NULL;
11378
0
    }
11379
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11380
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11381
0
        return NULL;
11382
0
    }
11383
11384
0
    int result;
11385
0
    Py_BEGIN_ALLOW_THREADS
11386
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11387
0
    Py_END_ALLOW_THREADS
11388
0
    if (result == -1) {
11389
0
        return PyErr_SetFromErrno(PyExc_OSError);
11390
0
    }
11391
0
    return build_itimerspec(&old_value);
11392
0
}
11393
11394
11395
/*[clinic input]
11396
os.timerfd_settime_ns
11397
11398
    fd: fildes
11399
        A timer file descriptor.
11400
    /
11401
    *
11402
    flags: int = 0
11403
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11404
    initial: long_long = 0
11405
        initial expiration timing in seconds.
11406
    interval: long_long = 0
11407
        interval for the timer in seconds.
11408
11409
Alter a timer file descriptor's internal timer in nanoseconds.
11410
[clinic start generated code]*/
11411
11412
static PyObject *
11413
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11414
                           long long initial, long long interval)
11415
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11416
0
{
11417
0
    struct itimerspec new_value;
11418
0
    struct itimerspec old_value;
11419
0
    int result;
11420
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11421
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11422
0
        return NULL;
11423
0
    }
11424
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11425
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11426
0
        return NULL;
11427
0
    }
11428
0
    Py_BEGIN_ALLOW_THREADS
11429
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11430
0
    Py_END_ALLOW_THREADS
11431
0
    if (result == -1) {
11432
0
        return PyErr_SetFromErrno(PyExc_OSError);
11433
0
    }
11434
0
    return build_itimerspec_ns(&old_value);
11435
0
}
11436
11437
/*[clinic input]
11438
@permit_long_summary
11439
os.timerfd_gettime
11440
11441
    fd: fildes
11442
        A timer file descriptor.
11443
    /
11444
11445
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11446
[clinic start generated code]*/
11447
11448
static PyObject *
11449
os_timerfd_gettime_impl(PyObject *module, int fd)
11450
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11451
0
{
11452
0
    struct itimerspec curr_value;
11453
0
    int result;
11454
0
    Py_BEGIN_ALLOW_THREADS
11455
0
    result = timerfd_gettime(fd, &curr_value);
11456
0
    Py_END_ALLOW_THREADS
11457
0
    if (result == -1) {
11458
0
        return PyErr_SetFromErrno(PyExc_OSError);
11459
0
    }
11460
0
    return build_itimerspec(&curr_value);
11461
0
}
11462
11463
11464
/*[clinic input]
11465
@permit_long_summary
11466
os.timerfd_gettime_ns
11467
11468
    fd: fildes
11469
        A timer file descriptor.
11470
    /
11471
11472
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11473
[clinic start generated code]*/
11474
11475
static PyObject *
11476
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11477
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11478
0
{
11479
0
    struct itimerspec curr_value;
11480
0
    int result;
11481
0
    Py_BEGIN_ALLOW_THREADS
11482
0
    result = timerfd_gettime(fd, &curr_value);
11483
0
    Py_END_ALLOW_THREADS
11484
0
    if (result == -1) {
11485
0
        return PyErr_SetFromErrno(PyExc_OSError);
11486
0
    }
11487
0
    return build_itimerspec_ns(&curr_value);
11488
0
}
11489
11490
#undef ONE_SECOND_IN_NS
11491
#undef EXTRACT_NSEC
11492
11493
#endif  /* HAVE_TIMERFD_CREATE */
11494
11495
#ifdef HAVE_GETSID
11496
/*[clinic input]
11497
os.getsid
11498
11499
    pid: pid_t
11500
    /
11501
11502
Call the system call getsid(pid) and return the result.
11503
[clinic start generated code]*/
11504
11505
static PyObject *
11506
os_getsid_impl(PyObject *module, pid_t pid)
11507
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11508
0
{
11509
0
    int sid;
11510
0
    sid = getsid(pid);
11511
0
    if (sid < 0)
11512
0
        return posix_error();
11513
0
    return PyLong_FromLong((long)sid);
11514
0
}
11515
#endif /* HAVE_GETSID */
11516
11517
11518
#ifdef HAVE_SETSID
11519
/*[clinic input]
11520
os.setsid
11521
11522
Call the system call setsid().
11523
[clinic start generated code]*/
11524
11525
static PyObject *
11526
os_setsid_impl(PyObject *module)
11527
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11528
0
{
11529
0
    if (setsid() < 0)
11530
0
        return posix_error();
11531
0
    Py_RETURN_NONE;
11532
0
}
11533
#endif /* HAVE_SETSID */
11534
11535
11536
#ifdef HAVE_SETPGID
11537
/*[clinic input]
11538
os.setpgid
11539
11540
    pid: pid_t
11541
    pgrp: pid_t
11542
    /
11543
11544
Call the system call setpgid(pid, pgrp).
11545
[clinic start generated code]*/
11546
11547
static PyObject *
11548
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11549
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11550
0
{
11551
0
    if (setpgid(pid, pgrp) < 0)
11552
0
        return posix_error();
11553
0
    Py_RETURN_NONE;
11554
0
}
11555
#endif /* HAVE_SETPGID */
11556
11557
11558
#ifdef HAVE_TCGETPGRP
11559
/*[clinic input]
11560
os.tcgetpgrp
11561
11562
    fd: int
11563
    /
11564
11565
Return the process group associated with the terminal specified by fd.
11566
[clinic start generated code]*/
11567
11568
static PyObject *
11569
os_tcgetpgrp_impl(PyObject *module, int fd)
11570
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11571
0
{
11572
0
    pid_t pgid = tcgetpgrp(fd);
11573
0
    if (pgid < 0)
11574
0
        return posix_error();
11575
0
    return PyLong_FromPid(pgid);
11576
0
}
11577
#endif /* HAVE_TCGETPGRP */
11578
11579
11580
#ifdef HAVE_TCSETPGRP
11581
/*[clinic input]
11582
os.tcsetpgrp
11583
11584
    fd: int
11585
    pgid: pid_t
11586
    /
11587
11588
Set the process group associated with the terminal specified by fd.
11589
[clinic start generated code]*/
11590
11591
static PyObject *
11592
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11593
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11594
0
{
11595
0
    if (tcsetpgrp(fd, pgid) < 0)
11596
0
        return posix_error();
11597
0
    Py_RETURN_NONE;
11598
0
}
11599
#endif /* HAVE_TCSETPGRP */
11600
11601
/* Functions acting on file descriptors */
11602
11603
#ifdef O_CLOEXEC
11604
extern int _Py_open_cloexec_works;
11605
#endif
11606
11607
11608
/*[clinic input]
11609
os.open -> int
11610
    path: path_t
11611
    flags: int
11612
    mode: int = 0o777
11613
    *
11614
    dir_fd: dir_fd(requires='openat') = None
11615
11616
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11617
11618
Open a file for low level IO.  Returns a file descriptor (integer).
11619
11620
If dir_fd is not None, it should be a file descriptor open to a directory,
11621
  and path should be relative; path will then be relative to that directory.
11622
dir_fd may not be implemented on your platform.
11623
  If it is unavailable, using it will raise a NotImplementedError.
11624
[clinic start generated code]*/
11625
11626
static int
11627
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11628
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11629
185k
{
11630
185k
    int fd;
11631
185k
    int async_err = 0;
11632
185k
#ifdef HAVE_OPENAT
11633
185k
    int openat_unavailable = 0;
11634
185k
#endif
11635
11636
185k
#ifdef O_CLOEXEC
11637
185k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11638
#elif !defined(MS_WINDOWS)
11639
    int *atomic_flag_works = NULL;
11640
#endif
11641
11642
#ifdef MS_WINDOWS
11643
    flags |= O_NOINHERIT;
11644
#elif defined(O_CLOEXEC)
11645
185k
    flags |= O_CLOEXEC;
11646
185k
#endif
11647
11648
185k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11649
0
        return -1;
11650
0
    }
11651
11652
185k
    _Py_BEGIN_SUPPRESS_IPH
11653
185k
    do {
11654
185k
        Py_BEGIN_ALLOW_THREADS
11655
#ifdef MS_WINDOWS
11656
        fd = _wopen(path->wide, flags, mode);
11657
#else
11658
185k
#ifdef HAVE_OPENAT
11659
185k
        if (dir_fd != DEFAULT_DIR_FD) {
11660
180k
            if (HAVE_OPENAT_RUNTIME) {
11661
180k
                fd = openat(dir_fd, path->narrow, flags, mode);
11662
11663
180k
            } else {
11664
0
                openat_unavailable = 1;
11665
0
                fd = -1;
11666
0
            }
11667
180k
        } else
11668
4.90k
#endif /* HAVE_OPENAT */
11669
4.90k
            fd = open(path->narrow, flags, mode);
11670
185k
#endif /* !MS_WINDOWS */
11671
185k
        Py_END_ALLOW_THREADS
11672
185k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11673
185k
    _Py_END_SUPPRESS_IPH
11674
11675
185k
#ifdef HAVE_OPENAT
11676
185k
    if (openat_unavailable) {
11677
0
        argument_unavailable_error(NULL, "dir_fd");
11678
0
        return -1;
11679
0
    }
11680
185k
#endif
11681
11682
185k
    if (fd < 0) {
11683
0
        if (!async_err)
11684
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11685
0
        return -1;
11686
0
    }
11687
11688
185k
#ifndef MS_WINDOWS
11689
185k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11690
0
        close(fd);
11691
0
        return -1;
11692
0
    }
11693
185k
#endif
11694
11695
185k
    return fd;
11696
185k
}
11697
11698
11699
/*[clinic input]
11700
os.close
11701
11702
    fd: int
11703
11704
Close a file descriptor.
11705
[clinic start generated code]*/
11706
11707
static PyObject *
11708
os_close_impl(PyObject *module, int fd)
11709
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11710
184k
{
11711
184k
    int res;
11712
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11713
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11714
     * for more details.
11715
     */
11716
184k
    Py_BEGIN_ALLOW_THREADS
11717
184k
    _Py_BEGIN_SUPPRESS_IPH
11718
184k
    res = close(fd);
11719
184k
    _Py_END_SUPPRESS_IPH
11720
184k
    Py_END_ALLOW_THREADS
11721
184k
    if (res < 0)
11722
0
        return posix_error();
11723
184k
    Py_RETURN_NONE;
11724
184k
}
11725
11726
/*[clinic input]
11727
os.closerange
11728
11729
    fd_low: int
11730
    fd_high: int
11731
    /
11732
11733
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11734
[clinic start generated code]*/
11735
11736
static PyObject *
11737
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11738
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11739
0
{
11740
0
    Py_BEGIN_ALLOW_THREADS
11741
0
    _Py_closerange(fd_low, fd_high - 1);
11742
0
    Py_END_ALLOW_THREADS
11743
0
    Py_RETURN_NONE;
11744
0
}
11745
11746
11747
/*[clinic input]
11748
os.dup -> int
11749
11750
    fd: int
11751
    /
11752
11753
Return a duplicate of a file descriptor.
11754
[clinic start generated code]*/
11755
11756
static int
11757
os_dup_impl(PyObject *module, int fd)
11758
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11759
0
{
11760
0
    return _Py_dup(fd);
11761
0
}
11762
11763
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11764
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11765
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11766
/*[clinic input]
11767
os.dup2 -> int
11768
    fd: int
11769
    fd2: int
11770
    inheritable: bool=True
11771
11772
Duplicate file descriptor.
11773
[clinic start generated code]*/
11774
11775
static int
11776
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11777
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11778
0
{
11779
0
    int res = 0;
11780
0
#if defined(HAVE_DUP3) && \
11781
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11782
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11783
0
    static int dup3_works = -1;
11784
0
#endif
11785
11786
    /* dup2() can fail with EINTR if the target FD is already open, because it
11787
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11788
     * upon close(), and therefore below.
11789
     */
11790
#ifdef MS_WINDOWS
11791
    Py_BEGIN_ALLOW_THREADS
11792
    _Py_BEGIN_SUPPRESS_IPH
11793
    res = dup2(fd, fd2);
11794
    _Py_END_SUPPRESS_IPH
11795
    Py_END_ALLOW_THREADS
11796
    if (res < 0) {
11797
        posix_error();
11798
        return -1;
11799
    }
11800
    res = fd2; // msvcrt dup2 returns 0 on success.
11801
11802
    /* Character files like console cannot be make non-inheritable */
11803
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11804
        close(fd2);
11805
        return -1;
11806
    }
11807
11808
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11809
    Py_BEGIN_ALLOW_THREADS
11810
    if (!inheritable)
11811
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11812
    else
11813
        res = dup2(fd, fd2);
11814
    Py_END_ALLOW_THREADS
11815
    if (res < 0) {
11816
        posix_error();
11817
        return -1;
11818
    }
11819
11820
#else
11821
11822
0
#ifdef HAVE_DUP3
11823
0
    if (!inheritable && dup3_works != 0) {
11824
0
        Py_BEGIN_ALLOW_THREADS
11825
0
        res = dup3(fd, fd2, O_CLOEXEC);
11826
0
        Py_END_ALLOW_THREADS
11827
0
        if (res < 0) {
11828
0
            if (dup3_works == -1)
11829
0
                dup3_works = (errno != ENOSYS);
11830
0
            if (dup3_works) {
11831
0
                posix_error();
11832
0
                return -1;
11833
0
            }
11834
0
        }
11835
0
    }
11836
11837
0
    if (inheritable || dup3_works == 0)
11838
0
    {
11839
0
#endif
11840
0
        Py_BEGIN_ALLOW_THREADS
11841
0
        res = dup2(fd, fd2);
11842
0
        Py_END_ALLOW_THREADS
11843
0
        if (res < 0) {
11844
0
            posix_error();
11845
0
            return -1;
11846
0
        }
11847
11848
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11849
0
            close(fd2);
11850
0
            return -1;
11851
0
        }
11852
0
#ifdef HAVE_DUP3
11853
0
    }
11854
0
#endif
11855
11856
0
#endif
11857
11858
0
    return res;
11859
0
}
11860
#endif
11861
11862
11863
#ifdef HAVE_LOCKF
11864
/*[clinic input]
11865
os.lockf
11866
11867
    fd: int
11868
        An open file descriptor.
11869
    command: int
11870
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11871
    length: Py_off_t
11872
        The number of bytes to lock, starting at the current position.
11873
    /
11874
11875
Apply, test or remove a POSIX lock on an open file descriptor.
11876
11877
[clinic start generated code]*/
11878
11879
static PyObject *
11880
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11881
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11882
0
{
11883
0
    int res;
11884
11885
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11886
0
        return NULL;
11887
0
    }
11888
11889
0
    Py_BEGIN_ALLOW_THREADS
11890
0
    res = lockf(fd, command, length);
11891
0
    Py_END_ALLOW_THREADS
11892
11893
0
    if (res < 0)
11894
0
        return posix_error();
11895
11896
0
    Py_RETURN_NONE;
11897
0
}
11898
#endif /* HAVE_LOCKF */
11899
11900
11901
/*[clinic input]
11902
@permit_long_docstring_body
11903
os.lseek -> Py_off_t
11904
11905
    fd: int
11906
        An open file descriptor, as returned by os.open().
11907
    position: Py_off_t
11908
        Position, interpreted relative to 'whence'.
11909
    whence as how: int
11910
        The relative position to seek from. Valid values are:
11911
        - SEEK_SET: seek from the start of the file.
11912
        - SEEK_CUR: seek from the current file position.
11913
        - SEEK_END: seek from the end of the file.
11914
    /
11915
11916
Set the position of a file descriptor.  Return the new position.
11917
11918
The return value is the number of bytes relative to the beginning of the file.
11919
[clinic start generated code]*/
11920
11921
static Py_off_t
11922
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11923
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11924
0
{
11925
0
    Py_off_t result;
11926
11927
0
#ifdef SEEK_SET
11928
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11929
0
    switch (how) {
11930
0
        case 0: how = SEEK_SET; break;
11931
0
        case 1: how = SEEK_CUR; break;
11932
0
        case 2: how = SEEK_END; break;
11933
0
    }
11934
0
#endif /* SEEK_END */
11935
11936
0
    Py_BEGIN_ALLOW_THREADS
11937
0
    _Py_BEGIN_SUPPRESS_IPH
11938
#ifdef MS_WINDOWS
11939
    result = _lseeki64(fd, position, how);
11940
#else
11941
0
    result = lseek(fd, position, how);
11942
0
#endif
11943
0
    _Py_END_SUPPRESS_IPH
11944
0
    Py_END_ALLOW_THREADS
11945
0
    if (result < 0)
11946
0
        posix_error();
11947
11948
0
    return result;
11949
0
}
11950
11951
11952
/*[clinic input]
11953
os.read
11954
    fd: int
11955
    length: Py_ssize_t
11956
    /
11957
11958
Read from a file descriptor.  Returns a bytes object.
11959
[clinic start generated code]*/
11960
11961
static PyObject *
11962
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11963
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11964
0
{
11965
0
    if (length < 0) {
11966
0
        errno = EINVAL;
11967
0
        return posix_error();
11968
0
    }
11969
11970
0
    length = Py_MIN(length, _PY_READ_MAX);
11971
11972
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11973
0
    if (writer == NULL) {
11974
0
        return NULL;
11975
0
    }
11976
11977
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11978
0
    if (n == -1) {
11979
0
        PyBytesWriter_Discard(writer);
11980
0
        return NULL;
11981
0
    }
11982
11983
0
    return PyBytesWriter_FinishWithSize(writer, n);
11984
0
}
11985
11986
/*[clinic input]
11987
@permit_long_docstring_body
11988
os.readinto -> Py_ssize_t
11989
    fd: int
11990
    buffer: Py_buffer(accept={rwbuffer})
11991
    /
11992
11993
Read into a buffer object from a file descriptor.
11994
11995
The buffer should be mutable and bytes-like. On success, returns the number of
11996
bytes read. Less bytes may be read than the size of the buffer. The underlying
11997
system call will be retried when interrupted by a signal, unless the signal
11998
handler raises an exception. Other errors will not be retried and an error will
11999
be raised.
12000
12001
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
12002
(which can be used to check for errors without reading data). Never returns
12003
negative.
12004
[clinic start generated code]*/
12005
12006
static Py_ssize_t
12007
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12008
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
12009
0
{
12010
0
    assert(buffer->len >= 0);
12011
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12012
    /* Ensure negative is never returned without an error. Simplifies calling
12013
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12014
        error. */
12015
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12016
0
    return result;
12017
0
}
12018
12019
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12020
                                || defined(__APPLE__))) \
12021
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12022
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12023
static int
12024
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12025
0
{
12026
0
    Py_ssize_t i, j;
12027
12028
0
    *iov = PyMem_New(struct iovec, cnt);
12029
0
    if (*iov == NULL) {
12030
0
        PyErr_NoMemory();
12031
0
        return -1;
12032
0
    }
12033
12034
0
    *buf = PyMem_New(Py_buffer, cnt);
12035
0
    if (*buf == NULL) {
12036
0
        PyMem_Free(*iov);
12037
0
        PyErr_NoMemory();
12038
0
        return -1;
12039
0
    }
12040
12041
0
    for (i = 0; i < cnt; i++) {
12042
0
        PyObject *item = PySequence_GetItem(seq, i);
12043
0
        if (item == NULL)
12044
0
            goto fail;
12045
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12046
0
            Py_DECREF(item);
12047
0
            goto fail;
12048
0
        }
12049
0
        Py_DECREF(item);
12050
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12051
0
        (*iov)[i].iov_len = (*buf)[i].len;
12052
0
    }
12053
0
    return 0;
12054
12055
0
fail:
12056
0
    PyMem_Free(*iov);
12057
0
    for (j = 0; j < i; j++) {
12058
0
        PyBuffer_Release(&(*buf)[j]);
12059
0
    }
12060
0
    PyMem_Free(*buf);
12061
0
    return -1;
12062
0
}
12063
12064
static void
12065
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12066
0
{
12067
0
    int i;
12068
0
    PyMem_Free(iov);
12069
0
    for (i = 0; i < cnt; i++) {
12070
0
        PyBuffer_Release(&buf[i]);
12071
0
    }
12072
0
    PyMem_Free(buf);
12073
0
}
12074
#endif
12075
12076
12077
#ifdef HAVE_READV
12078
/*[clinic input]
12079
os.readv -> Py_ssize_t
12080
12081
    fd: int
12082
    buffers: object
12083
    /
12084
12085
Read from a file descriptor fd into an iterable of buffers.
12086
12087
The buffers should be mutable buffers accepting bytes.
12088
readv will transfer data into each buffer until it is full
12089
and then move on to the next buffer in the sequence to hold
12090
the rest of the data.
12091
12092
readv returns the total number of bytes read,
12093
which may be less than the total capacity of all the buffers.
12094
[clinic start generated code]*/
12095
12096
static Py_ssize_t
12097
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12098
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12099
0
{
12100
0
    Py_ssize_t cnt, n;
12101
0
    int async_err = 0;
12102
0
    struct iovec *iov;
12103
0
    Py_buffer *buf;
12104
12105
0
    if (!PySequence_Check(buffers)) {
12106
0
        PyErr_SetString(PyExc_TypeError,
12107
0
            "readv() arg 2 must be a sequence");
12108
0
        return -1;
12109
0
    }
12110
12111
0
    cnt = PySequence_Size(buffers);
12112
0
    if (cnt < 0)
12113
0
        return -1;
12114
12115
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12116
0
        return -1;
12117
12118
0
    do {
12119
0
        Py_BEGIN_ALLOW_THREADS
12120
0
        n = readv(fd, iov, cnt);
12121
0
        Py_END_ALLOW_THREADS
12122
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12123
12124
0
    int saved_errno = errno;
12125
0
    iov_cleanup(iov, buf, cnt);
12126
0
    if (n < 0) {
12127
0
        if (!async_err) {
12128
0
            errno = saved_errno;
12129
0
            posix_error();
12130
0
        }
12131
0
        return -1;
12132
0
    }
12133
12134
0
    return n;
12135
0
}
12136
#endif /* HAVE_READV */
12137
12138
12139
#ifdef HAVE_PREAD
12140
/*[clinic input]
12141
@permit_long_summary
12142
os.pread
12143
12144
    fd: int
12145
    length: Py_ssize_t
12146
    offset: Py_off_t
12147
    /
12148
12149
Read a number of bytes from a file descriptor starting at a particular offset.
12150
12151
Read length bytes from file descriptor fd, starting at offset bytes from
12152
the beginning of the file.  The file offset remains unchanged.
12153
[clinic start generated code]*/
12154
12155
static PyObject *
12156
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12157
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12158
0
{
12159
0
    Py_ssize_t n;
12160
0
    int async_err = 0;
12161
12162
0
    if (length < 0) {
12163
0
        errno = EINVAL;
12164
0
        return posix_error();
12165
0
    }
12166
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12167
0
    if (writer == NULL) {
12168
0
        return NULL;
12169
0
    }
12170
12171
0
    do {
12172
0
        Py_BEGIN_ALLOW_THREADS
12173
0
        _Py_BEGIN_SUPPRESS_IPH
12174
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12175
0
        _Py_END_SUPPRESS_IPH
12176
0
        Py_END_ALLOW_THREADS
12177
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12178
12179
0
    if (n < 0) {
12180
0
        if (!async_err) {
12181
0
            posix_error();
12182
0
        }
12183
0
        PyBytesWriter_Discard(writer);
12184
0
        return NULL;
12185
0
    }
12186
0
    return PyBytesWriter_FinishWithSize(writer, n);
12187
0
}
12188
#endif /* HAVE_PREAD */
12189
12190
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12191
/*[clinic input]
12192
@permit_long_docstring_body
12193
os.preadv -> Py_ssize_t
12194
12195
    fd: int
12196
    buffers: object
12197
    offset: Py_off_t
12198
    flags: int = 0
12199
    /
12200
12201
Reads from a file descriptor into a number of mutable bytes-like objects.
12202
12203
Combines the functionality of readv() and pread(). As readv(), it will
12204
transfer data into each buffer until it is full and then move on to the next
12205
buffer in the sequence to hold the rest of the data. Its fourth argument,
12206
specifies the file offset at which the input operation is to be performed. It
12207
will return the total number of bytes read (which can be less than the total
12208
capacity of all the objects).
12209
12210
The flags argument contains a bitwise OR of zero or more of the following flags:
12211
12212
- RWF_HIPRI
12213
- RWF_NOWAIT
12214
- RWF_DONTCACHE
12215
12216
Using non-zero flags requires Linux 4.6 or newer.
12217
[clinic start generated code]*/
12218
12219
static Py_ssize_t
12220
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12221
               int flags)
12222
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
12223
0
{
12224
0
    Py_ssize_t cnt, n;
12225
0
    int async_err = 0;
12226
0
    struct iovec *iov;
12227
0
    Py_buffer *buf;
12228
12229
0
    if (!PySequence_Check(buffers)) {
12230
0
        PyErr_SetString(PyExc_TypeError,
12231
0
            "preadv2() arg 2 must be a sequence");
12232
0
        return -1;
12233
0
    }
12234
12235
0
    cnt = PySequence_Size(buffers);
12236
0
    if (cnt < 0) {
12237
0
        return -1;
12238
0
    }
12239
12240
#ifndef HAVE_PREADV2
12241
    if(flags != 0) {
12242
        argument_unavailable_error("preadv2", "flags");
12243
        return -1;
12244
    }
12245
#endif
12246
12247
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12248
0
        return -1;
12249
0
    }
12250
0
#ifdef HAVE_PREADV2
12251
0
    do {
12252
0
        Py_BEGIN_ALLOW_THREADS
12253
0
        _Py_BEGIN_SUPPRESS_IPH
12254
0
        n = preadv2(fd, iov, cnt, offset, flags);
12255
0
        _Py_END_SUPPRESS_IPH
12256
0
        Py_END_ALLOW_THREADS
12257
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12258
#else
12259
    do {
12260
#if defined(__APPLE__) && defined(__clang__)
12261
/* This entire function will be removed from the module dict when the API
12262
 * is not available.
12263
 */
12264
#pragma clang diagnostic push
12265
#pragma clang diagnostic ignored "-Wunguarded-availability"
12266
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12267
#endif
12268
        Py_BEGIN_ALLOW_THREADS
12269
        _Py_BEGIN_SUPPRESS_IPH
12270
        n = preadv(fd, iov, cnt, offset);
12271
        _Py_END_SUPPRESS_IPH
12272
        Py_END_ALLOW_THREADS
12273
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12274
12275
#if defined(__APPLE__) && defined(__clang__)
12276
#pragma clang diagnostic pop
12277
#endif
12278
12279
#endif
12280
12281
0
    int saved_errno = errno;
12282
0
    iov_cleanup(iov, buf, cnt);
12283
0
    if (n < 0) {
12284
0
        if (!async_err) {
12285
0
            errno = saved_errno;
12286
0
            posix_error();
12287
0
        }
12288
0
        return -1;
12289
0
    }
12290
12291
0
    return n;
12292
0
}
12293
#endif /* HAVE_PREADV */
12294
12295
12296
/*[clinic input]
12297
os.write -> Py_ssize_t
12298
12299
    fd: int
12300
    data: Py_buffer
12301
    /
12302
12303
Write a bytes object to a file descriptor.
12304
[clinic start generated code]*/
12305
12306
static Py_ssize_t
12307
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12308
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12309
2
{
12310
2
    return _Py_write(fd, data->buf, data->len);
12311
2
}
12312
12313
#ifdef HAVE_SENDFILE
12314
#ifdef __APPLE__
12315
/*[clinic input]
12316
os.sendfile
12317
12318
    out_fd: int
12319
    in_fd: int
12320
    offset: Py_off_t
12321
    count as sbytes: Py_off_t
12322
    headers: object(c_default="NULL") = ()
12323
    trailers: object(c_default="NULL") = ()
12324
    flags: int = 0
12325
12326
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12327
[clinic start generated code]*/
12328
12329
static PyObject *
12330
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12331
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12332
                 int flags)
12333
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12334
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12335
/*[clinic input]
12336
os.sendfile
12337
12338
    out_fd: int
12339
    in_fd: int
12340
    offset: Py_off_t
12341
    count: Py_ssize_t(allow_negative=False)
12342
    headers: object(c_default="NULL") = ()
12343
    trailers: object(c_default="NULL") = ()
12344
    flags: int = 0
12345
12346
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12347
[clinic start generated code]*/
12348
12349
static PyObject *
12350
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12351
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12352
                 int flags)
12353
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12354
#else
12355
/*[clinic input]
12356
os.sendfile
12357
12358
    out_fd: int
12359
    in_fd: int
12360
    offset as offobj: object
12361
    count: Py_ssize_t(allow_negative=False)
12362
12363
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12364
[clinic start generated code]*/
12365
12366
static PyObject *
12367
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12368
                 Py_ssize_t count)
12369
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12370
#endif
12371
0
{
12372
0
    Py_ssize_t ret;
12373
0
    int async_err = 0;
12374
12375
#ifdef __APPLE__
12376
    if(sbytes < 0) {
12377
        PyErr_SetString(PyExc_ValueError,
12378
                        "count cannot be negative");
12379
        return NULL;
12380
    }
12381
#else
12382
0
    assert(count >= 0);
12383
0
#endif
12384
12385
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12386
#ifndef __APPLE__
12387
    off_t sbytes;
12388
#endif
12389
    Py_buffer *hbuf, *tbuf;
12390
    struct sf_hdtr sf;
12391
12392
    sf.headers = NULL;
12393
    sf.trailers = NULL;
12394
12395
    if (headers != NULL) {
12396
        if (!PySequence_Check(headers)) {
12397
            PyErr_SetString(PyExc_TypeError,
12398
                "sendfile() headers must be a sequence");
12399
            return NULL;
12400
        } else {
12401
            Py_ssize_t i = PySequence_Size(headers);
12402
            if (i < 0)
12403
                return NULL;
12404
            if (i > INT_MAX) {
12405
                PyErr_SetString(PyExc_OverflowError,
12406
                    "sendfile() header is too large");
12407
                return NULL;
12408
            }
12409
            if (i > 0) {
12410
                sf.hdr_cnt = (int)i;
12411
                if (iov_setup(&(sf.headers), &hbuf,
12412
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12413
                    return NULL;
12414
#ifdef __APPLE__
12415
                for (i = 0; i < sf.hdr_cnt; i++) {
12416
                    Py_ssize_t blen = sf.headers[i].iov_len;
12417
# define OFF_T_MAX 0x7fffffffffffffff
12418
                    if (sbytes >= OFF_T_MAX - blen) {
12419
                        PyErr_SetString(PyExc_OverflowError,
12420
                            "sendfile() header is too large");
12421
                        return NULL;
12422
                    }
12423
                    sbytes += blen;
12424
                }
12425
#endif
12426
            }
12427
        }
12428
    }
12429
    if (trailers != NULL) {
12430
        if (!PySequence_Check(trailers)) {
12431
            PyErr_SetString(PyExc_TypeError,
12432
                "sendfile() trailers must be a sequence");
12433
            return NULL;
12434
        } else {
12435
            Py_ssize_t i = PySequence_Size(trailers);
12436
            if (i < 0)
12437
                return NULL;
12438
            if (i > INT_MAX) {
12439
                PyErr_SetString(PyExc_OverflowError,
12440
                    "sendfile() trailer is too large");
12441
                return NULL;
12442
            }
12443
            if (i > 0) {
12444
                sf.trl_cnt = (int)i;
12445
                if (iov_setup(&(sf.trailers), &tbuf,
12446
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12447
                    return NULL;
12448
            }
12449
        }
12450
    }
12451
12452
    _Py_BEGIN_SUPPRESS_IPH
12453
    do {
12454
        Py_BEGIN_ALLOW_THREADS
12455
#ifdef __APPLE__
12456
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12457
#else
12458
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12459
#endif
12460
        Py_END_ALLOW_THREADS
12461
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12462
    _Py_END_SUPPRESS_IPH
12463
12464
    int saved_errno = errno;
12465
    if (sf.headers != NULL)
12466
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12467
    if (sf.trailers != NULL)
12468
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12469
12470
    if (ret < 0) {
12471
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12472
            if (sbytes != 0) {
12473
                // some data has been sent
12474
                goto done;
12475
            }
12476
            // no data has been sent; upper application is supposed
12477
            // to retry on EAGAIN or EBUSY
12478
        }
12479
        if (!async_err) {
12480
            errno = saved_errno;
12481
            posix_error();
12482
        }
12483
        return NULL;
12484
    }
12485
    goto done;
12486
12487
done:
12488
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12489
        return PyLong_FromLong(sbytes);
12490
    #else
12491
        return PyLong_FromLongLong(sbytes);
12492
    #endif
12493
12494
#else
12495
0
#ifdef __linux__
12496
0
    if (offobj == Py_None) {
12497
0
        do {
12498
0
            Py_BEGIN_ALLOW_THREADS
12499
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12500
0
            Py_END_ALLOW_THREADS
12501
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12502
0
        if (ret < 0)
12503
0
            return (!async_err) ? posix_error() : NULL;
12504
0
        return PyLong_FromSsize_t(ret);
12505
0
    }
12506
0
#endif
12507
0
    off_t offset;
12508
0
    if (!Py_off_t_converter(offobj, &offset))
12509
0
        return NULL;
12510
12511
#if defined(__sun) && defined(__SVR4)
12512
    // On Solaris, sendfile raises EINVAL rather than returning 0
12513
    // when the offset is equal or bigger than the in_fd size.
12514
    struct stat st;
12515
12516
    do {
12517
        Py_BEGIN_ALLOW_THREADS
12518
        ret = fstat(in_fd, &st);
12519
        Py_END_ALLOW_THREADS
12520
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12521
    if (ret < 0)
12522
        return (!async_err) ? posix_error() : NULL;
12523
12524
    if (offset >= st.st_size) {
12525
        return PyLong_FromLong(0);
12526
    }
12527
12528
    // On illumos specifically sendfile() may perform a partial write but
12529
    // return -1/an error (in one confirmed case the destination socket
12530
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12531
    // code to check if the offset parameter was modified by sendfile().
12532
    //
12533
    // We need this variable to track said change.
12534
    off_t original_offset = offset;
12535
#endif
12536
12537
0
    do {
12538
0
        Py_BEGIN_ALLOW_THREADS
12539
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12540
#if defined(__sun) && defined(__SVR4)
12541
        // This handles illumos-specific sendfile() partial write behavior,
12542
        // see a comment above for more details.
12543
        if (ret < 0 && offset != original_offset) {
12544
            ret = offset - original_offset;
12545
        }
12546
#endif
12547
0
        Py_END_ALLOW_THREADS
12548
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12549
0
    if (ret < 0)
12550
0
        return (!async_err) ? posix_error() : NULL;
12551
0
    return PyLong_FromSsize_t(ret);
12552
0
#endif
12553
0
}
12554
#endif /* HAVE_SENDFILE */
12555
12556
12557
#if defined(__APPLE__)
12558
/*[clinic input]
12559
os._fcopyfile
12560
12561
    in_fd: int
12562
    out_fd: int
12563
    flags: int
12564
    /
12565
12566
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12567
[clinic start generated code]*/
12568
12569
static PyObject *
12570
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12571
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12572
{
12573
    int ret;
12574
12575
    Py_BEGIN_ALLOW_THREADS
12576
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12577
    Py_END_ALLOW_THREADS
12578
    if (ret < 0)
12579
        return posix_error();
12580
    Py_RETURN_NONE;
12581
}
12582
#endif
12583
12584
12585
/*[clinic input]
12586
os.fstat
12587
12588
    fd : int
12589
12590
Perform a stat system call on the given file descriptor.
12591
12592
Like stat(), but for an open file descriptor.
12593
Equivalent to os.stat(fd).
12594
[clinic start generated code]*/
12595
12596
static PyObject *
12597
os_fstat_impl(PyObject *module, int fd)
12598
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12599
184k
{
12600
184k
    STRUCT_STAT st;
12601
184k
    int res;
12602
184k
    int async_err = 0;
12603
12604
184k
    do {
12605
184k
        Py_BEGIN_ALLOW_THREADS
12606
184k
        res = FSTAT(fd, &st);
12607
184k
        Py_END_ALLOW_THREADS
12608
184k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12609
184k
    if (res != 0) {
12610
#ifdef MS_WINDOWS
12611
        return PyErr_SetFromWindowsErr(0);
12612
#else
12613
0
        return (!async_err) ? posix_error() : NULL;
12614
0
#endif
12615
0
    }
12616
12617
184k
    return _pystat_fromstructstat(module, &st);
12618
184k
}
12619
12620
12621
/*[clinic input]
12622
os.isatty -> bool
12623
    fd: int
12624
    /
12625
12626
Return True if the fd is connected to a terminal.
12627
12628
Return True if the file descriptor is an open file descriptor
12629
connected to the slave end of a terminal.
12630
[clinic start generated code]*/
12631
12632
static int
12633
os_isatty_impl(PyObject *module, int fd)
12634
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12635
0
{
12636
0
    int return_value;
12637
0
    Py_BEGIN_ALLOW_THREADS
12638
0
    _Py_BEGIN_SUPPRESS_IPH
12639
0
    return_value = isatty(fd);
12640
0
    _Py_END_SUPPRESS_IPH
12641
0
    Py_END_ALLOW_THREADS
12642
0
    return return_value;
12643
0
}
12644
12645
12646
#ifdef HAVE_PIPE
12647
/*[clinic input]
12648
os.pipe
12649
12650
Create a pipe.
12651
12652
Returns a tuple of two file descriptors:
12653
  (read_fd, write_fd)
12654
[clinic start generated code]*/
12655
12656
static PyObject *
12657
os_pipe_impl(PyObject *module)
12658
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12659
0
{
12660
0
    int fds[2];
12661
#ifdef MS_WINDOWS
12662
    HANDLE read, write;
12663
    SECURITY_ATTRIBUTES attr;
12664
    BOOL ok;
12665
#else
12666
0
    int res;
12667
0
#endif
12668
12669
#ifdef MS_WINDOWS
12670
    attr.nLength = sizeof(attr);
12671
    attr.lpSecurityDescriptor = NULL;
12672
    attr.bInheritHandle = FALSE;
12673
12674
    Py_BEGIN_ALLOW_THREADS
12675
    ok = CreatePipe(&read, &write, &attr, 0);
12676
    if (ok) {
12677
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12678
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12679
        if (fds[0] == -1 || fds[1] == -1) {
12680
            CloseHandle(read);
12681
            CloseHandle(write);
12682
            ok = 0;
12683
        }
12684
    }
12685
    Py_END_ALLOW_THREADS
12686
12687
    if (!ok)
12688
        return PyErr_SetFromWindowsErr(0);
12689
#else
12690
12691
0
#ifdef HAVE_PIPE2
12692
0
    Py_BEGIN_ALLOW_THREADS
12693
0
    res = pipe2(fds, O_CLOEXEC);
12694
0
    Py_END_ALLOW_THREADS
12695
12696
0
    if (res != 0 && errno == ENOSYS)
12697
0
    {
12698
0
#endif
12699
0
        Py_BEGIN_ALLOW_THREADS
12700
0
        res = pipe(fds);
12701
0
        Py_END_ALLOW_THREADS
12702
12703
0
        if (res == 0) {
12704
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12705
0
                close(fds[0]);
12706
0
                close(fds[1]);
12707
0
                return NULL;
12708
0
            }
12709
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12710
0
                close(fds[0]);
12711
0
                close(fds[1]);
12712
0
                return NULL;
12713
0
            }
12714
0
        }
12715
0
#ifdef HAVE_PIPE2
12716
0
    }
12717
0
#endif
12718
12719
0
    if (res != 0)
12720
0
        return PyErr_SetFromErrno(PyExc_OSError);
12721
0
#endif /* !MS_WINDOWS */
12722
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12723
0
}
12724
#endif  /* HAVE_PIPE */
12725
12726
12727
#ifdef HAVE_PIPE2
12728
/*[clinic input]
12729
os.pipe2
12730
12731
    flags: int
12732
    /
12733
12734
Create a pipe with flags set atomically.
12735
12736
Returns a tuple of two file descriptors:
12737
  (read_fd, write_fd)
12738
12739
flags can be constructed by ORing together one or more of these values:
12740
O_NONBLOCK, O_CLOEXEC.
12741
[clinic start generated code]*/
12742
12743
static PyObject *
12744
os_pipe2_impl(PyObject *module, int flags)
12745
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12746
0
{
12747
0
    int fds[2];
12748
0
    int res;
12749
12750
0
    res = pipe2(fds, flags);
12751
0
    if (res != 0)
12752
0
        return posix_error();
12753
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12754
0
}
12755
#endif /* HAVE_PIPE2 */
12756
12757
12758
#ifdef HAVE_WRITEV
12759
/*[clinic input]
12760
os.writev -> Py_ssize_t
12761
    fd: int
12762
    buffers: object
12763
    /
12764
12765
Iterate over buffers, and write the contents of each to a file descriptor.
12766
12767
Returns the total number of bytes written.
12768
buffers must be a sequence of bytes-like objects.
12769
[clinic start generated code]*/
12770
12771
static Py_ssize_t
12772
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12773
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12774
0
{
12775
0
    Py_ssize_t cnt;
12776
0
    Py_ssize_t result;
12777
0
    int async_err = 0;
12778
0
    struct iovec *iov;
12779
0
    Py_buffer *buf;
12780
12781
0
    if (!PySequence_Check(buffers)) {
12782
0
        PyErr_SetString(PyExc_TypeError,
12783
0
            "writev() arg 2 must be a sequence");
12784
0
        return -1;
12785
0
    }
12786
0
    cnt = PySequence_Size(buffers);
12787
0
    if (cnt < 0)
12788
0
        return -1;
12789
12790
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12791
0
        return -1;
12792
0
    }
12793
12794
0
    do {
12795
0
        Py_BEGIN_ALLOW_THREADS
12796
0
        result = writev(fd, iov, cnt);
12797
0
        Py_END_ALLOW_THREADS
12798
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12799
12800
0
    if (result < 0 && !async_err)
12801
0
        posix_error();
12802
12803
0
    iov_cleanup(iov, buf, cnt);
12804
0
    return result;
12805
0
}
12806
#endif /* HAVE_WRITEV */
12807
12808
12809
#ifdef HAVE_PWRITE
12810
/*[clinic input]
12811
os.pwrite -> Py_ssize_t
12812
12813
    fd: int
12814
    buffer: Py_buffer
12815
    offset: Py_off_t
12816
    /
12817
12818
Write bytes to a file descriptor starting at a particular offset.
12819
12820
Write buffer to fd, starting at offset bytes from the beginning of
12821
the file.  Returns the number of bytes written.  Does not change the
12822
current file offset.
12823
[clinic start generated code]*/
12824
12825
static Py_ssize_t
12826
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12827
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12828
0
{
12829
0
    Py_ssize_t size;
12830
0
    int async_err = 0;
12831
12832
0
    do {
12833
0
        Py_BEGIN_ALLOW_THREADS
12834
0
        _Py_BEGIN_SUPPRESS_IPH
12835
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12836
0
        _Py_END_SUPPRESS_IPH
12837
0
        Py_END_ALLOW_THREADS
12838
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12839
12840
0
    if (size < 0 && !async_err)
12841
0
        posix_error();
12842
0
    return size;
12843
0
}
12844
#endif /* HAVE_PWRITE */
12845
12846
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12847
/*[clinic input]
12848
@permit_long_summary
12849
@permit_long_docstring_body
12850
os.pwritev -> Py_ssize_t
12851
12852
    fd: int
12853
    buffers: object
12854
    offset: Py_off_t
12855
    flags: int = 0
12856
    /
12857
12858
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12859
12860
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12861
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12862
buffer is written before proceeding to second, and so on. The operating system may
12863
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12864
This function writes the contents of each object to the file descriptor and returns
12865
the total number of bytes written.
12866
12867
The flags argument contains a bitwise OR of zero or more of the following flags:
12868
12869
- RWF_DSYNC
12870
- RWF_SYNC
12871
- RWF_APPEND
12872
- RWF_DONTCACHE
12873
- RWF_ATOMIC
12874
12875
Using non-zero flags requires Linux 4.7 or newer.
12876
[clinic start generated code]*/
12877
12878
static Py_ssize_t
12879
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12880
                int flags)
12881
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=7de72245873f56bf]*/
12882
0
{
12883
0
    Py_ssize_t cnt;
12884
0
    Py_ssize_t result;
12885
0
    int async_err = 0;
12886
0
    struct iovec *iov;
12887
0
    Py_buffer *buf;
12888
12889
0
    if (!PySequence_Check(buffers)) {
12890
0
        PyErr_SetString(PyExc_TypeError,
12891
0
            "pwritev() arg 2 must be a sequence");
12892
0
        return -1;
12893
0
    }
12894
12895
0
    cnt = PySequence_Size(buffers);
12896
0
    if (cnt < 0) {
12897
0
        return -1;
12898
0
    }
12899
12900
#ifndef HAVE_PWRITEV2
12901
    if(flags != 0) {
12902
        argument_unavailable_error("pwritev2", "flags");
12903
        return -1;
12904
    }
12905
#endif
12906
12907
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12908
0
        return -1;
12909
0
    }
12910
0
#ifdef HAVE_PWRITEV2
12911
0
    do {
12912
0
        Py_BEGIN_ALLOW_THREADS
12913
0
        _Py_BEGIN_SUPPRESS_IPH
12914
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12915
0
        _Py_END_SUPPRESS_IPH
12916
0
        Py_END_ALLOW_THREADS
12917
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12918
#else
12919
12920
#if defined(__APPLE__) && defined(__clang__)
12921
/* This entire function will be removed from the module dict when the API
12922
 * is not available.
12923
 */
12924
#pragma clang diagnostic push
12925
#pragma clang diagnostic ignored "-Wunguarded-availability"
12926
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12927
#endif
12928
    do {
12929
        Py_BEGIN_ALLOW_THREADS
12930
        _Py_BEGIN_SUPPRESS_IPH
12931
        result = pwritev(fd, iov, cnt, offset);
12932
        _Py_END_SUPPRESS_IPH
12933
        Py_END_ALLOW_THREADS
12934
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12935
12936
#if defined(__APPLE__) && defined(__clang__)
12937
#pragma clang diagnostic pop
12938
#endif
12939
12940
#endif
12941
12942
0
    if (result < 0) {
12943
0
        if (!async_err) {
12944
0
            posix_error();
12945
0
        }
12946
0
        result = -1;
12947
0
    }
12948
0
    iov_cleanup(iov, buf, cnt);
12949
12950
0
    return result;
12951
0
}
12952
#endif /* HAVE_PWRITEV */
12953
12954
#ifdef HAVE_COPY_FILE_RANGE
12955
/*[clinic input]
12956
12957
os.copy_file_range
12958
    src: int
12959
        Source file descriptor.
12960
    dst: int
12961
        Destination file descriptor.
12962
    count: Py_ssize_t(allow_negative=False)
12963
        Number of bytes to copy.
12964
    offset_src: object = None
12965
        Starting offset in src.
12966
    offset_dst: object = None
12967
        Starting offset in dst.
12968
12969
Copy count bytes from one file descriptor to another.
12970
12971
If offset_src is None, then src is read from the current position;
12972
respectively for offset_dst.
12973
[clinic start generated code]*/
12974
12975
static PyObject *
12976
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12977
                        PyObject *offset_src, PyObject *offset_dst)
12978
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12979
0
{
12980
0
    off_t offset_src_val, offset_dst_val;
12981
0
    off_t *p_offset_src = NULL;
12982
0
    off_t *p_offset_dst = NULL;
12983
0
    Py_ssize_t ret;
12984
0
    int async_err = 0;
12985
    /* The flags argument is provided to allow
12986
     * for future extensions and currently must be to 0. */
12987
0
    int flags = 0;
12988
12989
12990
0
    if (offset_src != Py_None) {
12991
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12992
0
            return NULL;
12993
0
        }
12994
0
        p_offset_src = &offset_src_val;
12995
0
    }
12996
12997
0
    if (offset_dst != Py_None) {
12998
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12999
0
            return NULL;
13000
0
        }
13001
0
        p_offset_dst = &offset_dst_val;
13002
0
    }
13003
13004
0
    do {
13005
0
        Py_BEGIN_ALLOW_THREADS
13006
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13007
0
        Py_END_ALLOW_THREADS
13008
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13009
13010
0
    if (ret < 0) {
13011
0
        return (!async_err) ? posix_error() : NULL;
13012
0
    }
13013
13014
0
    return PyLong_FromSsize_t(ret);
13015
0
}
13016
#endif /* HAVE_COPY_FILE_RANGE*/
13017
13018
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13019
/*[clinic input]
13020
13021
os.splice
13022
    src: int
13023
        Source file descriptor.
13024
    dst: int
13025
        Destination file descriptor.
13026
    count: Py_ssize_t(allow_negative=False)
13027
        Number of bytes to copy.
13028
    offset_src: object = None
13029
        Starting offset in src.
13030
    offset_dst: object = None
13031
        Starting offset in dst.
13032
    flags: unsigned_int = 0
13033
        Flags to modify the semantics of the call.
13034
13035
Transfer count bytes from one pipe to a descriptor or vice versa.
13036
13037
If offset_src is None, then src is read from the current position;
13038
respectively for offset_dst. The offset associated to the file
13039
descriptor that refers to a pipe must be None.
13040
[clinic start generated code]*/
13041
13042
static PyObject *
13043
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13044
               PyObject *offset_src, PyObject *offset_dst,
13045
               unsigned int flags)
13046
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13047
0
{
13048
0
    off_t offset_src_val, offset_dst_val;
13049
0
    off_t *p_offset_src = NULL;
13050
0
    off_t *p_offset_dst = NULL;
13051
0
    Py_ssize_t ret;
13052
0
    int async_err = 0;
13053
13054
13055
0
    if (offset_src != Py_None) {
13056
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13057
0
            return NULL;
13058
0
        }
13059
0
        p_offset_src = &offset_src_val;
13060
0
    }
13061
13062
0
    if (offset_dst != Py_None) {
13063
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13064
0
            return NULL;
13065
0
        }
13066
0
        p_offset_dst = &offset_dst_val;
13067
0
    }
13068
13069
0
    do {
13070
0
        Py_BEGIN_ALLOW_THREADS
13071
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13072
0
        Py_END_ALLOW_THREADS
13073
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13074
13075
0
    if (ret < 0) {
13076
0
        return (!async_err) ? posix_error() : NULL;
13077
0
    }
13078
13079
0
    return PyLong_FromSsize_t(ret);
13080
0
}
13081
#endif /* HAVE_SPLICE*/
13082
13083
#ifdef HAVE_MKFIFO
13084
/*[clinic input]
13085
os.mkfifo
13086
13087
    path: path_t
13088
    mode: int=0o666
13089
    *
13090
    dir_fd: dir_fd(requires='mkfifoat')=None
13091
13092
Create a "fifo" (a POSIX named pipe).
13093
13094
If dir_fd is not None, it should be a file descriptor open to a directory,
13095
  and path should be relative; path will then be relative to that directory.
13096
dir_fd may not be implemented on your platform.
13097
  If it is unavailable, using it will raise a NotImplementedError.
13098
[clinic start generated code]*/
13099
13100
static PyObject *
13101
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13102
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
13103
0
{
13104
0
    int result;
13105
0
    int async_err = 0;
13106
0
#ifdef HAVE_MKFIFOAT
13107
0
    int mkfifoat_unavailable = 0;
13108
0
#endif
13109
13110
0
    do {
13111
0
        Py_BEGIN_ALLOW_THREADS
13112
0
#ifdef HAVE_MKFIFOAT
13113
0
        if (dir_fd != DEFAULT_DIR_FD) {
13114
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13115
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13116
13117
0
            } else {
13118
0
                mkfifoat_unavailable = 1;
13119
0
                result = 0;
13120
0
            }
13121
0
        } else
13122
0
#endif
13123
0
            result = mkfifo(path->narrow, mode);
13124
0
        Py_END_ALLOW_THREADS
13125
0
    } while (result != 0 && errno == EINTR &&
13126
0
             !(async_err = PyErr_CheckSignals()));
13127
13128
0
#ifdef HAVE_MKFIFOAT
13129
0
    if (mkfifoat_unavailable) {
13130
0
        argument_unavailable_error(NULL, "dir_fd");
13131
0
        return NULL;
13132
0
    }
13133
0
#endif
13134
13135
0
    if (result != 0)
13136
0
        return (!async_err) ? posix_error() : NULL;
13137
13138
0
    Py_RETURN_NONE;
13139
0
}
13140
#endif /* HAVE_MKFIFO */
13141
13142
13143
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13144
/*[clinic input]
13145
@permit_long_docstring_body
13146
os.mknod
13147
13148
    path: path_t
13149
    mode: int=0o600
13150
    device: dev_t=0
13151
    *
13152
    dir_fd: dir_fd(requires='mknodat')=None
13153
13154
Create a node in the file system.
13155
13156
Create a node in the file system (file, device special file or named pipe)
13157
at path.  mode specifies both the permissions to use and the
13158
type of node to be created, being combined (bitwise OR) with one of
13159
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
13160
device defines the newly created device special file (probably using
13161
os.makedev()).  Otherwise device is ignored.
13162
13163
If dir_fd is not None, it should be a file descriptor open to a directory,
13164
  and path should be relative; path will then be relative to that directory.
13165
dir_fd may not be implemented on your platform.
13166
  If it is unavailable, using it will raise a NotImplementedError.
13167
[clinic start generated code]*/
13168
13169
static PyObject *
13170
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13171
              int dir_fd)
13172
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
13173
0
{
13174
0
    int result;
13175
0
    int async_err = 0;
13176
0
#ifdef HAVE_MKNODAT
13177
0
    int mknodat_unavailable = 0;
13178
0
#endif
13179
13180
0
    do {
13181
0
        Py_BEGIN_ALLOW_THREADS
13182
0
#ifdef HAVE_MKNODAT
13183
0
        if (dir_fd != DEFAULT_DIR_FD) {
13184
0
            if (HAVE_MKNODAT_RUNTIME) {
13185
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13186
13187
0
            } else {
13188
0
                mknodat_unavailable = 1;
13189
0
                result = 0;
13190
0
            }
13191
0
        } else
13192
0
#endif
13193
0
            result = mknod(path->narrow, mode, device);
13194
0
        Py_END_ALLOW_THREADS
13195
0
    } while (result != 0 && errno == EINTR &&
13196
0
             !(async_err = PyErr_CheckSignals()));
13197
0
#ifdef HAVE_MKNODAT
13198
0
    if (mknodat_unavailable) {
13199
0
        argument_unavailable_error(NULL, "dir_fd");
13200
0
        return NULL;
13201
0
    }
13202
0
#endif
13203
0
    if (result != 0)
13204
0
        return (!async_err) ? posix_error() : NULL;
13205
13206
0
    Py_RETURN_NONE;
13207
0
}
13208
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13209
13210
13211
#ifdef HAVE_DEVICE_MACROS
13212
static PyObject *
13213
major_minor_conv(unsigned int value)
13214
0
{
13215
0
#ifdef NODEV
13216
0
    if (value == (unsigned int)NODEV) {
13217
0
        return PyLong_FromLong((int)NODEV);
13218
0
    }
13219
0
#endif
13220
0
    return PyLong_FromUnsignedLong(value);
13221
0
}
13222
13223
static int
13224
major_minor_check(dev_t value)
13225
0
{
13226
0
#ifdef NODEV
13227
0
    if (value == NODEV) {
13228
0
        return 1;
13229
0
    }
13230
0
#endif
13231
0
    return (dev_t)(unsigned int)value == value;
13232
0
}
13233
13234
/*[clinic input]
13235
os.major
13236
13237
    device: dev_t
13238
    /
13239
13240
Extracts a device major number from a raw device number.
13241
[clinic start generated code]*/
13242
13243
static PyObject *
13244
os_major_impl(PyObject *module, dev_t device)
13245
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13246
0
{
13247
0
    return major_minor_conv(major(device));
13248
0
}
13249
13250
13251
/*[clinic input]
13252
os.minor
13253
13254
    device: dev_t
13255
    /
13256
13257
Extracts a device minor number from a raw device number.
13258
[clinic start generated code]*/
13259
13260
static PyObject *
13261
os_minor_impl(PyObject *module, dev_t device)
13262
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13263
0
{
13264
0
    return major_minor_conv(minor(device));
13265
0
}
13266
13267
13268
/*[clinic input]
13269
os.makedev -> dev_t
13270
13271
    major: dev_t
13272
    minor: dev_t
13273
    /
13274
13275
Composes a raw device number from the major and minor device numbers.
13276
[clinic start generated code]*/
13277
13278
static dev_t
13279
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13280
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13281
0
{
13282
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13283
0
        PyErr_SetString(PyExc_OverflowError,
13284
0
                        "Python int too large to convert to C unsigned int");
13285
0
        return (dev_t)-1;
13286
0
    }
13287
0
    return makedev(major, minor);
13288
0
}
13289
#endif /* HAVE_DEVICE_MACROS */
13290
13291
13292
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13293
/*[clinic input]
13294
os.ftruncate
13295
13296
    fd: int
13297
    length: Py_off_t
13298
    /
13299
13300
Truncate a file, specified by file descriptor, to a specific length.
13301
[clinic start generated code]*/
13302
13303
static PyObject *
13304
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13305
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13306
0
{
13307
0
    int result;
13308
0
    int async_err = 0;
13309
13310
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13311
0
        return NULL;
13312
0
    }
13313
13314
0
    do {
13315
0
        Py_BEGIN_ALLOW_THREADS
13316
0
        _Py_BEGIN_SUPPRESS_IPH
13317
#ifdef MS_WINDOWS
13318
        result = _chsize_s(fd, length);
13319
#else
13320
0
        result = ftruncate(fd, length);
13321
0
#endif
13322
0
        _Py_END_SUPPRESS_IPH
13323
0
        Py_END_ALLOW_THREADS
13324
0
    } while (result != 0 && errno == EINTR &&
13325
0
             !(async_err = PyErr_CheckSignals()));
13326
0
    if (result != 0)
13327
0
        return (!async_err) ? posix_error() : NULL;
13328
0
    Py_RETURN_NONE;
13329
0
}
13330
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13331
13332
13333
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13334
/*[clinic input]
13335
os.truncate
13336
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13337
    length: Py_off_t
13338
13339
Truncate a file, specified by path, to a specific length.
13340
13341
On some platforms, path may also be specified as an open file descriptor.
13342
  If this functionality is unavailable, using it raises an exception.
13343
[clinic start generated code]*/
13344
13345
static PyObject *
13346
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13347
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
13348
0
{
13349
0
    int result;
13350
#ifdef MS_WINDOWS
13351
    int fd;
13352
#endif
13353
13354
0
    if (path->fd != -1)
13355
0
        return os_ftruncate_impl(module, path->fd, length);
13356
13357
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13358
0
        return NULL;
13359
0
    }
13360
13361
0
    Py_BEGIN_ALLOW_THREADS
13362
0
    _Py_BEGIN_SUPPRESS_IPH
13363
#ifdef MS_WINDOWS
13364
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13365
    if (fd < 0)
13366
        result = -1;
13367
    else {
13368
        result = _chsize_s(fd, length);
13369
        close(fd);
13370
        if (result < 0)
13371
            errno = result;
13372
    }
13373
#else
13374
0
    result = truncate(path->narrow, length);
13375
0
#endif
13376
0
    _Py_END_SUPPRESS_IPH
13377
0
    Py_END_ALLOW_THREADS
13378
0
    if (result < 0)
13379
0
        return posix_path_error(path);
13380
13381
0
    Py_RETURN_NONE;
13382
0
}
13383
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13384
13385
13386
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13387
   OSs, support was dropped in WASI preview2. */
13388
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13389
/*[clinic input]
13390
os.posix_fallocate
13391
13392
    fd: int
13393
    offset: Py_off_t
13394
    length: Py_off_t
13395
    /
13396
13397
Ensure a file has allocated at least a particular number of bytes on disk.
13398
13399
Ensure that the file specified by fd encompasses a range of bytes
13400
starting at offset bytes from the beginning and continuing for length bytes.
13401
[clinic start generated code]*/
13402
13403
static PyObject *
13404
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13405
                        Py_off_t length)
13406
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
13407
0
{
13408
0
    int result;
13409
0
    int async_err = 0;
13410
13411
0
    do {
13412
0
        Py_BEGIN_ALLOW_THREADS
13413
0
        result = posix_fallocate(fd, offset, length);
13414
0
        Py_END_ALLOW_THREADS
13415
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13416
13417
0
    if (result == 0)
13418
0
        Py_RETURN_NONE;
13419
13420
0
    if (async_err)
13421
0
        return NULL;
13422
13423
0
    errno = result;
13424
0
    return posix_error();
13425
0
}
13426
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13427
13428
13429
#if defined(HAVE_POSIX_FADVISE)
13430
/*[clinic input]
13431
os.posix_fadvise
13432
13433
    fd: int
13434
    offset: Py_off_t
13435
    length: Py_off_t
13436
    advice: int
13437
    /
13438
13439
Announce an intention to access data in a specific pattern.
13440
13441
Announce an intention to access data in a specific pattern, thus allowing
13442
the kernel to make optimizations.
13443
The advice applies to the region of the file specified by fd starting at
13444
offset and continuing for length bytes.
13445
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13446
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13447
POSIX_FADV_DONTNEED.
13448
[clinic start generated code]*/
13449
13450
static PyObject *
13451
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13452
                      Py_off_t length, int advice)
13453
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13454
0
{
13455
0
    int result;
13456
0
    int async_err = 0;
13457
13458
0
    do {
13459
0
        Py_BEGIN_ALLOW_THREADS
13460
0
        result = posix_fadvise(fd, offset, length, advice);
13461
0
        Py_END_ALLOW_THREADS
13462
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13463
13464
0
    if (result == 0)
13465
0
        Py_RETURN_NONE;
13466
13467
0
    if (async_err)
13468
0
        return NULL;
13469
13470
0
    errno = result;
13471
0
    return posix_error();
13472
0
}
13473
#endif /* HAVE_POSIX_FADVISE */
13474
13475
13476
#ifdef MS_WINDOWS
13477
static PyObject*
13478
win32_putenv(PyObject *name, PyObject *value)
13479
{
13480
    /* Search from index 1 because on Windows starting '=' is allowed for
13481
       defining hidden environment variables. */
13482
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13483
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13484
    {
13485
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13486
        return NULL;
13487
    }
13488
    PyObject *unicode;
13489
    if (value != NULL) {
13490
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13491
    }
13492
    else {
13493
        unicode = PyUnicode_FromFormat("%U=", name);
13494
    }
13495
    if (unicode == NULL) {
13496
        return NULL;
13497
    }
13498
13499
    Py_ssize_t size;
13500
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13501
    Py_DECREF(unicode);
13502
13503
    if (env == NULL) {
13504
        return NULL;
13505
    }
13506
    if (size > _MAX_ENV) {
13507
        PyErr_Format(PyExc_ValueError,
13508
                     "the environment variable is longer than %u characters",
13509
                     _MAX_ENV);
13510
        PyMem_Free(env);
13511
        return NULL;
13512
    }
13513
    if (wcslen(env) != (size_t)size) {
13514
        PyErr_SetString(PyExc_ValueError,
13515
                        "embedded null character");
13516
        PyMem_Free(env);
13517
        return NULL;
13518
    }
13519
13520
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13521
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13522
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13523
13524
       Prefer _wputenv() to be compatible with C libraries using CRT
13525
       variables and CRT functions using these variables (ex: getenv()). */
13526
    int err = _wputenv(env);
13527
13528
    if (err) {
13529
        posix_error();
13530
        PyMem_Free(env);
13531
        return NULL;
13532
    }
13533
    PyMem_Free(env);
13534
13535
    Py_RETURN_NONE;
13536
}
13537
#endif
13538
13539
13540
#ifdef MS_WINDOWS
13541
/*[clinic input]
13542
os.putenv
13543
13544
    name: unicode
13545
    value: unicode
13546
    /
13547
13548
Change or add an environment variable.
13549
[clinic start generated code]*/
13550
13551
static PyObject *
13552
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13553
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13554
{
13555
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13556
        return NULL;
13557
    }
13558
    return win32_putenv(name, value);
13559
}
13560
#else
13561
/*[clinic input]
13562
os.putenv
13563
13564
    name: unicode_fs_encoded
13565
    value: unicode_fs_encoded
13566
    /
13567
13568
Change or add an environment variable.
13569
[clinic start generated code]*/
13570
13571
static PyObject *
13572
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13573
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13574
0
{
13575
0
    const char *name_string = PyBytes_AS_STRING(name);
13576
0
    const char *value_string = PyBytes_AS_STRING(value);
13577
13578
0
    if (strchr(name_string, '=') != NULL) {
13579
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13580
0
        return NULL;
13581
0
    }
13582
13583
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13584
0
        return NULL;
13585
0
    }
13586
13587
0
    if (setenv(name_string, value_string, 1)) {
13588
0
        return posix_error();
13589
0
    }
13590
0
    Py_RETURN_NONE;
13591
0
}
13592
#endif  /* !defined(MS_WINDOWS) */
13593
13594
13595
#ifdef MS_WINDOWS
13596
/*[clinic input]
13597
os.unsetenv
13598
    name: unicode
13599
    /
13600
13601
Delete an environment variable.
13602
[clinic start generated code]*/
13603
13604
static PyObject *
13605
os_unsetenv_impl(PyObject *module, PyObject *name)
13606
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13607
{
13608
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13609
        return NULL;
13610
    }
13611
    return win32_putenv(name, NULL);
13612
}
13613
#else
13614
/*[clinic input]
13615
os.unsetenv
13616
    name: unicode_fs_encoded
13617
    /
13618
13619
Delete an environment variable.
13620
[clinic start generated code]*/
13621
13622
static PyObject *
13623
os_unsetenv_impl(PyObject *module, PyObject *name)
13624
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13625
0
{
13626
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13627
0
        return NULL;
13628
0
    }
13629
#ifdef HAVE_BROKEN_UNSETENV
13630
    unsetenv(PyBytes_AS_STRING(name));
13631
#else
13632
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13633
0
    if (err) {
13634
0
        return posix_error();
13635
0
    }
13636
0
#endif
13637
13638
0
    Py_RETURN_NONE;
13639
0
}
13640
#endif /* !MS_WINDOWS */
13641
13642
13643
#ifdef HAVE_CLEARENV
13644
/*[clinic input]
13645
os._clearenv
13646
[clinic start generated code]*/
13647
13648
static PyObject *
13649
os__clearenv_impl(PyObject *module)
13650
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13651
0
{
13652
0
    errno = 0;
13653
0
    int err = clearenv();
13654
0
    if (err) {
13655
0
        return posix_error();
13656
0
    }
13657
0
    Py_RETURN_NONE;
13658
0
}
13659
#endif
13660
13661
13662
/*[clinic input]
13663
os.strerror
13664
13665
    code: int
13666
    /
13667
13668
Translate an error code to a message string.
13669
[clinic start generated code]*/
13670
13671
static PyObject *
13672
os_strerror_impl(PyObject *module, int code)
13673
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13674
0
{
13675
0
    char *message = strerror(code);
13676
0
    if (message == NULL) {
13677
0
        PyErr_SetString(PyExc_ValueError,
13678
0
                        "strerror() argument out of range");
13679
0
        return NULL;
13680
0
    }
13681
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13682
0
}
13683
13684
13685
#ifdef HAVE_SYS_WAIT_H
13686
#ifdef WCOREDUMP
13687
/*[clinic input]
13688
os.WCOREDUMP -> bool
13689
13690
    status: int
13691
    /
13692
13693
Return True if the process returning status was dumped to a core file.
13694
[clinic start generated code]*/
13695
13696
static int
13697
os_WCOREDUMP_impl(PyObject *module, int status)
13698
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13699
0
{
13700
0
    WAIT_TYPE wait_status;
13701
0
    WAIT_STATUS_INT(wait_status) = status;
13702
0
    return WCOREDUMP(wait_status);
13703
0
}
13704
#endif /* WCOREDUMP */
13705
13706
13707
#ifdef WIFCONTINUED
13708
/*[clinic input]
13709
os.WIFCONTINUED -> bool
13710
13711
    status: int
13712
13713
Return True if a particular process was continued from a job control stop.
13714
13715
Return True if the process returning status was continued from a
13716
job control stop.
13717
[clinic start generated code]*/
13718
13719
static int
13720
os_WIFCONTINUED_impl(PyObject *module, int status)
13721
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13722
0
{
13723
0
    WAIT_TYPE wait_status;
13724
0
    WAIT_STATUS_INT(wait_status) = status;
13725
0
    return WIFCONTINUED(wait_status);
13726
0
}
13727
#endif /* WIFCONTINUED */
13728
13729
13730
#ifdef WIFSTOPPED
13731
/*[clinic input]
13732
os.WIFSTOPPED -> bool
13733
13734
    status: int
13735
13736
Return True if the process returning status was stopped.
13737
[clinic start generated code]*/
13738
13739
static int
13740
os_WIFSTOPPED_impl(PyObject *module, int status)
13741
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13742
0
{
13743
0
    WAIT_TYPE wait_status;
13744
0
    WAIT_STATUS_INT(wait_status) = status;
13745
0
    return WIFSTOPPED(wait_status);
13746
0
}
13747
#endif /* WIFSTOPPED */
13748
13749
13750
#ifdef WIFSIGNALED
13751
/*[clinic input]
13752
os.WIFSIGNALED -> bool
13753
13754
    status: int
13755
13756
Return True if the process returning status was terminated by a signal.
13757
[clinic start generated code]*/
13758
13759
static int
13760
os_WIFSIGNALED_impl(PyObject *module, int status)
13761
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13762
0
{
13763
0
    WAIT_TYPE wait_status;
13764
0
    WAIT_STATUS_INT(wait_status) = status;
13765
0
    return WIFSIGNALED(wait_status);
13766
0
}
13767
#endif /* WIFSIGNALED */
13768
13769
13770
#ifdef WIFEXITED
13771
/*[clinic input]
13772
@permit_long_summary
13773
os.WIFEXITED -> bool
13774
13775
    status: int
13776
13777
Return True if the process returning status exited via the exit() system call.
13778
[clinic start generated code]*/
13779
13780
static int
13781
os_WIFEXITED_impl(PyObject *module, int status)
13782
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13783
0
{
13784
0
    WAIT_TYPE wait_status;
13785
0
    WAIT_STATUS_INT(wait_status) = status;
13786
0
    return WIFEXITED(wait_status);
13787
0
}
13788
#endif /* WIFEXITED */
13789
13790
13791
#ifdef WEXITSTATUS
13792
/*[clinic input]
13793
os.WEXITSTATUS -> int
13794
13795
    status: int
13796
13797
Return the process return code from status.
13798
[clinic start generated code]*/
13799
13800
static int
13801
os_WEXITSTATUS_impl(PyObject *module, int status)
13802
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13803
0
{
13804
0
    WAIT_TYPE wait_status;
13805
0
    WAIT_STATUS_INT(wait_status) = status;
13806
0
    return WEXITSTATUS(wait_status);
13807
0
}
13808
#endif /* WEXITSTATUS */
13809
13810
13811
#ifdef WTERMSIG
13812
/*[clinic input]
13813
@permit_long_summary
13814
os.WTERMSIG -> int
13815
13816
    status: int
13817
13818
Return the signal that terminated the process that provided the status value.
13819
[clinic start generated code]*/
13820
13821
static int
13822
os_WTERMSIG_impl(PyObject *module, int status)
13823
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13824
0
{
13825
0
    WAIT_TYPE wait_status;
13826
0
    WAIT_STATUS_INT(wait_status) = status;
13827
0
    return WTERMSIG(wait_status);
13828
0
}
13829
#endif /* WTERMSIG */
13830
13831
13832
#ifdef WSTOPSIG
13833
/*[clinic input]
13834
os.WSTOPSIG -> int
13835
13836
    status: int
13837
13838
Return the signal that stopped the process that provided the status value.
13839
[clinic start generated code]*/
13840
13841
static int
13842
os_WSTOPSIG_impl(PyObject *module, int status)
13843
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13844
0
{
13845
0
    WAIT_TYPE wait_status;
13846
0
    WAIT_STATUS_INT(wait_status) = status;
13847
0
    return WSTOPSIG(wait_status);
13848
0
}
13849
#endif /* WSTOPSIG */
13850
#endif /* HAVE_SYS_WAIT_H */
13851
13852
13853
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13854
#ifdef _SCO_DS
13855
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13856
   needed definitions in sys/statvfs.h */
13857
#define _SVID3
13858
#endif
13859
#include <sys/statvfs.h>
13860
13861
#ifdef __APPLE__
13862
/* On macOS struct statvfs uses 32-bit integers for block counts,
13863
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13864
 * os.statvfs is implemented in terms of statfs(2).
13865
 */
13866
13867
static PyObject*
13868
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13869
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13870
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13871
    if (v == NULL) {
13872
        return NULL;
13873
    }
13874
13875
    long flags = 0;
13876
    if (st.f_flags & MNT_RDONLY) {
13877
        flags |= ST_RDONLY;
13878
    }
13879
    if (st.f_flags & MNT_NOSUID) {
13880
        flags |= ST_NOSUID;
13881
    }
13882
13883
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13884
13885
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13886
    do {                                                 \
13887
        PyObject *obj = (EXPR);                          \
13888
        if (obj == NULL) {                               \
13889
            Py_DECREF((SEQ));                            \
13890
            return NULL;                                 \
13891
        }                                                \
13892
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13893
    } while (0)
13894
13895
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13896
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13897
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13898
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13899
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13900
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13901
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13902
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13903
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13904
13905
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13906
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13907
13908
#undef SET_ITEM
13909
13910
    return v;
13911
}
13912
13913
#else
13914
13915
13916
13917
static PyObject*
13918
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13919
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13920
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13921
0
    if (v == NULL)
13922
0
        return NULL;
13923
13924
0
    int pos = 0;
13925
13926
0
#define SET_RESULT(CALL)                                     \
13927
0
    do {                                                     \
13928
0
        PyObject *item = (CALL);                             \
13929
0
        if (item == NULL) {                                  \
13930
0
            Py_DECREF(v);                                    \
13931
0
            return NULL;                                     \
13932
0
        }                                                    \
13933
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13934
0
    } while(0)
13935
13936
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13937
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13938
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13939
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13940
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13941
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13942
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13943
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13944
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13945
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13946
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13947
#else
13948
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13949
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13950
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13951
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13952
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13953
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13954
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13955
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13956
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13957
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13958
#endif
13959
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13960
 * (issue #32390). */
13961
#if defined(_AIX) && defined(_ALL_SOURCE)
13962
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13963
#else
13964
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13965
0
#endif
13966
13967
0
#undef SET_RESULT
13968
13969
0
    return v;
13970
0
}
13971
13972
#endif
13973
13974
13975
/*[clinic input]
13976
os.fstatvfs
13977
    fd: int
13978
    /
13979
13980
Perform an fstatvfs system call on the given fd.
13981
13982
Equivalent to statvfs(fd).
13983
[clinic start generated code]*/
13984
13985
static PyObject *
13986
os_fstatvfs_impl(PyObject *module, int fd)
13987
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13988
0
{
13989
0
    int result;
13990
0
    int async_err = 0;
13991
#ifdef __APPLE__
13992
    struct statfs st;
13993
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13994
     * the former uses 32-bit values for block counts.
13995
     */
13996
    do {
13997
        Py_BEGIN_ALLOW_THREADS
13998
        result = fstatfs(fd, &st);
13999
        Py_END_ALLOW_THREADS
14000
    } while (result != 0 && errno == EINTR &&
14001
             !(async_err = PyErr_CheckSignals()));
14002
    if (result != 0)
14003
        return (!async_err) ? posix_error() : NULL;
14004
14005
    return _pystatvfs_fromstructstatfs(module, st);
14006
#else
14007
0
    struct statvfs st;
14008
14009
0
    do {
14010
0
        Py_BEGIN_ALLOW_THREADS
14011
0
        result = fstatvfs(fd, &st);
14012
0
        Py_END_ALLOW_THREADS
14013
0
    } while (result != 0 && errno == EINTR &&
14014
0
             !(async_err = PyErr_CheckSignals()));
14015
0
    if (result != 0)
14016
0
        return (!async_err) ? posix_error() : NULL;
14017
14018
0
    return _pystatvfs_fromstructstatvfs(module, st);
14019
0
#endif
14020
0
}
14021
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14022
14023
14024
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14025
#include <sys/statvfs.h>
14026
/*[clinic input]
14027
os.statvfs
14028
14029
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14030
14031
Perform a statvfs system call on the given path.
14032
14033
path may always be specified as a string.
14034
On some platforms, path may also be specified as an open file descriptor.
14035
  If this functionality is unavailable, using it raises an exception.
14036
[clinic start generated code]*/
14037
14038
static PyObject *
14039
os_statvfs_impl(PyObject *module, path_t *path)
14040
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
14041
0
{
14042
0
    int result;
14043
14044
#ifdef __APPLE__
14045
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14046
     * the former uses 32-bit values for block counts.
14047
     */
14048
    struct statfs st;
14049
14050
    Py_BEGIN_ALLOW_THREADS
14051
    if (path->fd != -1) {
14052
        result = fstatfs(path->fd, &st);
14053
    }
14054
    else
14055
        result = statfs(path->narrow, &st);
14056
    Py_END_ALLOW_THREADS
14057
14058
    if (result) {
14059
        return path_error(path);
14060
    }
14061
14062
    return _pystatvfs_fromstructstatfs(module, st);
14063
14064
#else
14065
0
    struct statvfs st;
14066
14067
0
    Py_BEGIN_ALLOW_THREADS
14068
0
#ifdef HAVE_FSTATVFS
14069
0
    if (path->fd != -1) {
14070
0
        result = fstatvfs(path->fd, &st);
14071
0
    }
14072
0
    else
14073
0
#endif
14074
0
        result = statvfs(path->narrow, &st);
14075
0
    Py_END_ALLOW_THREADS
14076
14077
0
    if (result) {
14078
0
        return path_error(path);
14079
0
    }
14080
14081
0
    return _pystatvfs_fromstructstatvfs(module, st);
14082
0
#endif
14083
0
}
14084
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14085
14086
14087
#ifdef MS_WINDOWS
14088
/*[clinic input]
14089
os._getdiskusage
14090
14091
    path: path_t
14092
14093
Return disk usage statistics about the given path as a (total, free) tuple.
14094
[clinic start generated code]*/
14095
14096
static PyObject *
14097
os__getdiskusage_impl(PyObject *module, path_t *path)
14098
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
14099
{
14100
    BOOL retval;
14101
    ULARGE_INTEGER _, total, free;
14102
    DWORD err = 0;
14103
14104
    Py_BEGIN_ALLOW_THREADS
14105
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14106
    Py_END_ALLOW_THREADS
14107
    if (retval == 0) {
14108
        if (GetLastError() == ERROR_DIRECTORY) {
14109
            wchar_t *dir_path = NULL;
14110
14111
            dir_path = PyMem_New(wchar_t, path->length + 1);
14112
            if (dir_path == NULL) {
14113
                return PyErr_NoMemory();
14114
            }
14115
14116
            wcscpy_s(dir_path, path->length + 1, path->wide);
14117
14118
            if (_dirnameW(dir_path) != -1) {
14119
                Py_BEGIN_ALLOW_THREADS
14120
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14121
                Py_END_ALLOW_THREADS
14122
            }
14123
            /* Record the last error in case it's modified by PyMem_Free. */
14124
            err = GetLastError();
14125
            PyMem_Free(dir_path);
14126
            if (retval) {
14127
                goto success;
14128
            }
14129
        }
14130
        return PyErr_SetFromWindowsErr(err);
14131
    }
14132
14133
success:
14134
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14135
}
14136
#endif /* MS_WINDOWS */
14137
14138
14139
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14140
 * It maps strings representing configuration variable names to
14141
 * integer values, allowing those functions to be called with the
14142
 * magic names instead of polluting the module's namespace with tons of
14143
 * rarely-used constants.  There are three separate tables that use
14144
 * these definitions.
14145
 *
14146
 * This code is always included, even if none of the interfaces that
14147
 * need it are included.  The #if hackery needed to avoid it would be
14148
 * sufficiently pervasive that it's not worth the loss of readability.
14149
 */
14150
struct constdef {
14151
    const char *name;
14152
    int value;
14153
};
14154
14155
static int
14156
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14157
4
{
14158
4
    if (PyUnicode_Check(arg)) {
14159
4
        PyObject *table = PyObject_GetAttrString(module, tablename);
14160
4
        if (table == NULL) {
14161
0
            return 0;
14162
0
        }
14163
14164
4
        arg = PyObject_GetItem(table, arg);
14165
4
        Py_DECREF(table);
14166
4
        if (arg == NULL) {
14167
0
            PyErr_SetString(
14168
0
                PyExc_ValueError, "unrecognized configuration name");
14169
0
            return 0;
14170
0
        }
14171
4
    } else {
14172
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14173
0
    }
14174
14175
4
    int success = 0;
14176
4
    if (!PyIndex_Check(arg)) {
14177
0
        PyErr_SetString(PyExc_TypeError,
14178
0
            "configuration names must be strings or integers");
14179
4
    } else {
14180
4
        int value = PyLong_AsInt(arg);
14181
4
        if (!(value == -1 && PyErr_Occurred())) {
14182
4
            *valuep = value;
14183
4
            success = 1;
14184
4
        }
14185
4
    }
14186
4
    Py_DECREF(arg);
14187
4
    return success;
14188
4
}
14189
14190
14191
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14192
static struct constdef  posix_constants_pathconf[] = {
14193
#ifdef _PC_ABI_AIO_XFER_MAX
14194
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14195
#endif
14196
#ifdef _PC_ABI_ASYNC_IO
14197
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14198
#endif
14199
#ifdef _PC_ASYNC_IO
14200
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14201
#endif
14202
#ifdef _PC_CHOWN_RESTRICTED
14203
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14204
#endif
14205
#ifdef _PC_FILESIZEBITS
14206
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14207
#endif
14208
#ifdef _PC_LAST
14209
    {"PC_LAST", _PC_LAST},
14210
#endif
14211
#ifdef _PC_LINK_MAX
14212
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14213
#endif
14214
#ifdef _PC_MAX_CANON
14215
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14216
#endif
14217
#ifdef _PC_MAX_INPUT
14218
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14219
#endif
14220
#ifdef _PC_NAME_MAX
14221
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14222
#endif
14223
#ifdef _PC_NO_TRUNC
14224
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14225
#endif
14226
#ifdef _PC_PATH_MAX
14227
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14228
#endif
14229
#ifdef _PC_PIPE_BUF
14230
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14231
#endif
14232
#ifdef _PC_PRIO_IO
14233
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14234
#endif
14235
#ifdef _PC_SOCK_MAXBUF
14236
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14237
#endif
14238
#ifdef _PC_SYNC_IO
14239
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14240
#endif
14241
#ifdef _PC_VDISABLE
14242
    {"PC_VDISABLE",     _PC_VDISABLE},
14243
#endif
14244
#ifdef _PC_ACL_ENABLED
14245
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14246
#endif
14247
#ifdef _PC_MIN_HOLE_SIZE
14248
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14249
#endif
14250
#ifdef _PC_ALLOC_SIZE_MIN
14251
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14252
#endif
14253
#ifdef _PC_REC_INCR_XFER_SIZE
14254
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14255
#endif
14256
#ifdef _PC_REC_MAX_XFER_SIZE
14257
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14258
#endif
14259
#ifdef _PC_REC_MIN_XFER_SIZE
14260
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14261
#endif
14262
#ifdef _PC_REC_XFER_ALIGN
14263
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14264
#endif
14265
#ifdef _PC_SYMLINK_MAX
14266
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14267
#endif
14268
#ifdef _PC_XATTR_ENABLED
14269
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14270
#endif
14271
#ifdef _PC_XATTR_EXISTS
14272
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14273
#endif
14274
#ifdef _PC_TIMESTAMP_RESOLUTION
14275
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14276
#endif
14277
};
14278
#endif
14279
14280
14281
#ifdef HAVE_FPATHCONF
14282
/*[clinic input]
14283
os.fpathconf -> long
14284
14285
    fd: fildes
14286
    name: confname(table="pathconf_names")
14287
    /
14288
14289
Return the configuration limit name for the file descriptor fd.
14290
14291
If there is no limit, return -1.
14292
[clinic start generated code]*/
14293
14294
static long
14295
os_fpathconf_impl(PyObject *module, int fd, int name)
14296
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14297
0
{
14298
0
    long limit;
14299
14300
0
    errno = 0;
14301
0
    limit = fpathconf(fd, name);
14302
0
    if (limit == -1 && errno != 0)
14303
0
        posix_error();
14304
14305
0
    return limit;
14306
0
}
14307
#endif /* HAVE_FPATHCONF */
14308
14309
14310
#ifdef HAVE_PATHCONF
14311
/*[clinic input]
14312
os.pathconf -> long
14313
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14314
    name: confname(table="pathconf_names")
14315
14316
Return the configuration limit name for the file or directory path.
14317
14318
If there is no limit, return -1.
14319
On some platforms, path may also be specified as an open file descriptor.
14320
  If this functionality is unavailable, using it raises an exception.
14321
[clinic start generated code]*/
14322
14323
static long
14324
os_pathconf_impl(PyObject *module, path_t *path, int name)
14325
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
14326
0
{
14327
0
    long limit;
14328
14329
0
    errno = 0;
14330
0
#ifdef HAVE_FPATHCONF
14331
0
    if (path->fd != -1)
14332
0
        limit = fpathconf(path->fd, name);
14333
0
    else
14334
0
#endif
14335
0
        limit = pathconf(path->narrow, name);
14336
0
    if (limit == -1 && errno != 0) {
14337
0
        if (errno == EINVAL)
14338
            /* could be a path or name problem */
14339
0
            posix_error();
14340
0
        else
14341
0
            path_error(path);
14342
0
    }
14343
14344
0
    return limit;
14345
0
}
14346
#endif /* HAVE_PATHCONF */
14347
14348
#ifdef HAVE_CONFSTR
14349
static struct constdef posix_constants_confstr[] = {
14350
#ifdef _CS_ARCHITECTURE
14351
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14352
#endif
14353
#ifdef _CS_GNU_LIBC_VERSION
14354
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14355
#endif
14356
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14357
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14358
#endif
14359
#ifdef _CS_HOSTNAME
14360
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14361
#endif
14362
#ifdef _CS_HW_PROVIDER
14363
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14364
#endif
14365
#ifdef _CS_HW_SERIAL
14366
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14367
#endif
14368
#ifdef _CS_INITTAB_NAME
14369
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14370
#endif
14371
#ifdef _CS_LFS64_CFLAGS
14372
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14373
#endif
14374
#ifdef _CS_LFS64_LDFLAGS
14375
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14376
#endif
14377
#ifdef _CS_LFS64_LIBS
14378
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14379
#endif
14380
#ifdef _CS_LFS64_LINTFLAGS
14381
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14382
#endif
14383
#ifdef _CS_LFS_CFLAGS
14384
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14385
#endif
14386
#ifdef _CS_LFS_LDFLAGS
14387
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14388
#endif
14389
#ifdef _CS_LFS_LIBS
14390
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14391
#endif
14392
#ifdef _CS_LFS_LINTFLAGS
14393
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14394
#endif
14395
#ifdef _CS_MACHINE
14396
    {"CS_MACHINE",      _CS_MACHINE},
14397
#endif
14398
#ifdef _CS_PATH
14399
    {"CS_PATH", _CS_PATH},
14400
#endif
14401
#ifdef _CS_RELEASE
14402
    {"CS_RELEASE",      _CS_RELEASE},
14403
#endif
14404
#ifdef _CS_SRPC_DOMAIN
14405
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14406
#endif
14407
#ifdef _CS_SYSNAME
14408
    {"CS_SYSNAME",      _CS_SYSNAME},
14409
#endif
14410
#ifdef _CS_VERSION
14411
    {"CS_VERSION",      _CS_VERSION},
14412
#endif
14413
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14414
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14415
#endif
14416
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14417
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14418
#endif
14419
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14420
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14421
#endif
14422
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14423
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14424
#endif
14425
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14426
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14427
#endif
14428
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14429
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14430
#endif
14431
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14432
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14433
#endif
14434
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14435
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14436
#endif
14437
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14438
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14439
#endif
14440
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14441
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14442
#endif
14443
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14444
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14445
#endif
14446
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14447
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14448
#endif
14449
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14450
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14451
#endif
14452
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14453
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14454
#endif
14455
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14456
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14457
#endif
14458
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14459
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14460
#endif
14461
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14462
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14463
#endif
14464
#ifdef _MIPS_CS_BASE
14465
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14466
#endif
14467
#ifdef _MIPS_CS_HOSTID
14468
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14469
#endif
14470
#ifdef _MIPS_CS_HW_NAME
14471
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14472
#endif
14473
#ifdef _MIPS_CS_NUM_PROCESSORS
14474
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14475
#endif
14476
#ifdef _MIPS_CS_OSREL_MAJ
14477
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14478
#endif
14479
#ifdef _MIPS_CS_OSREL_MIN
14480
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14481
#endif
14482
#ifdef _MIPS_CS_OSREL_PATCH
14483
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14484
#endif
14485
#ifdef _MIPS_CS_OS_NAME
14486
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14487
#endif
14488
#ifdef _MIPS_CS_OS_PROVIDER
14489
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14490
#endif
14491
#ifdef _MIPS_CS_PROCESSORS
14492
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14493
#endif
14494
#ifdef _MIPS_CS_SERIAL
14495
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14496
#endif
14497
#ifdef _MIPS_CS_VENDOR
14498
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14499
#endif
14500
};
14501
14502
14503
/*[clinic input]
14504
os.confstr
14505
14506
    name: confname(table="confstr_names")
14507
    /
14508
14509
Return a string-valued system configuration variable.
14510
[clinic start generated code]*/
14511
14512
static PyObject *
14513
os_confstr_impl(PyObject *module, int name)
14514
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14515
2
{
14516
2
    PyObject *result = NULL;
14517
2
    char buffer[255];
14518
2
    size_t len;
14519
14520
2
    errno = 0;
14521
2
    len = confstr(name, buffer, sizeof(buffer));
14522
2
    if (len == 0) {
14523
0
        if (errno) {
14524
0
            posix_error();
14525
0
            return NULL;
14526
0
        }
14527
0
        else {
14528
0
            Py_RETURN_NONE;
14529
0
        }
14530
0
    }
14531
14532
2
    if (len >= sizeof(buffer)) {
14533
0
        size_t len2;
14534
0
        char *buf = PyMem_Malloc(len);
14535
0
        if (buf == NULL)
14536
0
            return PyErr_NoMemory();
14537
0
        len2 = confstr(name, buf, len);
14538
0
        assert(len == len2);
14539
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14540
0
        PyMem_Free(buf);
14541
0
    }
14542
2
    else
14543
2
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14544
2
    return result;
14545
2
}
14546
#endif /* HAVE_CONFSTR */
14547
14548
14549
#ifdef HAVE_SYSCONF
14550
static struct constdef posix_constants_sysconf[] = {
14551
#ifdef _SC_2_CHAR_TERM
14552
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14553
#endif
14554
#ifdef _SC_2_C_BIND
14555
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14556
#endif
14557
#ifdef _SC_2_C_DEV
14558
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14559
#endif
14560
#ifdef _SC_2_C_VERSION
14561
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14562
#endif
14563
#ifdef _SC_2_FORT_DEV
14564
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14565
#endif
14566
#ifdef _SC_2_FORT_RUN
14567
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14568
#endif
14569
#ifdef _SC_2_LOCALEDEF
14570
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14571
#endif
14572
#ifdef _SC_2_SW_DEV
14573
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14574
#endif
14575
#ifdef _SC_2_UPE
14576
    {"SC_2_UPE",        _SC_2_UPE},
14577
#endif
14578
#ifdef _SC_2_VERSION
14579
    {"SC_2_VERSION",    _SC_2_VERSION},
14580
#endif
14581
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14582
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14583
#endif
14584
#ifdef _SC_ACL
14585
    {"SC_ACL",  _SC_ACL},
14586
#endif
14587
#ifdef _SC_AIO_LISTIO_MAX
14588
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14589
#endif
14590
#ifdef _SC_AIO_MAX
14591
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14592
#endif
14593
#ifdef _SC_AIO_PRIO_DELTA_MAX
14594
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14595
#endif
14596
#ifdef _SC_ARG_MAX
14597
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14598
#endif
14599
#ifdef _SC_ASYNCHRONOUS_IO
14600
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14601
#endif
14602
#ifdef _SC_ATEXIT_MAX
14603
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14604
#endif
14605
#ifdef _SC_AUDIT
14606
    {"SC_AUDIT",        _SC_AUDIT},
14607
#endif
14608
#ifdef _SC_AVPHYS_PAGES
14609
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14610
#endif
14611
#ifdef _SC_BC_BASE_MAX
14612
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14613
#endif
14614
#ifdef _SC_BC_DIM_MAX
14615
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14616
#endif
14617
#ifdef _SC_BC_SCALE_MAX
14618
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14619
#endif
14620
#ifdef _SC_BC_STRING_MAX
14621
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14622
#endif
14623
#ifdef _SC_CAP
14624
    {"SC_CAP",  _SC_CAP},
14625
#endif
14626
#ifdef _SC_CHARCLASS_NAME_MAX
14627
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14628
#endif
14629
#ifdef _SC_CHAR_BIT
14630
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14631
#endif
14632
#ifdef _SC_CHAR_MAX
14633
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14634
#endif
14635
#ifdef _SC_CHAR_MIN
14636
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14637
#endif
14638
#ifdef _SC_CHILD_MAX
14639
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14640
#endif
14641
#ifdef _SC_CLK_TCK
14642
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14643
#endif
14644
#ifdef _SC_COHER_BLKSZ
14645
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14646
#endif
14647
#ifdef _SC_COLL_WEIGHTS_MAX
14648
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14649
#endif
14650
#ifdef _SC_DCACHE_ASSOC
14651
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14652
#endif
14653
#ifdef _SC_DCACHE_BLKSZ
14654
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14655
#endif
14656
#ifdef _SC_DCACHE_LINESZ
14657
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14658
#endif
14659
#ifdef _SC_DCACHE_SZ
14660
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14661
#endif
14662
#ifdef _SC_DCACHE_TBLKSZ
14663
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14664
#endif
14665
#ifdef _SC_DELAYTIMER_MAX
14666
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14667
#endif
14668
#ifdef _SC_EQUIV_CLASS_MAX
14669
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14670
#endif
14671
#ifdef _SC_EXPR_NEST_MAX
14672
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14673
#endif
14674
#ifdef _SC_FSYNC
14675
    {"SC_FSYNC",        _SC_FSYNC},
14676
#endif
14677
#ifdef _SC_GETGR_R_SIZE_MAX
14678
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14679
#endif
14680
#ifdef _SC_GETPW_R_SIZE_MAX
14681
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14682
#endif
14683
#ifdef _SC_ICACHE_ASSOC
14684
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14685
#endif
14686
#ifdef _SC_ICACHE_BLKSZ
14687
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14688
#endif
14689
#ifdef _SC_ICACHE_LINESZ
14690
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14691
#endif
14692
#ifdef _SC_ICACHE_SZ
14693
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14694
#endif
14695
#ifdef _SC_INF
14696
    {"SC_INF",  _SC_INF},
14697
#endif
14698
#ifdef _SC_INT_MAX
14699
    {"SC_INT_MAX",      _SC_INT_MAX},
14700
#endif
14701
#ifdef _SC_INT_MIN
14702
    {"SC_INT_MIN",      _SC_INT_MIN},
14703
#endif
14704
#ifdef _SC_IOV_MAX
14705
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14706
#endif
14707
#ifdef _SC_IP_SECOPTS
14708
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14709
#endif
14710
#ifdef _SC_JOB_CONTROL
14711
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14712
#endif
14713
#ifdef _SC_KERN_POINTERS
14714
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14715
#endif
14716
#ifdef _SC_KERN_SIM
14717
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14718
#endif
14719
#ifdef _SC_LINE_MAX
14720
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14721
#endif
14722
#ifdef _SC_LOGIN_NAME_MAX
14723
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14724
#endif
14725
#ifdef _SC_LOGNAME_MAX
14726
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14727
#endif
14728
#ifdef _SC_LONG_BIT
14729
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14730
#endif
14731
#ifdef _SC_MAC
14732
    {"SC_MAC",  _SC_MAC},
14733
#endif
14734
#ifdef _SC_MAPPED_FILES
14735
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14736
#endif
14737
#ifdef _SC_MAXPID
14738
    {"SC_MAXPID",       _SC_MAXPID},
14739
#endif
14740
#ifdef _SC_MB_LEN_MAX
14741
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14742
#endif
14743
#ifdef _SC_MEMLOCK
14744
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14745
#endif
14746
#ifdef _SC_MEMLOCK_RANGE
14747
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14748
#endif
14749
#ifdef _SC_MEMORY_PROTECTION
14750
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14751
#endif
14752
#ifdef _SC_MESSAGE_PASSING
14753
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14754
#endif
14755
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14756
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14757
#endif
14758
#ifdef _SC_MQ_OPEN_MAX
14759
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14760
#endif
14761
#ifdef _SC_MQ_PRIO_MAX
14762
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14763
#endif
14764
#ifdef _SC_NACLS_MAX
14765
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14766
#endif
14767
#ifdef _SC_NGROUPS_MAX
14768
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14769
#endif
14770
#ifdef _SC_NL_ARGMAX
14771
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14772
#endif
14773
#ifdef _SC_NL_LANGMAX
14774
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14775
#endif
14776
#ifdef _SC_NL_MSGMAX
14777
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14778
#endif
14779
#ifdef _SC_NL_NMAX
14780
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14781
#endif
14782
#ifdef _SC_NL_SETMAX
14783
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14784
#endif
14785
#ifdef _SC_NL_TEXTMAX
14786
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14787
#endif
14788
#ifdef _SC_NPROCESSORS_CONF
14789
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14790
#endif
14791
#ifdef _SC_NPROCESSORS_ONLN
14792
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14793
#endif
14794
#ifdef _SC_NPROC_CONF
14795
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14796
#endif
14797
#ifdef _SC_NPROC_ONLN
14798
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14799
#endif
14800
#ifdef _SC_NZERO
14801
    {"SC_NZERO",        _SC_NZERO},
14802
#endif
14803
#ifdef _SC_OPEN_MAX
14804
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14805
#endif
14806
#ifdef _SC_PAGESIZE
14807
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14808
#endif
14809
#ifdef _SC_PAGE_SIZE
14810
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14811
#endif
14812
#ifdef _SC_AIX_REALMEM
14813
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14814
#endif
14815
#ifdef _SC_PASS_MAX
14816
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14817
#endif
14818
#ifdef _SC_PHYS_PAGES
14819
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14820
#endif
14821
#ifdef _SC_PII
14822
    {"SC_PII",  _SC_PII},
14823
#endif
14824
#ifdef _SC_PII_INTERNET
14825
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14826
#endif
14827
#ifdef _SC_PII_INTERNET_DGRAM
14828
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14829
#endif
14830
#ifdef _SC_PII_INTERNET_STREAM
14831
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14832
#endif
14833
#ifdef _SC_PII_OSI
14834
    {"SC_PII_OSI",      _SC_PII_OSI},
14835
#endif
14836
#ifdef _SC_PII_OSI_CLTS
14837
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14838
#endif
14839
#ifdef _SC_PII_OSI_COTS
14840
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14841
#endif
14842
#ifdef _SC_PII_OSI_M
14843
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14844
#endif
14845
#ifdef _SC_PII_SOCKET
14846
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14847
#endif
14848
#ifdef _SC_PII_XTI
14849
    {"SC_PII_XTI",      _SC_PII_XTI},
14850
#endif
14851
#ifdef _SC_POLL
14852
    {"SC_POLL", _SC_POLL},
14853
#endif
14854
#ifdef _SC_PRIORITIZED_IO
14855
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14856
#endif
14857
#ifdef _SC_PRIORITY_SCHEDULING
14858
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14859
#endif
14860
#ifdef _SC_REALTIME_SIGNALS
14861
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14862
#endif
14863
#ifdef _SC_RE_DUP_MAX
14864
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14865
#endif
14866
#ifdef _SC_RTSIG_MAX
14867
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14868
#endif
14869
#ifdef _SC_SAVED_IDS
14870
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14871
#endif
14872
#ifdef _SC_SCHAR_MAX
14873
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14874
#endif
14875
#ifdef _SC_SCHAR_MIN
14876
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14877
#endif
14878
#ifdef _SC_SELECT
14879
    {"SC_SELECT",       _SC_SELECT},
14880
#endif
14881
#ifdef _SC_SEMAPHORES
14882
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14883
#endif
14884
#ifdef _SC_SEM_NSEMS_MAX
14885
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14886
#endif
14887
#ifdef _SC_SEM_VALUE_MAX
14888
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14889
#endif
14890
#ifdef _SC_SHARED_MEMORY_OBJECTS
14891
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14892
#endif
14893
#ifdef _SC_SHRT_MAX
14894
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14895
#endif
14896
#ifdef _SC_SHRT_MIN
14897
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14898
#endif
14899
#ifdef _SC_SIGQUEUE_MAX
14900
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14901
#endif
14902
#ifdef _SC_SIGRT_MAX
14903
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14904
#endif
14905
#ifdef _SC_SIGRT_MIN
14906
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14907
#endif
14908
#ifdef _SC_SOFTPOWER
14909
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14910
#endif
14911
#ifdef _SC_SPLIT_CACHE
14912
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14913
#endif
14914
#ifdef _SC_SSIZE_MAX
14915
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14916
#endif
14917
#ifdef _SC_STACK_PROT
14918
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14919
#endif
14920
#ifdef _SC_STREAM_MAX
14921
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14922
#endif
14923
#ifdef _SC_SYNCHRONIZED_IO
14924
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14925
#endif
14926
#ifdef _SC_THREADS
14927
    {"SC_THREADS",      _SC_THREADS},
14928
#endif
14929
#ifdef _SC_THREAD_ATTR_STACKADDR
14930
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14931
#endif
14932
#ifdef _SC_THREAD_ATTR_STACKSIZE
14933
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14934
#endif
14935
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14936
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14937
#endif
14938
#ifdef _SC_THREAD_KEYS_MAX
14939
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14940
#endif
14941
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14942
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14943
#endif
14944
#ifdef _SC_THREAD_PRIO_INHERIT
14945
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14946
#endif
14947
#ifdef _SC_THREAD_PRIO_PROTECT
14948
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14949
#endif
14950
#ifdef _SC_THREAD_PROCESS_SHARED
14951
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14952
#endif
14953
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14954
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14955
#endif
14956
#ifdef _SC_THREAD_STACK_MIN
14957
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14958
#endif
14959
#ifdef _SC_THREAD_THREADS_MAX
14960
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14961
#endif
14962
#ifdef _SC_TIMERS
14963
    {"SC_TIMERS",       _SC_TIMERS},
14964
#endif
14965
#ifdef _SC_TIMER_MAX
14966
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14967
#endif
14968
#ifdef _SC_TTY_NAME_MAX
14969
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14970
#endif
14971
#ifdef _SC_TZNAME_MAX
14972
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14973
#endif
14974
#ifdef _SC_T_IOV_MAX
14975
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14976
#endif
14977
#ifdef _SC_UCHAR_MAX
14978
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14979
#endif
14980
#ifdef _SC_UINT_MAX
14981
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14982
#endif
14983
#ifdef _SC_UIO_MAXIOV
14984
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14985
#endif
14986
#ifdef _SC_ULONG_MAX
14987
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14988
#endif
14989
#ifdef _SC_USHRT_MAX
14990
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14991
#endif
14992
#ifdef _SC_VERSION
14993
    {"SC_VERSION",      _SC_VERSION},
14994
#endif
14995
#ifdef _SC_WORD_BIT
14996
    {"SC_WORD_BIT",     _SC_WORD_BIT},
14997
#endif
14998
#ifdef _SC_XBS5_ILP32_OFF32
14999
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15000
#endif
15001
#ifdef _SC_XBS5_ILP32_OFFBIG
15002
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15003
#endif
15004
#ifdef _SC_XBS5_LP64_OFF64
15005
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15006
#endif
15007
#ifdef _SC_XBS5_LPBIG_OFFBIG
15008
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15009
#endif
15010
#ifdef _SC_XOPEN_CRYPT
15011
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15012
#endif
15013
#ifdef _SC_XOPEN_ENH_I18N
15014
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15015
#endif
15016
#ifdef _SC_XOPEN_LEGACY
15017
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15018
#endif
15019
#ifdef _SC_XOPEN_REALTIME
15020
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15021
#endif
15022
#ifdef _SC_XOPEN_REALTIME_THREADS
15023
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15024
#endif
15025
#ifdef _SC_XOPEN_SHM
15026
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15027
#endif
15028
#ifdef _SC_XOPEN_UNIX
15029
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15030
#endif
15031
#ifdef _SC_XOPEN_VERSION
15032
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15033
#endif
15034
#ifdef _SC_XOPEN_XCU_VERSION
15035
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15036
#endif
15037
#ifdef _SC_XOPEN_XPG2
15038
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15039
#endif
15040
#ifdef _SC_XOPEN_XPG3
15041
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15042
#endif
15043
#ifdef _SC_XOPEN_XPG4
15044
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15045
#endif
15046
#ifdef _SC_MINSIGSTKSZ
15047
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15048
#endif
15049
};
15050
15051
15052
/*[clinic input]
15053
os.sysconf -> long
15054
    name: confname(table="sysconf_names")
15055
    /
15056
15057
Return an integer-valued system configuration variable.
15058
[clinic start generated code]*/
15059
15060
static long
15061
os_sysconf_impl(PyObject *module, int name)
15062
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15063
2
{
15064
2
    long value;
15065
15066
2
    errno = 0;
15067
2
    value = sysconf(name);
15068
2
    if (value == -1 && errno != 0)
15069
0
        posix_error();
15070
2
    return value;
15071
2
}
15072
#endif /* HAVE_SYSCONF */
15073
15074
15075
static int
15076
setup_confname_table(struct constdef *table, size_t tablesize,
15077
                     const char *tablename, PyObject *module)
15078
96
{
15079
96
    PyObject *d = PyDict_New();
15080
96
    if (d == NULL)
15081
0
        return -1;
15082
15083
5.88k
    for (size_t i=0; i < tablesize; ++i) {
15084
5.79k
        PyObject *o = PyLong_FromLong(table[i].value);
15085
5.79k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15086
0
            Py_XDECREF(o);
15087
0
            Py_DECREF(d);
15088
0
            return -1;
15089
0
        }
15090
5.79k
        Py_DECREF(o);
15091
5.79k
    }
15092
96
    return PyModule_Add(module, tablename, d);
15093
96
}
15094
15095
/* Return -1 on failure, 0 on success. */
15096
static int
15097
setup_confname_tables(PyObject *module)
15098
32
{
15099
32
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15100
32
    if (setup_confname_table(posix_constants_pathconf,
15101
32
                             sizeof(posix_constants_pathconf)
15102
32
                               / sizeof(struct constdef),
15103
32
                             "pathconf_names", module))
15104
0
        return -1;
15105
32
#endif
15106
32
#ifdef HAVE_CONFSTR
15107
32
    if (setup_confname_table(posix_constants_confstr,
15108
32
                             sizeof(posix_constants_confstr)
15109
32
                               / sizeof(struct constdef),
15110
32
                             "confstr_names", module))
15111
0
        return -1;
15112
32
#endif
15113
32
#ifdef HAVE_SYSCONF
15114
32
    if (setup_confname_table(posix_constants_sysconf,
15115
32
                             sizeof(posix_constants_sysconf)
15116
32
                               / sizeof(struct constdef),
15117
32
                             "sysconf_names", module))
15118
0
        return -1;
15119
32
#endif
15120
32
    return 0;
15121
32
}
15122
15123
15124
/*[clinic input]
15125
os.abort
15126
15127
Abort the interpreter immediately.
15128
15129
This function 'dumps core' or otherwise fails in the hardest way possible
15130
on the hosting operating system.  This function never returns.
15131
[clinic start generated code]*/
15132
15133
static PyObject *
15134
os_abort_impl(PyObject *module)
15135
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
15136
0
{
15137
0
    abort();
15138
    /*NOTREACHED*/
15139
#ifndef __clang__
15140
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15141
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15142
       is smarter and emits a warning on the return. */
15143
    Py_FatalError("abort() called from Python code didn't abort!");
15144
    return NULL;
15145
#endif
15146
0
}
15147
15148
#ifdef MS_WINDOWS
15149
/* Grab ShellExecute dynamically from shell32 */
15150
static int has_ShellExecute = -1;
15151
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15152
                                              LPCWSTR, INT);
15153
static int
15154
check_ShellExecute(void)
15155
{
15156
    HINSTANCE hShell32;
15157
15158
    /* only recheck */
15159
    if (-1 == has_ShellExecute) {
15160
        Py_BEGIN_ALLOW_THREADS
15161
        /* Security note: this call is not vulnerable to "DLL hijacking".
15162
           SHELL32 is part of "KnownDLLs" and so Windows always load
15163
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15164
           in the DLL search path. */
15165
        hShell32 = LoadLibraryW(L"SHELL32");
15166
        if (hShell32) {
15167
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15168
                                            "ShellExecuteW");
15169
            has_ShellExecute = Py_ShellExecuteW != NULL;
15170
        } else {
15171
            has_ShellExecute = 0;
15172
        }
15173
        Py_END_ALLOW_THREADS
15174
    }
15175
    return has_ShellExecute;
15176
}
15177
15178
15179
/*[clinic input]
15180
os.startfile
15181
    filepath: path_t
15182
    operation: Py_UNICODE = NULL
15183
    arguments: Py_UNICODE = NULL
15184
    cwd: path_t(nullable=True) = None
15185
    show_cmd: int = 1
15186
15187
Start a file with its associated application.
15188
15189
When "operation" is not specified or "open", this acts like
15190
double-clicking the file in Explorer, or giving the file name as an
15191
argument to the DOS "start" command: the file is opened with whatever
15192
application (if any) its extension is associated.
15193
When another "operation" is given, it specifies what should be done with
15194
the file.  A typical operation is "print".
15195
15196
"arguments" is passed to the application, but should be omitted if the
15197
file is a document.
15198
15199
"cwd" is the working directory for the operation. If "filepath" is
15200
relative, it will be resolved against this directory. This argument
15201
should usually be an absolute path.
15202
15203
"show_cmd" can be used to override the recommended visibility option.
15204
See the Windows ShellExecute documentation for values.
15205
15206
startfile returns as soon as the associated application is launched.
15207
There is no option to wait for the application to close, and no way
15208
to retrieve the application's exit status.
15209
15210
The filepath is relative to the current directory.  If you want to use
15211
an absolute path, make sure the first character is not a slash ("/");
15212
the underlying Win32 ShellExecute function doesn't work if it is.
15213
[clinic start generated code]*/
15214
15215
static PyObject *
15216
os_startfile_impl(PyObject *module, path_t *filepath,
15217
                  const wchar_t *operation, const wchar_t *arguments,
15218
                  path_t *cwd, int show_cmd)
15219
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15220
{
15221
    HINSTANCE rc;
15222
15223
    if(!check_ShellExecute()) {
15224
        /* If the OS doesn't have ShellExecute, return a
15225
           NotImplementedError. */
15226
        return PyErr_Format(PyExc_NotImplementedError,
15227
            "startfile not available on this platform");
15228
    }
15229
15230
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15231
        return NULL;
15232
    }
15233
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15234
                    arguments, cwd->object ? cwd->object : Py_None,
15235
                    show_cmd) < 0) {
15236
        return NULL;
15237
    }
15238
15239
    Py_BEGIN_ALLOW_THREADS
15240
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15241
                          arguments, cwd->wide, show_cmd);
15242
    Py_END_ALLOW_THREADS
15243
15244
    if (rc <= (HINSTANCE)32) {
15245
        win32_error_object("startfile", filepath->object);
15246
        return NULL;
15247
    }
15248
    Py_RETURN_NONE;
15249
}
15250
#endif /* MS_WINDOWS */
15251
15252
15253
#ifdef HAVE_GETLOADAVG
15254
/*[clinic input]
15255
os.getloadavg
15256
15257
Return average recent system load information.
15258
15259
Return the number of processes in the system run queue averaged over
15260
the last 1, 5, and 15 minutes as a tuple of three floats.
15261
Raises OSError if the load average was unobtainable.
15262
[clinic start generated code]*/
15263
15264
static PyObject *
15265
os_getloadavg_impl(PyObject *module)
15266
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15267
0
{
15268
0
    double loadavg[3];
15269
0
    if (getloadavg(loadavg, 3)!=3) {
15270
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15271
0
        return NULL;
15272
0
    } else
15273
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15274
0
}
15275
#endif /* HAVE_GETLOADAVG */
15276
15277
15278
/*[clinic input]
15279
os.device_encoding
15280
    fd: int
15281
15282
Return a string describing the encoding of a terminal's file descriptor.
15283
15284
The file descriptor must be attached to a terminal.
15285
If the device is not a terminal, return None.
15286
[clinic start generated code]*/
15287
15288
static PyObject *
15289
os_device_encoding_impl(PyObject *module, int fd)
15290
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15291
0
{
15292
0
    return _Py_device_encoding(fd);
15293
0
}
15294
15295
15296
#ifdef HAVE_SETRESUID
15297
/*[clinic input]
15298
os.setresuid
15299
15300
    ruid: uid_t
15301
    euid: uid_t
15302
    suid: uid_t
15303
    /
15304
15305
Set the current process's real, effective, and saved user ids.
15306
[clinic start generated code]*/
15307
15308
static PyObject *
15309
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15310
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15311
0
{
15312
0
    if (setresuid(ruid, euid, suid) < 0)
15313
0
        return posix_error();
15314
0
    Py_RETURN_NONE;
15315
0
}
15316
#endif /* HAVE_SETRESUID */
15317
15318
15319
#ifdef HAVE_SETRESGID
15320
/*[clinic input]
15321
os.setresgid
15322
15323
    rgid: gid_t
15324
    egid: gid_t
15325
    sgid: gid_t
15326
    /
15327
15328
Set the current process's real, effective, and saved group ids.
15329
[clinic start generated code]*/
15330
15331
static PyObject *
15332
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15333
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15334
0
{
15335
0
    if (setresgid(rgid, egid, sgid) < 0)
15336
0
        return posix_error();
15337
0
    Py_RETURN_NONE;
15338
0
}
15339
#endif /* HAVE_SETRESGID */
15340
15341
15342
#ifdef HAVE_GETRESUID
15343
/*[clinic input]
15344
os.getresuid
15345
15346
Return a tuple of the current process's real, effective, and saved user ids.
15347
[clinic start generated code]*/
15348
15349
static PyObject *
15350
os_getresuid_impl(PyObject *module)
15351
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
15352
0
{
15353
0
    uid_t ruid, euid, suid;
15354
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15355
0
        return posix_error();
15356
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15357
0
                                  _PyLong_FromUid(euid),
15358
0
                                  _PyLong_FromUid(suid));
15359
0
}
15360
#endif /* HAVE_GETRESUID */
15361
15362
15363
#ifdef HAVE_GETRESGID
15364
/*[clinic input]
15365
@permit_long_summary
15366
os.getresgid
15367
15368
Return a tuple of the current process's real, effective, and saved group ids.
15369
[clinic start generated code]*/
15370
15371
static PyObject *
15372
os_getresgid_impl(PyObject *module)
15373
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15374
0
{
15375
0
    gid_t rgid, egid, sgid;
15376
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15377
0
        return posix_error();
15378
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15379
0
                                  _PyLong_FromGid(egid),
15380
0
                                  _PyLong_FromGid(sgid));
15381
0
}
15382
#endif /* HAVE_GETRESGID */
15383
15384
15385
#ifdef USE_XATTRS
15386
/*[clinic input]
15387
os.getxattr
15388
15389
    path: path_t(allow_fd=True)
15390
    attribute: path_t
15391
    *
15392
    follow_symlinks: bool = True
15393
15394
Return the value of extended attribute attribute on path.
15395
15396
path may be either a string, a path-like object, or an open file descriptor.
15397
If follow_symlinks is False, and the last element of the path is a symbolic
15398
  link, getxattr will examine the symbolic link itself instead of the file
15399
  the link points to.
15400
15401
[clinic start generated code]*/
15402
15403
static PyObject *
15404
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15405
                 int follow_symlinks)
15406
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
15407
0
{
15408
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
15409
0
        return NULL;
15410
15411
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15412
0
        return NULL;
15413
0
    }
15414
15415
0
    for (Py_ssize_t i = 0; ; i++) {
15416
0
        ssize_t result;
15417
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15418
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15419
0
        if (!buffer_size) {
15420
0
            path_error(path);
15421
0
            return NULL;
15422
0
        }
15423
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15424
0
        if (writer == NULL) {
15425
0
            return NULL;
15426
0
        }
15427
0
        void *ptr = PyBytesWriter_GetData(writer);
15428
15429
0
        Py_BEGIN_ALLOW_THREADS;
15430
0
        if (path->fd >= 0)
15431
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15432
0
        else if (follow_symlinks)
15433
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15434
0
        else
15435
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15436
0
        Py_END_ALLOW_THREADS;
15437
15438
0
        if (result < 0) {
15439
0
            PyBytesWriter_Discard(writer);
15440
0
            if (errno == ERANGE) {
15441
0
                continue;
15442
0
            }
15443
0
            path_error(path);
15444
0
            return NULL;
15445
0
        }
15446
15447
0
        return PyBytesWriter_FinishWithSize(writer, result);
15448
0
    }
15449
0
}
15450
15451
15452
/*[clinic input]
15453
@permit_long_docstring_body
15454
os.setxattr
15455
15456
    path: path_t(allow_fd=True)
15457
    attribute: path_t
15458
    value: Py_buffer
15459
    flags: int = 0
15460
    *
15461
    follow_symlinks: bool = True
15462
15463
Set extended attribute attribute on path to value.
15464
15465
path may be either a string, a path-like object,  or an open file descriptor.
15466
If follow_symlinks is False, and the last element of the path is a symbolic
15467
  link, setxattr will modify the symbolic link itself instead of the file
15468
  the link points to.
15469
15470
[clinic start generated code]*/
15471
15472
static PyObject *
15473
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15474
                 Py_buffer *value, int flags, int follow_symlinks)
15475
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15476
0
{
15477
0
    ssize_t result;
15478
15479
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
15480
0
        return NULL;
15481
15482
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15483
0
                    value->buf, value->len, flags) < 0) {
15484
0
        return NULL;
15485
0
    }
15486
15487
0
    Py_BEGIN_ALLOW_THREADS;
15488
0
    if (path->fd > -1)
15489
0
        result = fsetxattr(path->fd, attribute->narrow,
15490
0
                           value->buf, value->len, flags);
15491
0
    else if (follow_symlinks)
15492
0
        result = setxattr(path->narrow, attribute->narrow,
15493
0
                           value->buf, value->len, flags);
15494
0
    else
15495
0
        result = lsetxattr(path->narrow, attribute->narrow,
15496
0
                           value->buf, value->len, flags);
15497
0
    Py_END_ALLOW_THREADS;
15498
15499
0
    if (result) {
15500
0
        path_error(path);
15501
0
        return NULL;
15502
0
    }
15503
15504
0
    Py_RETURN_NONE;
15505
0
}
15506
15507
15508
/*[clinic input]
15509
os.removexattr
15510
15511
    path: path_t(allow_fd=True)
15512
    attribute: path_t
15513
    *
15514
    follow_symlinks: bool = True
15515
15516
Remove extended attribute attribute on path.
15517
15518
path may be either a string, a path-like object, or an open file descriptor.
15519
If follow_symlinks is False, and the last element of the path is a symbolic
15520
  link, removexattr will modify the symbolic link itself instead of the file
15521
  the link points to.
15522
15523
[clinic start generated code]*/
15524
15525
static PyObject *
15526
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15527
                    int follow_symlinks)
15528
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15529
0
{
15530
0
    ssize_t result;
15531
15532
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
15533
0
        return NULL;
15534
15535
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15536
0
        return NULL;
15537
0
    }
15538
15539
0
    Py_BEGIN_ALLOW_THREADS;
15540
0
    if (path->fd > -1)
15541
0
        result = fremovexattr(path->fd, attribute->narrow);
15542
0
    else if (follow_symlinks)
15543
0
        result = removexattr(path->narrow, attribute->narrow);
15544
0
    else
15545
0
        result = lremovexattr(path->narrow, attribute->narrow);
15546
0
    Py_END_ALLOW_THREADS;
15547
15548
0
    if (result) {
15549
0
        return path_error(path);
15550
0
    }
15551
15552
0
    Py_RETURN_NONE;
15553
0
}
15554
15555
15556
/*[clinic input]
15557
@permit_long_docstring_body
15558
os.listxattr
15559
15560
    path: path_t(allow_fd=True, nullable=True) = None
15561
    *
15562
    follow_symlinks: bool = True
15563
15564
Return a list of extended attributes on path.
15565
15566
path may be either None, a string, a path-like object, or an open file descriptor.
15567
if path is None, listxattr will examine the current directory.
15568
If follow_symlinks is False, and the last element of the path is a symbolic
15569
  link, listxattr will examine the symbolic link itself instead of the file
15570
  the link points to.
15571
[clinic start generated code]*/
15572
15573
static PyObject *
15574
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15575
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15576
0
{
15577
0
    Py_ssize_t i;
15578
0
    PyObject *result = NULL;
15579
0
    const char *name;
15580
0
    char *buffer = NULL;
15581
15582
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
15583
0
        goto exit;
15584
15585
0
    if (PySys_Audit("os.listxattr", "(O)",
15586
0
                    path->object ? path->object : Py_None) < 0) {
15587
0
        return NULL;
15588
0
    }
15589
15590
0
    name = path->narrow ? path->narrow : ".";
15591
15592
0
    for (i = 0; ; i++) {
15593
0
        const char *start, *trace, *end;
15594
0
        ssize_t length;
15595
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15596
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15597
0
        if (!buffer_size) {
15598
            /* ERANGE */
15599
0
            path_error(path);
15600
0
            break;
15601
0
        }
15602
0
        buffer = PyMem_Malloc(buffer_size);
15603
0
        if (!buffer) {
15604
0
            PyErr_NoMemory();
15605
0
            break;
15606
0
        }
15607
15608
0
        Py_BEGIN_ALLOW_THREADS;
15609
0
        if (path->fd > -1)
15610
0
            length = flistxattr(path->fd, buffer, buffer_size);
15611
0
        else if (follow_symlinks)
15612
0
            length = listxattr(name, buffer, buffer_size);
15613
0
        else
15614
0
            length = llistxattr(name, buffer, buffer_size);
15615
0
        Py_END_ALLOW_THREADS;
15616
15617
0
        if (length < 0) {
15618
0
            if (errno == ERANGE) {
15619
0
                PyMem_Free(buffer);
15620
0
                buffer = NULL;
15621
0
                continue;
15622
0
            }
15623
0
            path_error(path);
15624
0
            break;
15625
0
        }
15626
15627
0
        result = PyList_New(0);
15628
0
        if (!result) {
15629
0
            goto exit;
15630
0
        }
15631
15632
0
        end = buffer + length;
15633
0
        for (trace = start = buffer; trace != end; trace++) {
15634
0
            if (!*trace) {
15635
0
                int error;
15636
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15637
0
                                                                 trace - start);
15638
0
                if (!attribute) {
15639
0
                    Py_SETREF(result, NULL);
15640
0
                    goto exit;
15641
0
                }
15642
0
                error = PyList_Append(result, attribute);
15643
0
                Py_DECREF(attribute);
15644
0
                if (error) {
15645
0
                    Py_SETREF(result, NULL);
15646
0
                    goto exit;
15647
0
                }
15648
0
                start = trace + 1;
15649
0
            }
15650
0
        }
15651
0
    break;
15652
0
    }
15653
0
exit:
15654
0
    if (buffer)
15655
0
        PyMem_Free(buffer);
15656
0
    return result;
15657
0
}
15658
#endif /* USE_XATTRS */
15659
15660
15661
/*[clinic input]
15662
@permit_long_summary
15663
os.urandom
15664
15665
    size: Py_ssize_t(allow_negative=False)
15666
    /
15667
15668
Return a bytes object containing random bytes suitable for cryptographic use.
15669
[clinic start generated code]*/
15670
15671
static PyObject *
15672
os_urandom_impl(PyObject *module, Py_ssize_t size)
15673
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15674
0
{
15675
0
    if (size < 0) {
15676
0
        return PyErr_Format(PyExc_ValueError,
15677
0
                            "negative argument not allowed");
15678
0
    }
15679
15680
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15681
0
    if (writer == NULL) {
15682
0
        return NULL;
15683
0
    }
15684
15685
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15686
0
    if (result == -1) {
15687
0
        PyBytesWriter_Discard(writer);
15688
0
        return NULL;
15689
0
    }
15690
0
    return PyBytesWriter_Finish(writer);
15691
0
}
15692
15693
#ifdef HAVE_MEMFD_CREATE
15694
/*[clinic input]
15695
os.memfd_create
15696
15697
    name: unicode_fs_encoded
15698
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15699
15700
[clinic start generated code]*/
15701
15702
static PyObject *
15703
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15704
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15705
0
{
15706
0
    int fd;
15707
0
    const char *bytes = PyBytes_AS_STRING(name);
15708
0
    Py_BEGIN_ALLOW_THREADS
15709
0
    fd = memfd_create(bytes, flags);
15710
0
    Py_END_ALLOW_THREADS
15711
0
    if (fd == -1) {
15712
0
        return PyErr_SetFromErrno(PyExc_OSError);
15713
0
    }
15714
0
    return PyLong_FromLong(fd);
15715
0
}
15716
#endif
15717
15718
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15719
/*[clinic input]
15720
os.eventfd
15721
15722
    initval: unsigned_int
15723
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15724
15725
Creates and returns an event notification file descriptor.
15726
[clinic start generated code]*/
15727
15728
static PyObject *
15729
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15730
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15731
15732
0
{
15733
    /* initval is limited to uint32_t, internal counter is uint64_t */
15734
0
    int fd;
15735
0
    Py_BEGIN_ALLOW_THREADS
15736
0
    fd = eventfd(initval, flags);
15737
0
    Py_END_ALLOW_THREADS
15738
0
    if (fd == -1) {
15739
0
        return PyErr_SetFromErrno(PyExc_OSError);
15740
0
    }
15741
0
    return PyLong_FromLong(fd);
15742
0
}
15743
15744
/*[clinic input]
15745
os.eventfd_read
15746
15747
    fd: fildes
15748
15749
Read eventfd value
15750
[clinic start generated code]*/
15751
15752
static PyObject *
15753
os_eventfd_read_impl(PyObject *module, int fd)
15754
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15755
0
{
15756
0
    eventfd_t value;
15757
0
    int result;
15758
0
    Py_BEGIN_ALLOW_THREADS
15759
0
    result = eventfd_read(fd, &value);
15760
0
    Py_END_ALLOW_THREADS
15761
0
    if (result == -1) {
15762
0
        return PyErr_SetFromErrno(PyExc_OSError);
15763
0
    }
15764
0
    return PyLong_FromUnsignedLongLong(value);
15765
0
}
15766
15767
/*[clinic input]
15768
os.eventfd_write
15769
15770
    fd: fildes
15771
    value: unsigned_long_long
15772
15773
Write eventfd value.
15774
[clinic start generated code]*/
15775
15776
static PyObject *
15777
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15778
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15779
0
{
15780
0
    int result;
15781
0
    Py_BEGIN_ALLOW_THREADS
15782
0
    result = eventfd_write(fd, value);
15783
0
    Py_END_ALLOW_THREADS
15784
0
    if (result == -1) {
15785
0
        return PyErr_SetFromErrno(PyExc_OSError);
15786
0
    }
15787
0
    Py_RETURN_NONE;
15788
0
}
15789
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15790
15791
/* Terminal size querying */
15792
15793
PyDoc_STRVAR(TerminalSize_docstring,
15794
    "A tuple of (columns, lines) for holding terminal window size");
15795
15796
static PyStructSequence_Field TerminalSize_fields[] = {
15797
    {"columns", "width of the terminal window in characters"},
15798
    {"lines", "height of the terminal window in characters"},
15799
    {NULL, NULL}
15800
};
15801
15802
static PyStructSequence_Desc TerminalSize_desc = {
15803
    "os.terminal_size",
15804
    TerminalSize_docstring,
15805
    TerminalSize_fields,
15806
    2,
15807
};
15808
15809
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15810
/*[clinic input]
15811
os.get_terminal_size
15812
15813
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15814
    /
15815
15816
Return the size of the terminal window as (columns, lines).
15817
15818
The optional argument fd (default standard output) specifies
15819
which file descriptor should be queried.
15820
15821
If the file descriptor is not connected to a terminal, an OSError
15822
is thrown.
15823
15824
This function will only be defined if an implementation is
15825
available for this system.
15826
15827
shutil.get_terminal_size is the high-level function which should
15828
normally be used, os.get_terminal_size is the low-level implementation.
15829
[clinic start generated code]*/
15830
15831
static PyObject *
15832
os_get_terminal_size_impl(PyObject *module, int fd)
15833
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15834
0
{
15835
0
    int columns, lines;
15836
0
    PyObject *termsize;
15837
15838
    /* Under some conditions stdout may not be connected and
15839
     * fileno(stdout) may point to an invalid file descriptor. For example
15840
     * GUI apps don't have valid standard streams by default.
15841
     *
15842
     * If this happens, and the optional fd argument is not present,
15843
     * the ioctl below will fail returning EBADF. This is what we want.
15844
     */
15845
15846
0
#ifdef TERMSIZE_USE_IOCTL
15847
0
    {
15848
0
        struct winsize w;
15849
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15850
0
            return PyErr_SetFromErrno(PyExc_OSError);
15851
0
        columns = w.ws_col;
15852
0
        lines = w.ws_row;
15853
0
    }
15854
0
#endif /* TERMSIZE_USE_IOCTL */
15855
15856
#ifdef TERMSIZE_USE_CONIO
15857
    {
15858
        HANDLE handle;
15859
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15860
        handle = _Py_get_osfhandle(fd);
15861
        if (handle == INVALID_HANDLE_VALUE)
15862
            return NULL;
15863
15864
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15865
            return PyErr_SetFromWindowsErr(0);
15866
15867
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15868
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15869
    }
15870
#endif /* TERMSIZE_USE_CONIO */
15871
15872
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15873
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15874
0
    if (termsize == NULL)
15875
0
        return NULL;
15876
15877
0
    int pos = 0;
15878
15879
0
#define SET_TERMSIZE(CALL)                                   \
15880
0
    do {                                                     \
15881
0
        PyObject *item = (CALL);                             \
15882
0
        if (item == NULL) {                                  \
15883
0
            Py_DECREF(termsize);                             \
15884
0
            return NULL;                                     \
15885
0
        }                                                    \
15886
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15887
0
    } while(0)
15888
15889
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15890
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15891
0
#undef SET_TERMSIZE
15892
15893
0
    return termsize;
15894
0
}
15895
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15896
15897
/*[clinic input]
15898
os.cpu_count
15899
15900
Return the number of logical CPUs in the system.
15901
15902
Return None if indeterminable.
15903
[clinic start generated code]*/
15904
15905
static PyObject *
15906
os_cpu_count_impl(PyObject *module)
15907
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15908
0
{
15909
0
    const PyConfig *config = _Py_GetConfig();
15910
0
    if (config->cpu_count > 0) {
15911
0
        return PyLong_FromLong(config->cpu_count);
15912
0
    }
15913
15914
0
    int ncpu = 0;
15915
#ifdef MS_WINDOWS
15916
# ifdef MS_WINDOWS_DESKTOP
15917
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15918
# else
15919
    ncpu = 0;
15920
# endif
15921
15922
#elif defined(__hpux)
15923
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15924
15925
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15926
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15927
15928
#elif defined(__VXWORKS__)
15929
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15930
15931
#elif defined(__DragonFly__) || \
15932
      defined(__OpenBSD__)   || \
15933
      defined(__FreeBSD__)   || \
15934
      defined(__NetBSD__)    || \
15935
      defined(__APPLE__)
15936
    ncpu = 0;
15937
    size_t len = sizeof(ncpu);
15938
    int mib[2] = {CTL_HW, HW_NCPU};
15939
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15940
        ncpu = 0;
15941
    }
15942
#endif
15943
15944
0
    if (ncpu < 1) {
15945
0
        Py_RETURN_NONE;
15946
0
    }
15947
0
    return PyLong_FromLong(ncpu);
15948
0
}
15949
15950
15951
/*[clinic input]
15952
os.get_inheritable -> bool
15953
15954
    fd: int
15955
    /
15956
15957
Get the close-on-exe flag of the specified file descriptor.
15958
[clinic start generated code]*/
15959
15960
static int
15961
os_get_inheritable_impl(PyObject *module, int fd)
15962
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15963
0
{
15964
0
    int return_value;
15965
0
    _Py_BEGIN_SUPPRESS_IPH
15966
0
    return_value = _Py_get_inheritable(fd);
15967
0
    _Py_END_SUPPRESS_IPH
15968
0
    return return_value;
15969
0
}
15970
15971
15972
/*[clinic input]
15973
os.set_inheritable
15974
    fd: int
15975
    inheritable: int
15976
    /
15977
15978
Set the inheritable flag of the specified file descriptor.
15979
[clinic start generated code]*/
15980
15981
static PyObject *
15982
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15983
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15984
0
{
15985
0
    int result;
15986
15987
0
    _Py_BEGIN_SUPPRESS_IPH
15988
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15989
0
    _Py_END_SUPPRESS_IPH
15990
0
    if (result < 0)
15991
0
        return NULL;
15992
0
    Py_RETURN_NONE;
15993
0
}
15994
15995
15996
#ifdef MS_WINDOWS
15997
#ifndef HANDLE_FLAG_INHERIT
15998
#define HANDLE_FLAG_INHERIT 0x00000001
15999
#endif
16000
16001
/*[clinic input]
16002
os.get_handle_inheritable -> bool
16003
    handle: intptr_t
16004
    /
16005
16006
Get the close-on-exe flag of the specified file descriptor.
16007
[clinic start generated code]*/
16008
16009
static int
16010
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16011
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16012
{
16013
    DWORD flags;
16014
16015
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16016
        PyErr_SetFromWindowsErr(0);
16017
        return -1;
16018
    }
16019
16020
    return flags & HANDLE_FLAG_INHERIT;
16021
}
16022
16023
16024
/*[clinic input]
16025
os.set_handle_inheritable
16026
    handle: intptr_t
16027
    inheritable: bool
16028
    /
16029
16030
Set the inheritable flag of the specified handle.
16031
[clinic start generated code]*/
16032
16033
static PyObject *
16034
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16035
                               int inheritable)
16036
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16037
{
16038
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16039
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16040
        PyErr_SetFromWindowsErr(0);
16041
        return NULL;
16042
    }
16043
    Py_RETURN_NONE;
16044
}
16045
#endif /* MS_WINDOWS */
16046
16047
/*[clinic input]
16048
os.get_blocking -> bool
16049
    fd: int
16050
    /
16051
16052
Get the blocking mode of the file descriptor.
16053
16054
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16055
[clinic start generated code]*/
16056
16057
static int
16058
os_get_blocking_impl(PyObject *module, int fd)
16059
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16060
0
{
16061
0
    int blocking;
16062
16063
0
    _Py_BEGIN_SUPPRESS_IPH
16064
0
    blocking = _Py_get_blocking(fd);
16065
0
    _Py_END_SUPPRESS_IPH
16066
0
    return blocking;
16067
0
}
16068
16069
/*[clinic input]
16070
os.set_blocking
16071
    fd: int
16072
    blocking: bool
16073
    /
16074
16075
Set the blocking mode of the specified file descriptor.
16076
16077
Set the O_NONBLOCK flag if blocking is False,
16078
clear the O_NONBLOCK flag otherwise.
16079
[clinic start generated code]*/
16080
16081
static PyObject *
16082
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16083
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16084
0
{
16085
0
    int result;
16086
16087
0
    _Py_BEGIN_SUPPRESS_IPH
16088
0
    result = _Py_set_blocking(fd, blocking);
16089
0
    _Py_END_SUPPRESS_IPH
16090
0
    if (result < 0)
16091
0
        return NULL;
16092
0
    Py_RETURN_NONE;
16093
0
}
16094
16095
16096
/*[clinic input]
16097
class os.DirEntry "DirEntry *" "DirEntryType"
16098
[clinic start generated code]*/
16099
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16100
16101
typedef struct {
16102
    PyObject_HEAD
16103
    PyObject *name;
16104
    PyObject *path;
16105
    PyObject *stat;
16106
    PyObject *lstat;
16107
#ifdef MS_WINDOWS
16108
    struct _Py_stat_struct win32_lstat;
16109
    uint64_t win32_file_index;
16110
    uint64_t win32_file_index_high;
16111
    int got_file_index;
16112
#else /* POSIX */
16113
#ifdef HAVE_DIRENT_D_TYPE
16114
    unsigned char d_type;
16115
#endif
16116
    ino_t d_ino;
16117
    int dir_fd;
16118
#endif
16119
} DirEntry;
16120
16121
216k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16122
16123
static void
16124
DirEntry_dealloc(PyObject *op)
16125
216k
{
16126
216k
    DirEntry *entry = DirEntry_CAST(op);
16127
216k
    PyTypeObject *tp = Py_TYPE(entry);
16128
216k
    Py_XDECREF(entry->name);
16129
216k
    Py_XDECREF(entry->path);
16130
216k
    Py_XDECREF(entry->stat);
16131
216k
    Py_XDECREF(entry->lstat);
16132
216k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16133
216k
    free_func(entry);
16134
216k
    Py_DECREF(tp);
16135
216k
}
16136
16137
/* Forward reference */
16138
static int
16139
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16140
                   int follow_symlinks, unsigned short mode_bits);
16141
16142
/*[clinic input]
16143
os.DirEntry.is_symlink -> bool
16144
    defining_class: defining_class
16145
    /
16146
16147
Return True if the entry is a symbolic link; cached per entry.
16148
[clinic start generated code]*/
16149
16150
static int
16151
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16152
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16153
0
{
16154
#ifdef MS_WINDOWS
16155
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16156
#elif defined(HAVE_DIRENT_D_TYPE)
16157
    /* POSIX */
16158
0
    if (self->d_type != DT_UNKNOWN)
16159
0
        return self->d_type == DT_LNK;
16160
0
    else
16161
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16162
#else
16163
    /* POSIX without d_type */
16164
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16165
#endif
16166
0
}
16167
16168
/*[clinic input]
16169
os.DirEntry.is_junction -> bool
16170
16171
Return True if the entry is a junction; cached per entry.
16172
[clinic start generated code]*/
16173
16174
static int
16175
os_DirEntry_is_junction_impl(DirEntry *self)
16176
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16177
0
{
16178
#ifdef MS_WINDOWS
16179
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16180
#else
16181
0
    return 0;
16182
0
#endif
16183
0
}
16184
16185
static PyObject *
16186
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16187
180k
{
16188
180k
    int result;
16189
180k
    STRUCT_STAT st;
16190
180k
    PyObject *ub;
16191
16192
#ifdef MS_WINDOWS
16193
    if (!PyUnicode_FSDecoder(self->path, &ub))
16194
        return NULL;
16195
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16196
    Py_DECREF(ub);
16197
#else /* POSIX */
16198
180k
    if (!PyUnicode_FSConverter(self->path, &ub))
16199
0
        return NULL;
16200
180k
    const char *path = PyBytes_AS_STRING(ub);
16201
180k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16202
180k
#ifdef HAVE_FSTATAT
16203
180k
      if (HAVE_FSTATAT_RUNTIME) {
16204
180k
        Py_BEGIN_ALLOW_THREADS
16205
180k
        result = fstatat(self->dir_fd, path, &st,
16206
180k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16207
180k
        Py_END_ALLOW_THREADS
16208
180k
      } else
16209
16210
0
#endif /* HAVE_FSTATAT */
16211
0
      {
16212
0
        Py_DECREF(ub);
16213
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16214
0
        return NULL;
16215
0
      }
16216
180k
    }
16217
0
    else
16218
0
#endif
16219
0
    {
16220
0
        Py_BEGIN_ALLOW_THREADS
16221
0
        if (follow_symlinks) {
16222
0
            result = STAT(path, &st);
16223
0
        }
16224
0
        else {
16225
0
            result = LSTAT(path, &st);
16226
0
        }
16227
0
        Py_END_ALLOW_THREADS
16228
0
    }
16229
16230
180k
    int saved_errno = errno;
16231
#if defined(MS_WINDOWS)
16232
    PyMem_Free(path);
16233
#else
16234
180k
    Py_DECREF(ub);
16235
180k
#endif
16236
16237
180k
    if (result != 0) {
16238
0
        errno = saved_errno;
16239
0
        path_object_error(self->path);
16240
0
        return NULL;
16241
0
    }
16242
16243
180k
    return _pystat_fromstructstat(module, &st);
16244
180k
}
16245
16246
static PyObject *
16247
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16248
180k
{
16249
180k
    if (!self->lstat) {
16250
180k
        PyObject *module = PyType_GetModule(defining_class);
16251
#ifdef MS_WINDOWS
16252
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16253
#else /* POSIX */
16254
180k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16255
180k
#endif
16256
180k
    }
16257
180k
    return Py_XNewRef(self->lstat);
16258
180k
}
16259
16260
/*[clinic input]
16261
os.DirEntry.stat
16262
    defining_class: defining_class
16263
    /
16264
    *
16265
    follow_symlinks: bool = True
16266
16267
Return stat_result object for the entry; cached per entry.
16268
[clinic start generated code]*/
16269
16270
static PyObject *
16271
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16272
                      int follow_symlinks)
16273
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16274
180k
{
16275
180k
    if (!follow_symlinks) {
16276
180k
        return DirEntry_get_lstat(defining_class, self);
16277
180k
    }
16278
16279
0
    if (!self->stat) {
16280
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16281
0
        if (result == -1) {
16282
0
            return NULL;
16283
0
        }
16284
0
        if (result) {
16285
0
            PyObject *module = PyType_GetModule(defining_class);
16286
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16287
0
        }
16288
0
        else {
16289
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16290
0
        }
16291
0
    }
16292
16293
0
    return Py_XNewRef(self->stat);
16294
0
}
16295
16296
/* Set exception and return -1 on error, 0 for False, 1 for True */
16297
static int
16298
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16299
                   int follow_symlinks, unsigned short mode_bits)
16300
216k
{
16301
216k
    PyObject *stat = NULL;
16302
216k
    PyObject *st_mode = NULL;
16303
216k
    long mode;
16304
216k
    int result;
16305
216k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16306
216k
    int is_symlink;
16307
216k
    int need_stat;
16308
216k
#endif
16309
#ifdef MS_WINDOWS
16310
    unsigned long dir_bits;
16311
#endif
16312
16313
#ifdef MS_WINDOWS
16314
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16315
    need_stat = follow_symlinks && is_symlink;
16316
#elif defined(HAVE_DIRENT_D_TYPE)
16317
216k
    is_symlink = self->d_type == DT_LNK;
16318
216k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16319
216k
#endif
16320
16321
216k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16322
216k
    if (need_stat) {
16323
0
#endif
16324
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16325
0
        if (!stat) {
16326
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16327
                /* If file doesn't exist (anymore), then return False
16328
                   (i.e., say it's not a file/directory) */
16329
0
                PyErr_Clear();
16330
0
                return 0;
16331
0
            }
16332
0
            goto error;
16333
0
        }
16334
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16335
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16336
0
        if (!st_mode)
16337
0
            goto error;
16338
16339
0
        mode = PyLong_AsLong(st_mode);
16340
0
        if (mode == -1 && PyErr_Occurred())
16341
0
            goto error;
16342
0
        Py_CLEAR(st_mode);
16343
0
        Py_CLEAR(stat);
16344
0
        result = (mode & S_IFMT) == mode_bits;
16345
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16346
0
    }
16347
216k
    else if (is_symlink) {
16348
0
        assert(mode_bits != S_IFLNK);
16349
0
        result = 0;
16350
0
    }
16351
216k
    else {
16352
216k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16353
#ifdef MS_WINDOWS
16354
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16355
        if (mode_bits == S_IFDIR)
16356
            result = dir_bits != 0;
16357
        else
16358
            result = dir_bits == 0;
16359
#else /* POSIX */
16360
216k
        if (mode_bits == S_IFDIR)
16361
216k
            result = self->d_type == DT_DIR;
16362
0
        else
16363
0
            result = self->d_type == DT_REG;
16364
216k
#endif
16365
216k
    }
16366
216k
#endif
16367
16368
216k
    return result;
16369
16370
0
error:
16371
0
    Py_XDECREF(st_mode);
16372
0
    Py_XDECREF(stat);
16373
0
    return -1;
16374
216k
}
16375
16376
/*[clinic input]
16377
os.DirEntry.is_dir -> bool
16378
    defining_class: defining_class
16379
    /
16380
    *
16381
    follow_symlinks: bool = True
16382
16383
Return True if the entry is a directory; cached per entry.
16384
[clinic start generated code]*/
16385
16386
static int
16387
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16388
                        int follow_symlinks)
16389
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16390
216k
{
16391
216k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16392
216k
}
16393
16394
/*[clinic input]
16395
os.DirEntry.is_file -> bool
16396
    defining_class: defining_class
16397
    /
16398
    *
16399
    follow_symlinks: bool = True
16400
16401
Return True if the entry is a file; cached per entry.
16402
[clinic start generated code]*/
16403
16404
static int
16405
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16406
                         int follow_symlinks)
16407
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16408
0
{
16409
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16410
0
}
16411
16412
/*[clinic input]
16413
os.DirEntry.inode
16414
16415
Return inode of the entry; cached per entry.
16416
[clinic start generated code]*/
16417
16418
static PyObject *
16419
os_DirEntry_inode_impl(DirEntry *self)
16420
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16421
0
{
16422
#ifdef MS_WINDOWS
16423
    if (!self->got_file_index) {
16424
        PyObject *unicode;
16425
        STRUCT_STAT stat;
16426
        int result;
16427
16428
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16429
            return NULL;
16430
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16431
        Py_DECREF(unicode);
16432
        result = LSTAT(path, &stat);
16433
16434
        int saved_errno = errno;
16435
        PyMem_Free(path);
16436
16437
        if (result != 0) {
16438
            errno = saved_errno;
16439
            return path_object_error(self->path);
16440
        }
16441
16442
        self->win32_file_index = stat.st_ino;
16443
        self->win32_file_index_high = stat.st_ino_high;
16444
        self->got_file_index = 1;
16445
    }
16446
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16447
#else /* POSIX */
16448
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16449
0
                  "DirEntry.d_ino is larger than unsigned long long");
16450
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16451
0
#endif
16452
0
}
16453
16454
static PyObject *
16455
DirEntry_repr(PyObject *op)
16456
0
{
16457
0
    DirEntry *self = DirEntry_CAST(op);
16458
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16459
0
}
16460
16461
/*[clinic input]
16462
os.DirEntry.__fspath__
16463
16464
Returns the path for the entry.
16465
[clinic start generated code]*/
16466
16467
static PyObject *
16468
os_DirEntry___fspath___impl(DirEntry *self)
16469
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16470
0
{
16471
0
    return Py_NewRef(self->path);
16472
0
}
16473
16474
static PyMemberDef DirEntry_members[] = {
16475
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16476
     "the entry's base filename, relative to scandir() \"path\" argument"},
16477
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16478
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16479
    {NULL}
16480
};
16481
16482
#include "clinic/posixmodule.c.h"
16483
16484
static PyMethodDef DirEntry_methods[] = {
16485
    OS_DIRENTRY_IS_DIR_METHODDEF
16486
    OS_DIRENTRY_IS_FILE_METHODDEF
16487
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16488
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16489
    OS_DIRENTRY_STAT_METHODDEF
16490
    OS_DIRENTRY_INODE_METHODDEF
16491
    OS_DIRENTRY___FSPATH___METHODDEF
16492
    {"__class_getitem__",       Py_GenericAlias,
16493
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16494
    {NULL}
16495
};
16496
16497
static PyType_Slot DirEntryType_slots[] = {
16498
    {Py_tp_dealloc, DirEntry_dealloc},
16499
    {Py_tp_repr, DirEntry_repr},
16500
    {Py_tp_methods, DirEntry_methods},
16501
    {Py_tp_members, DirEntry_members},
16502
    {0, 0},
16503
};
16504
16505
static PyType_Spec DirEntryType_spec = {
16506
    .name = MODNAME ".DirEntry",
16507
    .basicsize = sizeof(DirEntry),
16508
    .flags = (
16509
        Py_TPFLAGS_DEFAULT
16510
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16511
        | Py_TPFLAGS_IMMUTABLETYPE
16512
    ),
16513
    .slots = DirEntryType_slots
16514
};
16515
16516
16517
#ifdef MS_WINDOWS
16518
16519
static wchar_t *
16520
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16521
{
16522
    Py_ssize_t path_len;
16523
    Py_ssize_t size;
16524
    wchar_t *result;
16525
    wchar_t ch;
16526
16527
    if (!path_wide) { /* Default arg: "." */
16528
        path_wide = L".";
16529
        path_len = 1;
16530
    }
16531
    else {
16532
        path_len = wcslen(path_wide);
16533
    }
16534
16535
    /* The +1's are for the path separator and the NUL */
16536
    size = path_len + 1 + wcslen(filename) + 1;
16537
    result = PyMem_New(wchar_t, size);
16538
    if (!result) {
16539
        PyErr_NoMemory();
16540
        return NULL;
16541
    }
16542
    wcscpy(result, path_wide);
16543
    if (path_len > 0) {
16544
        ch = result[path_len - 1];
16545
        if (ch != SEP && ch != ALTSEP && ch != L':')
16546
            result[path_len++] = SEP;
16547
        wcscpy(result + path_len, filename);
16548
    }
16549
    return result;
16550
}
16551
16552
static PyObject *
16553
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16554
{
16555
    DirEntry *entry;
16556
    BY_HANDLE_FILE_INFORMATION file_info;
16557
    ULONG reparse_tag;
16558
    wchar_t *joined_path;
16559
16560
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16561
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16562
    if (!entry)
16563
        return NULL;
16564
    entry->name = NULL;
16565
    entry->path = NULL;
16566
    entry->stat = NULL;
16567
    entry->lstat = NULL;
16568
    entry->got_file_index = 0;
16569
16570
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16571
    if (!entry->name)
16572
        goto error;
16573
    int return_bytes = path->wide && PyBytes_Check(path->object);
16574
    if (return_bytes) {
16575
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16576
        if (!entry->name)
16577
            goto error;
16578
    }
16579
16580
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16581
    if (!joined_path)
16582
        goto error;
16583
16584
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16585
    PyMem_Free(joined_path);
16586
    if (!entry->path)
16587
        goto error;
16588
    if (return_bytes) {
16589
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16590
        if (!entry->path)
16591
            goto error;
16592
    }
16593
16594
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16595
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16596
16597
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16598
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16599
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16600
16601
    return (PyObject *)entry;
16602
16603
error:
16604
    Py_DECREF(entry);
16605
    return NULL;
16606
}
16607
16608
#else /* POSIX */
16609
16610
static char *
16611
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16612
0
{
16613
0
    Py_ssize_t path_len;
16614
0
    Py_ssize_t size;
16615
0
    char *result;
16616
16617
0
    if (!path_narrow) { /* Default arg: "." */
16618
0
        path_narrow = ".";
16619
0
        path_len = 1;
16620
0
    }
16621
0
    else {
16622
0
        path_len = strlen(path_narrow);
16623
0
    }
16624
16625
0
    if (filename_len == -1)
16626
0
        filename_len = strlen(filename);
16627
16628
    /* The +1's are for the path separator and the NUL */
16629
0
    size = path_len + 1 + filename_len + 1;
16630
0
    result = PyMem_New(char, size);
16631
0
    if (!result) {
16632
0
        PyErr_NoMemory();
16633
0
        return NULL;
16634
0
    }
16635
0
    strcpy(result, path_narrow);
16636
0
    if (path_len > 0 && result[path_len - 1] != '/')
16637
0
        result[path_len++] = '/';
16638
0
    strcpy(result + path_len, filename);
16639
0
    return result;
16640
0
}
16641
16642
static PyObject *
16643
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16644
                         Py_ssize_t name_len, ino_t d_ino
16645
#ifdef HAVE_DIRENT_D_TYPE
16646
                         , unsigned char d_type
16647
#endif
16648
                         )
16649
216k
{
16650
216k
    DirEntry *entry;
16651
216k
    char *joined_path;
16652
16653
216k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16654
216k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16655
216k
    if (!entry)
16656
0
        return NULL;
16657
216k
    entry->name = NULL;
16658
216k
    entry->path = NULL;
16659
216k
    entry->stat = NULL;
16660
216k
    entry->lstat = NULL;
16661
16662
216k
    if (path->fd != -1) {
16663
216k
        entry->dir_fd = path->fd;
16664
216k
        joined_path = NULL;
16665
216k
    }
16666
0
    else {
16667
0
        entry->dir_fd = DEFAULT_DIR_FD;
16668
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16669
0
        if (!joined_path)
16670
0
            goto error;
16671
0
    }
16672
16673
216k
    if (!path->narrow || !PyBytes_Check(path->object)) {
16674
216k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16675
216k
        if (joined_path)
16676
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16677
216k
    }
16678
0
    else {
16679
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16680
0
        if (joined_path)
16681
0
            entry->path = PyBytes_FromString(joined_path);
16682
0
    }
16683
216k
    PyMem_Free(joined_path);
16684
216k
    if (!entry->name)
16685
0
        goto error;
16686
16687
216k
    if (path->fd != -1) {
16688
216k
        entry->path = Py_NewRef(entry->name);
16689
216k
    }
16690
0
    else if (!entry->path)
16691
0
        goto error;
16692
16693
216k
#ifdef HAVE_DIRENT_D_TYPE
16694
216k
    entry->d_type = d_type;
16695
216k
#endif
16696
216k
    entry->d_ino = d_ino;
16697
16698
216k
    return (PyObject *)entry;
16699
16700
0
error:
16701
0
    Py_XDECREF(entry);
16702
0
    return NULL;
16703
216k
}
16704
16705
#endif
16706
16707
16708
typedef struct {
16709
    PyObject_HEAD
16710
    path_t path;
16711
#ifdef MS_WINDOWS
16712
    HANDLE handle;
16713
    WIN32_FIND_DATAW file_data;
16714
    int first_time;
16715
#else /* POSIX */
16716
    DIR *dirp;
16717
#endif
16718
#ifdef HAVE_FDOPENDIR
16719
    int fd;
16720
#endif
16721
} ScandirIterator;
16722
16723
771k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16724
16725
#ifdef MS_WINDOWS
16726
16727
static int
16728
ScandirIterator_is_closed(ScandirIterator *iterator)
16729
{
16730
    return iterator->handle == INVALID_HANDLE_VALUE;
16731
}
16732
16733
static void
16734
ScandirIterator_closedir(ScandirIterator *iterator)
16735
{
16736
    HANDLE handle = iterator->handle;
16737
16738
    if (handle == INVALID_HANDLE_VALUE)
16739
        return;
16740
16741
    iterator->handle = INVALID_HANDLE_VALUE;
16742
    Py_BEGIN_ALLOW_THREADS
16743
    FindClose(handle);
16744
    Py_END_ALLOW_THREADS
16745
}
16746
16747
static PyObject *
16748
ScandirIterator_iternext(PyObject *op)
16749
{
16750
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16751
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16752
    BOOL success;
16753
    PyObject *entry;
16754
16755
    /* Happens if the iterator is iterated twice, or closed explicitly */
16756
    if (iterator->handle == INVALID_HANDLE_VALUE)
16757
        return NULL;
16758
16759
    while (1) {
16760
        if (!iterator->first_time) {
16761
            Py_BEGIN_ALLOW_THREADS
16762
            success = FindNextFileW(iterator->handle, file_data);
16763
            Py_END_ALLOW_THREADS
16764
            if (!success) {
16765
                /* Error or no more files */
16766
                if (GetLastError() != ERROR_NO_MORE_FILES)
16767
                    path_error(&iterator->path);
16768
                break;
16769
            }
16770
        }
16771
        iterator->first_time = 0;
16772
16773
        /* Skip over . and .. */
16774
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16775
            wcscmp(file_data->cFileName, L"..") != 0)
16776
        {
16777
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16778
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16779
            if (!entry)
16780
                break;
16781
            return entry;
16782
        }
16783
16784
        /* Loop till we get a non-dot directory or finish iterating */
16785
    }
16786
16787
    /* Error or no more files */
16788
    ScandirIterator_closedir(iterator);
16789
    return NULL;
16790
}
16791
16792
#else /* POSIX */
16793
16794
static int
16795
ScandirIterator_is_closed(ScandirIterator *iterator)
16796
184k
{
16797
184k
    return !iterator->dirp;
16798
184k
}
16799
16800
static void
16801
ScandirIterator_closedir(ScandirIterator *iterator)
16802
369k
{
16803
369k
    DIR *dirp = iterator->dirp;
16804
16805
369k
    if (!dirp)
16806
184k
        return;
16807
16808
184k
    iterator->dirp = NULL;
16809
184k
    Py_BEGIN_ALLOW_THREADS
16810
184k
#ifdef HAVE_FDOPENDIR
16811
184k
    if (iterator->path.fd != -1)
16812
184k
        rewinddir(dirp);
16813
184k
#endif
16814
184k
    closedir(dirp);
16815
184k
    Py_END_ALLOW_THREADS
16816
184k
    return;
16817
369k
}
16818
16819
static PyObject *
16820
ScandirIterator_iternext(PyObject *op)
16821
401k
{
16822
401k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16823
401k
    struct dirent *direntp;
16824
401k
    Py_ssize_t name_len;
16825
401k
    int is_dot;
16826
401k
    PyObject *entry;
16827
16828
    /* Happens if the iterator is iterated twice, or closed explicitly */
16829
401k
    if (!iterator->dirp)
16830
0
        return NULL;
16831
16832
771k
    while (1) {
16833
771k
        errno = 0;
16834
771k
        Py_BEGIN_ALLOW_THREADS
16835
771k
        direntp = readdir(iterator->dirp);
16836
771k
        Py_END_ALLOW_THREADS
16837
16838
771k
        if (!direntp) {
16839
            /* Error or no more files */
16840
184k
            if (errno != 0)
16841
0
                path_error(&iterator->path);
16842
184k
            break;
16843
184k
        }
16844
16845
        /* Skip over . and .. */
16846
586k
        name_len = NAMLEN(direntp);
16847
586k
        is_dot = direntp->d_name[0] == '.' &&
16848
371k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16849
586k
        if (!is_dot) {
16850
216k
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16851
216k
            entry = DirEntry_from_posix_info(module,
16852
216k
                                             &iterator->path, direntp->d_name,
16853
216k
                                             name_len, direntp->d_ino
16854
216k
#ifdef HAVE_DIRENT_D_TYPE
16855
216k
                                             , direntp->d_type
16856
216k
#endif
16857
216k
                                            );
16858
216k
            if (!entry)
16859
0
                break;
16860
216k
            return entry;
16861
216k
        }
16862
16863
        /* Loop till we get a non-dot directory or finish iterating */
16864
586k
    }
16865
16866
    /* Error or no more files */
16867
184k
    ScandirIterator_closedir(iterator);
16868
184k
    return NULL;
16869
401k
}
16870
16871
#endif
16872
16873
static PyObject *
16874
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16875
0
{
16876
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16877
0
    ScandirIterator_closedir(self);
16878
0
    Py_RETURN_NONE;
16879
0
}
16880
16881
static PyObject *
16882
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16883
184k
{
16884
184k
    return Py_NewRef(self);
16885
184k
}
16886
16887
static PyObject *
16888
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16889
184k
{
16890
184k
    ScandirIterator *self = ScandirIterator_CAST(op);
16891
184k
    ScandirIterator_closedir(self);
16892
184k
    Py_RETURN_NONE;
16893
184k
}
16894
16895
static void
16896
ScandirIterator_finalize(PyObject *op)
16897
184k
{
16898
184k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16899
    /* Save the current exception, if any. */
16900
184k
    PyObject *exc = PyErr_GetRaisedException();
16901
16902
184k
    if (!ScandirIterator_is_closed(iterator)) {
16903
0
        ScandirIterator_closedir(iterator);
16904
16905
0
        if (PyErr_ResourceWarning(op, 1,
16906
0
                                  "unclosed scandir iterator %R", iterator))
16907
0
        {
16908
            /* Spurious errors can appear at shutdown */
16909
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16910
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16911
0
                                       "scandir iterator %R", iterator);
16912
0
            }
16913
0
        }
16914
0
    }
16915
16916
184k
    path_cleanup(&iterator->path);
16917
16918
    /* Restore the saved exception. */
16919
184k
    PyErr_SetRaisedException(exc);
16920
184k
}
16921
16922
static void
16923
ScandirIterator_dealloc(PyObject *op)
16924
184k
{
16925
184k
    PyTypeObject *tp = Py_TYPE(op);
16926
184k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16927
0
        return;
16928
16929
184k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16930
184k
    free_func(op);
16931
184k
    Py_DECREF(tp);
16932
184k
}
16933
16934
static PyMethodDef ScandirIterator_methods[] = {
16935
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16936
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16937
    {"close", ScandirIterator_close, METH_NOARGS},
16938
    {NULL}
16939
};
16940
16941
static PyType_Slot ScandirIteratorType_slots[] = {
16942
    {Py_tp_dealloc, ScandirIterator_dealloc},
16943
    {Py_tp_finalize, ScandirIterator_finalize},
16944
    {Py_tp_iter, PyObject_SelfIter},
16945
    {Py_tp_iternext, ScandirIterator_iternext},
16946
    {Py_tp_methods, ScandirIterator_methods},
16947
    {0, 0},
16948
};
16949
16950
static PyType_Spec ScandirIteratorType_spec = {
16951
    .name = MODNAME ".ScandirIterator",
16952
    .basicsize = sizeof(ScandirIterator),
16953
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16954
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16955
    .flags = (
16956
        Py_TPFLAGS_DEFAULT
16957
        | Py_TPFLAGS_HAVE_FINALIZE
16958
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16959
        | Py_TPFLAGS_IMMUTABLETYPE
16960
    ),
16961
    .slots = ScandirIteratorType_slots
16962
};
16963
16964
/*[clinic input]
16965
os.scandir
16966
16967
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16968
16969
Return an iterator of DirEntry objects for given path.
16970
16971
path can be specified as either str, bytes, or a path-like object.  If path
16972
is bytes, the names of yielded DirEntry objects will also be bytes; in
16973
all other circumstances they will be str.
16974
16975
If path is None, uses the path='.'.
16976
[clinic start generated code]*/
16977
16978
static PyObject *
16979
os_scandir_impl(PyObject *module, path_t *path)
16980
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16981
184k
{
16982
184k
    ScandirIterator *iterator;
16983
#ifdef MS_WINDOWS
16984
    wchar_t *path_strW;
16985
#else
16986
184k
    const char *path_str;
16987
184k
#ifdef HAVE_FDOPENDIR
16988
184k
    int fd = -1;
16989
184k
#endif
16990
184k
#endif
16991
16992
184k
    if (PySys_Audit("os.scandir", "O",
16993
184k
                    path->object ? path->object : Py_None) < 0) {
16994
0
        return NULL;
16995
0
    }
16996
16997
184k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
16998
184k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
16999
184k
    if (!iterator)
17000
0
        return NULL;
17001
17002
#ifdef MS_WINDOWS
17003
    iterator->handle = INVALID_HANDLE_VALUE;
17004
#else
17005
184k
    iterator->dirp = NULL;
17006
184k
#endif
17007
17008
    /* Move the ownership to iterator->path */
17009
184k
    memcpy(&iterator->path, path, sizeof(path_t));
17010
184k
    memset(path, 0, sizeof(path_t));
17011
17012
#ifdef MS_WINDOWS
17013
    iterator->first_time = 1;
17014
17015
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
17016
    if (!path_strW)
17017
        goto error;
17018
17019
    Py_BEGIN_ALLOW_THREADS
17020
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17021
    Py_END_ALLOW_THREADS
17022
17023
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17024
        path_error(&iterator->path);
17025
        PyMem_Free(path_strW);
17026
        goto error;
17027
    }
17028
    PyMem_Free(path_strW);
17029
#else /* POSIX */
17030
184k
    errno = 0;
17031
184k
#ifdef HAVE_FDOPENDIR
17032
184k
    if (iterator->path.fd != -1) {
17033
184k
      if (HAVE_FDOPENDIR_RUNTIME) {
17034
        /* closedir() closes the FD, so we duplicate it */
17035
184k
        fd = _Py_dup(iterator->path.fd);
17036
184k
        if (fd == -1)
17037
0
            goto error;
17038
17039
184k
        Py_BEGIN_ALLOW_THREADS
17040
184k
        iterator->dirp = fdopendir(fd);
17041
184k
        Py_END_ALLOW_THREADS
17042
184k
      } else {
17043
0
        PyErr_SetString(PyExc_TypeError,
17044
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17045
0
        return NULL;
17046
0
      }
17047
184k
    }
17048
0
    else
17049
0
#endif
17050
0
    {
17051
0
        if (iterator->path.narrow)
17052
0
            path_str = iterator->path.narrow;
17053
0
        else
17054
0
            path_str = ".";
17055
17056
0
        Py_BEGIN_ALLOW_THREADS
17057
0
        iterator->dirp = opendir(path_str);
17058
0
        Py_END_ALLOW_THREADS
17059
0
    }
17060
17061
184k
    if (!iterator->dirp) {
17062
0
        path_error(&iterator->path);
17063
0
#ifdef HAVE_FDOPENDIR
17064
0
        if (fd != -1) {
17065
0
            Py_BEGIN_ALLOW_THREADS
17066
0
            close(fd);
17067
0
            Py_END_ALLOW_THREADS
17068
0
        }
17069
0
#endif
17070
0
        goto error;
17071
0
    }
17072
184k
#endif
17073
17074
184k
    return (PyObject *)iterator;
17075
17076
0
error:
17077
0
    Py_DECREF(iterator);
17078
0
    return NULL;
17079
184k
}
17080
17081
/*
17082
    Return the file system path representation of the object.
17083
17084
    If the object is str or bytes, then allow it to pass through with
17085
    an incremented refcount. If the object defines __fspath__(), then
17086
    return the result of that method. All other types raise a TypeError.
17087
*/
17088
PyObject *
17089
PyOS_FSPath(PyObject *path)
17090
1.58M
{
17091
    /* For error message reasons, this function is manually inlined in
17092
       path_converter(). */
17093
1.58M
    PyObject *func = NULL;
17094
1.58M
    PyObject *path_repr = NULL;
17095
17096
1.58M
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17097
1.58M
        return Py_NewRef(path);
17098
1.58M
    }
17099
17100
458
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17101
458
    if ((NULL == func) || (func == Py_None)) {
17102
0
        return PyErr_Format(PyExc_TypeError,
17103
0
                            "expected str, bytes or os.PathLike object, "
17104
0
                            "not %.200s",
17105
0
                            _PyType_Name(Py_TYPE(path)));
17106
0
    }
17107
17108
458
    path_repr = _PyObject_CallNoArgs(func);
17109
458
    Py_DECREF(func);
17110
458
    if (NULL == path_repr) {
17111
0
        return NULL;
17112
0
    }
17113
17114
458
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17115
0
        PyErr_Format(PyExc_TypeError,
17116
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17117
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17118
0
                     _PyType_Name(Py_TYPE(path_repr)));
17119
0
        Py_DECREF(path_repr);
17120
0
        return NULL;
17121
0
    }
17122
17123
458
    return path_repr;
17124
458
}
17125
17126
/*[clinic input]
17127
@permit_long_docstring_body
17128
os.fspath
17129
17130
    path: object
17131
17132
Return the file system path representation of the object.
17133
17134
If the object is str or bytes, then allow it to pass through as-is. If the
17135
object defines __fspath__(), then return the result of that method. All other
17136
types raise a TypeError.
17137
[clinic start generated code]*/
17138
17139
static PyObject *
17140
os_fspath_impl(PyObject *module, PyObject *path)
17141
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
17142
1.29M
{
17143
1.29M
    return PyOS_FSPath(path);
17144
1.29M
}
17145
17146
#ifdef HAVE_GETRANDOM_SYSCALL
17147
/*[clinic input]
17148
os.getrandom
17149
17150
    size: Py_ssize_t
17151
    flags: int=0
17152
17153
Obtain a series of random bytes.
17154
[clinic start generated code]*/
17155
17156
static PyObject *
17157
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17158
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17159
0
{
17160
0
    if (size < 0) {
17161
0
        errno = EINVAL;
17162
0
        return posix_error();
17163
0
    }
17164
17165
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17166
0
    if (writer == NULL) {
17167
0
        return NULL;
17168
0
    }
17169
0
    void *data = PyBytesWriter_GetData(writer);
17170
17171
0
    Py_ssize_t n;
17172
0
    while (1) {
17173
0
        n = syscall(SYS_getrandom, data, size, flags);
17174
0
        if (n < 0 && errno == EINTR) {
17175
0
            if (PyErr_CheckSignals() < 0) {
17176
0
                goto error;
17177
0
            }
17178
17179
            /* getrandom() was interrupted by a signal: retry */
17180
0
            continue;
17181
0
        }
17182
0
        break;
17183
0
    }
17184
17185
0
    if (n < 0) {
17186
0
        PyErr_SetFromErrno(PyExc_OSError);
17187
0
        goto error;
17188
0
    }
17189
17190
0
    return PyBytesWriter_FinishWithSize(writer, n);
17191
17192
0
error:
17193
0
    PyBytesWriter_Discard(writer);
17194
0
    return NULL;
17195
0
}
17196
#endif   /* HAVE_GETRANDOM_SYSCALL */
17197
17198
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17199
17200
/* bpo-36085: Helper functions for managing DLL search directories
17201
 * on win32
17202
 */
17203
17204
/*[clinic input]
17205
os._add_dll_directory
17206
17207
    path: path_t
17208
17209
Add a path to the DLL search path.
17210
17211
This search path is used when resolving dependencies for imported
17212
extension modules (the module itself is resolved through sys.path),
17213
and also by ctypes.
17214
17215
Returns an opaque value that may be passed to os.remove_dll_directory
17216
to remove this directory from the search path.
17217
[clinic start generated code]*/
17218
17219
static PyObject *
17220
os__add_dll_directory_impl(PyObject *module, path_t *path)
17221
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17222
{
17223
    DLL_DIRECTORY_COOKIE cookie = 0;
17224
    DWORD err = 0;
17225
17226
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17227
        return NULL;
17228
    }
17229
17230
    Py_BEGIN_ALLOW_THREADS
17231
    if (!(cookie = AddDllDirectory(path->wide))) {
17232
        err = GetLastError();
17233
    }
17234
    Py_END_ALLOW_THREADS
17235
17236
    if (err) {
17237
        return win32_error_object_err("add_dll_directory",
17238
                                      path->object, err);
17239
    }
17240
17241
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17242
}
17243
17244
/*[clinic input]
17245
os._remove_dll_directory
17246
17247
    cookie: object
17248
17249
Removes a path from the DLL search path.
17250
17251
The parameter is an opaque value that was returned from
17252
os.add_dll_directory. You can only remove directories that you added
17253
yourself.
17254
[clinic start generated code]*/
17255
17256
static PyObject *
17257
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17258
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17259
{
17260
    DLL_DIRECTORY_COOKIE cookieValue;
17261
    DWORD err = 0;
17262
17263
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17264
        PyErr_SetString(PyExc_TypeError,
17265
            "Provided cookie was not returned from os.add_dll_directory");
17266
        return NULL;
17267
    }
17268
17269
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17270
        cookie, "DLL directory cookie");
17271
17272
    Py_BEGIN_ALLOW_THREADS
17273
    if (!RemoveDllDirectory(cookieValue)) {
17274
        err = GetLastError();
17275
    }
17276
    Py_END_ALLOW_THREADS
17277
17278
    if (err) {
17279
        return win32_error_object_err("remove_dll_directory",
17280
                                      NULL, err);
17281
    }
17282
17283
    if (PyCapsule_SetName(cookie, NULL)) {
17284
        return NULL;
17285
    }
17286
17287
    Py_RETURN_NONE;
17288
}
17289
17290
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17291
17292
17293
/* Only check if WIFEXITED is available: expect that it comes
17294
   with WEXITSTATUS, WIFSIGNALED, etc.
17295
17296
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17297
   subprocess can safely call it during late Python finalization without
17298
   risking that used os attributes were set to None by finalize_modules(). */
17299
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17300
/*[clinic input]
17301
os.waitstatus_to_exitcode
17302
17303
    status as status_obj: object
17304
17305
Convert a wait status to an exit code.
17306
17307
On Unix:
17308
17309
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17310
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17311
* Otherwise, raise a ValueError.
17312
17313
On Windows, return status shifted right by 8 bits.
17314
17315
On Unix, if the process is being traced or if waitpid() was called with
17316
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
17317
This function must not be called if WIFSTOPPED(status) is true.
17318
[clinic start generated code]*/
17319
17320
static PyObject *
17321
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17322
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
17323
0
{
17324
0
#ifndef MS_WINDOWS
17325
0
    int status = PyLong_AsInt(status_obj);
17326
0
    if (status == -1 && PyErr_Occurred()) {
17327
0
        return NULL;
17328
0
    }
17329
17330
0
    WAIT_TYPE wait_status;
17331
0
    WAIT_STATUS_INT(wait_status) = status;
17332
0
    int exitcode;
17333
0
    if (WIFEXITED(wait_status)) {
17334
0
        exitcode = WEXITSTATUS(wait_status);
17335
        /* Sanity check to provide warranty on the function behavior.
17336
           It should not occur in practice */
17337
0
        if (exitcode < 0) {
17338
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17339
0
            return NULL;
17340
0
        }
17341
0
    }
17342
0
    else if (WIFSIGNALED(wait_status)) {
17343
0
        int signum = WTERMSIG(wait_status);
17344
        /* Sanity check to provide warranty on the function behavior.
17345
           It should not occurs in practice */
17346
0
        if (signum <= 0) {
17347
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17348
0
            return NULL;
17349
0
        }
17350
0
        exitcode = -signum;
17351
0
    } else if (WIFSTOPPED(wait_status)) {
17352
        /* Status only received if the process is being traced
17353
           or if waitpid() was called with WUNTRACED option. */
17354
0
        int signum = WSTOPSIG(wait_status);
17355
0
        PyErr_Format(PyExc_ValueError,
17356
0
                     "process stopped by delivery of signal %i",
17357
0
                     signum);
17358
0
        return NULL;
17359
0
    }
17360
0
    else {
17361
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17362
0
        return NULL;
17363
0
    }
17364
0
    return PyLong_FromLong(exitcode);
17365
#else
17366
    /* Windows implementation: see os.waitpid() implementation
17367
       which uses _cwait(). */
17368
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17369
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17370
        return NULL;
17371
    }
17372
17373
    unsigned long long exitcode = (status >> 8);
17374
    /* ExitProcess() accepts an UINT type:
17375
       reject exit code which doesn't fit in an UINT */
17376
    if (exitcode > UINT_MAX) {
17377
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17378
        return NULL;
17379
    }
17380
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17381
#endif
17382
0
}
17383
#endif
17384
17385
#if defined(MS_WINDOWS)
17386
/*[clinic input]
17387
os._supports_virtual_terminal
17388
17389
Checks if virtual terminal is supported in windows
17390
[clinic start generated code]*/
17391
17392
static PyObject *
17393
os__supports_virtual_terminal_impl(PyObject *module)
17394
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17395
{
17396
#ifdef HAVE_WINDOWS_CONSOLE_IO
17397
    DWORD mode = 0;
17398
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17399
    if (!GetConsoleMode(handle, &mode)) {
17400
        Py_RETURN_FALSE;
17401
    }
17402
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17403
#else
17404
    Py_RETURN_FALSE;
17405
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17406
}
17407
#endif
17408
17409
/*[clinic input]
17410
os._inputhook
17411
17412
Calls PyOS_InputHook dropping the GIL first
17413
[clinic start generated code]*/
17414
17415
static PyObject *
17416
os__inputhook_impl(PyObject *module)
17417
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17418
0
{
17419
0
     int result = 0;
17420
0
     if (PyOS_InputHook) {
17421
0
         Py_BEGIN_ALLOW_THREADS;
17422
0
         result = PyOS_InputHook();
17423
0
         Py_END_ALLOW_THREADS;
17424
0
     }
17425
0
     return PyLong_FromLong(result);
17426
0
}
17427
17428
/*[clinic input]
17429
os._is_inputhook_installed
17430
17431
Checks if PyOS_InputHook is set
17432
[clinic start generated code]*/
17433
17434
static PyObject *
17435
os__is_inputhook_installed_impl(PyObject *module)
17436
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17437
0
{
17438
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17439
0
}
17440
17441
/*[clinic input]
17442
os._create_environ
17443
17444
Create the environment dictionary.
17445
[clinic start generated code]*/
17446
17447
static PyObject *
17448
os__create_environ_impl(PyObject *module)
17449
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17450
0
{
17451
0
    return convertenviron();
17452
0
}
17453
17454
17455
#ifdef __EMSCRIPTEN__
17456
/*[clinic input]
17457
os._emscripten_debugger
17458
17459
Create a breakpoint for the JavaScript debugger. Emscripten only.
17460
[clinic start generated code]*/
17461
17462
static PyObject *
17463
os__emscripten_debugger_impl(PyObject *module)
17464
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17465
{
17466
    emscripten_debugger();
17467
    Py_RETURN_NONE;
17468
}
17469
17470
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17471
    console.warn(UTF8ToString(arg));
17472
});
17473
17474
/*[clinic input]
17475
os._emscripten_log
17476
   arg: str
17477
17478
Log something to the JS console. Emscripten only.
17479
[clinic start generated code]*/
17480
17481
static PyObject *
17482
os__emscripten_log_impl(PyObject *module, const char *arg)
17483
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17484
{
17485
    emscripten_log_impl_js(arg);
17486
    Py_RETURN_NONE;
17487
}
17488
#endif /* __EMSCRIPTEN__ */
17489
17490
17491
static PyMethodDef posix_methods[] = {
17492
    OS_STAT_METHODDEF
17493
    OS_STATX_METHODDEF
17494
    OS_ACCESS_METHODDEF
17495
    OS_TTYNAME_METHODDEF
17496
    OS_CHDIR_METHODDEF
17497
    OS_CHFLAGS_METHODDEF
17498
    OS_CHMOD_METHODDEF
17499
    OS_FCHMOD_METHODDEF
17500
    OS_LCHMOD_METHODDEF
17501
    OS_CHOWN_METHODDEF
17502
    OS_FCHOWN_METHODDEF
17503
    OS_LCHOWN_METHODDEF
17504
    OS_LCHFLAGS_METHODDEF
17505
    OS_CHROOT_METHODDEF
17506
    OS_CTERMID_METHODDEF
17507
    OS_GETCWD_METHODDEF
17508
    OS_GETCWDB_METHODDEF
17509
    OS_LINK_METHODDEF
17510
    OS_LISTDIR_METHODDEF
17511
    OS_LISTDRIVES_METHODDEF
17512
    OS_LISTMOUNTS_METHODDEF
17513
    OS_LISTVOLUMES_METHODDEF
17514
    OS_LSTAT_METHODDEF
17515
    OS_MKDIR_METHODDEF
17516
    OS_NICE_METHODDEF
17517
    OS_GETPRIORITY_METHODDEF
17518
    OS_SETPRIORITY_METHODDEF
17519
    OS_POSIX_SPAWN_METHODDEF
17520
    OS_POSIX_SPAWNP_METHODDEF
17521
    OS_READLINK_METHODDEF
17522
    OS_COPY_FILE_RANGE_METHODDEF
17523
    OS_SPLICE_METHODDEF
17524
    OS_RENAME_METHODDEF
17525
    OS_REPLACE_METHODDEF
17526
    OS_RMDIR_METHODDEF
17527
    OS_SYMLINK_METHODDEF
17528
    OS_SYSTEM_METHODDEF
17529
    OS_UMASK_METHODDEF
17530
    OS_UNAME_METHODDEF
17531
    OS_UNLINK_METHODDEF
17532
    OS_REMOVE_METHODDEF
17533
    OS_UTIME_METHODDEF
17534
    OS_TIMES_METHODDEF
17535
    OS__EXIT_METHODDEF
17536
    OS__FCOPYFILE_METHODDEF
17537
    OS_EXECV_METHODDEF
17538
    OS_EXECVE_METHODDEF
17539
    OS_SPAWNV_METHODDEF
17540
    OS_SPAWNVE_METHODDEF
17541
    OS_FORK1_METHODDEF
17542
    OS_FORK_METHODDEF
17543
    OS_REGISTER_AT_FORK_METHODDEF
17544
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17545
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17546
    OS_SCHED_GETPARAM_METHODDEF
17547
    OS_SCHED_GETSCHEDULER_METHODDEF
17548
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17549
    OS_SCHED_SETPARAM_METHODDEF
17550
    OS_SCHED_SETSCHEDULER_METHODDEF
17551
    OS_SCHED_YIELD_METHODDEF
17552
    OS_SCHED_SETAFFINITY_METHODDEF
17553
    OS_SCHED_GETAFFINITY_METHODDEF
17554
    OS_POSIX_OPENPT_METHODDEF
17555
    OS_GRANTPT_METHODDEF
17556
    OS_UNLOCKPT_METHODDEF
17557
    OS_PTSNAME_METHODDEF
17558
    OS_OPENPTY_METHODDEF
17559
    OS_LOGIN_TTY_METHODDEF
17560
    OS_FORKPTY_METHODDEF
17561
    OS_GETEGID_METHODDEF
17562
    OS_GETEUID_METHODDEF
17563
    OS_GETGID_METHODDEF
17564
    OS_GETGROUPLIST_METHODDEF
17565
    OS_GETGROUPS_METHODDEF
17566
    OS_GETPID_METHODDEF
17567
    OS_GETPGRP_METHODDEF
17568
    OS_GETPPID_METHODDEF
17569
    OS_GETUID_METHODDEF
17570
    OS_GETLOGIN_METHODDEF
17571
    OS_KILL_METHODDEF
17572
    OS_KILLPG_METHODDEF
17573
    OS_PLOCK_METHODDEF
17574
    OS_STARTFILE_METHODDEF
17575
    OS_SETUID_METHODDEF
17576
    OS_SETEUID_METHODDEF
17577
    OS_SETREUID_METHODDEF
17578
    OS_SETGID_METHODDEF
17579
    OS_SETEGID_METHODDEF
17580
    OS_SETREGID_METHODDEF
17581
    OS_SETGROUPS_METHODDEF
17582
    OS_INITGROUPS_METHODDEF
17583
    OS_GETPGID_METHODDEF
17584
    OS_SETPGRP_METHODDEF
17585
    OS_WAIT_METHODDEF
17586
    OS_WAIT3_METHODDEF
17587
    OS_WAIT4_METHODDEF
17588
    OS_WAITID_METHODDEF
17589
    OS_WAITPID_METHODDEF
17590
    OS_PIDFD_OPEN_METHODDEF
17591
    OS_GETSID_METHODDEF
17592
    OS_SETSID_METHODDEF
17593
    OS_SETPGID_METHODDEF
17594
    OS_TCGETPGRP_METHODDEF
17595
    OS_TCSETPGRP_METHODDEF
17596
    OS_OPEN_METHODDEF
17597
    OS_CLOSE_METHODDEF
17598
    OS_CLOSERANGE_METHODDEF
17599
    OS_DEVICE_ENCODING_METHODDEF
17600
    OS_DUP_METHODDEF
17601
    OS_DUP2_METHODDEF
17602
    OS_LOCKF_METHODDEF
17603
    OS_LSEEK_METHODDEF
17604
    OS_READ_METHODDEF
17605
    OS_READINTO_METHODDEF
17606
    OS_READV_METHODDEF
17607
    OS_PREAD_METHODDEF
17608
    OS_PREADV_METHODDEF
17609
    OS_WRITE_METHODDEF
17610
    OS_WRITEV_METHODDEF
17611
    OS_PWRITE_METHODDEF
17612
    OS_PWRITEV_METHODDEF
17613
    OS_SENDFILE_METHODDEF
17614
    OS_FSTAT_METHODDEF
17615
    OS_ISATTY_METHODDEF
17616
    OS_PIPE_METHODDEF
17617
    OS_PIPE2_METHODDEF
17618
    OS_MKFIFO_METHODDEF
17619
    OS_MKNOD_METHODDEF
17620
    OS_MAJOR_METHODDEF
17621
    OS_MINOR_METHODDEF
17622
    OS_MAKEDEV_METHODDEF
17623
    OS_FTRUNCATE_METHODDEF
17624
    OS_TRUNCATE_METHODDEF
17625
    OS_POSIX_FALLOCATE_METHODDEF
17626
    OS_POSIX_FADVISE_METHODDEF
17627
    OS_PUTENV_METHODDEF
17628
    OS_UNSETENV_METHODDEF
17629
    OS__CLEARENV_METHODDEF
17630
    OS_STRERROR_METHODDEF
17631
    OS_FCHDIR_METHODDEF
17632
    OS_FSYNC_METHODDEF
17633
    OS_SYNC_METHODDEF
17634
    OS_FDATASYNC_METHODDEF
17635
    OS_WCOREDUMP_METHODDEF
17636
    OS_WIFCONTINUED_METHODDEF
17637
    OS_WIFSTOPPED_METHODDEF
17638
    OS_WIFSIGNALED_METHODDEF
17639
    OS_WIFEXITED_METHODDEF
17640
    OS_WEXITSTATUS_METHODDEF
17641
    OS_WTERMSIG_METHODDEF
17642
    OS_WSTOPSIG_METHODDEF
17643
    OS_FSTATVFS_METHODDEF
17644
    OS_STATVFS_METHODDEF
17645
    OS_CONFSTR_METHODDEF
17646
    OS_SYSCONF_METHODDEF
17647
    OS_FPATHCONF_METHODDEF
17648
    OS_PATHCONF_METHODDEF
17649
    OS_ABORT_METHODDEF
17650
    OS__GETFULLPATHNAME_METHODDEF
17651
    OS__GETDISKUSAGE_METHODDEF
17652
    OS__GETFINALPATHNAME_METHODDEF
17653
    OS__FINDFIRSTFILE_METHODDEF
17654
    OS__GETVOLUMEPATHNAME_METHODDEF
17655
    OS__PATH_SPLITROOT_METHODDEF
17656
    OS__PATH_SPLITROOT_EX_METHODDEF
17657
    OS__PATH_NORMPATH_METHODDEF
17658
    OS_GETLOADAVG_METHODDEF
17659
    OS_URANDOM_METHODDEF
17660
    OS_SETRESUID_METHODDEF
17661
    OS_SETRESGID_METHODDEF
17662
    OS_GETRESUID_METHODDEF
17663
    OS_GETRESGID_METHODDEF
17664
17665
    OS_GETXATTR_METHODDEF
17666
    OS_SETXATTR_METHODDEF
17667
    OS_REMOVEXATTR_METHODDEF
17668
    OS_LISTXATTR_METHODDEF
17669
17670
    OS_GET_TERMINAL_SIZE_METHODDEF
17671
    OS_CPU_COUNT_METHODDEF
17672
    OS_GET_INHERITABLE_METHODDEF
17673
    OS_SET_INHERITABLE_METHODDEF
17674
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17675
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17676
    OS_GET_BLOCKING_METHODDEF
17677
    OS_SET_BLOCKING_METHODDEF
17678
    OS_SCANDIR_METHODDEF
17679
    OS_FSPATH_METHODDEF
17680
    OS_GETRANDOM_METHODDEF
17681
    OS_MEMFD_CREATE_METHODDEF
17682
    OS_EVENTFD_METHODDEF
17683
    OS_EVENTFD_READ_METHODDEF
17684
    OS_EVENTFD_WRITE_METHODDEF
17685
    OS__ADD_DLL_DIRECTORY_METHODDEF
17686
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17687
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17688
    OS_SETNS_METHODDEF
17689
    OS_UNSHARE_METHODDEF
17690
    OS_TIMERFD_CREATE_METHODDEF
17691
    OS_TIMERFD_SETTIME_METHODDEF
17692
    OS_TIMERFD_SETTIME_NS_METHODDEF
17693
    OS_TIMERFD_GETTIME_METHODDEF
17694
    OS_TIMERFD_GETTIME_NS_METHODDEF
17695
17696
    OS__PATH_ISDEVDRIVE_METHODDEF
17697
    OS__PATH_ISDIR_METHODDEF
17698
    OS__PATH_ISFILE_METHODDEF
17699
    OS__PATH_ISLINK_METHODDEF
17700
    OS__PATH_ISJUNCTION_METHODDEF
17701
    OS__PATH_EXISTS_METHODDEF
17702
    OS__PATH_LEXISTS_METHODDEF
17703
17704
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17705
    OS__INPUTHOOK_METHODDEF
17706
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17707
    OS__CREATE_ENVIRON_METHODDEF
17708
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17709
    OS__EMSCRIPTEN_LOG_METHODDEF
17710
    {NULL,              NULL}            /* Sentinel */
17711
};
17712
17713
static int
17714
all_ins(PyObject *m)
17715
32
{
17716
32
#ifdef F_OK
17717
32
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17718
32
#endif
17719
32
#ifdef R_OK
17720
32
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17721
32
#endif
17722
32
#ifdef W_OK
17723
32
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17724
32
#endif
17725
32
#ifdef X_OK
17726
32
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17727
32
#endif
17728
32
#ifdef NGROUPS_MAX
17729
32
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17730
32
#endif
17731
32
#ifdef TMP_MAX
17732
32
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17733
32
#endif
17734
32
#ifdef WCONTINUED
17735
32
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17736
32
#endif
17737
32
#ifdef WNOHANG
17738
32
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17739
32
#endif
17740
32
#ifdef WUNTRACED
17741
32
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17742
32
#endif
17743
32
#ifdef O_RDONLY
17744
32
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17745
32
#endif
17746
32
#ifdef O_WRONLY
17747
32
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17748
32
#endif
17749
32
#ifdef O_RDWR
17750
32
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17751
32
#endif
17752
32
#ifdef O_NDELAY
17753
32
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17754
32
#endif
17755
32
#ifdef O_NONBLOCK
17756
32
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17757
32
#endif
17758
32
#ifdef O_APPEND
17759
32
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17760
32
#endif
17761
32
#ifdef O_DSYNC
17762
32
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17763
32
#endif
17764
32
#ifdef O_RSYNC
17765
32
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17766
32
#endif
17767
32
#ifdef O_SYNC
17768
32
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17769
32
#endif
17770
32
#ifdef O_NOCTTY
17771
32
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17772
32
#endif
17773
32
#ifdef O_CREAT
17774
32
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17775
32
#endif
17776
32
#ifdef O_EXCL
17777
32
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17778
32
#endif
17779
32
#ifdef O_TRUNC
17780
32
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17781
32
#endif
17782
#ifdef O_BINARY
17783
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17784
#endif
17785
#ifdef O_TEXT
17786
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17787
#endif
17788
#ifdef O_XATTR
17789
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17790
#endif
17791
32
#ifdef O_LARGEFILE
17792
32
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17793
32
#endif
17794
32
#ifndef __GNU__
17795
#ifdef O_SHLOCK
17796
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17797
#endif
17798
#ifdef O_EXLOCK
17799
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17800
#endif
17801
32
#endif
17802
#ifdef O_EXEC
17803
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17804
#endif
17805
#ifdef O_SEARCH
17806
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17807
#endif
17808
32
#ifdef O_PATH
17809
32
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17810
32
#endif
17811
#ifdef O_TTY_INIT
17812
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17813
#endif
17814
32
#ifdef O_TMPFILE
17815
32
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17816
32
#endif
17817
32
#ifdef PRIO_PROCESS
17818
32
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17819
32
#endif
17820
32
#ifdef PRIO_PGRP
17821
32
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17822
32
#endif
17823
32
#ifdef PRIO_USER
17824
32
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17825
32
#endif
17826
#ifdef PRIO_DARWIN_THREAD
17827
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17828
#endif
17829
#ifdef PRIO_DARWIN_PROCESS
17830
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17831
#endif
17832
#ifdef PRIO_DARWIN_BG
17833
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17834
#endif
17835
#ifdef PRIO_DARWIN_NONUI
17836
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17837
#endif
17838
32
#ifdef O_CLOEXEC
17839
32
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17840
32
#endif
17841
32
#ifdef O_ACCMODE
17842
32
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17843
32
#endif
17844
#ifdef O_EVTONLY
17845
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17846
#endif
17847
32
#ifdef O_FSYNC
17848
32
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17849
32
#endif
17850
#ifdef O_SYMLINK
17851
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17852
#endif
17853
17854
32
#ifdef SEEK_HOLE
17855
32
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17856
32
#endif
17857
32
#ifdef SEEK_DATA
17858
32
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17859
32
#endif
17860
17861
/* MS Windows */
17862
#ifdef O_NOINHERIT
17863
    /* Don't inherit in child processes. */
17864
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17865
#endif
17866
#ifdef _O_SHORT_LIVED
17867
    /* Optimize for short life (keep in memory). */
17868
    /* MS forgot to define this one with a non-underscore form too. */
17869
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17870
#endif
17871
#ifdef O_TEMPORARY
17872
    /* Automatically delete when last handle is closed. */
17873
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17874
#endif
17875
#ifdef O_RANDOM
17876
    /* Optimize for random access. */
17877
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17878
#endif
17879
#ifdef O_SEQUENTIAL
17880
    /* Optimize for sequential access. */
17881
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17882
#endif
17883
17884
/* GNU extensions. */
17885
32
#ifdef O_ASYNC
17886
    /* Send a SIGIO signal whenever input or output
17887
       becomes available on file descriptor */
17888
32
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17889
32
#endif
17890
32
#ifdef O_DIRECT
17891
    /* Direct disk access. */
17892
32
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17893
32
#endif
17894
32
#ifdef O_DIRECTORY
17895
    /* Must be a directory.      */
17896
32
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17897
32
#endif
17898
32
#ifdef O_NOFOLLOW
17899
    /* Do not follow links.      */
17900
32
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17901
32
#endif
17902
#ifdef O_NOFOLLOW_ANY
17903
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17904
#endif
17905
#ifdef O_NOLINKS
17906
    /* Fails if link count of the named file is greater than 1 */
17907
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17908
#endif
17909
32
#ifdef O_NOATIME
17910
    /* Do not update the access time. */
17911
32
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17912
32
#endif
17913
17914
    /* These come from sysexits.h */
17915
32
#ifdef EX_OK
17916
32
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17917
32
#endif /* EX_OK */
17918
32
#ifdef EX_USAGE
17919
32
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17920
32
#endif /* EX_USAGE */
17921
32
#ifdef EX_DATAERR
17922
32
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17923
32
#endif /* EX_DATAERR */
17924
32
#ifdef EX_NOINPUT
17925
32
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17926
32
#endif /* EX_NOINPUT */
17927
32
#ifdef EX_NOUSER
17928
32
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17929
32
#endif /* EX_NOUSER */
17930
32
#ifdef EX_NOHOST
17931
32
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17932
32
#endif /* EX_NOHOST */
17933
32
#ifdef EX_UNAVAILABLE
17934
32
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17935
32
#endif /* EX_UNAVAILABLE */
17936
32
#ifdef EX_SOFTWARE
17937
32
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17938
32
#endif /* EX_SOFTWARE */
17939
32
#ifdef EX_OSERR
17940
32
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17941
32
#endif /* EX_OSERR */
17942
32
#ifdef EX_OSFILE
17943
32
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17944
32
#endif /* EX_OSFILE */
17945
32
#ifdef EX_CANTCREAT
17946
32
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17947
32
#endif /* EX_CANTCREAT */
17948
32
#ifdef EX_IOERR
17949
32
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17950
32
#endif /* EX_IOERR */
17951
32
#ifdef EX_TEMPFAIL
17952
32
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17953
32
#endif /* EX_TEMPFAIL */
17954
32
#ifdef EX_PROTOCOL
17955
32
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17956
32
#endif /* EX_PROTOCOL */
17957
32
#ifdef EX_NOPERM
17958
32
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17959
32
#endif /* EX_NOPERM */
17960
32
#ifdef EX_CONFIG
17961
32
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17962
32
#endif /* EX_CONFIG */
17963
#ifdef EX_NOTFOUND
17964
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17965
#endif /* EX_NOTFOUND */
17966
17967
    /* statvfs */
17968
32
#ifdef ST_RDONLY
17969
32
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17970
32
#endif /* ST_RDONLY */
17971
32
#ifdef ST_NOSUID
17972
32
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17973
32
#endif /* ST_NOSUID */
17974
17975
       /* GNU extensions */
17976
32
#ifdef ST_NODEV
17977
32
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17978
32
#endif /* ST_NODEV */
17979
32
#ifdef ST_NOEXEC
17980
32
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17981
32
#endif /* ST_NOEXEC */
17982
32
#ifdef ST_SYNCHRONOUS
17983
32
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17984
32
#endif /* ST_SYNCHRONOUS */
17985
32
#ifdef ST_MANDLOCK
17986
32
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17987
32
#endif /* ST_MANDLOCK */
17988
32
#ifdef ST_WRITE
17989
32
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17990
32
#endif /* ST_WRITE */
17991
32
#ifdef ST_APPEND
17992
32
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
17993
32
#endif /* ST_APPEND */
17994
32
#ifdef ST_NOATIME
17995
32
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
17996
32
#endif /* ST_NOATIME */
17997
32
#ifdef ST_NODIRATIME
17998
32
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
17999
32
#endif /* ST_NODIRATIME */
18000
32
#ifdef ST_RELATIME
18001
32
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18002
32
#endif /* ST_RELATIME */
18003
18004
    /* FreeBSD sendfile() constants */
18005
#ifdef SF_NODISKIO
18006
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18007
#endif
18008
    /* is obsolete since the 11.x release */
18009
#ifdef SF_MNOWAIT
18010
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18011
#endif
18012
#ifdef SF_SYNC
18013
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18014
#endif
18015
#ifdef SF_NOCACHE
18016
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18017
#endif
18018
18019
32
#ifdef TFD_NONBLOCK
18020
32
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18021
32
#endif
18022
32
#ifdef TFD_CLOEXEC
18023
32
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18024
32
#endif
18025
32
#ifdef TFD_TIMER_ABSTIME
18026
32
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18027
32
#endif
18028
32
#ifdef TFD_TIMER_CANCEL_ON_SET
18029
32
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18030
32
#endif
18031
18032
    /* constants for posix_fadvise */
18033
32
#ifdef POSIX_FADV_NORMAL
18034
32
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18035
32
#endif
18036
32
#ifdef POSIX_FADV_SEQUENTIAL
18037
32
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18038
32
#endif
18039
32
#ifdef POSIX_FADV_RANDOM
18040
32
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18041
32
#endif
18042
32
#ifdef POSIX_FADV_NOREUSE
18043
32
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18044
32
#endif
18045
32
#ifdef POSIX_FADV_WILLNEED
18046
32
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18047
32
#endif
18048
32
#ifdef POSIX_FADV_DONTNEED
18049
32
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18050
32
#endif
18051
18052
    /* constants for waitid */
18053
32
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18054
32
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18055
32
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18056
32
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18057
32
#ifdef P_PIDFD
18058
32
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18059
32
#endif
18060
#ifdef PIDFD_NONBLOCK
18061
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18062
#endif
18063
32
#endif
18064
32
#ifdef WEXITED
18065
32
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18066
32
#endif
18067
32
#ifdef WNOWAIT
18068
32
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18069
32
#endif
18070
32
#ifdef WSTOPPED
18071
32
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18072
32
#endif
18073
32
#ifdef CLD_EXITED
18074
32
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18075
32
#endif
18076
32
#ifdef CLD_KILLED
18077
32
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18078
32
#endif
18079
32
#ifdef CLD_DUMPED
18080
32
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18081
32
#endif
18082
32
#ifdef CLD_TRAPPED
18083
32
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18084
32
#endif
18085
32
#ifdef CLD_STOPPED
18086
32
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18087
32
#endif
18088
32
#ifdef CLD_CONTINUED
18089
32
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18090
32
#endif
18091
18092
    /* constants for lockf */
18093
32
#ifdef F_LOCK
18094
32
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18095
32
#endif
18096
32
#ifdef F_TLOCK
18097
32
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18098
32
#endif
18099
32
#ifdef F_ULOCK
18100
32
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18101
32
#endif
18102
32
#ifdef F_TEST
18103
32
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18104
32
#endif
18105
18106
32
#ifdef RWF_DSYNC
18107
32
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18108
32
#endif
18109
32
#ifdef RWF_HIPRI
18110
32
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18111
32
#endif
18112
32
#ifdef RWF_SYNC
18113
32
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18114
32
#endif
18115
32
#ifdef RWF_NOWAIT
18116
32
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18117
32
#endif
18118
#ifdef RWF_DONTCACHE
18119
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18120
#endif
18121
#ifdef RWF_ATOMIC
18122
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18123
#endif
18124
32
#ifdef RWF_APPEND
18125
32
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18126
32
#endif
18127
18128
/* constants for splice */
18129
32
#if defined(HAVE_SPLICE) && defined(__linux__)
18130
32
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18131
32
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18132
32
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18133
32
#endif
18134
18135
/* constants for posix_spawn */
18136
32
#ifdef HAVE_POSIX_SPAWN
18137
32
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18138
32
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18139
32
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18140
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18141
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18142
#endif
18143
32
#endif
18144
18145
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18146
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18147
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18148
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18149
#endif
18150
#ifdef HAVE_SPAWNV
18151
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18152
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18153
#endif
18154
18155
32
#ifdef HAVE_SCHED_H
18156
32
#ifdef SCHED_OTHER
18157
32
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18158
32
#endif
18159
32
#ifdef SCHED_DEADLINE
18160
32
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18161
32
#endif
18162
32
#ifdef SCHED_FIFO
18163
32
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18164
32
#endif
18165
32
#ifdef SCHED_NORMAL
18166
32
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18167
32
#endif
18168
32
#ifdef SCHED_RR
18169
32
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18170
32
#endif
18171
#ifdef SCHED_SPORADIC
18172
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18173
#endif
18174
32
#ifdef SCHED_BATCH
18175
32
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18176
32
#endif
18177
32
#ifdef SCHED_IDLE
18178
32
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18179
32
#endif
18180
32
#ifdef SCHED_RESET_ON_FORK
18181
32
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18182
32
#endif
18183
#ifdef SCHED_SYS
18184
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18185
#endif
18186
#ifdef SCHED_IA
18187
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18188
#endif
18189
#ifdef SCHED_FSS
18190
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18191
#endif
18192
#ifdef SCHED_FX
18193
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18194
#endif
18195
18196
/* constants for namespaces */
18197
32
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18198
32
#ifdef CLONE_FS
18199
32
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18200
32
#endif
18201
32
#ifdef CLONE_FILES
18202
32
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18203
32
#endif
18204
32
#ifdef CLONE_NEWNS
18205
32
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18206
32
#endif
18207
32
#ifdef CLONE_NEWCGROUP
18208
32
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18209
32
#endif
18210
32
#ifdef CLONE_NEWUTS
18211
32
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18212
32
#endif
18213
32
#ifdef CLONE_NEWIPC
18214
32
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18215
32
#endif
18216
32
#ifdef CLONE_NEWUSER
18217
32
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18218
32
#endif
18219
32
#ifdef CLONE_NEWPID
18220
32
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18221
32
#endif
18222
32
#ifdef CLONE_NEWNET
18223
32
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18224
32
#endif
18225
#ifdef CLONE_NEWTIME
18226
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18227
#endif
18228
32
#ifdef CLONE_SYSVSEM
18229
32
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18230
32
#endif
18231
32
#ifdef CLONE_THREAD
18232
32
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18233
32
#endif
18234
32
#ifdef CLONE_SIGHAND
18235
32
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18236
32
#endif
18237
32
#ifdef CLONE_VM
18238
32
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18239
32
#endif
18240
32
#endif
18241
18242
32
#endif
18243
18244
32
#ifdef USE_XATTRS
18245
32
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18246
32
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18247
32
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18248
32
#endif
18249
18250
32
#if HAVE_DECL_RTLD_LAZY
18251
32
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18252
32
#endif
18253
32
#if HAVE_DECL_RTLD_NOW
18254
32
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18255
32
#endif
18256
32
#if HAVE_DECL_RTLD_GLOBAL
18257
32
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18258
32
#endif
18259
32
#if HAVE_DECL_RTLD_LOCAL
18260
32
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18261
32
#endif
18262
32
#if HAVE_DECL_RTLD_NODELETE
18263
32
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18264
32
#endif
18265
32
#if HAVE_DECL_RTLD_NOLOAD
18266
32
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18267
32
#endif
18268
32
#if HAVE_DECL_RTLD_DEEPBIND
18269
32
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18270
32
#endif
18271
#if HAVE_DECL_RTLD_MEMBER
18272
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18273
#endif
18274
18275
32
#ifdef HAVE_GETRANDOM_SYSCALL
18276
32
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18277
32
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18278
32
#endif
18279
32
#ifdef HAVE_MEMFD_CREATE
18280
32
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18281
32
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18282
32
#ifdef MFD_HUGETLB
18283
32
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18284
32
#endif
18285
32
#ifdef MFD_HUGE_SHIFT
18286
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18287
32
#endif
18288
32
#ifdef MFD_HUGE_MASK
18289
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18290
32
#endif
18291
32
#ifdef MFD_HUGE_64KB
18292
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18293
32
#endif
18294
32
#ifdef MFD_HUGE_512KB
18295
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18296
32
#endif
18297
32
#ifdef MFD_HUGE_1MB
18298
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18299
32
#endif
18300
32
#ifdef MFD_HUGE_2MB
18301
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18302
32
#endif
18303
32
#ifdef MFD_HUGE_8MB
18304
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18305
32
#endif
18306
32
#ifdef MFD_HUGE_16MB
18307
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18308
32
#endif
18309
32
#ifdef MFD_HUGE_32MB
18310
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18311
32
#endif
18312
32
#ifdef MFD_HUGE_256MB
18313
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18314
32
#endif
18315
32
#ifdef MFD_HUGE_512MB
18316
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18317
32
#endif
18318
32
#ifdef MFD_HUGE_1GB
18319
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18320
32
#endif
18321
32
#ifdef MFD_HUGE_2GB
18322
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18323
32
#endif
18324
32
#ifdef MFD_HUGE_16GB
18325
32
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18326
32
#endif
18327
32
#endif /* HAVE_MEMFD_CREATE */
18328
18329
32
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18330
32
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18331
32
#ifdef EFD_NONBLOCK
18332
32
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18333
32
#endif
18334
32
#ifdef EFD_SEMAPHORE
18335
32
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18336
32
#endif
18337
32
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18338
18339
32
#ifdef NODEV
18340
32
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18341
32
#endif
18342
18343
32
#ifdef AT_NO_AUTOMOUNT
18344
32
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18345
32
#endif
18346
18347
32
#ifdef HAVE_STATX
18348
32
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18349
32
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18350
32
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18351
32
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18352
32
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18353
32
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18354
32
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18355
32
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18356
32
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18357
32
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18358
32
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18359
32
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18360
32
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18361
#ifdef STATX_MNT_ID
18362
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18363
#endif
18364
#ifdef STATX_DIOALIGN
18365
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18366
#endif
18367
#ifdef STATX_MNT_ID_UNIQUE
18368
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18369
#endif
18370
#ifdef STATX_SUBVOL
18371
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18372
#endif
18373
#ifdef STATX_WRITE_ATOMIC
18374
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18375
#endif
18376
#ifdef STATX_DIO_READ_ALIGN
18377
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18378
#endif
18379
    /* STATX_ALL intentionally omitted because it is deprecated */
18380
32
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18381
32
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18382
32
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18383
    /* STATX_ATTR_* constants are in the stat module */
18384
32
#endif /* HAVE_STATX */
18385
18386
#if defined(__APPLE__)
18387
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18388
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18389
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18390
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18391
#endif
18392
18393
#ifdef MS_WINDOWS
18394
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18395
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18396
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18397
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18398
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18399
#endif
18400
18401
32
    return 0;
18402
32
}
18403
18404
18405
18406
#define PROBE(name, test) \
18407
   static int name(void)  \
18408
544
   {                      \
18409
544
      if (test) {        \
18410
544
          return 1;       \
18411
544
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
544
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_futimens
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_linkat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_openat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_renameat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18408
32
   {                      \
18409
32
      if (test) {        \
18410
32
          return 1;       \
18411
32
      } else {            \
18412
0
          return 0;       \
18413
0
      }                   \
18414
32
   }
18415
18416
#ifdef HAVE_FSTATAT
18417
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18418
#endif
18419
18420
#ifdef HAVE_FACCESSAT
18421
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18422
#endif
18423
18424
#ifdef HAVE_FCHMODAT
18425
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18426
#endif
18427
18428
#ifdef HAVE_FCHOWNAT
18429
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18430
#endif
18431
18432
#ifdef HAVE_LINKAT
18433
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18434
#endif
18435
18436
#ifdef HAVE_FDOPENDIR
18437
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18438
#endif
18439
18440
#ifdef HAVE_MKDIRAT
18441
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18442
#endif
18443
18444
#ifdef HAVE_MKFIFOAT
18445
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18446
#endif
18447
18448
#ifdef HAVE_MKNODAT
18449
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18450
#endif
18451
18452
#ifdef HAVE_RENAMEAT
18453
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18454
#endif
18455
18456
#ifdef HAVE_UNLINKAT
18457
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18458
#endif
18459
18460
#ifdef HAVE_OPENAT
18461
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18462
#endif
18463
18464
#ifdef HAVE_READLINKAT
18465
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18466
#endif
18467
18468
#ifdef HAVE_SYMLINKAT
18469
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18470
#endif
18471
18472
#ifdef HAVE_FUTIMENS
18473
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18474
#endif
18475
18476
#ifdef HAVE_UTIMENSAT
18477
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18478
#endif
18479
18480
#ifdef HAVE_PTSNAME_R
18481
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18482
#endif
18483
18484
18485
18486
static const struct have_function {
18487
    const char * const label;
18488
    int (*probe)(void);
18489
} have_functions[] = {
18490
18491
#ifdef HAVE_EVENTFD
18492
    {"HAVE_EVENTFD", NULL},
18493
#endif
18494
18495
#ifdef HAVE_TIMERFD_CREATE
18496
    {"HAVE_TIMERFD_CREATE", NULL},
18497
#endif
18498
18499
#ifdef HAVE_FACCESSAT
18500
    { "HAVE_FACCESSAT", probe_faccessat },
18501
#endif
18502
18503
#ifdef HAVE_FCHDIR
18504
    { "HAVE_FCHDIR", NULL },
18505
#endif
18506
18507
#ifdef HAVE_FCHMOD
18508
    { "HAVE_FCHMOD", NULL },
18509
#endif
18510
18511
#ifdef HAVE_FCHMODAT
18512
    { "HAVE_FCHMODAT", probe_fchmodat },
18513
#endif
18514
18515
#ifdef HAVE_FCHOWN
18516
    { "HAVE_FCHOWN", NULL },
18517
#endif
18518
18519
#ifdef HAVE_FCHOWNAT
18520
    { "HAVE_FCHOWNAT", probe_fchownat },
18521
#endif
18522
18523
#ifdef HAVE_FEXECVE
18524
    { "HAVE_FEXECVE", NULL },
18525
#endif
18526
18527
#ifdef HAVE_FDOPENDIR
18528
    { "HAVE_FDOPENDIR", probe_fdopendir },
18529
#endif
18530
18531
#ifdef HAVE_FPATHCONF
18532
    { "HAVE_FPATHCONF", NULL },
18533
#endif
18534
18535
#ifdef HAVE_FSTATAT
18536
    { "HAVE_FSTATAT", probe_fstatat },
18537
#endif
18538
18539
#ifdef HAVE_FSTATVFS
18540
    { "HAVE_FSTATVFS", NULL },
18541
#endif
18542
18543
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18544
    { "HAVE_FTRUNCATE", NULL },
18545
#endif
18546
18547
#ifdef HAVE_FUTIMENS
18548
    { "HAVE_FUTIMENS", probe_futimens },
18549
#endif
18550
18551
#ifdef HAVE_FUTIMES
18552
    { "HAVE_FUTIMES", NULL },
18553
#endif
18554
18555
#ifdef HAVE_FUTIMESAT
18556
    { "HAVE_FUTIMESAT", NULL },
18557
#endif
18558
18559
#ifdef HAVE_LINKAT
18560
    { "HAVE_LINKAT", probe_linkat },
18561
#endif
18562
18563
#ifdef HAVE_LCHFLAGS
18564
    { "HAVE_LCHFLAGS", NULL },
18565
#endif
18566
18567
#ifdef HAVE_LCHMOD
18568
    { "HAVE_LCHMOD", NULL },
18569
#endif
18570
18571
#ifdef HAVE_LCHOWN
18572
    { "HAVE_LCHOWN", NULL },
18573
#endif
18574
18575
#ifdef HAVE_LSTAT
18576
    { "HAVE_LSTAT", NULL },
18577
#endif
18578
18579
#ifdef HAVE_LUTIMES
18580
    { "HAVE_LUTIMES", NULL },
18581
#endif
18582
18583
#ifdef HAVE_MEMFD_CREATE
18584
    { "HAVE_MEMFD_CREATE", NULL },
18585
#endif
18586
18587
#ifdef HAVE_MKDIRAT
18588
    { "HAVE_MKDIRAT", probe_mkdirat },
18589
#endif
18590
18591
#ifdef HAVE_MKFIFOAT
18592
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18593
#endif
18594
18595
#ifdef HAVE_MKNODAT
18596
    { "HAVE_MKNODAT", probe_mknodat },
18597
#endif
18598
18599
#ifdef HAVE_OPENAT
18600
    { "HAVE_OPENAT", probe_openat },
18601
#endif
18602
18603
#ifdef HAVE_READLINKAT
18604
    { "HAVE_READLINKAT", probe_readlinkat },
18605
#endif
18606
18607
#ifdef HAVE_RENAMEAT
18608
    { "HAVE_RENAMEAT", probe_renameat },
18609
#endif
18610
18611
#ifdef HAVE_SYMLINKAT
18612
    { "HAVE_SYMLINKAT", probe_symlinkat },
18613
#endif
18614
18615
#ifdef HAVE_UNLINKAT
18616
    { "HAVE_UNLINKAT", probe_unlinkat },
18617
#endif
18618
18619
#ifdef HAVE_UTIMENSAT
18620
    { "HAVE_UTIMENSAT", probe_utimensat },
18621
#endif
18622
18623
#ifdef HAVE_PTSNAME_R
18624
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18625
#endif
18626
18627
#ifdef MS_WINDOWS
18628
    { "MS_WINDOWS", NULL },
18629
#endif
18630
18631
    { NULL, NULL }
18632
};
18633
18634
18635
static int
18636
posixmodule_exec(PyObject *m)
18637
32
{
18638
32
    _posixstate *state = get_posix_state(m);
18639
18640
32
#if defined(HAVE_PWRITEV)
18641
32
    if (HAVE_PWRITEV_RUNTIME) {} else {
18642
0
        PyObject* dct = PyModule_GetDict(m);
18643
18644
0
        if (dct == NULL) {
18645
0
            return -1;
18646
0
        }
18647
18648
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18649
0
            return -1;
18650
0
        }
18651
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18652
0
            return -1;
18653
0
        }
18654
0
    }
18655
32
#endif
18656
18657
32
#ifdef HAVE_STATX
18658
32
    if (statx == NULL) {
18659
0
        PyObject* dct = PyModule_GetDict(m);
18660
0
        if (dct == NULL) {
18661
0
            return -1;
18662
0
        }
18663
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18664
0
            return -1;
18665
0
        }
18666
0
    }
18667
32
    else {
18668
32
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18669
32
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18670
0
            return -1;
18671
0
        }
18672
32
    }
18673
32
#endif
18674
18675
    /* Initialize environ dictionary */
18676
32
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18677
0
        return -1;
18678
0
    }
18679
18680
32
    if (all_ins(m))
18681
0
        return -1;
18682
18683
32
    if (setup_confname_tables(m))
18684
0
        return -1;
18685
18686
32
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18687
0
        return -1;
18688
0
    }
18689
18690
32
#if defined(HAVE_WAITID)
18691
32
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18692
32
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18693
0
        return -1;
18694
0
    }
18695
32
#endif
18696
18697
32
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18698
32
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18699
32
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18700
32
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18701
32
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18702
0
        return -1;
18703
0
    }
18704
32
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18705
32
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18706
18707
32
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18708
32
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18709
0
        return -1;
18710
0
    }
18711
18712
32
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18713
32
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18714
32
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18715
0
        return -1;
18716
0
    }
18717
32
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18718
32
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18719
32
                          &os_sched_param_reduce_method) < 0)
18720
0
    {
18721
0
        return -1;
18722
0
    }
18723
32
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18724
32
#endif
18725
18726
    /* initialize TerminalSize_info */
18727
32
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18728
32
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18729
0
        return -1;
18730
0
    }
18731
18732
    /* initialize scandir types */
18733
32
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18734
32
    if (ScandirIteratorType == NULL) {
18735
0
        return -1;
18736
0
    }
18737
32
    state->ScandirIteratorType = ScandirIteratorType;
18738
18739
32
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18740
32
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18741
0
        return -1;
18742
0
    }
18743
18744
32
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18745
32
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18746
0
        return -1;
18747
0
    }
18748
18749
32
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18750
32
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18751
0
        return -1;
18752
0
    }
18753
18754
32
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18755
0
        return -1;
18756
32
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18757
32
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18758
32
    if (state->struct_rusage == NULL)
18759
0
        return -1;
18760
32
#endif
18761
32
    state->st_mode = PyUnicode_InternFromString("st_mode");
18762
32
    if (state->st_mode == NULL)
18763
0
        return -1;
18764
18765
    /* suppress "function not used" warnings */
18766
32
    {
18767
32
    int ignored;
18768
32
    fd_specified("", -1);
18769
32
    follow_symlinks_specified("", 1);
18770
32
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18771
32
    dir_fd_converter(Py_None, &ignored);
18772
32
    dir_fd_unavailable(Py_None, &ignored);
18773
32
    }
18774
18775
    /*
18776
     * provide list of locally available functions
18777
     * so os.py can populate support_* lists
18778
     */
18779
32
    PyObject *list = PyList_New(0);
18780
32
    if (!list) {
18781
0
        return -1;
18782
0
    }
18783
1.05k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18784
1.02k
        PyObject *unicode;
18785
1.02k
        if (trace->probe && !trace->probe()) continue;
18786
1.02k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18787
1.02k
        if (!unicode)
18788
0
            return -1;
18789
1.02k
        if (PyList_Append(list, unicode))
18790
0
            return -1;
18791
1.02k
        Py_DECREF(unicode);
18792
1.02k
    }
18793
18794
32
#ifndef MS_WINDOWS
18795
32
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18796
0
        PyErr_SetString(PyExc_RuntimeError,
18797
0
                        "cannot read ticks_per_second");
18798
0
        return -1;
18799
0
    }
18800
32
    assert(state->ticks_per_second >= 1);
18801
32
#endif
18802
18803
32
    return PyModule_Add(m, "_have_functions", list);
18804
32
}
18805
18806
18807
static PyModuleDef_Slot posixmodile_slots[] = {
18808
    {Py_mod_exec, posixmodule_exec},
18809
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18810
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18811
    {0, NULL}
18812
};
18813
18814
static struct PyModuleDef posixmodule = {
18815
    PyModuleDef_HEAD_INIT,
18816
    .m_name = MODNAME,
18817
    .m_doc = posix__doc__,
18818
    .m_size = sizeof(_posixstate),
18819
    .m_methods = posix_methods,
18820
    .m_slots = posixmodile_slots,
18821
    .m_traverse = _posix_traverse,
18822
    .m_clear = _posix_clear,
18823
    .m_free = _posix_free,
18824
};
18825
18826
PyMODINIT_FUNC
18827
INITFUNC(void)
18828
32
{
18829
32
    return PyModuleDef_Init(&posixmodule);
18830
32
}