Coverage Report

Created: 2026-03-23 06:45

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
470k
#  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
274k
#  define STAT stat
407
11.2k
#  define LSTAT lstat
408
144k
#  define FSTAT fstat
409
570k
#  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
140k
#  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
144k
#  define HAVE_FDOPENDIR_RUNTIME 1
608
0
#  define HAVE_MKDIRAT_RUNTIME 1
609
0
#  define HAVE_RENAMEAT_RUNTIME 1
610
163k
#  define HAVE_UNLINKAT_RUNTIME 1
611
140k
#  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
36
#  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
90
{
798
90
    if (func == NULL)  /* nothing to register? do nothing. */
799
52
        return 0;
800
38
    if (*lst == NULL) {
801
20
        *lst = PyList_New(0);
802
20
        if (*lst == NULL)
803
0
            return -1;
804
20
    }
805
38
    return PyList_Append(*lst, func);
806
38
}
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
353k
{
835
353k
    if (uid == (uid_t)-1)
836
0
        return PyLong_FromLong(-1);
837
353k
    return PyLong_FromUnsignedLong(uid);
838
353k
}
839
840
PyObject *
841
_PyLong_FromGid(gid_t gid)
842
353k
{
843
353k
    if (gid == (gid_t)-1)
844
0
        return PyLong_FromLong(-1);
845
353k
    return PyLong_FromUnsignedLong(gid);
846
353k
}
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
707k
{
1066
707k
#ifdef NODEV
1067
707k
    if (dev == NODEV) {
1068
36
        return PyLong_FromLongLong((long long)dev);
1069
36
    }
1070
707k
#endif
1071
707k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1072
707k
}
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
2.52M
#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
447k
{
1137
447k
    int overflow;
1138
447k
    long long_value;
1139
1140
447k
    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
447k
    PyObject *index = _PyNumber_Index(o);
1148
447k
    if (index == NULL) {
1149
0
        return 0;
1150
0
    }
1151
1152
447k
    assert(PyLong_Check(index));
1153
447k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1154
447k
    Py_DECREF(index);
1155
447k
    assert(!PyErr_Occurred());
1156
447k
    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
447k
    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
447k
    *p = (int)long_value;
1168
447k
    return 1;
1169
447k
}
1170
1171
static int
1172
dir_fd_converter(PyObject *o, void *p)
1173
319k
{
1174
319k
    if (o == Py_None) {
1175
15.5k
        *(int *)p = DEFAULT_DIR_FD;
1176
15.5k
        return 1;
1177
15.5k
    }
1178
303k
    else if (PyIndex_Check(o)) {
1179
303k
        return _fd_converter(o, (int *)p);
1180
303k
    }
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
319k
}
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
662k
{
1222
662k
    void *state = _PyModule_GetState(module);
1223
662k
    assert(state != NULL);
1224
662k
    return (_posixstate *)state;
1225
662k
}
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
 *   path.is_fd
1284
 *     True if path was provided as a file descriptor.
1285
 *
1286
 *     WARNING: if your "path" parameter is optional, and is
1287
 *     unspecified, path_converter will never get called.
1288
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1289
 *     yourself!
1290
 *   path.value_error
1291
 *     If nonzero, then suppress_value_error was specified and a ValueError
1292
 *     occurred.
1293
 *   path.length
1294
 *     The length of the path in characters, if specified as
1295
 *     a string.
1296
 *   path.object
1297
 *     The original object passed in (if get a PathLike object,
1298
 *     the result of PyOS_FSPath() is treated as the original object).
1299
 *     Own a reference to the object.
1300
 *   path.cleanup
1301
 *     For internal use only.  May point to a temporary object.
1302
 *     (Pay no attention to the man behind the curtain.)
1303
 *
1304
 *   At most one of path.wide or path.narrow will be non-NULL.
1305
 *   If path was None and path.nullable was set,
1306
 *     or if path was an integer and path.allow_fd was set,
1307
 *     both path.wide and path.narrow will be NULL
1308
 *     and path.length will be 0.
1309
 *
1310
 *   path_converter takes care to not write to the path_t
1311
 *   unless it's successful.  However it must reset the
1312
 *   "cleanup" field each time it's called.
1313
 *
1314
 * Use as follows:
1315
 *      path_t path;
1316
 *      memset(&path, 0, sizeof(path));
1317
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1318
 *      // ... use values from path ...
1319
 *      path_cleanup(&path);
1320
 *
1321
 * (Note that if PyArg_Parse fails you don't need to call
1322
 * path_cleanup().  However it is safe to do so.)
1323
 */
1324
typedef struct {
1325
    // Input fields
1326
    const char *function_name;
1327
    const char *argument_name;
1328
    int nullable;
1329
    int nonstrict;
1330
    int make_wide;
1331
    int suppress_value_error;
1332
    int allow_fd;
1333
    // Output fields
1334
    const wchar_t *wide;
1335
    const char *narrow;
1336
    int fd;
1337
    bool is_fd;
1338
    int value_error;
1339
    Py_ssize_t length;
1340
    PyObject *object;
1341
    PyObject *cleanup;
1342
} path_t;
1343
1344
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1345
                          make_wide, suppress_value_error, allow_fd) \
1346
1.08M
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1347
1.08M
     suppress_value_error, allow_fd, NULL, NULL, -1, false, 0, 0, NULL, NULL}
1348
#ifdef MS_WINDOWS
1349
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1350
                            nonstrict, suppress_value_error, allow_fd) \
1351
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1352
                      suppress_value_error, allow_fd)
1353
#else
1354
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1355
                            nonstrict, suppress_value_error, allow_fd) \
1356
886k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1357
886k
                      suppress_value_error, allow_fd)
1358
#endif
1359
1360
static void
1361
path_cleanup(path_t *path)
1362
1.23M
{
1363
1.23M
    wchar_t *wide = (wchar_t *)path->wide;
1364
1.23M
    path->wide = NULL;
1365
1.23M
    PyMem_Free(wide);
1366
1.23M
    Py_CLEAR(path->object);
1367
1.23M
    Py_CLEAR(path->cleanup);
1368
1.23M
}
1369
1370
static int
1371
path_converter(PyObject *o, void *p)
1372
1.08M
{
1373
1.08M
    path_t *path = (path_t *)p;
1374
1.08M
    PyObject *bytes = NULL;
1375
1.08M
    Py_ssize_t length = 0;
1376
1.08M
    int is_index, is_bytes, is_unicode;
1377
1.08M
    const char *narrow;
1378
1.08M
    PyObject *wo = NULL;
1379
1.08M
    wchar_t *wide = NULL;
1380
1381
1.08M
#define FORMAT_EXCEPTION(exc, fmt) \
1382
1.08M
    PyErr_Format(exc, "%s%s" fmt, \
1383
0
        path->function_name ? path->function_name : "", \
1384
0
        path->function_name ? ": "                : "", \
1385
0
        path->argument_name ? path->argument_name : "path")
1386
1387
    /* Py_CLEANUP_SUPPORTED support */
1388
1.08M
    if (o == NULL) {
1389
0
        path_cleanup(path);
1390
0
        return 1;
1391
0
    }
1392
1393
    /* Ensure it's always safe to call path_cleanup(). */
1394
1.08M
    path->object = path->cleanup = NULL;
1395
    /* path->object owns a reference to the original object */
1396
1.08M
    Py_INCREF(o);
1397
1398
1.08M
    if ((o == Py_None) && path->nullable) {
1399
0
        path->wide = NULL;
1400
0
        path->narrow = NULL;
1401
0
        path->fd = -1;
1402
0
        goto success_exit;
1403
0
    }
1404
1405
    /* Only call this here so that we don't treat the return value of
1406
       os.fspath() as an fd or buffer. */
1407
1.08M
    is_index = path->allow_fd && PyIndex_Check(o);
1408
1.08M
    is_bytes = PyBytes_Check(o);
1409
1.08M
    is_unicode = PyUnicode_Check(o);
1410
1411
1.08M
    if (!is_index && !is_unicode && !is_bytes) {
1412
        /* Inline PyOS_FSPath() for better error messages. */
1413
12
        PyObject *func, *res;
1414
1415
12
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1416
12
        if ((NULL == func) || (func == Py_None)) {
1417
0
            goto error_format;
1418
0
        }
1419
12
        res = _PyObject_CallNoArgs(func);
1420
12
        Py_DECREF(func);
1421
12
        if (NULL == res) {
1422
0
            goto error_exit;
1423
0
        }
1424
12
        else if (PyUnicode_Check(res)) {
1425
12
            is_unicode = 1;
1426
12
        }
1427
0
        else if (PyBytes_Check(res)) {
1428
0
            is_bytes = 1;
1429
0
        }
1430
0
        else {
1431
0
            PyErr_Format(PyExc_TypeError,
1432
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1433
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1434
0
                 _PyType_Name(Py_TYPE(res)));
1435
0
            Py_DECREF(res);
1436
0
            goto error_exit;
1437
0
        }
1438
1439
        /* still owns a reference to the original object */
1440
12
        Py_SETREF(o, res);
1441
12
    }
1442
1443
1.08M
    if (is_unicode) {
1444
942k
        if (path->make_wide) {
1445
199k
            wide = PyUnicode_AsWideCharString(o, &length);
1446
199k
            if (!wide) {
1447
0
                goto error_exit;
1448
0
            }
1449
#ifdef MS_WINDOWS
1450
            if (!path->nonstrict && length > 32767) {
1451
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1452
                goto error_exit;
1453
            }
1454
#endif
1455
199k
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1456
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1457
0
                                 "embedded null character in %s");
1458
0
                goto error_exit;
1459
0
            }
1460
1461
199k
            path->wide = wide;
1462
199k
            path->narrow = NULL;
1463
199k
            path->fd = -1;
1464
199k
            wide = NULL;
1465
199k
            goto success_exit;
1466
199k
        }
1467
742k
        bytes = PyUnicode_EncodeFSDefault(o);
1468
742k
        if (!bytes) {
1469
0
            goto error_exit;
1470
0
        }
1471
742k
    }
1472
144k
    else if (is_bytes) {
1473
0
        bytes = Py_NewRef(o);
1474
0
    }
1475
144k
    else if (is_index) {
1476
144k
        if (!_fd_converter(o, &path->fd)) {
1477
0
            goto error_exit;
1478
0
        }
1479
144k
        path->wide = NULL;
1480
144k
        path->narrow = NULL;
1481
144k
        path->is_fd = true;
1482
144k
        goto success_exit;
1483
144k
    }
1484
0
    else {
1485
0
 error_format:
1486
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1487
0
            path->function_name ? path->function_name : "",
1488
0
            path->function_name ? ": "                : "",
1489
0
            path->argument_name ? path->argument_name : "path",
1490
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1491
0
                                               "integer or None" :
1492
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1493
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1494
0
                             "string, bytes or os.PathLike",
1495
0
            _PyType_Name(Py_TYPE(o)));
1496
0
        goto error_exit;
1497
0
    }
1498
1499
742k
    length = PyBytes_GET_SIZE(bytes);
1500
742k
    narrow = PyBytes_AS_STRING(bytes);
1501
742k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1502
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1503
0
        goto error_exit;
1504
0
    }
1505
1506
742k
    if (path->make_wide) {
1507
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1508
0
        if (!wo) {
1509
0
            goto error_exit;
1510
0
        }
1511
1512
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1513
0
        Py_DECREF(wo);
1514
0
        if (!wide) {
1515
0
            goto error_exit;
1516
0
        }
1517
#ifdef MS_WINDOWS
1518
        if (!path->nonstrict && length > 32767) {
1519
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1520
            goto error_exit;
1521
        }
1522
#endif
1523
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1524
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1525
0
                             "embedded null character in %s");
1526
0
            goto error_exit;
1527
0
        }
1528
0
        path->wide = wide;
1529
0
        path->narrow = NULL;
1530
0
        Py_DECREF(bytes);
1531
0
        wide = NULL;
1532
0
    }
1533
742k
    else {
1534
742k
        path->wide = NULL;
1535
742k
        path->narrow = narrow;
1536
742k
        if (bytes == o) {
1537
            /* Still a reference owned by path->object, don't have to
1538
            worry about path->narrow is used after free. */
1539
0
            Py_DECREF(bytes);
1540
0
        }
1541
742k
        else {
1542
742k
            path->cleanup = bytes;
1543
742k
        }
1544
742k
    }
1545
742k
    path->fd = -1;
1546
1547
1.08M
 success_exit:
1548
1.08M
    path->value_error = 0;
1549
1.08M
    path->length = length;
1550
1.08M
    path->object = o;
1551
1.08M
    return Py_CLEANUP_SUPPORTED;
1552
1553
0
 error_exit:
1554
0
    Py_XDECREF(o);
1555
0
    Py_XDECREF(bytes);
1556
0
    PyMem_Free(wide);
1557
0
    if (!path->suppress_value_error ||
1558
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1559
0
    {
1560
0
        return 0;
1561
0
    }
1562
0
    PyErr_Clear();
1563
0
    path->wide = NULL;
1564
0
    path->narrow = NULL;
1565
0
    path->fd = -1;
1566
0
    path->value_error = 1;
1567
0
    path->length = 0;
1568
0
    path->object = NULL;
1569
0
    return Py_CLEANUP_SUPPORTED;
1570
0
}
1571
1572
static void
1573
argument_unavailable_error(const char *function_name, const char *argument_name)
1574
0
{
1575
0
    PyErr_Format(PyExc_NotImplementedError,
1576
0
        "%s%s%s unavailable on this platform",
1577
0
        (function_name != NULL) ? function_name : "",
1578
0
        (function_name != NULL) ? ": ": "",
1579
0
        argument_name);
1580
0
}
1581
1582
static int
1583
dir_fd_unavailable(PyObject *o, void *p)
1584
36
{
1585
36
    int dir_fd;
1586
36
    if (!dir_fd_converter(o, &dir_fd))
1587
0
        return 0;
1588
36
    if (dir_fd != DEFAULT_DIR_FD) {
1589
0
        argument_unavailable_error(NULL, "dir_fd");
1590
0
        return 0;
1591
0
    }
1592
36
    *(int *)p = dir_fd;
1593
36
    return 1;
1594
36
}
1595
1596
static int
1597
fd_specified(const char *function_name, int fd)
1598
36
{
1599
36
    if (fd == -1)
1600
36
        return 0;
1601
1602
0
    argument_unavailable_error(function_name, "fd");
1603
0
    return 1;
1604
36
}
1605
1606
static int
1607
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1608
36
{
1609
36
    if (follow_symlinks)
1610
36
        return 0;
1611
1612
0
    argument_unavailable_error(function_name, "follow_symlinks");
1613
0
    return 1;
1614
36
}
1615
1616
static int
1617
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1618
285k
{
1619
285k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1620
0
        PyErr_Format(PyExc_ValueError,
1621
0
                     "%s: can't specify dir_fd without matching path",
1622
0
                     function_name);
1623
0
        return 1;
1624
0
    }
1625
285k
    return 0;
1626
285k
}
1627
1628
static int
1629
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1630
285k
{
1631
285k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1632
0
        PyErr_Format(PyExc_ValueError,
1633
0
                     "%s: can't specify both dir_fd and fd",
1634
0
                     function_name);
1635
0
        return 1;
1636
0
    }
1637
285k
    return 0;
1638
285k
}
1639
1640
static int
1641
fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
1642
                               int follow_symlinks)
1643
285k
{
1644
285k
    if (is_fd && (!follow_symlinks)) {
1645
0
        PyErr_Format(PyExc_ValueError,
1646
0
                     "%s: cannot use fd and follow_symlinks together",
1647
0
                     function_name);
1648
0
        return 1;
1649
0
    }
1650
285k
    return 0;
1651
285k
}
1652
1653
static int
1654
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1655
                                   int follow_symlinks)
1656
36
{
1657
36
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1658
0
        PyErr_Format(PyExc_ValueError,
1659
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1660
0
                     function_name);
1661
0
        return 1;
1662
0
    }
1663
36
    return 0;
1664
36
}
1665
1666
#if defined(HAVE_WAITID)
1667
static int
1668
idtype_t_converter(PyObject *arg, void *addr)
1669
0
{
1670
0
    int value = PyLong_AsInt(arg);
1671
0
    if (value == -1 && PyErr_Occurred()) {
1672
0
        return 0;
1673
0
    }
1674
0
    *((idtype_t *)addr) = (idtype_t)(value);
1675
0
    return 1;
1676
0
}
1677
#endif
1678
1679
#ifdef MS_WINDOWS
1680
    typedef long long Py_off_t;
1681
#else
1682
    typedef off_t Py_off_t;
1683
#endif
1684
1685
static int
1686
Py_off_t_converter(PyObject *arg, void *addr)
1687
0
{
1688
#ifdef HAVE_LARGEFILE_SUPPORT
1689
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1690
#else
1691
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1692
0
#endif
1693
0
    if (PyErr_Occurred())
1694
0
        return 0;
1695
0
    return 1;
1696
0
}
1697
1698
static PyObject *
1699
PyLong_FromPy_off_t(Py_off_t offset)
1700
0
{
1701
#ifdef HAVE_LARGEFILE_SUPPORT
1702
    return PyLong_FromLongLong(offset);
1703
#else
1704
0
    return PyLong_FromLong(offset);
1705
0
#endif
1706
0
}
1707
1708
#ifdef HAVE_SIGSET_T
1709
/* Convert an iterable of integers to a sigset.
1710
   Return 1 on success, return 0 and raise an exception on error. */
1711
int
1712
_Py_Sigset_Converter(PyObject *obj, void *addr)
1713
0
{
1714
0
    sigset_t *mask = (sigset_t *)addr;
1715
0
    PyObject *iterator, *item;
1716
0
    long signum;
1717
0
    int overflow;
1718
1719
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1720
0
    if (sigemptyset(mask) < (0)) {
1721
        /* Probably only if mask == NULL. */
1722
0
        PyErr_SetFromErrno(PyExc_OSError);
1723
0
        return 0;
1724
0
    }
1725
1726
0
    iterator = PyObject_GetIter(obj);
1727
0
    if (iterator == NULL) {
1728
0
        return 0;
1729
0
    }
1730
1731
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1732
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1733
0
        Py_DECREF(item);
1734
0
        if (signum <= 0 || signum >= Py_NSIG) {
1735
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1736
0
                PyErr_Format(PyExc_ValueError,
1737
0
                             "signal number %ld out of range [1; %i]",
1738
0
                             signum, Py_NSIG - 1);
1739
0
            }
1740
0
            goto error;
1741
0
        }
1742
0
        if (sigaddset(mask, (int)signum)) {
1743
0
            if (errno != EINVAL) {
1744
                /* Probably impossible */
1745
0
                PyErr_SetFromErrno(PyExc_OSError);
1746
0
                goto error;
1747
0
            }
1748
            /* For backwards compatibility, allow idioms such as
1749
             * `range(1, NSIG)` but warn about invalid signal numbers
1750
             */
1751
0
            const char msg[] =
1752
0
                "invalid signal number %ld, please use valid_signals()";
1753
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1754
0
                goto error;
1755
0
            }
1756
0
        }
1757
0
    }
1758
0
    if (!PyErr_Occurred()) {
1759
0
        Py_DECREF(iterator);
1760
0
        return 1;
1761
0
    }
1762
1763
0
error:
1764
0
    Py_DECREF(iterator);
1765
0
    return 0;
1766
0
}
1767
#endif /* HAVE_SIGSET_T */
1768
1769
/* Return a dictionary corresponding to the POSIX environment table */
1770
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1771
/* On Darwin/MacOSX a shared library or framework has no access to
1772
** environ directly, we must obtain it with _NSGetEnviron(). See also
1773
** man environ(7).
1774
*/
1775
#include <crt_externs.h>
1776
#define USE_DARWIN_NS_GET_ENVIRON 1
1777
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1778
extern char **environ;
1779
#endif /* !_MSC_VER */
1780
1781
static PyObject *
1782
convertenviron(void)
1783
36
{
1784
36
    PyObject *d;
1785
#ifdef MS_WINDOWS
1786
    wchar_t **e;
1787
#else
1788
36
    char **e;
1789
36
#endif
1790
1791
36
    d = PyDict_New();
1792
36
    if (d == NULL)
1793
0
        return NULL;
1794
#ifdef MS_WINDOWS
1795
    /* _wenviron must be initialized in this way if the program is started
1796
       through main() instead of wmain(). */
1797
    (void)_wgetenv(L"");
1798
    e = _wenviron;
1799
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1800
    /* environ is not accessible as an extern in a shared object on OSX; use
1801
       _NSGetEnviron to resolve it. The value changes if you add environment
1802
       variables between calls to Py_Initialize, so don't cache the value. */
1803
    e = *_NSGetEnviron();
1804
#else
1805
36
    e = environ;
1806
36
#endif
1807
36
    if (e == NULL)
1808
0
        return d;
1809
1.26k
    for (; *e != NULL; e++) {
1810
1.22k
        PyObject *k;
1811
1.22k
        PyObject *v;
1812
#ifdef MS_WINDOWS
1813
        const wchar_t *p = wcschr(*e, L'=');
1814
#else
1815
1.22k
        const char *p = strchr(*e, '=');
1816
1.22k
#endif
1817
1.22k
        if (p == NULL)
1818
0
            continue;
1819
#ifdef MS_WINDOWS
1820
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1821
#else
1822
1.22k
        k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
1823
1.22k
#endif
1824
1.22k
        if (k == NULL) {
1825
0
            Py_DECREF(d);
1826
0
            return NULL;
1827
0
        }
1828
#ifdef MS_WINDOWS
1829
        v = PyUnicode_FromWideChar(p+1, -1);
1830
#else
1831
1.22k
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1832
1.22k
#endif
1833
1.22k
        if (v == NULL) {
1834
0
            Py_DECREF(k);
1835
0
            Py_DECREF(d);
1836
0
            return NULL;
1837
0
        }
1838
1.22k
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1839
0
            Py_DECREF(v);
1840
0
            Py_DECREF(k);
1841
0
            Py_DECREF(d);
1842
0
            return NULL;
1843
0
        }
1844
1.22k
        Py_DECREF(k);
1845
1.22k
        Py_DECREF(v);
1846
1.22k
    }
1847
36
    return d;
1848
36
}
1849
1850
/* Set a POSIX-specific error from errno, and return NULL */
1851
1852
static PyObject *
1853
posix_error(void)
1854
0
{
1855
0
    return PyErr_SetFromErrno(PyExc_OSError);
1856
0
}
1857
1858
#ifdef MS_WINDOWS
1859
static PyObject *
1860
win32_error(const char* function, const char* filename)
1861
{
1862
    /* XXX We should pass the function name along in the future.
1863
       (winreg.c also wants to pass the function name.)
1864
       This would however require an additional param to the
1865
       Windows error object, which is non-trivial.
1866
    */
1867
    errno = GetLastError();
1868
    if (filename)
1869
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1870
    else
1871
        return PyErr_SetFromWindowsErr(errno);
1872
}
1873
1874
static PyObject *
1875
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1876
{
1877
    /* XXX - see win32_error for comments on 'function' */
1878
    if (filename)
1879
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1880
                    PyExc_OSError,
1881
                    err,
1882
                    filename);
1883
    else
1884
        return PyErr_SetFromWindowsErr(err);
1885
}
1886
1887
static PyObject *
1888
win32_error_object(const char* function, PyObject* filename)
1889
{
1890
    errno = GetLastError();
1891
    return win32_error_object_err(function, filename, errno);
1892
}
1893
1894
#endif /* MS_WINDOWS */
1895
1896
static PyObject *
1897
posix_path_object_error(PyObject *path)
1898
217k
{
1899
217k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1900
217k
}
1901
1902
static PyObject *
1903
path_object_error(PyObject *path)
1904
217k
{
1905
#ifdef MS_WINDOWS
1906
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1907
                PyExc_OSError, 0, path);
1908
#else
1909
217k
    return posix_path_object_error(path);
1910
217k
#endif
1911
217k
}
1912
1913
static PyObject *
1914
path_object_error2(PyObject *path, PyObject *path2)
1915
0
{
1916
#ifdef MS_WINDOWS
1917
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1918
                PyExc_OSError, 0, path, path2);
1919
#else
1920
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1921
0
#endif
1922
0
}
1923
1924
static PyObject *
1925
path_error(path_t *path)
1926
217k
{
1927
217k
    return path_object_error(path->object);
1928
217k
}
1929
1930
static PyObject *
1931
posix_path_error(path_t *path)
1932
0
{
1933
0
    return posix_path_object_error(path->object);
1934
0
}
1935
1936
static PyObject *
1937
path_error2(path_t *path, path_t *path2)
1938
0
{
1939
0
    return path_object_error2(path->object, path2->object);
1940
0
}
1941
1942
1943
/* POSIX generic methods */
1944
1945
static PyObject *
1946
posix_fildes_fd(int fd, int (*func)(int))
1947
0
{
1948
0
    int res;
1949
0
    int async_err = 0;
1950
1951
0
    do {
1952
0
        Py_BEGIN_ALLOW_THREADS
1953
0
        _Py_BEGIN_SUPPRESS_IPH
1954
0
        res = (*func)(fd);
1955
0
        _Py_END_SUPPRESS_IPH
1956
0
        Py_END_ALLOW_THREADS
1957
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1958
0
    if (res != 0)
1959
0
        return (!async_err) ? posix_error() : NULL;
1960
0
    Py_RETURN_NONE;
1961
0
}
1962
1963
1964
#ifdef MS_WINDOWS
1965
/* This is a reimplementation of the C library's chdir function,
1966
   but one that produces Win32 errors instead of DOS error codes.
1967
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1968
   it also needs to set "magic" environment variables indicating
1969
   the per-drive current directory, which are of the form =<drive>: */
1970
static BOOL __stdcall
1971
win32_wchdir(LPCWSTR path)
1972
{
1973
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1974
    int result;
1975
    wchar_t env[4] = L"=x:";
1976
1977
    if(!SetCurrentDirectoryW(path))
1978
        return FALSE;
1979
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1980
    if (!result)
1981
        return FALSE;
1982
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1983
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1984
        if (!new_path) {
1985
            SetLastError(ERROR_OUTOFMEMORY);
1986
            return FALSE;
1987
        }
1988
        result = GetCurrentDirectoryW(result, new_path);
1989
        if (!result) {
1990
            PyMem_RawFree(new_path);
1991
            return FALSE;
1992
        }
1993
    }
1994
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1995
                            wcsncmp(new_path, L"//", 2) == 0);
1996
    if (!is_unc_like_path) {
1997
        env[1] = new_path[0];
1998
        result = SetEnvironmentVariableW(env, new_path);
1999
    }
2000
    if (new_path != path_buf)
2001
        PyMem_RawFree(new_path);
2002
    return result ? TRUE : FALSE;
2003
}
2004
#endif
2005
2006
#ifdef MS_WINDOWS
2007
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2008
   - time stamps are restricted to second resolution
2009
   - file modification times suffer from forth-and-back conversions between
2010
     UTC and local time
2011
   Therefore, we implement our own stat, based on the Win32 API directly.
2012
*/
2013
#define HAVE_STAT_NSEC 1
2014
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2015
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2016
2017
static void
2018
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2019
                       BY_HANDLE_FILE_INFORMATION *info,
2020
                       ULONG *reparse_tag)
2021
{
2022
    memset(info, 0, sizeof(*info));
2023
    info->dwFileAttributes = pFileData->dwFileAttributes;
2024
    info->ftCreationTime   = pFileData->ftCreationTime;
2025
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
2026
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
2027
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
2028
    info->nFileSizeLow     = pFileData->nFileSizeLow;
2029
/*  info->nNumberOfLinks   = 1; */
2030
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2031
        *reparse_tag = pFileData->dwReserved0;
2032
    else
2033
        *reparse_tag = 0;
2034
}
2035
2036
static BOOL
2037
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
2038
{
2039
    HANDLE hFindFile;
2040
    WIN32_FIND_DATAW FileData;
2041
    LPCWSTR filename = pszFile;
2042
    size_t n = wcslen(pszFile);
2043
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2044
        // cannot use PyMem_Malloc here because we do not hold the GIL
2045
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2046
        if(!filename) {
2047
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2048
            return FALSE;
2049
        }
2050
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2051
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2052
            ((LPWSTR)filename)[n] = L'\0';
2053
        }
2054
        if (!n || (n == 1 && filename[1] == L':')) {
2055
            // Nothing left to query
2056
            free((void *)filename);
2057
            return FALSE;
2058
        }
2059
    }
2060
    hFindFile = FindFirstFileW(filename, &FileData);
2061
    if (pszFile != filename) {
2062
        free((void *)filename);
2063
    }
2064
    if (hFindFile == INVALID_HANDLE_VALUE) {
2065
        return FALSE;
2066
    }
2067
    FindClose(hFindFile);
2068
    find_data_to_file_info(&FileData, info, reparse_tag);
2069
    return TRUE;
2070
}
2071
2072
2073
static void
2074
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2075
                         struct _Py_stat_struct *result)
2076
{
2077
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2078
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2079
           the filename has an extension that is commonly used by files
2080
           that CreateProcessW can execute. A real implementation calls
2081
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2082
           AccessCheck to check for generic read, write, and execute
2083
           access. */
2084
        const wchar_t *fileExtension = wcsrchr(path, '.');
2085
        if (fileExtension) {
2086
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2087
                _wcsicmp(fileExtension, L".bat") == 0 ||
2088
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2089
                _wcsicmp(fileExtension, L".com") == 0) {
2090
                result->st_mode |= 0111;
2091
            }
2092
        }
2093
    }
2094
}
2095
2096
2097
static int
2098
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2099
                      BOOL traverse)
2100
{
2101
    HANDLE hFile;
2102
    BY_HANDLE_FILE_INFORMATION fileInfo;
2103
    FILE_BASIC_INFO basicInfo;
2104
    FILE_BASIC_INFO *pBasicInfo = NULL;
2105
    FILE_ID_INFO idInfo;
2106
    FILE_ID_INFO *pIdInfo = NULL;
2107
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2108
    DWORD fileType, error;
2109
    BOOL isUnhandledTag = FALSE;
2110
    int retval = 0;
2111
2112
    DWORD access = FILE_READ_ATTRIBUTES;
2113
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2114
    if (!traverse) {
2115
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2116
    }
2117
2118
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2119
    if (hFile == INVALID_HANDLE_VALUE) {
2120
        /* Either the path doesn't exist, or the caller lacks access. */
2121
        error = GetLastError();
2122
        switch (error) {
2123
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2124
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2125
            /* Try reading the parent directory. */
2126
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2127
                /* Cannot read the parent directory. */
2128
                switch (GetLastError()) {
2129
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2130
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2131
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2132
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2133
                    break;
2134
                /* Restore the error from CreateFileW(). */
2135
                default:
2136
                    SetLastError(error);
2137
                }
2138
2139
                return -1;
2140
            }
2141
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2142
                if (traverse ||
2143
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2144
                    /* The stat call has to traverse but cannot, so fail. */
2145
                    SetLastError(error);
2146
                    return -1;
2147
                }
2148
            }
2149
            break;
2150
2151
        case ERROR_INVALID_PARAMETER:
2152
            /* \\.\con requires read or write access. */
2153
            hFile = CreateFileW(path, access | GENERIC_READ,
2154
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2155
                        OPEN_EXISTING, flags, NULL);
2156
            if (hFile == INVALID_HANDLE_VALUE) {
2157
                SetLastError(error);
2158
                return -1;
2159
            }
2160
            break;
2161
2162
        case ERROR_CANT_ACCESS_FILE:
2163
            /* bpo37834: open unhandled reparse points if traverse fails. */
2164
            if (traverse) {
2165
                traverse = FALSE;
2166
                isUnhandledTag = TRUE;
2167
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2168
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2169
            }
2170
            if (hFile == INVALID_HANDLE_VALUE) {
2171
                SetLastError(error);
2172
                return -1;
2173
            }
2174
            break;
2175
2176
        default:
2177
            return -1;
2178
        }
2179
    }
2180
2181
    if (hFile != INVALID_HANDLE_VALUE) {
2182
        /* Handle types other than files on disk. */
2183
        fileType = GetFileType(hFile);
2184
        if (fileType != FILE_TYPE_DISK) {
2185
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2186
                retval = -1;
2187
                goto cleanup;
2188
            }
2189
            DWORD fileAttributes = GetFileAttributesW(path);
2190
            memset(result, 0, sizeof(*result));
2191
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2192
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2193
                /* \\.\pipe\ or \\.\mailslot\ */
2194
                result->st_mode = _S_IFDIR;
2195
            } else if (fileType == FILE_TYPE_CHAR) {
2196
                /* \\.\nul */
2197
                result->st_mode = _S_IFCHR;
2198
            } else if (fileType == FILE_TYPE_PIPE) {
2199
                /* \\.\pipe\spam */
2200
                result->st_mode = _S_IFIFO;
2201
            }
2202
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2203
            goto cleanup;
2204
        }
2205
2206
        /* Query the reparse tag, and traverse a non-link. */
2207
        if (!traverse) {
2208
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2209
                    &tagInfo, sizeof(tagInfo))) {
2210
                /* Allow devices that do not support FileAttributeTagInfo. */
2211
                switch (GetLastError()) {
2212
                case ERROR_INVALID_PARAMETER:
2213
                case ERROR_INVALID_FUNCTION:
2214
                case ERROR_NOT_SUPPORTED:
2215
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2216
                    tagInfo.ReparseTag = 0;
2217
                    break;
2218
                default:
2219
                    retval = -1;
2220
                    goto cleanup;
2221
                }
2222
            } else if (tagInfo.FileAttributes &
2223
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2224
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2225
                    if (isUnhandledTag) {
2226
                        /* Traversing previously failed for either this link
2227
                           or its target. */
2228
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2229
                        retval = -1;
2230
                        goto cleanup;
2231
                    }
2232
                /* Traverse a non-link, but not if traversing already failed
2233
                   for an unhandled tag. */
2234
                } else if (!isUnhandledTag) {
2235
                    CloseHandle(hFile);
2236
                    return win32_xstat_slow_impl(path, result, TRUE);
2237
                }
2238
            }
2239
        }
2240
2241
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2242
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2243
                                          &basicInfo, sizeof(basicInfo))) {
2244
            switch (GetLastError()) {
2245
            case ERROR_INVALID_PARAMETER:
2246
            case ERROR_INVALID_FUNCTION:
2247
            case ERROR_NOT_SUPPORTED:
2248
                /* Volumes and physical disks are block devices, e.g.
2249
                   \\.\C: and \\.\PhysicalDrive0. */
2250
                memset(result, 0, sizeof(*result));
2251
                result->st_mode = 0x6000; /* S_IFBLK */
2252
                goto cleanup;
2253
            }
2254
            retval = -1;
2255
            goto cleanup;
2256
        }
2257
2258
        /* Successfully got FileBasicInfo, so we'll pass it along */
2259
        pBasicInfo = &basicInfo;
2260
2261
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2262
            /* Successfully got FileIdInfo, so pass it along */
2263
            pIdInfo = &idInfo;
2264
        }
2265
    }
2266
2267
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2268
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2269
2270
cleanup:
2271
    if (hFile != INVALID_HANDLE_VALUE) {
2272
        /* Preserve last error if we are failing */
2273
        error = retval ? GetLastError() : 0;
2274
        if (!CloseHandle(hFile)) {
2275
            retval = -1;
2276
        } else if (retval) {
2277
            /* Restore last error */
2278
            SetLastError(error);
2279
        }
2280
    }
2281
2282
    return retval;
2283
}
2284
2285
static int
2286
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2287
                 BOOL traverse)
2288
{
2289
    FILE_STAT_BASIC_INFORMATION statInfo;
2290
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2291
                                     &statInfo, sizeof(statInfo))) {
2292
        if (// Cannot use fast path for reparse points ...
2293
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2294
            // ... unless it's a name surrogate (symlink) and we're not following
2295
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2296
        ) {
2297
            _Py_stat_basic_info_to_stat(&statInfo, result);
2298
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2299
            return 0;
2300
        }
2301
    } else {
2302
        switch(GetLastError()) {
2303
        case ERROR_FILE_NOT_FOUND:
2304
        case ERROR_PATH_NOT_FOUND:
2305
        case ERROR_NOT_READY:
2306
        case ERROR_BAD_NET_NAME:
2307
            /* These errors aren't worth retrying with the slow path */
2308
            return -1;
2309
        case ERROR_NOT_SUPPORTED:
2310
            /* indicates the API couldn't be loaded */
2311
            break;
2312
        }
2313
    }
2314
2315
    return win32_xstat_slow_impl(path, result, traverse);
2316
}
2317
2318
static int
2319
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2320
{
2321
    /* Protocol violation: we explicitly clear errno, instead of
2322
       setting it to a POSIX error. Callers should use GetLastError. */
2323
    int code = win32_xstat_impl(path, result, traverse);
2324
    errno = 0;
2325
2326
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2327
    result->st_ctime = result->st_birthtime;
2328
    result->st_ctime_nsec = result->st_birthtime_nsec;
2329
    return code;
2330
}
2331
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2332
2333
   In Posix, stat automatically traverses symlinks and returns the stat
2334
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2335
   default does not traverse symlinks and instead returns attributes for
2336
   the symlink.
2337
2338
   Instead, we will open the file (which *does* traverse symlinks by default)
2339
   and GetFileInformationByHandle(). */
2340
2341
static int
2342
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2343
{
2344
    return win32_xstat(path, result, FALSE);
2345
}
2346
2347
static int
2348
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2349
{
2350
    return win32_xstat(path, result, TRUE);
2351
}
2352
2353
#endif /* MS_WINDOWS */
2354
2355
PyDoc_STRVAR(stat_result__doc__,
2356
"stat_result: Result from stat, fstat, or lstat.\n\n\
2357
This object may be accessed either as a tuple of\n\
2358
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2359
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2360
\n\
2361
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2362
or st_flags, they are available as attributes only.\n\
2363
\n\
2364
See os.stat for more information.");
2365
2366
static PyStructSequence_Field stat_result_fields[] = {
2367
    {"st_mode",    "protection bits"},
2368
    {"st_ino",     "inode"},
2369
    {"st_dev",     "device"},
2370
    {"st_nlink",   "number of hard links"},
2371
    {"st_uid",     "user ID of owner"},
2372
    {"st_gid",     "group ID of owner"},
2373
    {"st_size",    "total size, in bytes"},
2374
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2375
    {NULL,   "integer time of last access"},
2376
    {NULL,   "integer time of last modification"},
2377
    {NULL,   "integer time of last change"},
2378
    {"st_atime",   "time of last access"},
2379
    {"st_mtime",   "time of last modification"},
2380
    {"st_ctime",   "time of last change"},
2381
    {"st_atime_ns",   "time of last access in nanoseconds"},
2382
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2383
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2384
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2385
    {"st_blksize", "blocksize for filesystem I/O"},
2386
#endif
2387
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2388
    {"st_blocks",  "number of blocks allocated"},
2389
#endif
2390
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2391
    {"st_rdev",    "device type (if inode device)"},
2392
#endif
2393
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2394
    {"st_flags",   "user defined flags for file"},
2395
#endif
2396
#ifdef HAVE_STRUCT_STAT_ST_GEN
2397
    {"st_gen",    "generation number"},
2398
#endif
2399
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2400
    {"st_birthtime",   "time of creation"},
2401
#endif
2402
#ifdef MS_WINDOWS
2403
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2404
#endif
2405
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2406
    {"st_file_attributes", "Windows file attribute bits"},
2407
#endif
2408
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2409
    {"st_fstype",  "Type of filesystem"},
2410
#endif
2411
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2412
    {"st_reparse_tag", "Windows reparse tag"},
2413
#endif
2414
    {0}
2415
};
2416
2417
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2418
#define ST_BLKSIZE_IDX 16
2419
#else
2420
#define ST_BLKSIZE_IDX 15
2421
#endif
2422
2423
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2424
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2425
#else
2426
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2427
#endif
2428
2429
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2430
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2431
#else
2432
#define ST_RDEV_IDX ST_BLOCKS_IDX
2433
#endif
2434
2435
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2436
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2437
#else
2438
#define ST_FLAGS_IDX ST_RDEV_IDX
2439
#endif
2440
2441
#ifdef HAVE_STRUCT_STAT_ST_GEN
2442
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2443
#else
2444
#define ST_GEN_IDX ST_FLAGS_IDX
2445
#endif
2446
2447
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2448
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2449
#else
2450
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2451
#endif
2452
2453
#ifdef MS_WINDOWS
2454
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2455
#else
2456
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2457
#endif
2458
2459
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2460
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2461
#else
2462
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2463
#endif
2464
2465
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2466
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2467
#else
2468
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2469
#endif
2470
2471
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2472
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2473
#else
2474
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2475
#endif
2476
2477
static PyStructSequence_Desc stat_result_desc = {
2478
    "os.stat_result", /* name; see issue gh-63408 */
2479
    stat_result__doc__, /* doc */
2480
    stat_result_fields,
2481
    10
2482
};
2483
2484
PyDoc_STRVAR(statvfs_result__doc__,
2485
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2486
This object may be accessed either as a tuple of\n\
2487
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2488
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2489
\n\
2490
See os.statvfs for more information.");
2491
2492
static PyStructSequence_Field statvfs_result_fields[] = {
2493
    {"f_bsize",  },
2494
    {"f_frsize", },
2495
    {"f_blocks", },
2496
    {"f_bfree",  },
2497
    {"f_bavail", },
2498
    {"f_files",  },
2499
    {"f_ffree",  },
2500
    {"f_favail", },
2501
    {"f_flag",   },
2502
    {"f_namemax",},
2503
    {"f_fsid",   },
2504
    {0}
2505
};
2506
2507
static PyStructSequence_Desc statvfs_result_desc = {
2508
    "os.statvfs_result", /* name; see issue gh-63408 */
2509
    statvfs_result__doc__, /* doc */
2510
    statvfs_result_fields,
2511
    10
2512
};
2513
2514
#if defined(HAVE_WAITID)
2515
PyDoc_STRVAR(waitid_result__doc__,
2516
"waitid_result: Result from waitid.\n\n\
2517
This object may be accessed either as a tuple of\n\
2518
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2519
or via the attributes si_pid, si_uid, and so on.\n\
2520
\n\
2521
See os.waitid for more information.");
2522
2523
static PyStructSequence_Field waitid_result_fields[] = {
2524
    {"si_pid",  },
2525
    {"si_uid", },
2526
    {"si_signo", },
2527
    {"si_status",  },
2528
    {"si_code", },
2529
    {0}
2530
};
2531
2532
static PyStructSequence_Desc waitid_result_desc = {
2533
    MODNAME ".waitid_result", /* name */
2534
    waitid_result__doc__, /* doc */
2535
    waitid_result_fields,
2536
    5
2537
};
2538
#endif
2539
2540
static PyObject *
2541
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2542
0
{
2543
0
    PyStructSequence *result;
2544
0
    int i;
2545
2546
    // ht_module doesn't get set in PyStructSequence_NewType(),
2547
    // so we can't use PyType_GetModule().
2548
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2549
0
    if (mod == NULL) {
2550
0
        return NULL;
2551
0
    }
2552
0
    _posixstate *state = get_posix_state(mod);
2553
0
    Py_DECREF(mod);
2554
0
    if (state == NULL) {
2555
0
        return NULL;
2556
0
    }
2557
0
#define structseq_new state->statresult_new_orig
2558
2559
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2560
0
    if (!result)
2561
0
        return NULL;
2562
    /* If we have been initialized from a tuple,
2563
       st_?time might be set to None. Initialize it
2564
       from the int slots.  */
2565
0
    for (i = 7; i <= 9; i++) {
2566
0
        if (result->ob_item[i+3] == Py_None) {
2567
0
            Py_DECREF(Py_None);
2568
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2569
0
        }
2570
0
    }
2571
0
    return (PyObject*)result;
2572
0
}
2573
2574
static int
2575
_posix_clear(PyObject *module)
2576
0
{
2577
0
    _posixstate *state = get_posix_state(module);
2578
0
    Py_CLEAR(state->billion);
2579
0
    Py_CLEAR(state->DirEntryType);
2580
0
    Py_CLEAR(state->ScandirIteratorType);
2581
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2582
0
    Py_CLEAR(state->SchedParamType);
2583
0
#endif
2584
0
    Py_CLEAR(state->StatResultType);
2585
0
#ifdef HAVE_STATX
2586
0
    Py_CLEAR(state->StatxResultType);
2587
0
#endif
2588
0
    Py_CLEAR(state->StatVFSResultType);
2589
0
    Py_CLEAR(state->TerminalSizeType);
2590
0
    Py_CLEAR(state->TimesResultType);
2591
0
    Py_CLEAR(state->UnameResultType);
2592
0
#if defined(HAVE_WAITID)
2593
0
    Py_CLEAR(state->WaitidResultType);
2594
0
#endif
2595
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2596
0
    Py_CLEAR(state->struct_rusage);
2597
0
#endif
2598
0
    Py_CLEAR(state->st_mode);
2599
0
    return 0;
2600
0
}
2601
2602
static int
2603
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2604
1.47k
{
2605
1.47k
    _posixstate *state = get_posix_state(module);
2606
1.47k
    Py_VISIT(state->billion);
2607
1.47k
    Py_VISIT(state->DirEntryType);
2608
1.47k
    Py_VISIT(state->ScandirIteratorType);
2609
1.47k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2610
1.47k
    Py_VISIT(state->SchedParamType);
2611
1.47k
#endif
2612
1.47k
    Py_VISIT(state->StatResultType);
2613
1.47k
#ifdef HAVE_STATX
2614
1.47k
    Py_VISIT(state->StatxResultType);
2615
1.47k
#endif
2616
1.47k
    Py_VISIT(state->StatVFSResultType);
2617
1.47k
    Py_VISIT(state->TerminalSizeType);
2618
1.47k
    Py_VISIT(state->TimesResultType);
2619
1.47k
    Py_VISIT(state->UnameResultType);
2620
1.47k
#if defined(HAVE_WAITID)
2621
1.47k
    Py_VISIT(state->WaitidResultType);
2622
1.47k
#endif
2623
1.47k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2624
1.47k
    Py_VISIT(state->struct_rusage);
2625
1.47k
#endif
2626
1.47k
    Py_VISIT(state->st_mode);
2627
1.47k
    return 0;
2628
1.47k
}
2629
2630
static void
2631
_posix_free(void *module)
2632
0
{
2633
0
   _posix_clear((PyObject *)module);
2634
0
}
2635
2636
2637
3.18M
#define SEC_TO_NS (1000000000LL)
2638
static PyObject *
2639
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2640
1.06M
{
2641
#if SIZEOF_TIME_T == 4
2642
    return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2643
#else
2644
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2645
1.06M
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2646
1.06M
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2647
1.06M
    }
2648
0
    else
2649
0
    {
2650
0
        PyObject *ns_total = NULL;
2651
0
        PyObject *s_in_ns = NULL;
2652
0
        PyObject *s = _PyLong_FromTime_t(sec);
2653
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2654
0
        if (s == NULL || ns_fractional == NULL) {
2655
0
            goto exit;
2656
0
        }
2657
2658
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2659
0
        if (s_in_ns == NULL) {
2660
0
            goto exit;
2661
0
        }
2662
2663
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2664
2665
0
    exit:
2666
0
        Py_XDECREF(s);
2667
0
        Py_XDECREF(ns_fractional);
2668
0
        Py_XDECREF(s_in_ns);
2669
0
        return ns_total;
2670
0
    }
2671
1.06M
#endif
2672
1.06M
}
2673
2674
static int
2675
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2676
          int ns_index, time_t sec, unsigned long nsec)
2677
1.06M
{
2678
1.06M
    assert(!PyErr_Occurred());
2679
1.06M
    assert(nsec < SEC_TO_NS);
2680
2681
1.06M
    if (s_index >= 0) {
2682
1.06M
        PyObject *s = _PyLong_FromTime_t(sec);
2683
1.06M
        if (s == NULL) {
2684
0
            return -1;
2685
0
        }
2686
1.06M
        PyStructSequence_SET_ITEM(v, s_index, s);
2687
1.06M
    }
2688
2689
1.06M
    if (f_index >= 0) {
2690
1.06M
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2691
1.06M
        if (float_s == NULL) {
2692
0
            return -1;
2693
0
        }
2694
1.06M
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2695
1.06M
    }
2696
2697
1.06M
    if (ns_index >= 0) {
2698
1.06M
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2699
1.06M
        if (ns_total == NULL) {
2700
0
            return -1;
2701
0
        }
2702
1.06M
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2703
1.06M
    }
2704
2705
1.06M
    assert(!PyErr_Occurred());
2706
1.06M
    return 0;
2707
1.06M
}
2708
#undef SEC_TO_NS
2709
2710
#ifdef MS_WINDOWS
2711
static PyObject*
2712
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2713
{
2714
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2715
    if (!o_low || !high) {
2716
        return o_low;
2717
    }
2718
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2719
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2720
    if (!l64) {
2721
        Py_XDECREF(o_high);
2722
        Py_DECREF(o_low);
2723
        return NULL;
2724
    }
2725
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2726
    Py_DECREF(l64);
2727
    if (!o_high) {
2728
        Py_DECREF(o_low);
2729
        return NULL;
2730
    }
2731
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2732
    Py_DECREF(o_high);
2733
    return o_low;
2734
}
2735
#endif
2736
2737
/* pack a system stat C structure into the Python stat tuple
2738
   (used by posix_stat() and posix_fstat()) */
2739
static PyObject*
2740
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2741
353k
{
2742
353k
    assert(!PyErr_Occurred());
2743
2744
353k
    _posixstate *state = get_posix_state(module);
2745
353k
    PyObject *StatResultType = state->StatResultType;
2746
353k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2747
353k
    if (v == NULL) {
2748
0
        return NULL;
2749
0
    }
2750
2751
353k
#define SET_ITEM(pos, expr) \
2752
3.53M
    do { \
2753
3.53M
        PyObject *obj = (expr); \
2754
3.53M
        if (obj == NULL) { \
2755
0
            goto error; \
2756
0
        } \
2757
3.53M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2758
3.53M
    } while (0)
2759
2760
353k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2761
#ifdef MS_WINDOWS
2762
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2763
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2764
#else
2765
353k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2766
353k
                  "stat.st_ino is larger than unsigned long long");
2767
353k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2768
353k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2769
353k
#endif
2770
353k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2771
#if defined(MS_WINDOWS)
2772
    SET_ITEM(4, PyLong_FromLong(0));
2773
    SET_ITEM(5, PyLong_FromLong(0));
2774
#else
2775
353k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2776
353k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2777
353k
#endif
2778
353k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2779
353k
                  "stat.st_size is larger than long long");
2780
353k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2781
2782
    // Set st_atime, st_mtime and st_ctime
2783
353k
    unsigned long ansec, mnsec, cnsec;
2784
353k
#if defined(HAVE_STAT_TV_NSEC)
2785
353k
    ansec = st->st_atim.tv_nsec;
2786
353k
    mnsec = st->st_mtim.tv_nsec;
2787
353k
    cnsec = st->st_ctim.tv_nsec;
2788
#elif defined(HAVE_STAT_TV_NSEC2)
2789
    ansec = st->st_atimespec.tv_nsec;
2790
    mnsec = st->st_mtimespec.tv_nsec;
2791
    cnsec = st->st_ctimespec.tv_nsec;
2792
#elif defined(HAVE_STAT_NSEC)
2793
    ansec = st->st_atime_nsec;
2794
    mnsec = st->st_mtime_nsec;
2795
    cnsec = st->st_ctime_nsec;
2796
#else
2797
    ansec = mnsec = cnsec = 0;
2798
#endif
2799
353k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2800
0
        goto error;
2801
0
    }
2802
353k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2803
0
        goto error;
2804
0
    }
2805
353k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2806
0
        goto error;
2807
0
    }
2808
2809
353k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2810
353k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2811
353k
#endif
2812
353k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2813
353k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2814
353k
#endif
2815
353k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2816
353k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2817
353k
#endif
2818
#ifdef HAVE_STRUCT_STAT_ST_GEN
2819
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2820
#endif
2821
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2822
    {
2823
      unsigned long bsec, bnsec;
2824
      bsec = (long)st->st_birthtime;
2825
#ifdef HAVE_STAT_TV_NSEC2
2826
      bnsec = st->st_birthtimespec.tv_nsec;
2827
#else
2828
      bnsec = 0;
2829
#endif
2830
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2831
    }
2832
#elif defined(MS_WINDOWS)
2833
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2834
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2835
        goto error;
2836
    }
2837
#endif
2838
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2839
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2840
#endif
2841
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2842
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2843
             PyLong_FromUnsignedLong(st->st_file_attributes));
2844
#endif
2845
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2846
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2847
#endif
2848
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2849
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2850
#endif
2851
2852
353k
    assert(!PyErr_Occurred());
2853
353k
    return v;
2854
2855
0
error:
2856
0
    Py_DECREF(v);
2857
0
    return NULL;
2858
2859
353k
#undef SET_ITEM
2860
353k
}
2861
2862
/* POSIX methods */
2863
2864
2865
static PyObject *
2866
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2867
              int dir_fd, int follow_symlinks)
2868
285k
{
2869
285k
    STRUCT_STAT st;
2870
285k
    int result;
2871
2872
285k
#ifdef HAVE_FSTATAT
2873
285k
    int fstatat_unavailable = 0;
2874
285k
#endif
2875
2876
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2877
    if (follow_symlinks_specified(function_name, follow_symlinks))
2878
        return NULL;
2879
#endif
2880
2881
285k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2882
285k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2883
285k
        fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
2884
0
        return NULL;
2885
2886
285k
    Py_BEGIN_ALLOW_THREADS
2887
285k
    if (path->is_fd) {
2888
0
        result = FSTAT(path->fd, &st);
2889
0
    }
2890
#ifdef MS_WINDOWS
2891
    else if (follow_symlinks)
2892
        result = win32_stat(path->wide, &st);
2893
    else
2894
        result = win32_lstat(path->wide, &st);
2895
#else
2896
285k
    else
2897
285k
#if defined(HAVE_LSTAT)
2898
285k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2899
11.2k
        result = LSTAT(path->narrow, &st);
2900
274k
    else
2901
274k
#endif /* HAVE_LSTAT */
2902
274k
#ifdef HAVE_FSTATAT
2903
274k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2904
0
        if (HAVE_FSTATAT_RUNTIME) {
2905
0
            result = fstatat(dir_fd, path->narrow, &st,
2906
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2907
2908
0
        } else {
2909
0
            fstatat_unavailable = 1;
2910
0
        }
2911
0
    } else
2912
274k
#endif /* HAVE_FSTATAT */
2913
274k
        result = STAT(path->narrow, &st);
2914
285k
#endif /* MS_WINDOWS */
2915
285k
    Py_END_ALLOW_THREADS
2916
2917
285k
#ifdef HAVE_FSTATAT
2918
285k
    if (fstatat_unavailable) {
2919
0
        argument_unavailable_error("stat", "dir_fd");
2920
0
        return NULL;
2921
0
    }
2922
285k
#endif
2923
2924
285k
    if (result != 0) {
2925
216k
        return path_error(path);
2926
216k
    }
2927
2928
69.2k
    return _pystat_fromstructstat(module, &st);
2929
285k
}
2930
2931
/*[python input]
2932
2933
for s in """
2934
2935
FACCESSAT
2936
FCHMODAT
2937
FCHOWNAT
2938
FSTATAT
2939
LINKAT
2940
MKDIRAT
2941
MKFIFOAT
2942
MKNODAT
2943
OPENAT
2944
READLINKAT
2945
SYMLINKAT
2946
UNLINKAT
2947
2948
""".strip().split():
2949
    s = s.strip()
2950
    print("""
2951
#ifdef HAVE_{s}
2952
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2953
#else
2954
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2955
#endif
2956
""".rstrip().format(s=s))
2957
2958
for s in """
2959
2960
FCHDIR
2961
FCHMOD
2962
FCHOWN
2963
FDOPENDIR
2964
FEXECVE
2965
FPATHCONF
2966
FSTATVFS
2967
FTRUNCATE
2968
2969
""".strip().split():
2970
    s = s.strip()
2971
    print("""
2972
#ifdef HAVE_{s}
2973
    #define PATH_HAVE_{s} 1
2974
#else
2975
    #define PATH_HAVE_{s} 0
2976
#endif
2977
2978
""".rstrip().format(s=s))
2979
[python start generated code]*/
2980
2981
#ifdef HAVE_FACCESSAT
2982
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2983
#else
2984
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2985
#endif
2986
2987
#ifdef HAVE_FCHMODAT
2988
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2989
#else
2990
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2991
#endif
2992
2993
#ifdef HAVE_FCHOWNAT
2994
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2995
#else
2996
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2997
#endif
2998
2999
#ifdef HAVE_FSTATAT
3000
7.72k
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
3001
#else
3002
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
3003
#endif
3004
3005
#ifdef HAVE_LINKAT
3006
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
3007
#else
3008
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3009
#endif
3010
3011
#ifdef HAVE_MKDIRAT
3012
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3013
#else
3014
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3015
#endif
3016
3017
#ifdef HAVE_MKFIFOAT
3018
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3019
#else
3020
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3021
#endif
3022
3023
#ifdef HAVE_MKNODAT
3024
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3025
#else
3026
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3027
#endif
3028
3029
#ifdef HAVE_OPENAT
3030
144k
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3031
#else
3032
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3033
#endif
3034
3035
#ifdef HAVE_READLINKAT
3036
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3037
#else
3038
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3039
#endif
3040
3041
#ifdef HAVE_SYMLINKAT
3042
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3043
#else
3044
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3045
#endif
3046
3047
#ifdef HAVE_UNLINKAT
3048
167k
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3049
#else
3050
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3051
#endif
3052
3053
#ifdef HAVE_FCHDIR
3054
    #define PATH_HAVE_FCHDIR 1
3055
#else
3056
    #define PATH_HAVE_FCHDIR 0
3057
#endif
3058
3059
#ifdef HAVE_FCHMOD
3060
    #define PATH_HAVE_FCHMOD 1
3061
#else
3062
    #define PATH_HAVE_FCHMOD 0
3063
#endif
3064
3065
#ifdef HAVE_FCHOWN
3066
    #define PATH_HAVE_FCHOWN 1
3067
#else
3068
    #define PATH_HAVE_FCHOWN 0
3069
#endif
3070
3071
#ifdef HAVE_FDOPENDIR
3072
    #define PATH_HAVE_FDOPENDIR 1
3073
#else
3074
    #define PATH_HAVE_FDOPENDIR 0
3075
#endif
3076
3077
#ifdef HAVE_FEXECVE
3078
    #define PATH_HAVE_FEXECVE 1
3079
#else
3080
    #define PATH_HAVE_FEXECVE 0
3081
#endif
3082
3083
#ifdef HAVE_FPATHCONF
3084
    #define PATH_HAVE_FPATHCONF 1
3085
#else
3086
    #define PATH_HAVE_FPATHCONF 0
3087
#endif
3088
3089
#ifdef HAVE_FSTATVFS
3090
    #define PATH_HAVE_FSTATVFS 1
3091
#else
3092
    #define PATH_HAVE_FSTATVFS 0
3093
#endif
3094
3095
#ifdef HAVE_FTRUNCATE
3096
    #define PATH_HAVE_FTRUNCATE 1
3097
#else
3098
    #define PATH_HAVE_FTRUNCATE 0
3099
#endif
3100
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3101
3102
#ifdef MS_WINDOWS
3103
    #undef PATH_HAVE_FTRUNCATE
3104
    #define PATH_HAVE_FTRUNCATE 1
3105
    #undef PATH_HAVE_FCHMOD
3106
    #define PATH_HAVE_FCHMOD 1
3107
#endif
3108
3109
/*[python input]
3110
3111
class path_t_converter(CConverter):
3112
3113
    type = "path_t"
3114
    impl_by_reference = True
3115
    parse_by_reference = True
3116
    default_type = ()
3117
    c_init_default = "<placeholder>"  # overridden in pre_render(()
3118
3119
    converter = 'path_converter'
3120
3121
    def converter_init(self, *, allow_fd=False, make_wide=None,
3122
                       nonstrict=False, nullable=False,
3123
                       suppress_value_error=False):
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
        if nullable:
3131
            self.default_type = NoneType
3132
3133
    def pre_render(self):
3134
        def strify(value):
3135
            if isinstance(value, str):
3136
                return value
3137
            return str(int(bool(value)))
3138
3139
        # add self.py_name here when merging with posixmodule conversion
3140
        if self.make_wide is None:
3141
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3142
                self.function.name,
3143
                self.name,
3144
                strify(self.nullable),
3145
                strify(self.nonstrict),
3146
                strify(self.suppress_value_error),
3147
                strify(self.allow_fd),
3148
            )
3149
        else:
3150
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3151
                self.function.name,
3152
                self.name,
3153
                strify(self.nullable),
3154
                strify(self.nonstrict),
3155
                strify(self.make_wide),
3156
                strify(self.suppress_value_error),
3157
                strify(self.allow_fd),
3158
            )
3159
3160
    def cleanup(self):
3161
        return "path_cleanup(&" + self.name + ");\n"
3162
3163
3164
class dir_fd_converter(CConverter):
3165
    type = 'int'
3166
    default_type = NoneType
3167
    c_init_default = 'DEFAULT_DIR_FD'
3168
3169
    def converter_init(self, requires=None):
3170
        if self.default in (unspecified, None):
3171
            self.c_default = 'DEFAULT_DIR_FD'
3172
        if isinstance(requires, str):
3173
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3174
        else:
3175
            self.converter = 'dir_fd_converter'
3176
3177
    def c_default_init(self):
3178
        self.c_default = 'DEFAULT_DIR_FD'
3179
3180
class uid_t_converter(CConverter):
3181
    type = "uid_t"
3182
    converter = '_Py_Uid_Converter'
3183
3184
class gid_t_converter(CConverter):
3185
    type = "gid_t"
3186
    converter = '_Py_Gid_Converter'
3187
3188
class dev_t_converter(CConverter):
3189
    type = 'dev_t'
3190
    converter = '_Py_Dev_Converter'
3191
3192
class dev_t_return_converter(unsigned_long_return_converter):
3193
    type = 'dev_t'
3194
    conversion_fn = '_PyLong_FromDev'
3195
    unsigned_cast = '(dev_t)'
3196
3197
class pid_t_converter(CConverter):
3198
    type = 'pid_t'
3199
    format_unit = '" _Py_PARSE_PID "'
3200
3201
    def parse_arg(self, argname, displayname, *, limited_capi):
3202
        return self.format_code("""
3203
            {paramname} = PyLong_AsPid({argname});
3204
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3205
                goto exit;
3206
            }}}}
3207
            """, argname=argname)
3208
3209
class idtype_t_converter(CConverter):
3210
    type = 'idtype_t'
3211
    converter = 'idtype_t_converter'
3212
3213
class id_t_converter(CConverter):
3214
    type = 'id_t'
3215
    format_unit = '" _Py_PARSE_PID "'
3216
3217
    def parse_arg(self, argname, displayname, *, limited_capi):
3218
        return self.format_code("""
3219
            {paramname} = (id_t)PyLong_AsPid({argname});
3220
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3221
                goto exit;
3222
            }}}}
3223
            """, argname=argname)
3224
3225
class intptr_t_converter(CConverter):
3226
    type = 'intptr_t'
3227
    format_unit = '" _Py_PARSE_INTPTR "'
3228
3229
    def parse_arg(self, argname, displayname, *, limited_capi):
3230
        return self.format_code("""
3231
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3232
            if (!{paramname} && PyErr_Occurred()) {{{{
3233
                goto exit;
3234
            }}}}
3235
            """, argname=argname)
3236
3237
class Py_off_t_converter(CConverter):
3238
    type = 'Py_off_t'
3239
    converter = 'Py_off_t_converter'
3240
3241
class Py_off_t_return_converter(long_return_converter):
3242
    type = 'Py_off_t'
3243
    conversion_fn = 'PyLong_FromPy_off_t'
3244
3245
class confname_converter(CConverter):
3246
    type="int"
3247
    converter="conv_confname"
3248
3249
    def converter_init(self, *, table):
3250
        self.table = table
3251
3252
    def parse_arg(self, argname, displayname, *, limited_capi):
3253
        return self.format_code("""
3254
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3255
                goto exit;
3256
            }}}}
3257
        """, argname=argname, converter=self.converter, table=self.table)
3258
3259
[python start generated code]*/
3260
/*[python end generated code: output=da39a3ee5e6b4b0d input=d58f18bdf3bd3565]*/
3261
3262
/*[clinic input]
3263
3264
os.stat
3265
3266
    path : path_t(allow_fd=True)
3267
        Path to be examined; can be string, bytes, a path-like object or
3268
        open-file-descriptor int.
3269
3270
    *
3271
3272
    dir_fd : dir_fd(requires='fstatat') = None
3273
        If not None, it should be a file descriptor open to a directory,
3274
        and path should be a relative string; path will then be relative to
3275
        that directory.
3276
3277
    follow_symlinks: bool = True
3278
        If False, and the last element of the path is a symbolic link,
3279
        stat will examine the symbolic link itself instead of the file
3280
        the link points to.
3281
3282
Perform a stat system call on the given path.
3283
3284
dir_fd and follow_symlinks may not be implemented
3285
  on your platform.  If they are unavailable, using them will raise a
3286
  NotImplementedError.
3287
3288
It's an error to use dir_fd or follow_symlinks when specifying path as
3289
  an open file descriptor.
3290
3291
[clinic start generated code]*/
3292
3293
static PyObject *
3294
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3295
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3296
274k
{
3297
274k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3298
274k
}
3299
3300
3301
/*[clinic input]
3302
@permit_long_summary
3303
os.lstat
3304
3305
    path : path_t
3306
3307
    *
3308
3309
    dir_fd : dir_fd(requires='fstatat') = None
3310
3311
Perform a stat system call on the given path, without following symbolic links.
3312
3313
Like stat(), but do not follow symbolic links.
3314
Equivalent to stat(path, follow_symlinks=False).
3315
[clinic start generated code]*/
3316
3317
static PyObject *
3318
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3319
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3320
11.2k
{
3321
11.2k
    int follow_symlinks = 0;
3322
11.2k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3323
11.2k
}
3324
3325
3326
#ifdef HAVE_STATX
3327
typedef struct {
3328
    PyObject_HEAD
3329
    dev_t rdev, dev;
3330
    struct statx stx;
3331
} Py_statx_result;
3332
3333
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3334
3335
#define M(attr, type, offset, doc) \
3336
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3337
#define MM(attr, type, member, doc) \
3338
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3339
#define MX(attr, type, member, doc) \
3340
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3341
3342
static PyMemberDef pystatx_result_members[] = {
3343
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3344
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3345
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3346
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3347
        "Mask of supported bits in stx_attributes"),
3348
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3349
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3350
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3351
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3352
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3353
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3354
    {NULL},
3355
};
3356
3357
#undef MX
3358
#undef MM
3359
#undef M
3360
3361
3362
#define STATX_GET_UINT(ATTR, MASK) \
3363
    static PyObject* \
3364
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3365
0
    { \
3366
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3367
0
        if (!(self->stx.stx_mask & MASK)) { \
3368
0
            Py_RETURN_NONE; \
3369
0
        } \
3370
0
        unsigned long value = self->stx.ATTR; \
3371
0
        return PyLong_FromUnsignedLong(value); \
3372
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
3373
3374
STATX_GET_UINT(stx_uid, STATX_UID)
3375
STATX_GET_UINT(stx_gid, STATX_GID)
3376
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3377
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3378
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3379
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3380
#endif
3381
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3382
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3383
#endif
3384
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3385
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3386
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3387
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3388
#endif
3389
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3390
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3391
#endif
3392
3393
3394
static PyObject*
3395
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3396
0
{
3397
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3398
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3399
0
        Py_RETURN_NONE;
3400
0
    }
3401
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3402
0
}
3403
3404
3405
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3406
    static PyObject* \
3407
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3408
0
    { \
3409
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3410
0
        if (!(self->stx.stx_mask & MASK)) { \
3411
0
            Py_RETURN_NONE; \
3412
0
        } \
3413
0
        unsigned long long value = self->stx.ATTR; \
3414
0
        return PyLong_FromUnsignedLongLong(value); \
3415
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
3416
3417
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3418
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3419
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3420
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3421
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3422
#endif
3423
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3424
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3425
#endif
3426
3427
3428
#define STATX_GET_DOUBLE(ATTR, MASK) \
3429
    static PyObject* \
3430
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3431
0
    { \
3432
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3433
0
        if (!(self->stx.stx_mask & MASK)) { \
3434
0
            Py_RETURN_NONE; \
3435
0
        } \
3436
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3437
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3438
0
        return PyFloat_FromDouble(sec); \
3439
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
3440
3441
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3442
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3443
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3444
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3445
3446
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3447
    static PyObject* \
3448
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3449
0
    { \
3450
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3451
0
        if (!(self->stx.stx_mask & MASK)) { \
3452
0
            Py_RETURN_NONE; \
3453
0
        } \
3454
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3455
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3456
0
        assert(state != NULL); \
3457
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3458
0
    }
3459
3460
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3461
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3462
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3463
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3464
3465
#define G(attr, doc) \
3466
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3467
3468
static PyGetSetDef pystatx_result_getset[] = {
3469
    G(stx_mode, "protection bits"),
3470
    G(stx_nlink, "number of hard links"),
3471
    G(stx_uid, "user ID of owner"),
3472
    G(stx_gid, "group ID of owner"),
3473
    G(stx_ino, "inode"),
3474
    G(stx_size, "total size, in bytes"),
3475
    G(stx_blocks, "number of blocks allocated"),
3476
    G(stx_atime, "time of last access"),
3477
    G(stx_atime_ns, "time of last access in nanoseconds"),
3478
    G(stx_btime, "time of creation"),
3479
    G(stx_btime_ns, "time of creation in nanoseconds"),
3480
    G(stx_ctime, "time of last change"),
3481
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3482
    G(stx_mtime, "time of last modification"),
3483
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3484
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3485
    G(stx_mnt_id, "mount ID"),
3486
#endif
3487
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3488
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3489
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3490
#endif
3491
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3492
    G(stx_subvol, "subvolume ID"),
3493
#endif
3494
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3495
    G(stx_atomic_write_unit_min,
3496
      "minimum size for direct I/O with torn-write protection"),
3497
    G(stx_atomic_write_unit_max,
3498
        "maximum size for direct I/O with torn-write protection"),
3499
    G(stx_atomic_write_segments_max,
3500
        "maximum iovecs for direct I/O with torn-write protection"),
3501
#endif
3502
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3503
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3504
#endif
3505
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3506
    G(stx_atomic_write_unit_max_opt,
3507
        "maximum optimized size for direct I/O with torn-write protection"),
3508
#endif
3509
    {NULL},
3510
};
3511
3512
#undef G
3513
3514
static PyObject *
3515
pystatx_result_repr(PyObject *op)
3516
0
{
3517
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3518
0
    if (writer == NULL) {
3519
0
        return NULL;
3520
0
    }
3521
0
#define WRITE_ASCII(s) \
3522
0
    do { \
3523
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3524
0
            goto error; \
3525
0
        } \
3526
0
    } while (0)
3527
3528
0
    WRITE_ASCII("os.statx_result(");
3529
3530
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3531
0
        if (i > 0) {
3532
0
            WRITE_ASCII(", ");
3533
0
        }
3534
3535
0
        PyMemberDef *d = &pystatx_result_members[i];
3536
0
        WRITE_ASCII(d->name);
3537
0
        WRITE_ASCII("=");
3538
3539
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3540
0
        if (o == NULL) {
3541
0
            goto error;
3542
0
        }
3543
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3544
0
            Py_DECREF(o);
3545
0
            goto error;
3546
0
        }
3547
0
        Py_DECREF(o);
3548
0
    }
3549
3550
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3551
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3552
0
        PyObject *o = d->get(op, d->closure);
3553
0
        if (o == NULL) {
3554
0
            goto error;
3555
0
        }
3556
0
        if (o == Py_None) {
3557
0
            continue;
3558
0
        }
3559
3560
0
        WRITE_ASCII(", ");
3561
0
        WRITE_ASCII(d->name);
3562
0
        WRITE_ASCII("=");
3563
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3564
0
            Py_DECREF(o);
3565
0
            goto error;
3566
0
        }
3567
0
        Py_DECREF(o);
3568
0
    }
3569
3570
0
    WRITE_ASCII(")");
3571
0
    return PyUnicodeWriter_Finish(writer);
3572
0
#undef WRITE_ASCII
3573
3574
0
error:
3575
0
    PyUnicodeWriter_Discard(writer);
3576
0
    return NULL;
3577
0
}
3578
3579
static int
3580
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3581
0
{
3582
0
    Py_VISIT(Py_TYPE(self));
3583
0
    return 0;
3584
0
}
3585
3586
static void
3587
pystatx_result_dealloc(PyObject *op)
3588
0
{
3589
0
    Py_statx_result *self = (Py_statx_result *) op;
3590
0
    PyTypeObject *tp = Py_TYPE(self);
3591
0
    PyObject_GC_UnTrack(self);
3592
0
    tp->tp_free(self);
3593
0
    Py_DECREF(tp);
3594
0
}
3595
3596
static PyType_Slot pystatx_result_slots[] = {
3597
    {Py_tp_repr, pystatx_result_repr},
3598
    {Py_tp_traverse, pystatx_result_traverse},
3599
    {Py_tp_dealloc, pystatx_result_dealloc},
3600
    {Py_tp_members, pystatx_result_members},
3601
    {Py_tp_getset, pystatx_result_getset},
3602
    {0, NULL},
3603
};
3604
3605
static PyType_Spec pystatx_result_spec = {
3606
    .name = "os.statx_result",
3607
    .basicsize = sizeof(Py_statx_result),
3608
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3609
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3610
    .slots = pystatx_result_slots,
3611
};
3612
3613
/*[clinic input]
3614
3615
os.statx
3616
3617
    path : path_t(allow_fd=True)
3618
        Path to be examined; can be string, bytes, a path-like object or
3619
        open-file-descriptor int.
3620
3621
    mask: unsigned_int(bitwise=True)
3622
        A bitmask of STATX_* constants defining the requested information.
3623
3624
    *
3625
3626
    flags: int = 0
3627
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3628
3629
    dir_fd : dir_fd = None
3630
        If not None, it should be a file descriptor open to a directory,
3631
        and path should be a relative string; path will then be relative to
3632
        that directory.
3633
3634
    follow_symlinks: bool = True
3635
        If False, and the last element of the path is a symbolic link,
3636
        statx will examine the symbolic link itself instead of the file
3637
        the link points to.
3638
3639
Perform a statx system call on the given path.
3640
3641
It's an error to use dir_fd or follow_symlinks when specifying path as
3642
  an open file descriptor.
3643
3644
[clinic start generated code]*/
3645
3646
static PyObject *
3647
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3648
              int dir_fd, int follow_symlinks)
3649
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3650
0
{
3651
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3652
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3653
0
        fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) {
3654
0
        return NULL;
3655
0
    }
3656
3657
    /* reject flags covered by kwargs, but allow unknown flags that may be
3658
       future AT_STATX_* extensions */
3659
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3660
0
        PyErr_Format(PyExc_ValueError,
3661
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3662
0
        return NULL;
3663
0
    }
3664
0
    if (flags & AT_EMPTY_PATH) {
3665
0
        PyErr_Format(PyExc_ValueError,
3666
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3667
0
        return NULL;
3668
0
    }
3669
3670
    /* Future bits may refer to members beyond the current size of struct
3671
       statx, so we need to mask them off to prevent memory corruption. */
3672
0
    mask &= _Py_STATX_KNOWN;
3673
3674
0
    _posixstate *state = get_posix_state(module);
3675
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3676
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3677
0
    if (v == NULL) {
3678
0
        return NULL;
3679
0
    }
3680
3681
0
    int result;
3682
0
    Py_BEGIN_ALLOW_THREADS
3683
0
    if (path->is_fd) {
3684
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3685
0
    }
3686
0
    else {
3687
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3688
0
    }
3689
0
    Py_END_ALLOW_THREADS
3690
3691
0
    if (result != 0) {
3692
0
        Py_DECREF(v);
3693
0
        return path_error(path);
3694
0
    }
3695
3696
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3697
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3698
3699
0
    assert(!PyErr_Occurred());
3700
0
    return (PyObject *)v;
3701
0
}
3702
#endif /* HAVE_STATX */
3703
3704
3705
/*[clinic input]
3706
os.access -> bool
3707
3708
    path: path_t
3709
        Path to be tested; can be string, bytes, or a path-like object.
3710
3711
    mode: int
3712
        Operating-system mode bitfield.  Can be F_OK to test existence,
3713
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3714
3715
    *
3716
3717
    dir_fd : dir_fd(requires='faccessat') = None
3718
        If not None, it should be a file descriptor open to a directory,
3719
        and path should be relative; path will then be relative to that
3720
        directory.
3721
3722
    effective_ids: bool = False
3723
        If True, access will use the effective uid/gid instead of
3724
        the real uid/gid.
3725
3726
    follow_symlinks: bool = True
3727
        If False, and the last element of the path is a symbolic link,
3728
        access will examine the symbolic link itself instead of the file
3729
        the link points to.
3730
3731
Use the real uid/gid to test for access to a path.
3732
3733
{parameters}
3734
dir_fd, effective_ids, and follow_symlinks may not be implemented
3735
  on your platform.  If they are unavailable, using them will raise a
3736
  NotImplementedError.
3737
3738
Note that most operations will use the effective uid/gid, therefore this
3739
  routine can be used in a suid/sgid environment to test if the invoking
3740
  user has the specified access to the path.
3741
3742
[clinic start generated code]*/
3743
3744
static int
3745
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3746
               int effective_ids, int follow_symlinks)
3747
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3748
0
{
3749
0
    int return_value;
3750
3751
#ifdef MS_WINDOWS
3752
    DWORD attr;
3753
#else
3754
0
    int result;
3755
0
#endif
3756
3757
0
#ifdef HAVE_FACCESSAT
3758
0
    int faccessat_unavailable = 0;
3759
0
#endif
3760
3761
#ifndef HAVE_FACCESSAT
3762
    if (follow_symlinks_specified("access", follow_symlinks))
3763
        return -1;
3764
3765
    if (effective_ids) {
3766
        argument_unavailable_error("access", "effective_ids");
3767
        return -1;
3768
    }
3769
#endif
3770
3771
#ifdef MS_WINDOWS
3772
    Py_BEGIN_ALLOW_THREADS
3773
    attr = GetFileAttributesW(path->wide);
3774
    Py_END_ALLOW_THREADS
3775
3776
    /*
3777
     * Access is possible if
3778
     *   * we didn't get a -1, and
3779
     *     * write access wasn't requested,
3780
     *     * or the file isn't read-only,
3781
     *     * or it's a directory.
3782
     * (Directories cannot be read-only on Windows.)
3783
    */
3784
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3785
            (!(mode & 2) ||
3786
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3787
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3788
#else
3789
3790
0
    Py_BEGIN_ALLOW_THREADS
3791
0
#ifdef HAVE_FACCESSAT
3792
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3793
0
        effective_ids ||
3794
0
        !follow_symlinks) {
3795
3796
0
        if (HAVE_FACCESSAT_RUNTIME) {
3797
0
            int flags = 0;
3798
0
            if (!follow_symlinks)
3799
0
                flags |= AT_SYMLINK_NOFOLLOW;
3800
0
            if (effective_ids)
3801
0
                flags |= AT_EACCESS;
3802
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3803
0
        } else {
3804
0
            faccessat_unavailable = 1;
3805
0
        }
3806
0
    }
3807
0
    else
3808
0
#endif
3809
0
        result = access(path->narrow, mode);
3810
0
    Py_END_ALLOW_THREADS
3811
3812
0
#ifdef HAVE_FACCESSAT
3813
0
    if (faccessat_unavailable) {
3814
0
        if (dir_fd != DEFAULT_DIR_FD) {
3815
0
            argument_unavailable_error("access", "dir_fd");
3816
0
            return -1;
3817
0
        }
3818
0
        if (follow_symlinks_specified("access", follow_symlinks))
3819
0
            return -1;
3820
3821
0
        if (effective_ids) {
3822
0
            argument_unavailable_error("access", "effective_ids");
3823
0
            return -1;
3824
0
        }
3825
        /* should be unreachable */
3826
0
        return -1;
3827
0
    }
3828
0
#endif
3829
0
    return_value = !result;
3830
0
#endif
3831
3832
0
    return return_value;
3833
0
}
3834
3835
#ifndef F_OK
3836
#define F_OK 0
3837
#endif
3838
#ifndef R_OK
3839
#define R_OK 4
3840
#endif
3841
#ifndef W_OK
3842
#define W_OK 2
3843
#endif
3844
#ifndef X_OK
3845
#define X_OK 1
3846
#endif
3847
3848
3849
#ifdef HAVE_TTYNAME_R
3850
/*[clinic input]
3851
os.ttyname
3852
3853
    fd: int
3854
        Integer file descriptor handle.
3855
3856
    /
3857
3858
Return the name of the terminal device connected to 'fd'.
3859
[clinic start generated code]*/
3860
3861
static PyObject *
3862
os_ttyname_impl(PyObject *module, int fd)
3863
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3864
0
{
3865
3866
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3867
0
    if (size == -1) {
3868
0
        return posix_error();
3869
0
    }
3870
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3871
0
    if (buffer == NULL) {
3872
0
        return PyErr_NoMemory();
3873
0
    }
3874
0
    int ret = ttyname_r(fd, buffer, size);
3875
0
    if (ret != 0) {
3876
0
        PyMem_RawFree(buffer);
3877
0
        errno = ret;
3878
0
        return posix_error();
3879
0
    }
3880
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3881
0
    PyMem_RawFree(buffer);
3882
0
    return res;
3883
0
}
3884
#endif
3885
3886
#ifdef HAVE_CTERMID
3887
/*[clinic input]
3888
os.ctermid
3889
3890
Return the name of the controlling terminal for this process.
3891
[clinic start generated code]*/
3892
3893
static PyObject *
3894
os_ctermid_impl(PyObject *module)
3895
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3896
0
{
3897
0
    char *ret;
3898
0
    char buffer[L_ctermid];
3899
3900
#ifdef USE_CTERMID_R
3901
    ret = ctermid_r(buffer);
3902
#else
3903
0
    ret = ctermid(buffer);
3904
0
#endif
3905
0
    if (ret == NULL)
3906
0
        return posix_error();
3907
0
    return PyUnicode_DecodeFSDefault(buffer);
3908
0
}
3909
#endif /* HAVE_CTERMID */
3910
3911
3912
/*[clinic input]
3913
os.chdir
3914
3915
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3916
3917
Change the current working directory to the specified path.
3918
3919
path may always be specified as a string.
3920
On some platforms, path may also be specified as an open file descriptor.
3921
If this functionality is unavailable, using it raises an exception.
3922
[clinic start generated code]*/
3923
3924
static PyObject *
3925
os_chdir_impl(PyObject *module, path_t *path)
3926
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3927
0
{
3928
0
    int result;
3929
3930
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3931
0
        return NULL;
3932
0
    }
3933
3934
0
    Py_BEGIN_ALLOW_THREADS
3935
#ifdef MS_WINDOWS
3936
    /* on unix, success = 0, on windows, success = !0 */
3937
    result = !win32_wchdir(path->wide);
3938
#else
3939
0
#ifdef HAVE_FCHDIR
3940
0
    if (path->is_fd)
3941
0
        result = fchdir(path->fd);
3942
0
    else
3943
0
#endif
3944
0
        result = chdir(path->narrow);
3945
0
#endif
3946
0
    Py_END_ALLOW_THREADS
3947
3948
0
    if (result) {
3949
0
        return path_error(path);
3950
0
    }
3951
3952
0
    Py_RETURN_NONE;
3953
0
}
3954
3955
3956
#ifdef HAVE_FCHDIR
3957
/*[clinic input]
3958
os.fchdir
3959
3960
    fd: fildes
3961
3962
Change to the directory of the given file descriptor.
3963
3964
fd must be opened on a directory, not a file.
3965
Equivalent to os.chdir(fd).
3966
3967
[clinic start generated code]*/
3968
3969
static PyObject *
3970
os_fchdir_impl(PyObject *module, int fd)
3971
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3972
0
{
3973
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3974
0
        return NULL;
3975
0
    }
3976
0
    return posix_fildes_fd(fd, fchdir);
3977
0
}
3978
#endif /* HAVE_FCHDIR */
3979
3980
#ifdef MS_WINDOWS
3981
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3982
#else
3983
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3984
#endif
3985
3986
#ifdef MS_WINDOWS
3987
static int
3988
win32_lchmod(LPCWSTR path, int mode)
3989
{
3990
    DWORD attr = GetFileAttributesW(path);
3991
    if (attr == INVALID_FILE_ATTRIBUTES) {
3992
        return 0;
3993
    }
3994
    if (mode & _S_IWRITE) {
3995
        attr &= ~FILE_ATTRIBUTE_READONLY;
3996
    }
3997
    else {
3998
        attr |= FILE_ATTRIBUTE_READONLY;
3999
    }
4000
    return SetFileAttributesW(path, attr);
4001
}
4002
4003
static int
4004
win32_hchmod(HANDLE hfile, int mode)
4005
{
4006
    FILE_BASIC_INFO info;
4007
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4008
                                      &info, sizeof(info)))
4009
    {
4010
        return 0;
4011
    }
4012
    if (mode & _S_IWRITE) {
4013
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4014
    }
4015
    else {
4016
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4017
    }
4018
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4019
                                      &info, sizeof(info));
4020
}
4021
4022
static int
4023
win32_fchmod(int fd, int mode)
4024
{
4025
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4026
    if (hfile == INVALID_HANDLE_VALUE) {
4027
        SetLastError(ERROR_INVALID_HANDLE);
4028
        return 0;
4029
    }
4030
    return win32_hchmod(hfile, mode);
4031
}
4032
4033
#endif /* MS_WINDOWS */
4034
4035
/*[clinic input]
4036
os.chmod
4037
4038
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4039
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
4040
        On some platforms, path may also be specified as an open file descriptor.
4041
        If this functionality is unavailable, using it raises an exception.
4042
4043
    mode: int
4044
        Operating-system mode bitfield.
4045
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4046
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4047
        Python.
4048
4049
    *
4050
4051
    dir_fd : dir_fd(requires='fchmodat') = None
4052
        If not None, it should be a file descriptor open to a directory,
4053
        and path should be relative; path will then be relative to that
4054
        directory.
4055
4056
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4057
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4058
        If False, and the last element of the path is a symbolic link,
4059
        chmod will modify the symbolic link itself instead of the file
4060
        the link points to.
4061
4062
Change the access permissions of a file.
4063
4064
It is an error to use dir_fd or follow_symlinks when specifying path as
4065
  an open file descriptor.
4066
dir_fd and follow_symlinks may not be implemented on your platform.
4067
  If they are unavailable, using them will raise a NotImplementedError.
4068
4069
[clinic start generated code]*/
4070
4071
static PyObject *
4072
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4073
              int follow_symlinks)
4074
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
4075
0
{
4076
0
    int result;
4077
4078
0
#ifdef HAVE_FCHMODAT
4079
0
    int fchmodat_nofollow_unsupported = 0;
4080
0
    int fchmodat_unsupported = 0;
4081
0
#endif
4082
4083
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4084
    if (follow_symlinks_specified("chmod", follow_symlinks))
4085
        return NULL;
4086
#endif
4087
4088
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4089
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4090
0
        return NULL;
4091
0
    }
4092
4093
#ifdef MS_WINDOWS
4094
    result = 0;
4095
    Py_BEGIN_ALLOW_THREADS
4096
    if (path->is_fd) {
4097
        result = win32_fchmod(path->fd, mode);
4098
    }
4099
    else if (follow_symlinks) {
4100
        HANDLE hfile = CreateFileW(path->wide,
4101
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4102
                                   0, NULL,
4103
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4104
        if (hfile != INVALID_HANDLE_VALUE) {
4105
            result = win32_hchmod(hfile, mode);
4106
            (void)CloseHandle(hfile);
4107
        }
4108
    }
4109
    else {
4110
        result = win32_lchmod(path->wide, mode);
4111
    }
4112
    Py_END_ALLOW_THREADS
4113
    if (!result) {
4114
        return path_error(path);
4115
    }
4116
#else /* MS_WINDOWS */
4117
0
    Py_BEGIN_ALLOW_THREADS
4118
0
#ifdef HAVE_FCHMOD
4119
0
    if (path->is_fd) {
4120
0
        result = fchmod(path->fd, mode);
4121
0
    }
4122
0
    else
4123
0
#endif /* HAVE_CHMOD */
4124
#ifdef HAVE_LCHMOD
4125
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4126
        result = lchmod(path->narrow, mode);
4127
    else
4128
#endif /* HAVE_LCHMOD */
4129
0
#ifdef HAVE_FCHMODAT
4130
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4131
0
        if (HAVE_FCHMODAT_RUNTIME) {
4132
            /*
4133
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4134
             * The documentation specifically shows how to use it,
4135
             * and then says it isn't implemented yet.
4136
             * (true on linux with glibc 2.15, and openindiana 3.x)
4137
             *
4138
             * Once it is supported, os.chmod will automatically
4139
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4140
             * Until then, we need to be careful what exception we raise.
4141
             */
4142
0
            result = fchmodat(dir_fd, path->narrow, mode,
4143
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4144
            /*
4145
             * But wait!  We can't throw the exception without allowing threads,
4146
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4147
             */
4148
0
            fchmodat_nofollow_unsupported =
4149
0
                             result &&
4150
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4151
0
                             !follow_symlinks;
4152
0
        } else {
4153
0
            fchmodat_unsupported = 1;
4154
0
            fchmodat_nofollow_unsupported = 1;
4155
4156
0
            result = -1;
4157
0
        }
4158
0
    }
4159
0
    else
4160
0
#endif /* HAVE_FHCMODAT */
4161
0
    {
4162
0
#ifdef HAVE_CHMOD
4163
0
        result = chmod(path->narrow, mode);
4164
#elif defined(__wasi__)
4165
        // WASI SDK 15.0 does not support chmod.
4166
        // Ignore missing syscall for now.
4167
        result = 0;
4168
#else
4169
        result = -1;
4170
        errno = ENOSYS;
4171
#endif
4172
0
    }
4173
0
    Py_END_ALLOW_THREADS
4174
4175
0
    if (result) {
4176
0
#ifdef HAVE_FCHMODAT
4177
0
        if (fchmodat_unsupported) {
4178
0
            if (dir_fd != DEFAULT_DIR_FD) {
4179
0
                argument_unavailable_error("chmod", "dir_fd");
4180
0
                return NULL;
4181
0
            }
4182
0
        }
4183
4184
0
        if (fchmodat_nofollow_unsupported) {
4185
0
            if (dir_fd != DEFAULT_DIR_FD)
4186
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4187
0
                                                   dir_fd, follow_symlinks);
4188
0
            else
4189
0
                follow_symlinks_specified("chmod", follow_symlinks);
4190
0
            return NULL;
4191
0
        }
4192
0
        else
4193
0
#endif /* HAVE_FCHMODAT */
4194
0
        return path_error(path);
4195
0
    }
4196
0
#endif /* MS_WINDOWS */
4197
4198
0
    Py_RETURN_NONE;
4199
0
}
4200
4201
4202
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4203
/*[clinic input]
4204
os.fchmod
4205
4206
    fd: int
4207
        The file descriptor of the file to be modified.
4208
    mode: int
4209
        Operating-system mode bitfield.
4210
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4211
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4212
        Python.
4213
4214
Change the access permissions of the file given by file descriptor fd.
4215
4216
Equivalent to os.chmod(fd, mode).
4217
[clinic start generated code]*/
4218
4219
static PyObject *
4220
os_fchmod_impl(PyObject *module, int fd, int mode)
4221
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
4222
0
{
4223
0
    int res;
4224
4225
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4226
0
        return NULL;
4227
0
    }
4228
4229
#ifdef MS_WINDOWS
4230
    res = 0;
4231
    Py_BEGIN_ALLOW_THREADS
4232
    res = win32_fchmod(fd, mode);
4233
    Py_END_ALLOW_THREADS
4234
    if (!res) {
4235
        return PyErr_SetFromWindowsErr(0);
4236
    }
4237
#else /* MS_WINDOWS */
4238
0
    int async_err = 0;
4239
0
    do {
4240
0
        Py_BEGIN_ALLOW_THREADS
4241
0
        res = fchmod(fd, mode);
4242
0
        Py_END_ALLOW_THREADS
4243
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4244
0
    if (res != 0)
4245
0
        return (!async_err) ? posix_error() : NULL;
4246
0
#endif /* MS_WINDOWS */
4247
4248
0
    Py_RETURN_NONE;
4249
0
}
4250
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4251
4252
4253
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4254
/*[clinic input]
4255
os.lchmod
4256
4257
    path: path_t
4258
    mode: int
4259
4260
Change the access permissions of a file, without following symbolic links.
4261
4262
If path is a symlink, this affects the link itself rather than the target.
4263
Equivalent to chmod(path, mode, follow_symlinks=False)."
4264
[clinic start generated code]*/
4265
4266
static PyObject *
4267
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4268
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
4269
{
4270
    int res;
4271
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4272
        return NULL;
4273
    }
4274
#ifdef MS_WINDOWS
4275
    Py_BEGIN_ALLOW_THREADS
4276
    res = win32_lchmod(path->wide, mode);
4277
    Py_END_ALLOW_THREADS
4278
    if (!res) {
4279
        path_error(path);
4280
        return NULL;
4281
    }
4282
#else /* MS_WINDOWS */
4283
    Py_BEGIN_ALLOW_THREADS
4284
    res = lchmod(path->narrow, mode);
4285
    Py_END_ALLOW_THREADS
4286
    if (res < 0) {
4287
        path_error(path);
4288
        return NULL;
4289
    }
4290
#endif /* MS_WINDOWS */
4291
    Py_RETURN_NONE;
4292
}
4293
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4294
4295
4296
#ifdef HAVE_CHFLAGS
4297
/*[clinic input]
4298
os.chflags
4299
4300
    path: path_t
4301
    flags: unsigned_long(bitwise=True)
4302
    follow_symlinks: bool=True
4303
4304
Set file flags.
4305
4306
If follow_symlinks is False, and the last element of the path is a symbolic
4307
  link, chflags will change flags on the symbolic link itself instead of the
4308
  file the link points to.
4309
follow_symlinks may not be implemented on your platform.  If it is
4310
unavailable, using it will raise a NotImplementedError.
4311
4312
[clinic start generated code]*/
4313
4314
static PyObject *
4315
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4316
                int follow_symlinks)
4317
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
4318
{
4319
    int result;
4320
4321
#ifndef HAVE_LCHFLAGS
4322
    if (follow_symlinks_specified("chflags", follow_symlinks))
4323
        return NULL;
4324
#endif
4325
4326
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4327
        return NULL;
4328
    }
4329
4330
    Py_BEGIN_ALLOW_THREADS
4331
#ifdef HAVE_LCHFLAGS
4332
    if (!follow_symlinks)
4333
        result = lchflags(path->narrow, flags);
4334
    else
4335
#endif
4336
        result = chflags(path->narrow, flags);
4337
    Py_END_ALLOW_THREADS
4338
4339
    if (result)
4340
        return path_error(path);
4341
4342
    Py_RETURN_NONE;
4343
}
4344
#endif /* HAVE_CHFLAGS */
4345
4346
4347
#ifdef HAVE_LCHFLAGS
4348
/*[clinic input]
4349
os.lchflags
4350
4351
    path: path_t
4352
    flags: unsigned_long(bitwise=True)
4353
4354
Set file flags.
4355
4356
This function will not follow symbolic links.
4357
Equivalent to chflags(path, flags, follow_symlinks=False).
4358
[clinic start generated code]*/
4359
4360
static PyObject *
4361
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4362
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4363
{
4364
    int res;
4365
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4366
        return NULL;
4367
    }
4368
    Py_BEGIN_ALLOW_THREADS
4369
    res = lchflags(path->narrow, flags);
4370
    Py_END_ALLOW_THREADS
4371
    if (res < 0) {
4372
        return path_error(path);
4373
    }
4374
    Py_RETURN_NONE;
4375
}
4376
#endif /* HAVE_LCHFLAGS */
4377
4378
4379
#ifdef HAVE_CHROOT
4380
/*[clinic input]
4381
os.chroot
4382
    path: path_t
4383
4384
Change root directory to path.
4385
4386
[clinic start generated code]*/
4387
4388
static PyObject *
4389
os_chroot_impl(PyObject *module, path_t *path)
4390
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4391
0
{
4392
0
    int res;
4393
0
    Py_BEGIN_ALLOW_THREADS
4394
0
    res = chroot(path->narrow);
4395
0
    Py_END_ALLOW_THREADS
4396
0
    if (res < 0)
4397
0
        return path_error(path);
4398
0
    Py_RETURN_NONE;
4399
0
}
4400
#endif /* HAVE_CHROOT */
4401
4402
4403
#ifdef HAVE_FSYNC
4404
/*[clinic input]
4405
os.fsync
4406
4407
    fd: fildes
4408
4409
Force write of fd to disk.
4410
[clinic start generated code]*/
4411
4412
static PyObject *
4413
os_fsync_impl(PyObject *module, int fd)
4414
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4415
0
{
4416
0
    return posix_fildes_fd(fd, fsync);
4417
0
}
4418
#endif /* HAVE_FSYNC */
4419
4420
4421
#ifdef HAVE_SYNC
4422
/*[clinic input]
4423
os.sync
4424
4425
Force write of everything to disk.
4426
[clinic start generated code]*/
4427
4428
static PyObject *
4429
os_sync_impl(PyObject *module)
4430
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4431
0
{
4432
0
    Py_BEGIN_ALLOW_THREADS
4433
0
    sync();
4434
0
    Py_END_ALLOW_THREADS
4435
0
    Py_RETURN_NONE;
4436
0
}
4437
#endif /* HAVE_SYNC */
4438
4439
4440
#ifdef HAVE_FDATASYNC
4441
#ifdef __hpux
4442
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4443
#endif
4444
4445
/*[clinic input]
4446
os.fdatasync
4447
4448
    fd: fildes
4449
4450
Force write of fd to disk without forcing update of metadata.
4451
[clinic start generated code]*/
4452
4453
static PyObject *
4454
os_fdatasync_impl(PyObject *module, int fd)
4455
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4456
0
{
4457
0
    return posix_fildes_fd(fd, fdatasync);
4458
0
}
4459
#endif /* HAVE_FDATASYNC */
4460
4461
4462
#ifdef HAVE_CHOWN
4463
/*[clinic input]
4464
os.chown
4465
4466
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4467
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4468
4469
    uid: uid_t
4470
4471
    gid: gid_t
4472
4473
    *
4474
4475
    dir_fd : dir_fd(requires='fchownat') = None
4476
        If not None, it should be a file descriptor open to a directory,
4477
        and path should be relative; path will then be relative to that
4478
        directory.
4479
4480
    follow_symlinks: bool = True
4481
        If False, and the last element of the path is a symbolic link,
4482
        stat will examine the symbolic link itself instead of the file
4483
        the link points to.
4484
4485
Change the owner and group id of path to the numeric uid and gid.\
4486
4487
path may always be specified as a string.
4488
On some platforms, path may also be specified as an open file descriptor.
4489
  If this functionality is unavailable, using it raises an exception.
4490
If dir_fd is not None, it should be a file descriptor open to a directory,
4491
  and path should be relative; path will then be relative to that directory.
4492
If follow_symlinks is False, and the last element of the path is a symbolic
4493
  link, chown will modify the symbolic link itself instead of the file the
4494
  link points to.
4495
It is an error to use dir_fd or follow_symlinks when specifying path as
4496
  an open file descriptor.
4497
dir_fd and follow_symlinks may not be implemented on your platform.
4498
  If they are unavailable, using them will raise a NotImplementedError.
4499
4500
[clinic start generated code]*/
4501
4502
static PyObject *
4503
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4504
              int dir_fd, int follow_symlinks)
4505
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4506
0
{
4507
0
    int result;
4508
4509
0
#if defined(HAVE_FCHOWNAT)
4510
0
    int fchownat_unsupported = 0;
4511
0
#endif
4512
4513
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4514
    if (follow_symlinks_specified("chown", follow_symlinks))
4515
        return NULL;
4516
#endif
4517
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4518
0
        fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
4519
0
        return NULL;
4520
4521
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4522
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4523
0
        return NULL;
4524
0
    }
4525
4526
0
    Py_BEGIN_ALLOW_THREADS
4527
0
#ifdef HAVE_FCHOWN
4528
0
    if (path->is_fd)
4529
0
        result = fchown(path->fd, uid, gid);
4530
0
    else
4531
0
#endif
4532
0
#ifdef HAVE_LCHOWN
4533
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4534
0
        result = lchown(path->narrow, uid, gid);
4535
0
    else
4536
0
#endif
4537
0
#ifdef HAVE_FCHOWNAT
4538
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4539
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4540
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4541
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4542
0
      } else {
4543
0
         fchownat_unsupported = 1;
4544
0
      }
4545
0
    } else
4546
0
#endif
4547
0
        result = chown(path->narrow, uid, gid);
4548
0
    Py_END_ALLOW_THREADS
4549
4550
0
#ifdef HAVE_FCHOWNAT
4551
0
    if (fchownat_unsupported) {
4552
        /* This would be incorrect if the current platform
4553
         * doesn't support lchown.
4554
         */
4555
0
        argument_unavailable_error(NULL, "dir_fd");
4556
0
        return NULL;
4557
0
    }
4558
0
#endif
4559
4560
0
    if (result)
4561
0
        return path_error(path);
4562
4563
0
    Py_RETURN_NONE;
4564
0
}
4565
#endif /* HAVE_CHOWN */
4566
4567
4568
#ifdef HAVE_FCHOWN
4569
/*[clinic input]
4570
os.fchown
4571
4572
    fd: int
4573
    uid: uid_t
4574
    gid: gid_t
4575
4576
Change the owner and group id of the file specified by file descriptor.
4577
4578
Equivalent to os.chown(fd, uid, gid).
4579
4580
[clinic start generated code]*/
4581
4582
static PyObject *
4583
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4584
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4585
0
{
4586
0
    int res;
4587
0
    int async_err = 0;
4588
4589
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4590
0
        return NULL;
4591
0
    }
4592
4593
0
    do {
4594
0
        Py_BEGIN_ALLOW_THREADS
4595
0
        res = fchown(fd, uid, gid);
4596
0
        Py_END_ALLOW_THREADS
4597
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4598
0
    if (res != 0)
4599
0
        return (!async_err) ? posix_error() : NULL;
4600
4601
0
    Py_RETURN_NONE;
4602
0
}
4603
#endif /* HAVE_FCHOWN */
4604
4605
4606
#ifdef HAVE_LCHOWN
4607
/*[clinic input]
4608
os.lchown
4609
4610
    path : path_t
4611
    uid: uid_t
4612
    gid: gid_t
4613
4614
Change the owner and group id of path to the numeric uid and gid.
4615
4616
This function will not follow symbolic links.
4617
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4618
[clinic start generated code]*/
4619
4620
static PyObject *
4621
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4622
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4623
0
{
4624
0
    int res;
4625
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4626
0
        return NULL;
4627
0
    }
4628
0
    Py_BEGIN_ALLOW_THREADS
4629
0
    res = lchown(path->narrow, uid, gid);
4630
0
    Py_END_ALLOW_THREADS
4631
0
    if (res < 0) {
4632
0
        return path_error(path);
4633
0
    }
4634
0
    Py_RETURN_NONE;
4635
0
}
4636
#endif /* HAVE_LCHOWN */
4637
4638
4639
static PyObject *
4640
posix_getcwd(int use_bytes)
4641
6
{
4642
#ifdef MS_WINDOWS
4643
    wchar_t wbuf[MAXPATHLEN];
4644
    wchar_t *wbuf2 = wbuf;
4645
    DWORD len;
4646
4647
    Py_BEGIN_ALLOW_THREADS
4648
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4649
    /* If the buffer is large enough, len does not include the
4650
       terminating \0. If the buffer is too small, len includes
4651
       the space needed for the terminator. */
4652
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4653
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4654
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4655
        }
4656
        else {
4657
            wbuf2 = NULL;
4658
        }
4659
        if (wbuf2) {
4660
            len = GetCurrentDirectoryW(len, wbuf2);
4661
        }
4662
    }
4663
    Py_END_ALLOW_THREADS
4664
4665
    if (!wbuf2) {
4666
        PyErr_NoMemory();
4667
        return NULL;
4668
    }
4669
    if (!len) {
4670
        PyErr_SetFromWindowsErr(0);
4671
        if (wbuf2 != wbuf)
4672
            PyMem_RawFree(wbuf2);
4673
        return NULL;
4674
    }
4675
4676
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4677
    if (wbuf2 != wbuf) {
4678
        PyMem_RawFree(wbuf2);
4679
    }
4680
4681
    if (use_bytes) {
4682
        if (resobj == NULL) {
4683
            return NULL;
4684
        }
4685
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4686
    }
4687
4688
    return resobj;
4689
#else
4690
6
    const size_t chunk = 1024;
4691
4692
6
    char *buf = NULL;
4693
6
    char *cwd = NULL;
4694
6
    size_t buflen = 0;
4695
4696
6
    Py_BEGIN_ALLOW_THREADS
4697
6
    do {
4698
6
        char *newbuf;
4699
6
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4700
6
            buflen += chunk;
4701
6
            newbuf = PyMem_RawRealloc(buf, buflen);
4702
6
        }
4703
0
        else {
4704
0
            newbuf = NULL;
4705
0
        }
4706
6
        if (newbuf == NULL) {
4707
0
            PyMem_RawFree(buf);
4708
0
            buf = NULL;
4709
0
            break;
4710
0
        }
4711
6
        buf = newbuf;
4712
4713
6
        cwd = getcwd(buf, buflen);
4714
6
    } while (cwd == NULL && errno == ERANGE);
4715
6
    Py_END_ALLOW_THREADS
4716
4717
6
    if (buf == NULL) {
4718
0
        return PyErr_NoMemory();
4719
0
    }
4720
6
    if (cwd == NULL) {
4721
0
        posix_error();
4722
0
        PyMem_RawFree(buf);
4723
0
        return NULL;
4724
0
    }
4725
4726
6
    PyObject *obj;
4727
6
    if (use_bytes) {
4728
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4729
0
    }
4730
6
    else {
4731
6
        obj = PyUnicode_DecodeFSDefault(buf);
4732
6
    }
4733
6
#ifdef __linux__
4734
6
    if (buf[0] != '/') {
4735
        /*
4736
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4737
         * relative pathname starting with '(unreachable)'. We detect this
4738
         * and fail with ENOENT, matching newer glibc behaviour.
4739
         */
4740
0
        errno = ENOENT;
4741
0
        path_object_error(obj);
4742
0
        PyMem_RawFree(buf);
4743
0
        return NULL;
4744
0
    }
4745
6
#endif
4746
6
    assert(buf[0] == '/');
4747
6
    PyMem_RawFree(buf);
4748
4749
6
    return obj;
4750
6
#endif   /* !MS_WINDOWS */
4751
6
}
4752
4753
4754
/*[clinic input]
4755
os.getcwd
4756
4757
Return a unicode string representing the current working directory.
4758
[clinic start generated code]*/
4759
4760
static PyObject *
4761
os_getcwd_impl(PyObject *module)
4762
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4763
6
{
4764
6
    return posix_getcwd(0);
4765
6
}
4766
4767
4768
/*[clinic input]
4769
os.getcwdb
4770
4771
Return a bytes string representing the current working directory.
4772
[clinic start generated code]*/
4773
4774
static PyObject *
4775
os_getcwdb_impl(PyObject *module)
4776
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4777
0
{
4778
0
    return posix_getcwd(1);
4779
0
}
4780
4781
4782
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4783
#define HAVE_LINK 1
4784
#endif
4785
4786
#ifdef HAVE_LINK
4787
/*[clinic input]
4788
4789
@permit_long_docstring_body
4790
os.link
4791
4792
    src : path_t
4793
    dst : path_t
4794
    *
4795
    src_dir_fd : dir_fd = None
4796
    dst_dir_fd : dir_fd = None
4797
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4798
4799
Create a hard link to a file.
4800
4801
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4802
  descriptor open to a directory, and the respective path string (src or dst)
4803
  should be relative; the path will then be relative to that directory.
4804
If follow_symlinks is False, and the last element of src is a symbolic
4805
  link, link will create a link to the symbolic link itself instead of the
4806
  file the link points to.
4807
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4808
  platform.  If they are unavailable, using them will raise a
4809
  NotImplementedError.
4810
[clinic start generated code]*/
4811
4812
static PyObject *
4813
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4814
             int dst_dir_fd, int follow_symlinks)
4815
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4816
0
{
4817
#ifdef MS_WINDOWS
4818
    BOOL result = FALSE;
4819
#else
4820
0
    int result;
4821
0
#endif
4822
4823
0
#ifdef HAVE_LINKAT
4824
0
    if (HAVE_LINKAT_RUNTIME) {
4825
0
        if (follow_symlinks < 0) {
4826
0
            follow_symlinks = 1;
4827
0
        }
4828
0
    }
4829
0
    else
4830
0
#endif
4831
0
    {
4832
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4833
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4834
0
            return NULL;
4835
0
        }
4836
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4837
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4838
0
#if defined(MS_WINDOWS) || defined(__linux__)
4839
0
        if (follow_symlinks == 1) {
4840
0
            argument_unavailable_error("link", "follow_symlinks=True");
4841
0
            return NULL;
4842
0
        }
4843
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4844
        if (follow_symlinks == 0) {
4845
            argument_unavailable_error("link", "follow_symlinks=False");
4846
            return NULL;
4847
        }
4848
#else
4849
        if (follow_symlinks >= 0) {
4850
            argument_unavailable_error("link", "follow_symlinks");
4851
            return NULL;
4852
        }
4853
#endif
4854
0
    }
4855
4856
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4857
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4858
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4859
0
        return NULL;
4860
0
    }
4861
4862
#ifdef MS_WINDOWS
4863
    Py_BEGIN_ALLOW_THREADS
4864
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4865
    Py_END_ALLOW_THREADS
4866
4867
    if (!result)
4868
        return path_error2(src, dst);
4869
#else
4870
0
    Py_BEGIN_ALLOW_THREADS
4871
0
#ifdef HAVE_LINKAT
4872
0
    if (HAVE_LINKAT_RUNTIME) {
4873
0
        result = linkat(src_dir_fd, src->narrow,
4874
0
            dst_dir_fd, dst->narrow,
4875
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4876
0
    }
4877
0
    else
4878
0
#endif
4879
0
    {
4880
        /* linkat not available */
4881
0
        result = link(src->narrow, dst->narrow);
4882
0
    }
4883
0
    Py_END_ALLOW_THREADS
4884
4885
0
    if (result)
4886
0
        return path_error2(src, dst);
4887
0
#endif /* MS_WINDOWS */
4888
4889
0
    Py_RETURN_NONE;
4890
0
}
4891
#endif
4892
4893
4894
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4895
static PyObject *
4896
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4897
{
4898
    PyObject *v;
4899
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4900
    BOOL result, return_bytes;
4901
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4902
    /* only claim to have space for MAX_PATH */
4903
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4904
    wchar_t *wnamebuf = NULL;
4905
4906
    WIN32_FIND_DATAW wFileData;
4907
    const wchar_t *po_wchars;
4908
4909
    if (!path->wide) { /* Default arg: "." */
4910
        po_wchars = L".";
4911
        len = 1;
4912
        return_bytes = 0;
4913
    } else {
4914
        po_wchars = path->wide;
4915
        len = wcslen(path->wide);
4916
        return_bytes = PyBytes_Check(path->object);
4917
    }
4918
    /* The +5 is so we can append "\\*.*\0" */
4919
    wnamebuf = PyMem_New(wchar_t, len + 5);
4920
    if (!wnamebuf) {
4921
        PyErr_NoMemory();
4922
        goto exit;
4923
    }
4924
    wcscpy(wnamebuf, po_wchars);
4925
    if (len > 0) {
4926
        wchar_t wch = wnamebuf[len-1];
4927
        if (wch != SEP && wch != ALTSEP && wch != L':')
4928
            wnamebuf[len++] = SEP;
4929
        wcscpy(wnamebuf + len, L"*.*");
4930
    }
4931
    if ((list = PyList_New(0)) == NULL) {
4932
        goto exit;
4933
    }
4934
    Py_BEGIN_ALLOW_THREADS
4935
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4936
    Py_END_ALLOW_THREADS
4937
    if (hFindFile == INVALID_HANDLE_VALUE) {
4938
        int error = GetLastError();
4939
        if (error == ERROR_FILE_NOT_FOUND)
4940
            goto exit;
4941
        path_error(path);
4942
        Py_CLEAR(list);
4943
        goto exit;
4944
    }
4945
    do {
4946
        /* Skip over . and .. */
4947
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4948
            wcscmp(wFileData.cFileName, L"..") != 0) {
4949
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4950
                                       wcslen(wFileData.cFileName));
4951
            if (return_bytes && v) {
4952
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4953
            }
4954
            if (v == NULL) {
4955
                Py_CLEAR(list);
4956
                break;
4957
            }
4958
            if (PyList_Append(list, v) != 0) {
4959
                Py_DECREF(v);
4960
                Py_CLEAR(list);
4961
                break;
4962
            }
4963
            Py_DECREF(v);
4964
        }
4965
        Py_BEGIN_ALLOW_THREADS
4966
        result = FindNextFileW(hFindFile, &wFileData);
4967
        Py_END_ALLOW_THREADS
4968
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4969
           it got to the end of the directory. */
4970
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4971
            path_error(path);
4972
            Py_CLEAR(list);
4973
            goto exit;
4974
        }
4975
    } while (result == TRUE);
4976
4977
exit:
4978
    if (hFindFile != INVALID_HANDLE_VALUE) {
4979
        if (FindClose(hFindFile) == FALSE) {
4980
            if (list != NULL) {
4981
                path_error(path);
4982
                Py_CLEAR(list);
4983
            }
4984
        }
4985
    }
4986
    PyMem_Free(wnamebuf);
4987
4988
    return list;
4989
}  /* end of _listdir_windows_no_opendir */
4990
4991
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4992
4993
static PyObject *
4994
_posix_listdir(path_t *path, PyObject *list)
4995
392
{
4996
392
    PyObject *v;
4997
392
    DIR *dirp = NULL;
4998
392
    struct dirent *ep;
4999
392
    int return_str; /* if false, return bytes */
5000
392
#ifdef HAVE_FDOPENDIR
5001
392
    int fd = -1;
5002
392
#endif
5003
5004
392
    errno = 0;
5005
392
#ifdef HAVE_FDOPENDIR
5006
392
    if (path->is_fd) {
5007
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5008
        /* closedir() closes the FD, so we duplicate it */
5009
0
        fd = _Py_dup(path->fd);
5010
0
        if (fd == -1)
5011
0
            return NULL;
5012
5013
0
        return_str = 1;
5014
5015
0
        Py_BEGIN_ALLOW_THREADS
5016
0
        dirp = fdopendir(fd);
5017
0
        Py_END_ALLOW_THREADS
5018
0
      } else {
5019
0
        PyErr_SetString(PyExc_TypeError,
5020
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5021
0
        return NULL;
5022
0
      }
5023
0
    }
5024
392
    else
5025
392
#endif
5026
392
    {
5027
392
        const char *name;
5028
392
        if (path->narrow) {
5029
392
            name = path->narrow;
5030
            /* only return bytes if they specified a bytes object */
5031
392
            return_str = !PyBytes_Check(path->object);
5032
392
        }
5033
0
        else {
5034
0
            name = ".";
5035
0
            return_str = 1;
5036
0
        }
5037
5038
392
        Py_BEGIN_ALLOW_THREADS
5039
392
        dirp = opendir(name);
5040
392
        Py_END_ALLOW_THREADS
5041
392
    }
5042
5043
392
    if (dirp == NULL) {
5044
8
        path_error(path);
5045
8
        list = NULL;
5046
8
#ifdef HAVE_FDOPENDIR
5047
8
        if (fd != -1) {
5048
0
            Py_BEGIN_ALLOW_THREADS
5049
0
            close(fd);
5050
0
            Py_END_ALLOW_THREADS
5051
0
        }
5052
8
#endif
5053
8
        goto exit;
5054
8
    }
5055
384
    if ((list = PyList_New(0)) == NULL) {
5056
0
        goto exit;
5057
0
    }
5058
18.9k
    for (;;) {
5059
18.9k
        errno = 0;
5060
18.9k
        Py_BEGIN_ALLOW_THREADS
5061
18.9k
        ep = readdir(dirp);
5062
18.9k
        Py_END_ALLOW_THREADS
5063
18.9k
        if (ep == NULL) {
5064
384
            if (errno == 0) {
5065
384
                break;
5066
384
            } else {
5067
0
                path_error(path);
5068
0
                Py_CLEAR(list);
5069
0
                goto exit;
5070
0
            }
5071
384
        }
5072
18.6k
        if (ep->d_name[0] == '.' &&
5073
768
            (NAMLEN(ep) == 1 ||
5074
384
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5075
768
            continue;
5076
17.8k
        if (return_str)
5077
17.8k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5078
0
        else
5079
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5080
17.8k
        if (v == NULL) {
5081
0
            Py_CLEAR(list);
5082
0
            break;
5083
0
        }
5084
17.8k
        if (PyList_Append(list, v) != 0) {
5085
0
            Py_DECREF(v);
5086
0
            Py_CLEAR(list);
5087
0
            break;
5088
0
        }
5089
17.8k
        Py_DECREF(v);
5090
17.8k
    }
5091
5092
392
exit:
5093
392
    if (dirp != NULL) {
5094
384
        Py_BEGIN_ALLOW_THREADS
5095
384
#ifdef HAVE_FDOPENDIR
5096
384
        if (fd > -1)
5097
0
            rewinddir(dirp);
5098
384
#endif
5099
384
        closedir(dirp);
5100
384
        Py_END_ALLOW_THREADS
5101
384
    }
5102
5103
392
    return list;
5104
384
}  /* end of _posix_listdir */
5105
#endif  /* which OS */
5106
5107
5108
/*[clinic input]
5109
@permit_long_docstring_body
5110
os.listdir
5111
5112
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5113
5114
Return a list containing the names of the files in the directory.
5115
5116
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
5117
  the filenames returned will also be bytes; in all other circumstances
5118
  the filenames returned will be str.
5119
If path is None, uses the path='.'.
5120
On some platforms, path may also be specified as an open file descriptor;\
5121
  the file descriptor must refer to a directory.
5122
  If this functionality is unavailable, using it raises NotImplementedError.
5123
5124
The list is in arbitrary order.  It does not include the special
5125
entries '.' and '..' even if they are present in the directory.
5126
5127
5128
[clinic start generated code]*/
5129
5130
static PyObject *
5131
os_listdir_impl(PyObject *module, path_t *path)
5132
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
5133
392
{
5134
392
    if (PySys_Audit("os.listdir", "O",
5135
392
                    path->object ? path->object : Py_None) < 0) {
5136
0
        return NULL;
5137
0
    }
5138
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5139
    return _listdir_windows_no_opendir(path, NULL);
5140
#else
5141
392
    return _posix_listdir(path, NULL);
5142
392
#endif
5143
392
}
5144
5145
5146
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5147
5148
/*[clinic input]
5149
os.listdrives
5150
5151
Return a list containing the names of drives in the system.
5152
5153
A drive name typically looks like 'C:\\'.
5154
5155
[clinic start generated code]*/
5156
5157
static PyObject *
5158
os_listdrives_impl(PyObject *module)
5159
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5160
{
5161
    /* Number of possible drives is limited, so 256 should always be enough.
5162
       On the day when it is not, listmounts() will have to be used. */
5163
    wchar_t buffer[256];
5164
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5165
    PyObject *result = NULL;
5166
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5167
        return NULL;
5168
    }
5169
5170
    Py_BEGIN_ALLOW_THREADS;
5171
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5172
    Py_END_ALLOW_THREADS;
5173
5174
    if (!buflen) {
5175
        PyErr_SetFromWindowsErr(0);
5176
        return NULL;
5177
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5178
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5179
        return NULL;
5180
    }
5181
5182
    /* buflen includes a null terminator, so remove it */
5183
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5184
    if (str) {
5185
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5186
        if (nullchar) {
5187
            result = PyUnicode_Split(str, nullchar, -1);
5188
            Py_DECREF(nullchar);
5189
        }
5190
        Py_DECREF(str);
5191
    }
5192
    return result;
5193
}
5194
5195
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5196
5197
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5198
5199
/*[clinic input]
5200
os.listvolumes
5201
5202
Return a list containing the volumes in the system.
5203
5204
Volumes are typically represented as a GUID path.
5205
5206
[clinic start generated code]*/
5207
5208
static PyObject *
5209
os_listvolumes_impl(PyObject *module)
5210
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5211
{
5212
    PyObject *result = PyList_New(0);
5213
    HANDLE find = INVALID_HANDLE_VALUE;
5214
    wchar_t buffer[MAX_PATH + 1];
5215
    if (!result) {
5216
        return NULL;
5217
    }
5218
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5219
        Py_DECREF(result);
5220
        return NULL;
5221
    }
5222
5223
    int err = 0;
5224
    Py_BEGIN_ALLOW_THREADS;
5225
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5226
    if (find == INVALID_HANDLE_VALUE) {
5227
        err = GetLastError();
5228
    }
5229
    Py_END_ALLOW_THREADS;
5230
5231
    while (!err) {
5232
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5233
        if (!s || PyList_Append(result, s) < 0) {
5234
            Py_XDECREF(s);
5235
            Py_CLEAR(result);
5236
            break;
5237
        }
5238
        Py_DECREF(s);
5239
5240
        Py_BEGIN_ALLOW_THREADS;
5241
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5242
            err = GetLastError();
5243
        }
5244
        Py_END_ALLOW_THREADS;
5245
    }
5246
5247
    if (find != INVALID_HANDLE_VALUE) {
5248
        Py_BEGIN_ALLOW_THREADS;
5249
        FindVolumeClose(find);
5250
        Py_END_ALLOW_THREADS;
5251
    }
5252
    if (err && err != ERROR_NO_MORE_FILES) {
5253
        PyErr_SetFromWindowsErr(err);
5254
        Py_XDECREF(result);
5255
        result = NULL;
5256
    }
5257
    return result;
5258
}
5259
5260
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5261
5262
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5263
5264
/*[clinic input]
5265
os.listmounts
5266
5267
    volume: path_t
5268
5269
Return a list containing mount points for a particular volume.
5270
5271
'volume' should be a GUID path as returned from os.listvolumes.
5272
5273
[clinic start generated code]*/
5274
5275
static PyObject *
5276
os_listmounts_impl(PyObject *module, path_t *volume)
5277
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5278
{
5279
    wchar_t default_buffer[MAX_PATH + 1];
5280
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5281
    LPWSTR buffer = default_buffer;
5282
    DWORD attributes;
5283
    PyObject *str = NULL;
5284
    PyObject *nullchar = NULL;
5285
    PyObject *result = NULL;
5286
5287
    /* Ensure we have a valid volume path before continuing */
5288
    Py_BEGIN_ALLOW_THREADS
5289
    attributes = GetFileAttributesW(volume->wide);
5290
    Py_END_ALLOW_THREADS
5291
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5292
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5293
    {
5294
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5295
    }
5296
5297
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5298
        return NULL;
5299
    }
5300
5301
    while (1) {
5302
        BOOL success;
5303
        Py_BEGIN_ALLOW_THREADS
5304
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5305
                                                   buflen, &buflen);
5306
        Py_END_ALLOW_THREADS
5307
        if (success) {
5308
            break;
5309
        }
5310
        if (GetLastError() != ERROR_MORE_DATA) {
5311
            PyErr_SetFromWindowsErr(0);
5312
            goto exit;
5313
        }
5314
        if (buffer != default_buffer) {
5315
            PyMem_Free((void *)buffer);
5316
        }
5317
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5318
        if (!buffer) {
5319
            PyErr_NoMemory();
5320
            goto exit;
5321
        }
5322
    }
5323
    if (buflen < 2) {
5324
        result = PyList_New(0);
5325
        goto exit;
5326
    }
5327
    // buflen includes two null terminators, one for the last string
5328
    // and one for the array of strings.
5329
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5330
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5331
    if (str && nullchar) {
5332
        result = PyUnicode_Split(str, nullchar, -1);
5333
    }
5334
exit:
5335
    if (buffer != default_buffer) {
5336
        PyMem_Free(buffer);
5337
    }
5338
    Py_XDECREF(nullchar);
5339
    Py_XDECREF(str);
5340
    return result;
5341
}
5342
5343
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5344
5345
#ifdef MS_WINDOWS
5346
5347
/*[clinic input]
5348
os._path_isdevdrive
5349
5350
    path: path_t
5351
5352
Determines whether the specified path is on a Windows Dev Drive.
5353
5354
[clinic start generated code]*/
5355
5356
static PyObject *
5357
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5358
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5359
{
5360
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5361
    /* This flag will be documented at
5362
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5363
       after release, and will be available in the latest WinSDK.
5364
       We include the flag to avoid a specific version dependency
5365
       on the latest WinSDK. */
5366
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5367
#endif
5368
    int err = 0;
5369
    PyObject *r = NULL;
5370
    wchar_t volume[MAX_PATH];
5371
5372
    Py_BEGIN_ALLOW_THREADS
5373
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5374
        /* invalid path of some kind */
5375
        /* Note that this also includes the case where a volume is mounted
5376
           in a path longer than 260 characters. This is likely to be rare
5377
           and problematic for other reasons, so a (soft) failure in this
5378
           check seems okay. */
5379
        err = GetLastError();
5380
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5381
        /* only care about local dev drives */
5382
        r = Py_False;
5383
    } else {
5384
        HANDLE hVolume = CreateFileW(
5385
            volume,
5386
            FILE_READ_ATTRIBUTES,
5387
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5388
            NULL,
5389
            OPEN_EXISTING,
5390
            FILE_FLAG_BACKUP_SEMANTICS,
5391
            NULL
5392
        );
5393
        if (hVolume == INVALID_HANDLE_VALUE) {
5394
            err = GetLastError();
5395
        } else {
5396
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5397
            volumeState.Version = 1;
5398
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5399
            if (!DeviceIoControl(
5400
                hVolume,
5401
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5402
                &volumeState,
5403
                sizeof(volumeState),
5404
                &volumeState,
5405
                sizeof(volumeState),
5406
                NULL,
5407
                NULL
5408
            )) {
5409
                err = GetLastError();
5410
            }
5411
            CloseHandle(hVolume);
5412
            if (err == ERROR_INVALID_PARAMETER) {
5413
                /* not supported on this platform */
5414
                r = Py_False;
5415
            } else if (!err) {
5416
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5417
                    ? Py_True : Py_False;
5418
            }
5419
        }
5420
    }
5421
    Py_END_ALLOW_THREADS
5422
5423
    if (err) {
5424
        PyErr_SetFromWindowsErr(err);
5425
        return NULL;
5426
    }
5427
5428
    if (r) {
5429
        return Py_NewRef(r);
5430
    }
5431
5432
    return NULL;
5433
}
5434
5435
5436
int
5437
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5438
{
5439
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5440
    DWORD result;
5441
5442
    result = GetFullPathNameW(path,
5443
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5444
                              NULL);
5445
    if (!result) {
5446
        return -1;
5447
    }
5448
5449
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5450
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5451
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5452
        }
5453
        else {
5454
            woutbufp = NULL;
5455
        }
5456
        if (!woutbufp) {
5457
            *abspath_p = NULL;
5458
            return 0;
5459
        }
5460
5461
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5462
        if (!result) {
5463
            PyMem_RawFree(woutbufp);
5464
            return -1;
5465
        }
5466
    }
5467
5468
    if (woutbufp != woutbuf) {
5469
        *abspath_p = woutbufp;
5470
        return 0;
5471
    }
5472
5473
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5474
    return 0;
5475
}
5476
5477
5478
/* A helper function for abspath on win32 */
5479
/*[clinic input]
5480
os._getfullpathname
5481
5482
    path: path_t
5483
    /
5484
5485
[clinic start generated code]*/
5486
5487
static PyObject *
5488
os__getfullpathname_impl(PyObject *module, path_t *path)
5489
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5490
{
5491
    wchar_t *abspath;
5492
5493
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5494
        return win32_error_object("GetFullPathNameW", path->object);
5495
    }
5496
    if (abspath == NULL) {
5497
        return PyErr_NoMemory();
5498
    }
5499
5500
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5501
    PyMem_RawFree(abspath);
5502
    if (str == NULL) {
5503
        return NULL;
5504
    }
5505
    if (PyBytes_Check(path->object)) {
5506
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5507
    }
5508
    return str;
5509
}
5510
5511
5512
/*[clinic input]
5513
os._getfinalpathname
5514
5515
    path: path_t
5516
    /
5517
5518
A helper function for samepath on windows.
5519
[clinic start generated code]*/
5520
5521
static PyObject *
5522
os__getfinalpathname_impl(PyObject *module, path_t *path)
5523
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5524
{
5525
    HANDLE hFile;
5526
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5527
    int buf_size = Py_ARRAY_LENGTH(buf);
5528
    int result_length;
5529
    PyObject *result;
5530
5531
    Py_BEGIN_ALLOW_THREADS
5532
    hFile = CreateFileW(
5533
        path->wide,
5534
        0, /* desired access */
5535
        0, /* share mode */
5536
        NULL, /* security attributes */
5537
        OPEN_EXISTING,
5538
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5539
        FILE_FLAG_BACKUP_SEMANTICS,
5540
        NULL);
5541
    Py_END_ALLOW_THREADS
5542
5543
    if (hFile == INVALID_HANDLE_VALUE) {
5544
        return win32_error_object("CreateFileW", path->object);
5545
    }
5546
5547
    /* We have a good handle to the target, use it to determine the
5548
       target path name. */
5549
    while (1) {
5550
        Py_BEGIN_ALLOW_THREADS
5551
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5552
                                                  buf_size, VOLUME_NAME_DOS);
5553
        Py_END_ALLOW_THREADS
5554
5555
        if (!result_length) {
5556
            result = win32_error_object("GetFinalPathNameByHandleW",
5557
                                         path->object);
5558
            goto cleanup;
5559
        }
5560
5561
        if (result_length < buf_size) {
5562
            break;
5563
        }
5564
5565
        wchar_t *tmp;
5566
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5567
                            result_length * sizeof(*tmp));
5568
        if (!tmp) {
5569
            result = PyErr_NoMemory();
5570
            goto cleanup;
5571
        }
5572
5573
        buf_size = result_length;
5574
        target_path = tmp;
5575
    }
5576
5577
    result = PyUnicode_FromWideChar(target_path, result_length);
5578
    if (result && PyBytes_Check(path->object)) {
5579
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5580
    }
5581
5582
cleanup:
5583
    if (target_path != buf) {
5584
        PyMem_Free(target_path);
5585
    }
5586
    CloseHandle(hFile);
5587
    return result;
5588
}
5589
5590
/*[clinic input]
5591
os._findfirstfile
5592
    path: path_t
5593
    /
5594
A function to get the real file name without accessing the file in Windows.
5595
[clinic start generated code]*/
5596
5597
static PyObject *
5598
os__findfirstfile_impl(PyObject *module, path_t *path)
5599
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5600
{
5601
    PyObject *result;
5602
    HANDLE hFindFile;
5603
    WIN32_FIND_DATAW wFileData;
5604
    WCHAR *wRealFileName;
5605
5606
    Py_BEGIN_ALLOW_THREADS
5607
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5608
    Py_END_ALLOW_THREADS
5609
5610
    if (hFindFile == INVALID_HANDLE_VALUE) {
5611
        path_error(path);
5612
        return NULL;
5613
    }
5614
5615
    wRealFileName = wFileData.cFileName;
5616
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5617
    FindClose(hFindFile);
5618
    return result;
5619
}
5620
5621
5622
/*[clinic input]
5623
os._getvolumepathname
5624
5625
    path: path_t
5626
5627
A helper function for ismount on Win32.
5628
[clinic start generated code]*/
5629
5630
static PyObject *
5631
os__getvolumepathname_impl(PyObject *module, path_t *path)
5632
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5633
{
5634
    PyObject *result;
5635
    wchar_t *mountpath=NULL;
5636
    size_t buflen;
5637
    BOOL ret;
5638
5639
    /* Volume path should be shorter than entire path */
5640
    buflen = Py_MAX(path->length, MAX_PATH);
5641
5642
    if (buflen > PY_DWORD_MAX) {
5643
        PyErr_SetString(PyExc_OverflowError, "path too long");
5644
        return NULL;
5645
    }
5646
5647
    mountpath = PyMem_New(wchar_t, buflen);
5648
    if (mountpath == NULL)
5649
        return PyErr_NoMemory();
5650
5651
    Py_BEGIN_ALLOW_THREADS
5652
    ret = GetVolumePathNameW(path->wide, mountpath,
5653
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5654
    Py_END_ALLOW_THREADS
5655
5656
    if (!ret) {
5657
        result = win32_error_object("_getvolumepathname", path->object);
5658
        goto exit;
5659
    }
5660
    result = PyUnicode_FromWideChar(mountpath, -1);
5661
    if (PyBytes_Check(path->object))
5662
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5663
5664
exit:
5665
    PyMem_Free(mountpath);
5666
    return result;
5667
}
5668
5669
5670
/*[clinic input]
5671
os._path_splitroot
5672
5673
    path: path_t
5674
    /
5675
5676
Removes everything after the root on Win32.
5677
[clinic start generated code]*/
5678
5679
static PyObject *
5680
os__path_splitroot_impl(PyObject *module, path_t *path)
5681
/*[clinic end generated code: output=ab7f1a88b654581c input=d356de1edb6050a2]*/
5682
{
5683
    wchar_t *buffer;
5684
    wchar_t *end;
5685
    PyObject *result = NULL;
5686
    HRESULT ret;
5687
5688
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5689
    if (!buffer) {
5690
        return NULL;
5691
    }
5692
    wcscpy(buffer, path->wide);
5693
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5694
        *p = L'\\';
5695
    }
5696
5697
    Py_BEGIN_ALLOW_THREADS
5698
    ret = PathCchSkipRoot(buffer, &end);
5699
    Py_END_ALLOW_THREADS
5700
    if (FAILED(ret)) {
5701
        result = Py_BuildValue("sO", "", path->object);
5702
    } else if (end != buffer) {
5703
        size_t rootLen = (size_t)(end - buffer);
5704
        result = Py_BuildValue("NN",
5705
            PyUnicode_FromWideChar(path->wide, rootLen),
5706
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5707
        );
5708
    } else {
5709
        result = Py_BuildValue("Os", path->object, "");
5710
    }
5711
    PyMem_Free(buffer);
5712
5713
    return result;
5714
}
5715
5716
5717
#define PY_IFREG  1 // Regular file
5718
#define PY_IFDIR  2 // Directory
5719
#define PY_IFLNK  4 // Symlink
5720
#define PY_IFMNT  8 // Mount Point (junction)
5721
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5722
#define PY_IFRRP 32 // Regular Reparse Point
5723
5724
static inline BOOL
5725
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5726
{
5727
    switch (testedType) {
5728
    case PY_IFREG:
5729
        return diskDevice && attributes &&
5730
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5731
    case PY_IFDIR:
5732
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5733
    case PY_IFLNK:
5734
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5735
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5736
    case PY_IFMNT:
5737
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5738
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5739
    case PY_IFLRP:
5740
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5741
               IsReparseTagNameSurrogate(reparseTag);
5742
    case PY_IFRRP:
5743
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5744
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5745
    }
5746
5747
    return FALSE;
5748
}
5749
5750
static BOOL
5751
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5752
{
5753
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5754
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5755
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5756
5757
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5758
    if (diskOnly && !diskDevice) {
5759
        return FALSE;
5760
    }
5761
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5762
        FILE_ATTRIBUTE_TAG_INFO info;
5763
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5764
                                            sizeof(info)) &&
5765
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5766
                         testedType);
5767
    }
5768
    FILE_BASIC_INFO info;
5769
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5770
                                        sizeof(info)) &&
5771
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5772
}
5773
5774
static BOOL
5775
_testFileTypeByName(LPCWSTR path, int testedType)
5776
{
5777
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5778
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5779
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5780
5781
    FILE_STAT_BASIC_INFORMATION info;
5782
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5783
                                     sizeof(info)))
5784
    {
5785
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5786
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5787
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5788
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5789
                                diskDevice, testedType);
5790
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5791
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5792
        {
5793
            return result;
5794
        }
5795
    }
5796
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5797
                GetLastError()))
5798
    {
5799
        return FALSE;
5800
    }
5801
5802
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5803
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5804
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5805
    }
5806
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5807
                               OPEN_EXISTING, flags, NULL);
5808
    if (hfile != INVALID_HANDLE_VALUE) {
5809
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5810
        CloseHandle(hfile);
5811
        return result;
5812
    }
5813
5814
    switch (GetLastError()) {
5815
    case ERROR_ACCESS_DENIED:
5816
    case ERROR_SHARING_VIOLATION:
5817
    case ERROR_CANT_ACCESS_FILE:
5818
    case ERROR_INVALID_PARAMETER:
5819
        int rc;
5820
        STRUCT_STAT st;
5821
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5822
            rc = STAT(path, &st);
5823
        }
5824
        else {
5825
            // PY_IFRRP is not generally supported in this case, except for
5826
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5827
            rc = LSTAT(path, &st);
5828
        }
5829
        if (!rc) {
5830
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5831
                             st.st_mode & S_IFREG, testedType);
5832
        }
5833
    }
5834
5835
    return FALSE;
5836
}
5837
5838
5839
static BOOL
5840
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5841
{
5842
    FILE_STAT_BASIC_INFORMATION info;
5843
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5844
                                     sizeof(info)))
5845
    {
5846
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5847
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5848
        {
5849
            return TRUE;
5850
        }
5851
    }
5852
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5853
                    GetLastError()))
5854
    {
5855
        return FALSE;
5856
    }
5857
5858
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5859
    if (!followLinks) {
5860
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5861
    }
5862
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5863
                               OPEN_EXISTING, flags, NULL);
5864
    if (hfile != INVALID_HANDLE_VALUE) {
5865
        if (followLinks) {
5866
            CloseHandle(hfile);
5867
            return TRUE;
5868
        }
5869
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5870
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5871
        CloseHandle(hfile);
5872
        if (!result) {
5873
            return TRUE;
5874
        }
5875
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5876
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5877
        if (hfile != INVALID_HANDLE_VALUE) {
5878
            CloseHandle(hfile);
5879
            return TRUE;
5880
        }
5881
    }
5882
5883
    switch (GetLastError()) {
5884
    case ERROR_ACCESS_DENIED:
5885
    case ERROR_SHARING_VIOLATION:
5886
    case ERROR_CANT_ACCESS_FILE:
5887
    case ERROR_INVALID_PARAMETER:
5888
        STRUCT_STAT _st;
5889
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5890
    }
5891
5892
    return FALSE;
5893
}
5894
5895
5896
static BOOL
5897
_testFileExists(path_t *path, BOOL followLinks)
5898
{
5899
    BOOL result = FALSE;
5900
    if (path->value_error) {
5901
        return FALSE;
5902
    }
5903
5904
    Py_BEGIN_ALLOW_THREADS
5905
    if (path->is_fd) {
5906
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5907
        if (hfile != INVALID_HANDLE_VALUE) {
5908
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5909
                result = TRUE;
5910
            }
5911
        }
5912
    }
5913
    else if (path->wide) {
5914
        result = _testFileExistsByName(path->wide, followLinks);
5915
    }
5916
    Py_END_ALLOW_THREADS
5917
5918
    return result;
5919
}
5920
5921
5922
static BOOL
5923
_testFileType(path_t *path, int testedType)
5924
{
5925
    BOOL result = FALSE;
5926
    if (path->value_error) {
5927
        return FALSE;
5928
    }
5929
5930
    Py_BEGIN_ALLOW_THREADS
5931
    if (path->is_fd) {
5932
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5933
        if (hfile != INVALID_HANDLE_VALUE) {
5934
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5935
        }
5936
    }
5937
    else if (path->wide) {
5938
        result = _testFileTypeByName(path->wide, testedType);
5939
    }
5940
    Py_END_ALLOW_THREADS
5941
5942
    return result;
5943
}
5944
5945
5946
/*[clinic input]
5947
os._path_exists -> bool
5948
5949
    path: path_t(allow_fd=True, suppress_value_error=True)
5950
5951
Test whether a path exists.  Returns False for broken symbolic links.
5952
5953
[clinic start generated code]*/
5954
5955
static int
5956
os__path_exists_impl(PyObject *module, path_t *path)
5957
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5958
{
5959
    return _testFileExists(path, TRUE);
5960
}
5961
5962
5963
/*[clinic input]
5964
os._path_lexists -> bool
5965
5966
    path: path_t(allow_fd=True, suppress_value_error=True)
5967
5968
Test whether a path exists.  Returns True for broken symbolic links.
5969
5970
[clinic start generated code]*/
5971
5972
static int
5973
os__path_lexists_impl(PyObject *module, path_t *path)
5974
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5975
{
5976
    return _testFileExists(path, FALSE);
5977
}
5978
5979
5980
/*[clinic input]
5981
os._path_isdir -> bool
5982
5983
    path: path_t(allow_fd=True, suppress_value_error=True)
5984
    /
5985
5986
Return true if the pathname refers to an existing directory.
5987
5988
[clinic start generated code]*/
5989
5990
static int
5991
os__path_isdir_impl(PyObject *module, path_t *path)
5992
/*[clinic end generated code: output=d5786196f9e2fa7a input=b15f9b697a7a759f]*/
5993
{
5994
    return _testFileType(path, PY_IFDIR);
5995
}
5996
5997
5998
/*[clinic input]
5999
os._path_isfile -> bool
6000
6001
    path: path_t(allow_fd=True, suppress_value_error=True)
6002
6003
Test whether a path is a regular file
6004
6005
[clinic start generated code]*/
6006
6007
static int
6008
os__path_isfile_impl(PyObject *module, path_t *path)
6009
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6010
{
6011
    return _testFileType(path, PY_IFREG);
6012
}
6013
6014
6015
/*[clinic input]
6016
os._path_islink -> bool
6017
6018
    path: path_t(allow_fd=True, suppress_value_error=True)
6019
6020
Test whether a path is a symbolic link
6021
6022
[clinic start generated code]*/
6023
6024
static int
6025
os__path_islink_impl(PyObject *module, path_t *path)
6026
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6027
{
6028
    return _testFileType(path, PY_IFLNK);
6029
}
6030
6031
6032
/*[clinic input]
6033
os._path_isjunction -> bool
6034
6035
    path: path_t(allow_fd=True, suppress_value_error=True)
6036
6037
Test whether a path is a junction
6038
6039
[clinic start generated code]*/
6040
6041
static int
6042
os__path_isjunction_impl(PyObject *module, path_t *path)
6043
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6044
{
6045
    return _testFileType(path, PY_IFMNT);
6046
}
6047
6048
#undef PY_IFREG
6049
#undef PY_IFDIR
6050
#undef PY_IFLNK
6051
#undef PY_IFMNT
6052
#undef PY_IFLRP
6053
#undef PY_IFRRP
6054
6055
#endif /* MS_WINDOWS */
6056
6057
6058
/*[clinic input]
6059
os._path_splitroot_ex
6060
6061
    path: path_t(make_wide=True, nonstrict=True)
6062
    /
6063
6064
Split a pathname into drive, root and tail.
6065
6066
The tail contains anything after the root.
6067
[clinic start generated code]*/
6068
6069
static PyObject *
6070
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6071
/*[clinic end generated code: output=4b0072b6cdf4b611 input=012fbfad14888b2b]*/
6072
168k
{
6073
168k
    Py_ssize_t drvsize, rootsize;
6074
168k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6075
6076
168k
    const wchar_t *buffer = path->wide;
6077
168k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6078
168k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6079
168k
    if (drv == NULL) {
6080
0
        goto exit;
6081
0
    }
6082
168k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6083
168k
    if (root == NULL) {
6084
0
        goto exit;
6085
0
    }
6086
168k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6087
168k
                                  path->length - drvsize - rootsize);
6088
168k
    if (tail == NULL) {
6089
0
        goto exit;
6090
0
    }
6091
168k
    if (PyBytes_Check(path->object)) {
6092
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6093
0
        if (drv == NULL) {
6094
0
            goto exit;
6095
0
        }
6096
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6097
0
        if (root == NULL) {
6098
0
            goto exit;
6099
0
        }
6100
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6101
0
        if (tail == NULL) {
6102
0
            goto exit;
6103
0
        }
6104
0
    }
6105
168k
    result = PyTuple_Pack(3, drv, root, tail);
6106
168k
exit:
6107
168k
    Py_XDECREF(drv);
6108
168k
    Py_XDECREF(root);
6109
168k
    Py_XDECREF(tail);
6110
168k
    return result;
6111
168k
}
6112
6113
6114
/*[clinic input]
6115
os._path_normpath
6116
6117
    path: path_t(make_wide=True, nonstrict=True)
6118
6119
Normalize path, eliminating double slashes, etc.
6120
[clinic start generated code]*/
6121
6122
static PyObject *
6123
os__path_normpath_impl(PyObject *module, path_t *path)
6124
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6125
31.1k
{
6126
31.1k
    PyObject *result;
6127
31.1k
    Py_ssize_t norm_len;
6128
31.1k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6129
31.1k
                                               path->length, &norm_len);
6130
31.1k
    if (!norm_len) {
6131
0
        result = PyUnicode_FromOrdinal('.');
6132
0
    }
6133
31.1k
    else {
6134
31.1k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6135
31.1k
    }
6136
31.1k
    if (PyBytes_Check(path->object)) {
6137
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6138
0
    }
6139
31.1k
    return result;
6140
31.1k
}
6141
6142
/*[clinic input]
6143
os.mkdir
6144
6145
    path : path_t
6146
6147
    mode: int = 0o777
6148
6149
    *
6150
6151
    dir_fd : dir_fd(requires='mkdirat') = None
6152
6153
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
6154
6155
Create a directory.
6156
6157
If dir_fd is not None, it should be a file descriptor open to a directory,
6158
  and path should be relative; path will then be relative to that directory.
6159
dir_fd may not be implemented on your platform.
6160
  If it is unavailable, using it will raise a NotImplementedError.
6161
6162
The mode argument is ignored on Windows. Where it is used, the current umask
6163
value is first masked out.
6164
[clinic start generated code]*/
6165
6166
static PyObject *
6167
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6168
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
6169
144k
{
6170
144k
    int result;
6171
#ifdef MS_WINDOWS
6172
    int error = 0;
6173
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6174
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6175
#endif
6176
144k
#ifdef HAVE_MKDIRAT
6177
144k
    int mkdirat_unavailable = 0;
6178
144k
#endif
6179
6180
144k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6181
144k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6182
0
        return NULL;
6183
0
    }
6184
6185
#ifdef MS_WINDOWS
6186
    Py_BEGIN_ALLOW_THREADS
6187
    // For API sets that don't support these APIs, we have no choice
6188
    // but to silently create a directory with default ACL.
6189
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6190
    if (mode == 0700 /* 0o700 */) {
6191
        ULONG sdSize;
6192
        pSecAttr = &secAttr;
6193
        // Set a discretionary ACL (D) that is protected (P) and includes
6194
        // inheritable (OICI) entries that allow (A) full control (FA) to
6195
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6196
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6197
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6198
            SDDL_REVISION_1,
6199
            &secAttr.lpSecurityDescriptor,
6200
            &sdSize
6201
        )) {
6202
            error = GetLastError();
6203
        }
6204
    }
6205
#endif
6206
    if (!error) {
6207
        result = CreateDirectoryW(path->wide, pSecAttr);
6208
        if (secAttr.lpSecurityDescriptor &&
6209
            // uncommonly, LocalFree returns non-zero on error, but still uses
6210
            // GetLastError() to see what the error code is
6211
            LocalFree(secAttr.lpSecurityDescriptor)) {
6212
            error = GetLastError();
6213
        }
6214
    }
6215
    Py_END_ALLOW_THREADS
6216
6217
    if (error) {
6218
        return PyErr_SetFromWindowsErr(error);
6219
    }
6220
    if (!result) {
6221
        return path_error(path);
6222
    }
6223
#else
6224
144k
    Py_BEGIN_ALLOW_THREADS
6225
144k
#if HAVE_MKDIRAT
6226
144k
    if (dir_fd != DEFAULT_DIR_FD) {
6227
0
      if (HAVE_MKDIRAT_RUNTIME) {
6228
0
        result = mkdirat(dir_fd, path->narrow, mode);
6229
6230
0
      } else {
6231
0
        mkdirat_unavailable = 1;
6232
0
      }
6233
0
    } else
6234
144k
#endif
6235
#if defined(__WATCOMC__) && !defined(__QNX__)
6236
        result = mkdir(path->narrow);
6237
#else
6238
144k
        result = mkdir(path->narrow, mode);
6239
144k
#endif
6240
144k
    Py_END_ALLOW_THREADS
6241
6242
144k
#if HAVE_MKDIRAT
6243
144k
    if (mkdirat_unavailable) {
6244
0
        argument_unavailable_error(NULL, "dir_fd");
6245
0
        return NULL;
6246
0
    }
6247
144k
#endif
6248
6249
144k
    if (result < 0)
6250
357
        return path_error(path);
6251
144k
#endif /* MS_WINDOWS */
6252
144k
    Py_RETURN_NONE;
6253
144k
}
6254
6255
6256
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6257
#if defined(HAVE_SYS_RESOURCE_H)
6258
#include <sys/resource.h>
6259
#endif
6260
6261
6262
#ifdef HAVE_NICE
6263
/*[clinic input]
6264
os.nice
6265
6266
    increment: int
6267
    /
6268
6269
Add increment to the priority of process and return the new priority.
6270
[clinic start generated code]*/
6271
6272
static PyObject *
6273
os_nice_impl(PyObject *module, int increment)
6274
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6275
0
{
6276
0
    int value;
6277
6278
    /* There are two flavours of 'nice': one that returns the new
6279
       priority (as required by almost all standards out there) and the
6280
       Linux/FreeBSD one, which returns '0' on success and advices
6281
       the use of getpriority() to get the new priority.
6282
6283
       If we are of the nice family that returns the new priority, we
6284
       need to clear errno before the call, and check if errno is filled
6285
       before calling posix_error() on a returnvalue of -1, because the
6286
       -1 may be the actual new priority! */
6287
6288
0
    errno = 0;
6289
0
    value = nice(increment);
6290
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6291
    if (value == 0)
6292
        value = getpriority(PRIO_PROCESS, 0);
6293
#endif
6294
0
    if (value == -1 && errno != 0)
6295
        /* either nice() or getpriority() returned an error */
6296
0
        return posix_error();
6297
0
    return PyLong_FromLong((long) value);
6298
0
}
6299
#endif /* HAVE_NICE */
6300
6301
6302
#ifdef HAVE_GETPRIORITY
6303
/*[clinic input]
6304
os.getpriority
6305
6306
    which: int
6307
    who: int
6308
6309
Return program scheduling priority.
6310
[clinic start generated code]*/
6311
6312
static PyObject *
6313
os_getpriority_impl(PyObject *module, int which, int who)
6314
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6315
0
{
6316
0
    int retval;
6317
6318
0
    errno = 0;
6319
0
    retval = getpriority(which, who);
6320
0
    if (errno != 0)
6321
0
        return posix_error();
6322
0
    return PyLong_FromLong((long)retval);
6323
0
}
6324
#endif /* HAVE_GETPRIORITY */
6325
6326
6327
#ifdef HAVE_SETPRIORITY
6328
/*[clinic input]
6329
os.setpriority
6330
6331
    which: int
6332
    who: int
6333
    priority: int
6334
6335
Set program scheduling priority.
6336
[clinic start generated code]*/
6337
6338
static PyObject *
6339
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6340
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6341
0
{
6342
0
    int retval;
6343
6344
0
    retval = setpriority(which, who, priority);
6345
0
    if (retval == -1)
6346
0
        return posix_error();
6347
0
    Py_RETURN_NONE;
6348
0
}
6349
#endif /* HAVE_SETPRIORITY */
6350
6351
6352
static PyObject *
6353
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6354
168
{
6355
168
    const char *function_name = is_replace ? "replace" : "rename";
6356
168
    int dir_fd_specified;
6357
6358
168
#ifdef HAVE_RENAMEAT
6359
168
    int renameat_unavailable = 0;
6360
168
#endif
6361
6362
#ifdef MS_WINDOWS
6363
    BOOL result;
6364
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6365
#else
6366
168
    int result;
6367
168
#endif
6368
6369
168
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6370
168
                       (dst_dir_fd != DEFAULT_DIR_FD);
6371
#ifndef HAVE_RENAMEAT
6372
    if (dir_fd_specified) {
6373
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6374
        return NULL;
6375
    }
6376
#endif
6377
6378
168
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6379
168
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6380
168
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6381
0
        return NULL;
6382
0
    }
6383
6384
#ifdef MS_WINDOWS
6385
    Py_BEGIN_ALLOW_THREADS
6386
    result = MoveFileExW(src->wide, dst->wide, flags);
6387
    Py_END_ALLOW_THREADS
6388
6389
    if (!result)
6390
        return path_error2(src, dst);
6391
6392
#else
6393
168
    Py_BEGIN_ALLOW_THREADS
6394
168
#ifdef HAVE_RENAMEAT
6395
168
    if (dir_fd_specified) {
6396
0
        if (HAVE_RENAMEAT_RUNTIME) {
6397
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6398
0
        } else {
6399
0
            renameat_unavailable = 1;
6400
0
        }
6401
0
    } else
6402
168
#endif
6403
168
    result = rename(src->narrow, dst->narrow);
6404
168
    Py_END_ALLOW_THREADS
6405
6406
6407
168
#ifdef HAVE_RENAMEAT
6408
168
    if (renameat_unavailable) {
6409
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6410
0
        return NULL;
6411
0
    }
6412
168
#endif
6413
6414
168
    if (result)
6415
0
        return path_error2(src, dst);
6416
168
#endif
6417
168
    Py_RETURN_NONE;
6418
168
}
6419
6420
6421
/*[clinic input]
6422
@permit_long_docstring_body
6423
os.rename
6424
6425
    src : path_t
6426
    dst : path_t
6427
    *
6428
    src_dir_fd : dir_fd = None
6429
    dst_dir_fd : dir_fd = None
6430
6431
Rename a file or directory.
6432
6433
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6434
  descriptor open to a directory, and the respective path string (src or dst)
6435
  should be relative; the path will then be relative to that directory.
6436
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6437
  If they are unavailable, using them will raise a NotImplementedError.
6438
[clinic start generated code]*/
6439
6440
static PyObject *
6441
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6442
               int dst_dir_fd)
6443
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6444
5
{
6445
5
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6446
5
}
6447
6448
6449
/*[clinic input]
6450
@permit_long_docstring_body
6451
os.replace = os.rename
6452
6453
Rename a file or directory, overwriting the destination.
6454
6455
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6456
  descriptor open to a directory, and the respective path string (src or dst)
6457
  should be relative; the path will then be relative to that directory.
6458
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6459
  If they are unavailable, using them will raise a NotImplementedError.
6460
[clinic start generated code]*/
6461
6462
static PyObject *
6463
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6464
                int dst_dir_fd)
6465
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6466
163
{
6467
163
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6468
163
}
6469
6470
6471
/*[clinic input]
6472
os.rmdir
6473
6474
    path: path_t
6475
    *
6476
    dir_fd: dir_fd(requires='unlinkat') = None
6477
6478
Remove a directory.
6479
6480
If dir_fd is not None, it should be a file descriptor open to a directory,
6481
  and path should be relative; path will then be relative to that directory.
6482
dir_fd may not be implemented on your platform.
6483
  If it is unavailable, using it will raise a NotImplementedError.
6484
[clinic start generated code]*/
6485
6486
static PyObject *
6487
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6488
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6489
144k
{
6490
144k
    int result;
6491
144k
#ifdef HAVE_UNLINKAT
6492
144k
    int unlinkat_unavailable = 0;
6493
144k
#endif
6494
6495
144k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6496
144k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6497
0
        return NULL;
6498
0
    }
6499
6500
144k
    Py_BEGIN_ALLOW_THREADS
6501
#ifdef MS_WINDOWS
6502
    /* Windows, success=1, UNIX, success=0 */
6503
    result = !RemoveDirectoryW(path->wide);
6504
#else
6505
144k
#ifdef HAVE_UNLINKAT
6506
144k
    if (dir_fd != DEFAULT_DIR_FD) {
6507
140k
      if (HAVE_UNLINKAT_RUNTIME) {
6508
140k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6509
140k
      } else {
6510
0
        unlinkat_unavailable = 1;
6511
0
        result = -1;
6512
0
      }
6513
140k
    } else
6514
3.87k
#endif
6515
3.87k
        result = rmdir(path->narrow);
6516
144k
#endif
6517
144k
    Py_END_ALLOW_THREADS
6518
6519
144k
#ifdef HAVE_UNLINKAT
6520
144k
    if (unlinkat_unavailable) {
6521
0
        argument_unavailable_error("rmdir", "dir_fd");
6522
0
        return NULL;
6523
0
    }
6524
144k
#endif
6525
6526
144k
    if (result)
6527
5
        return path_error(path);
6528
6529
144k
    Py_RETURN_NONE;
6530
144k
}
6531
6532
6533
#ifdef HAVE_SYSTEM
6534
#ifdef MS_WINDOWS
6535
/*[clinic input]
6536
os.system -> long
6537
6538
    command: Py_UNICODE
6539
6540
Execute the command in a subshell.
6541
[clinic start generated code]*/
6542
6543
static long
6544
os_system_impl(PyObject *module, const wchar_t *command)
6545
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6546
{
6547
    long result;
6548
6549
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6550
        return -1;
6551
    }
6552
6553
    Py_BEGIN_ALLOW_THREADS
6554
    _Py_BEGIN_SUPPRESS_IPH
6555
    result = _wsystem(command);
6556
    _Py_END_SUPPRESS_IPH
6557
    Py_END_ALLOW_THREADS
6558
    return result;
6559
}
6560
#else /* MS_WINDOWS */
6561
/*[clinic input]
6562
os.system -> long
6563
6564
    command: unicode_fs_encoded
6565
6566
Execute the command in a subshell.
6567
[clinic start generated code]*/
6568
6569
static long
6570
os_system_impl(PyObject *module, PyObject *command)
6571
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6572
0
{
6573
0
    long result;
6574
0
    const char *bytes = PyBytes_AsString(command);
6575
6576
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6577
0
        return -1;
6578
0
    }
6579
6580
0
    Py_BEGIN_ALLOW_THREADS
6581
0
    result = system(bytes);
6582
0
    Py_END_ALLOW_THREADS
6583
0
    return result;
6584
0
}
6585
#endif
6586
#endif /* HAVE_SYSTEM */
6587
6588
6589
#ifdef HAVE_UMASK
6590
/*[clinic input]
6591
os.umask
6592
6593
    mask: int
6594
    /
6595
6596
Set the current numeric umask and return the previous umask.
6597
[clinic start generated code]*/
6598
6599
static PyObject *
6600
os_umask_impl(PyObject *module, int mask)
6601
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6602
0
{
6603
0
    int i = (int)umask(mask);
6604
0
    if (i < 0)
6605
0
        return posix_error();
6606
0
    return PyLong_FromLong((long)i);
6607
0
}
6608
#endif
6609
6610
#ifdef MS_WINDOWS
6611
6612
/* override the default DeleteFileW behavior so that directory
6613
symlinks can be removed with this function, the same as with
6614
Unix symlinks */
6615
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6616
{
6617
    WIN32_FILE_ATTRIBUTE_DATA info;
6618
    WIN32_FIND_DATAW find_data;
6619
    HANDLE find_data_handle;
6620
    int is_directory = 0;
6621
    int is_link = 0;
6622
6623
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6624
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6625
6626
        /* Get WIN32_FIND_DATA structure for the path to determine if
6627
           it is a symlink */
6628
        if(is_directory &&
6629
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6630
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6631
6632
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6633
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6634
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6635
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6636
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6637
                FindClose(find_data_handle);
6638
            }
6639
        }
6640
    }
6641
6642
    if (is_directory && is_link)
6643
        return RemoveDirectoryW(lpFileName);
6644
6645
    return DeleteFileW(lpFileName);
6646
}
6647
#endif /* MS_WINDOWS */
6648
6649
6650
/*[clinic input]
6651
os.unlink
6652
6653
    path: path_t
6654
    *
6655
    dir_fd: dir_fd(requires='unlinkat')=None
6656
6657
Remove a file (same as remove()).
6658
6659
If dir_fd is not None, it should be a file descriptor open to a directory,
6660
  and path should be relative; path will then be relative to that directory.
6661
dir_fd may not be implemented on your platform.
6662
  If it is unavailable, using it will raise a NotImplementedError.
6663
6664
[clinic start generated code]*/
6665
6666
static PyObject *
6667
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6668
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6669
23.2k
{
6670
23.2k
    int result;
6671
23.2k
#ifdef HAVE_UNLINKAT
6672
23.2k
    int unlinkat_unavailable = 0;
6673
23.2k
#endif
6674
6675
23.2k
    if (PySys_Audit("os.remove", "Oi", path->object,
6676
23.2k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6677
0
        return NULL;
6678
0
    }
6679
6680
23.2k
    Py_BEGIN_ALLOW_THREADS
6681
23.2k
    _Py_BEGIN_SUPPRESS_IPH
6682
#ifdef MS_WINDOWS
6683
    /* Windows, success=1, UNIX, success=0 */
6684
    result = !Py_DeleteFileW(path->wide);
6685
#else
6686
23.2k
#ifdef HAVE_UNLINKAT
6687
23.2k
    if (dir_fd != DEFAULT_DIR_FD) {
6688
23.2k
      if (HAVE_UNLINKAT_RUNTIME) {
6689
6690
23.2k
        result = unlinkat(dir_fd, path->narrow, 0);
6691
23.2k
      } else {
6692
0
        unlinkat_unavailable = 1;
6693
0
      }
6694
23.2k
    } else
6695
2
#endif /* HAVE_UNLINKAT */
6696
2
        result = unlink(path->narrow);
6697
23.2k
#endif
6698
23.2k
    _Py_END_SUPPRESS_IPH
6699
23.2k
    Py_END_ALLOW_THREADS
6700
6701
23.2k
#ifdef HAVE_UNLINKAT
6702
23.2k
    if (unlinkat_unavailable) {
6703
0
        argument_unavailable_error(NULL, "dir_fd");
6704
0
        return NULL;
6705
0
    }
6706
23.2k
#endif
6707
6708
23.2k
    if (result)
6709
0
        return path_error(path);
6710
6711
23.2k
    Py_RETURN_NONE;
6712
23.2k
}
6713
6714
6715
/*[clinic input]
6716
os.remove = os.unlink
6717
6718
Remove a file (same as unlink()).
6719
6720
If dir_fd is not None, it should be a file descriptor open to a directory,
6721
  and path should be relative; path will then be relative to that directory.
6722
dir_fd may not be implemented on your platform.
6723
  If it is unavailable, using it will raise a NotImplementedError.
6724
[clinic start generated code]*/
6725
6726
static PyObject *
6727
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6728
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6729
0
{
6730
0
    return os_unlink_impl(module, path, dir_fd);
6731
0
}
6732
6733
6734
static PyStructSequence_Field uname_result_fields[] = {
6735
    {"sysname",    "operating system name"},
6736
    {"nodename",   "name of machine on network (implementation-defined)"},
6737
    {"release",    "operating system release"},
6738
    {"version",    "operating system version"},
6739
    {"machine",    "hardware identifier"},
6740
    {NULL}
6741
};
6742
6743
PyDoc_STRVAR(uname_result__doc__,
6744
"uname_result: Result from os.uname().\n\n\
6745
This object may be accessed either as a tuple of\n\
6746
  (sysname, nodename, release, version, machine),\n\
6747
or via the attributes sysname, nodename, release, version, and machine.\n\
6748
\n\
6749
See os.uname for more information.");
6750
6751
static PyStructSequence_Desc uname_result_desc = {
6752
    MODNAME ".uname_result", /* name */
6753
    uname_result__doc__, /* doc */
6754
    uname_result_fields,
6755
    5
6756
};
6757
6758
#ifdef HAVE_UNAME
6759
/*[clinic input]
6760
os.uname
6761
6762
Return an object identifying the current operating system.
6763
6764
The object behaves like a named tuple with the following fields:
6765
  (sysname, nodename, release, version, machine)
6766
6767
[clinic start generated code]*/
6768
6769
static PyObject *
6770
os_uname_impl(PyObject *module)
6771
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6772
4
{
6773
4
    struct utsname u;
6774
4
    int res;
6775
4
    PyObject *value;
6776
6777
4
    Py_BEGIN_ALLOW_THREADS
6778
4
    res = uname(&u);
6779
4
    Py_END_ALLOW_THREADS
6780
4
    if (res < 0)
6781
0
        return posix_error();
6782
6783
4
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6784
4
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6785
4
    if (value == NULL)
6786
0
        return NULL;
6787
6788
4
#define SET(i, field) \
6789
20
    { \
6790
20
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6791
20
    if (!o) { \
6792
0
        Py_DECREF(value); \
6793
0
        return NULL; \
6794
0
    } \
6795
20
    PyStructSequence_SET_ITEM(value, i, o); \
6796
20
    } \
6797
4
6798
8
    SET(0, u.sysname);
6799
8
    SET(1, u.nodename);
6800
4
    SET(2, u.release);
6801
4
    SET(3, u.version);
6802
4
    SET(4, u.machine);
6803
6804
4
#undef SET
6805
6806
4
    return value;
6807
4
}
6808
#endif /* HAVE_UNAME */
6809
6810
6811
6812
typedef struct {
6813
    int    now;
6814
    time_t atime_s;
6815
    long   atime_ns;
6816
    time_t mtime_s;
6817
    long   mtime_ns;
6818
} utime_t;
6819
6820
/*
6821
 * these macros assume that "ut" is a pointer to a utime_t
6822
 * they also intentionally leak the declaration of a pointer named "time"
6823
 */
6824
#define UTIME_TO_TIMESPEC \
6825
0
    struct timespec ts[2]; \
6826
0
    struct timespec *time; \
6827
0
    if (ut->now) \
6828
0
        time = NULL; \
6829
0
    else { \
6830
0
        ts[0].tv_sec = ut->atime_s; \
6831
0
        ts[0].tv_nsec = ut->atime_ns; \
6832
0
        ts[1].tv_sec = ut->mtime_s; \
6833
0
        ts[1].tv_nsec = ut->mtime_ns; \
6834
0
        time = ts; \
6835
0
    } \
6836
6837
#define UTIME_TO_TIMEVAL \
6838
0
    struct timeval tv[2]; \
6839
0
    struct timeval *time; \
6840
0
    if (ut->now) \
6841
0
        time = NULL; \
6842
0
    else { \
6843
0
        tv[0].tv_sec = ut->atime_s; \
6844
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6845
0
        tv[1].tv_sec = ut->mtime_s; \
6846
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6847
0
        time = tv; \
6848
0
    } \
6849
6850
#define UTIME_TO_UTIMBUF \
6851
    struct utimbuf u; \
6852
    struct utimbuf *time; \
6853
    if (ut->now) \
6854
        time = NULL; \
6855
    else { \
6856
        u.actime = ut->atime_s; \
6857
        u.modtime = ut->mtime_s; \
6858
        time = &u; \
6859
    }
6860
6861
#define UTIME_TO_TIME_T \
6862
    time_t timet[2]; \
6863
    time_t *time; \
6864
    if (ut->now) \
6865
        time = NULL; \
6866
    else { \
6867
        timet[0] = ut->atime_s; \
6868
        timet[1] = ut->mtime_s; \
6869
        time = timet; \
6870
    } \
6871
6872
6873
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6874
6875
static int
6876
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6877
0
{
6878
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6879
    if (HAVE_UTIMENSAT_RUNTIME) {
6880
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6881
        UTIME_TO_TIMESPEC;
6882
        return utimensat(dir_fd, path, time, flags);
6883
    }  else {
6884
        errno = ENOSYS;
6885
        return -1;
6886
    }
6887
#elif defined(HAVE_UTIMENSAT)
6888
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6889
0
    UTIME_TO_TIMESPEC;
6890
0
    return utimensat(dir_fd, path, time, flags);
6891
#elif defined(HAVE_FUTIMESAT)
6892
    UTIME_TO_TIMEVAL;
6893
    /*
6894
     * follow_symlinks will never be false here;
6895
     * we only allow !follow_symlinks and dir_fd together
6896
     * if we have utimensat()
6897
     */
6898
    assert(follow_symlinks);
6899
    return futimesat(dir_fd, path, time);
6900
#endif
6901
0
}
6902
6903
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6904
#else
6905
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6906
#endif
6907
6908
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6909
6910
static int
6911
utime_fd(utime_t *ut, int fd)
6912
0
{
6913
0
#ifdef HAVE_FUTIMENS
6914
6915
0
    if (HAVE_FUTIMENS_RUNTIME) {
6916
6917
0
    UTIME_TO_TIMESPEC;
6918
0
    return futimens(fd, time);
6919
6920
0
    } else
6921
#ifndef HAVE_FUTIMES
6922
    {
6923
        /* Not sure if this can happen */
6924
        PyErr_SetString(
6925
            PyExc_RuntimeError,
6926
            "neither futimens nor futimes are supported"
6927
            " on this system");
6928
        return -1;
6929
    }
6930
#endif
6931
6932
0
#endif
6933
0
#ifdef HAVE_FUTIMES
6934
0
    {
6935
0
    UTIME_TO_TIMEVAL;
6936
0
    return futimes(fd, time);
6937
0
    }
6938
0
#endif
6939
0
}
6940
6941
    #define PATH_UTIME_HAVE_FD 1
6942
#else
6943
    #define PATH_UTIME_HAVE_FD 0
6944
#endif
6945
6946
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6947
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6948
#endif
6949
6950
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6951
6952
static int
6953
utime_nofollow_symlinks(utime_t *ut, const char *path)
6954
0
{
6955
0
#ifdef HAVE_UTIMENSAT
6956
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6957
0
        UTIME_TO_TIMESPEC;
6958
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6959
0
    } else
6960
#ifndef HAVE_LUTIMES
6961
    {
6962
        /* Not sure if this can happen */
6963
        PyErr_SetString(
6964
            PyExc_RuntimeError,
6965
            "neither utimensat nor lutimes are supported"
6966
            " on this system");
6967
        return -1;
6968
    }
6969
#endif
6970
0
#endif
6971
6972
0
#ifdef HAVE_LUTIMES
6973
0
    {
6974
0
    UTIME_TO_TIMEVAL;
6975
0
    return lutimes(path, time);
6976
0
    }
6977
0
#endif
6978
0
}
6979
6980
#endif
6981
6982
#ifndef MS_WINDOWS
6983
6984
static int
6985
utime_default(utime_t *ut, const char *path)
6986
0
{
6987
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6988
    if (HAVE_UTIMENSAT_RUNTIME) {
6989
        UTIME_TO_TIMESPEC;
6990
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6991
    } else {
6992
        UTIME_TO_TIMEVAL;
6993
        return utimes(path, time);
6994
    }
6995
#elif defined(HAVE_UTIMENSAT)
6996
0
    UTIME_TO_TIMESPEC;
6997
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6998
#elif defined(HAVE_UTIMES)
6999
    UTIME_TO_TIMEVAL;
7000
    return utimes(path, time);
7001
#elif defined(HAVE_UTIME_H)
7002
    UTIME_TO_UTIMBUF;
7003
    return utime(path, time);
7004
#else
7005
    UTIME_TO_TIME_T;
7006
    return utime(path, time);
7007
#endif
7008
0
}
7009
7010
#endif
7011
7012
static int
7013
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7014
0
{
7015
0
    int result = 0;
7016
0
    PyObject *divmod;
7017
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7018
0
    if (!divmod)
7019
0
        goto exit;
7020
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7021
0
        PyErr_Format(PyExc_TypeError,
7022
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7023
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7024
0
        goto exit;
7025
0
    }
7026
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7027
0
    if ((*s == -1) && PyErr_Occurred())
7028
0
        goto exit;
7029
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7030
0
    if ((*ns == -1) && PyErr_Occurred())
7031
0
        goto exit;
7032
7033
0
    result = 1;
7034
0
exit:
7035
0
    Py_XDECREF(divmod);
7036
0
    return result;
7037
0
}
7038
7039
7040
/*[clinic input]
7041
os.utime
7042
7043
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7044
    times: object = None
7045
    *
7046
    ns: object = NULL
7047
    dir_fd: dir_fd(requires='futimensat') = None
7048
    follow_symlinks: bool=True
7049
7050
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
7051
7052
Set the access and modified time of path.
7053
7054
path may always be specified as a string.
7055
On some platforms, path may also be specified as an open file descriptor.
7056
  If this functionality is unavailable, using it raises an exception.
7057
7058
If times is not None, it must be a tuple (atime, mtime);
7059
    atime and mtime should be expressed as float seconds since the epoch.
7060
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7061
    atime_ns and mtime_ns should be expressed as integer nanoseconds
7062
    since the epoch.
7063
If times is None and ns is unspecified, utime uses the current time.
7064
Specifying tuples for both times and ns is an error.
7065
7066
If dir_fd is not None, it should be a file descriptor open to a directory,
7067
  and path should be relative; path will then be relative to that directory.
7068
If follow_symlinks is False, and the last element of the path is a symbolic
7069
  link, utime will modify the symbolic link itself instead of the file the
7070
  link points to.
7071
It is an error to use dir_fd or follow_symlinks when specifying path
7072
  as an open file descriptor.
7073
dir_fd and follow_symlinks may not be available on your platform.
7074
  If they are unavailable, using them will raise a NotImplementedError.
7075
7076
[clinic start generated code]*/
7077
7078
static PyObject *
7079
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7080
              int dir_fd, int follow_symlinks)
7081
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
7082
0
{
7083
#ifdef MS_WINDOWS
7084
    HANDLE hFile;
7085
    FILETIME atime, mtime;
7086
#else
7087
0
    int result;
7088
0
#endif
7089
7090
0
    utime_t utime;
7091
7092
0
    memset(&utime, 0, sizeof(utime_t));
7093
7094
0
    if (times != Py_None && ns) {
7095
0
        PyErr_SetString(PyExc_ValueError,
7096
0
                     "utime: you may specify either 'times'"
7097
0
                     " or 'ns' but not both");
7098
0
        return NULL;
7099
0
    }
7100
7101
0
    if (times != Py_None) {
7102
0
        time_t a_sec, m_sec;
7103
0
        long a_nsec, m_nsec;
7104
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7105
0
            PyErr_SetString(PyExc_TypeError,
7106
0
                         "utime: 'times' must be either"
7107
0
                         " a tuple of two numbers or None");
7108
0
            return NULL;
7109
0
        }
7110
0
        utime.now = 0;
7111
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7112
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7113
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7114
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7115
0
            return NULL;
7116
0
        }
7117
0
        utime.atime_s = a_sec;
7118
0
        utime.atime_ns = a_nsec;
7119
0
        utime.mtime_s = m_sec;
7120
0
        utime.mtime_ns = m_nsec;
7121
0
    }
7122
0
    else if (ns) {
7123
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7124
0
            PyErr_SetString(PyExc_TypeError,
7125
0
                         "utime: 'ns' must be a tuple of two ints");
7126
0
            return NULL;
7127
0
        }
7128
0
        utime.now = 0;
7129
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7130
0
                                      &utime.atime_s, &utime.atime_ns) ||
7131
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7132
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7133
0
            return NULL;
7134
0
        }
7135
0
    }
7136
0
    else {
7137
        /* times and ns are both None/unspecified. use "now". */
7138
0
        utime.now = 1;
7139
0
    }
7140
7141
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7142
    if (follow_symlinks_specified("utime", follow_symlinks))
7143
        return NULL;
7144
#endif
7145
7146
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7147
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7148
0
        fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
7149
0
        return NULL;
7150
7151
#if !defined(HAVE_UTIMENSAT)
7152
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7153
        PyErr_SetString(PyExc_ValueError,
7154
                     "utime: cannot use dir_fd and follow_symlinks "
7155
                     "together on this platform");
7156
        return NULL;
7157
    }
7158
#endif
7159
7160
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7161
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7162
0
        return NULL;
7163
0
    }
7164
7165
#ifdef MS_WINDOWS
7166
    Py_BEGIN_ALLOW_THREADS
7167
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7168
                        NULL, OPEN_EXISTING,
7169
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7170
    Py_END_ALLOW_THREADS
7171
    if (hFile == INVALID_HANDLE_VALUE) {
7172
        path_error(path);
7173
        return NULL;
7174
    }
7175
7176
    if (utime.now) {
7177
        GetSystemTimeAsFileTime(&mtime);
7178
        atime = mtime;
7179
    }
7180
    else {
7181
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7182
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7183
    }
7184
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7185
        path_error(path);
7186
        CloseHandle(hFile);
7187
        return NULL;
7188
    }
7189
    CloseHandle(hFile);
7190
#else /* MS_WINDOWS */
7191
0
    Py_BEGIN_ALLOW_THREADS
7192
7193
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7194
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7195
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7196
0
    else
7197
0
#endif
7198
7199
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7200
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7201
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7202
7203
0
    } else
7204
0
#endif
7205
7206
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7207
0
    if (path->is_fd)
7208
0
        result = utime_fd(&utime, path->fd);
7209
0
    else
7210
0
#endif
7211
7212
0
    result = utime_default(&utime, path->narrow);
7213
7214
0
    Py_END_ALLOW_THREADS
7215
7216
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7217
    /* See utime_dir_fd implementation */
7218
    if (result == -1 && errno == ENOSYS) {
7219
        argument_unavailable_error(NULL, "dir_fd");
7220
        return NULL;
7221
    }
7222
#endif
7223
7224
0
    if (result < 0) {
7225
0
        path_error(path);
7226
0
        return NULL;
7227
0
    }
7228
7229
0
#endif /* MS_WINDOWS */
7230
7231
0
    Py_RETURN_NONE;
7232
0
}
7233
7234
/* Process operations */
7235
7236
7237
/*[clinic input]
7238
os._exit
7239
7240
    status: int
7241
7242
Exit to the system with specified status, without normal exit processing.
7243
[clinic start generated code]*/
7244
7245
static PyObject *
7246
os__exit_impl(PyObject *module, int status)
7247
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
7248
0
{
7249
0
    _exit(status);
7250
0
    return NULL; /* Make gcc -Wall happy */
7251
0
}
7252
7253
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7254
#define EXECV_CHAR wchar_t
7255
#else
7256
0
#define EXECV_CHAR char
7257
#endif
7258
7259
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7260
static void
7261
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7262
0
{
7263
0
    Py_ssize_t i;
7264
0
    for (i = 0; i < count; i++)
7265
0
        PyMem_Free(array[i]);
7266
0
    PyMem_Free(array);
7267
0
}
7268
7269
static int
7270
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7271
0
{
7272
0
    Py_ssize_t size;
7273
0
    PyObject *ub;
7274
0
    int result = 0;
7275
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7276
    if (!PyUnicode_FSDecoder(o, &ub))
7277
        return 0;
7278
    *out = PyUnicode_AsWideCharString(ub, &size);
7279
    if (*out)
7280
        result = 1;
7281
#else
7282
0
    if (!PyUnicode_FSConverter(o, &ub))
7283
0
        return 0;
7284
0
    size = PyBytes_GET_SIZE(ub);
7285
0
    *out = PyMem_Malloc(size + 1);
7286
0
    if (*out) {
7287
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7288
0
        result = 1;
7289
0
    } else
7290
0
        PyErr_NoMemory();
7291
0
#endif
7292
0
    Py_DECREF(ub);
7293
0
    return result;
7294
0
}
7295
#endif
7296
7297
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7298
static EXECV_CHAR**
7299
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7300
0
{
7301
0
    Py_ssize_t i, pos, envc;
7302
0
    PyObject *keys = NULL, *vals = NULL;
7303
0
    PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
7304
0
    EXECV_CHAR **envlist;
7305
7306
0
    i = PyMapping_Size(env);
7307
0
    if (i < 0)
7308
0
        return NULL;
7309
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7310
0
    if (envlist == NULL) {
7311
0
        PyErr_NoMemory();
7312
0
        return NULL;
7313
0
    }
7314
0
    envc = 0;
7315
0
    keys = PyMapping_Keys(env);
7316
0
    if (!keys)
7317
0
        goto error;
7318
0
    vals = PyMapping_Values(env);
7319
0
    if (!vals)
7320
0
        goto error;
7321
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7322
0
        PyErr_Format(PyExc_TypeError,
7323
0
                     "env.keys() or env.values() is not a list");
7324
0
        goto error;
7325
0
    }
7326
7327
0
    for (pos = 0; pos < i; pos++) {
7328
        // The 'key' and 'val' must be strong references because of
7329
        // possible side-effects by PyUnicode_FS{Converter,Decoder}().
7330
0
        key = PyList_GetItemRef(keys, pos);
7331
0
        if (key == NULL) {
7332
0
            goto error;
7333
0
        }
7334
0
        val = PyList_GetItemRef(vals, pos);
7335
0
        if (val == NULL) {
7336
0
            goto error;
7337
0
        }
7338
7339
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7340
        if (!PyUnicode_FSDecoder(key, &key2)) {
7341
            goto error;
7342
        }
7343
        if (!PyUnicode_FSDecoder(val, &val2)) {
7344
            goto error;
7345
        }
7346
        /* Search from index 1 because on Windows starting '=' is allowed for
7347
           defining hidden environment variables. */
7348
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7349
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7350
        {
7351
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7352
            goto error;
7353
        }
7354
        PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7355
#else
7356
0
        if (!PyUnicode_FSConverter(key, &key2)) {
7357
0
            goto error;
7358
0
        }
7359
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7360
0
            goto error;
7361
0
        }
7362
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7363
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7364
0
        {
7365
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7366
0
            goto error;
7367
0
        }
7368
0
        PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7369
0
                                              PyBytes_AS_STRING(val2));
7370
0
#endif
7371
0
        if (!keyval) {
7372
0
            goto error;
7373
0
        }
7374
7375
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7376
0
            Py_DECREF(keyval);
7377
0
            goto error;
7378
0
        }
7379
7380
0
        Py_CLEAR(key);
7381
0
        Py_CLEAR(val);
7382
0
        Py_CLEAR(key2);
7383
0
        Py_CLEAR(val2);
7384
0
        Py_DECREF(keyval);
7385
0
    }
7386
0
    Py_DECREF(vals);
7387
0
    Py_DECREF(keys);
7388
7389
0
    envlist[envc] = 0;
7390
0
    *envc_ptr = envc;
7391
0
    return envlist;
7392
7393
0
error:
7394
0
    Py_XDECREF(key);
7395
0
    Py_XDECREF(val);
7396
0
    Py_XDECREF(key2);
7397
0
    Py_XDECREF(val2);
7398
0
    Py_XDECREF(keys);
7399
0
    Py_XDECREF(vals);
7400
0
    free_string_array(envlist, envc);
7401
0
    return NULL;
7402
0
}
7403
7404
static EXECV_CHAR**
7405
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7406
0
{
7407
0
    int i;
7408
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7409
0
    if (argvlist == NULL) {
7410
0
        PyErr_NoMemory();
7411
0
        return NULL;
7412
0
    }
7413
0
    for (i = 0; i < *argc; i++) {
7414
0
        PyObject* item = PySequence_ITEM(argv, i);
7415
0
        if (item == NULL)
7416
0
            goto fail;
7417
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7418
0
            Py_DECREF(item);
7419
0
            goto fail;
7420
0
        }
7421
0
        Py_DECREF(item);
7422
0
    }
7423
0
    argvlist[*argc] = NULL;
7424
0
    return argvlist;
7425
0
fail:
7426
0
    *argc = i;
7427
0
    free_string_array(argvlist, *argc);
7428
0
    return NULL;
7429
0
}
7430
7431
#endif
7432
7433
7434
#ifdef HAVE_EXECV
7435
/*[clinic input]
7436
os.execv
7437
7438
    path: path_t
7439
        Path of executable file.
7440
    argv: object
7441
        Tuple or list of strings.
7442
    /
7443
7444
Execute an executable path with arguments, replacing current process.
7445
[clinic start generated code]*/
7446
7447
static PyObject *
7448
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7449
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7450
0
{
7451
0
    EXECV_CHAR **argvlist;
7452
0
    Py_ssize_t argc;
7453
7454
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7455
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7456
0
        PyErr_SetString(PyExc_RuntimeError,
7457
0
                        "exec not supported for isolated subinterpreters");
7458
0
        return NULL;
7459
0
    }
7460
7461
    /* execv has two arguments: (path, argv), where
7462
       argv is a list or tuple of strings. */
7463
7464
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7465
0
        PyErr_SetString(PyExc_TypeError,
7466
0
                        "execv() arg 2 must be a tuple or list");
7467
0
        return NULL;
7468
0
    }
7469
0
    argc = PySequence_Size(argv);
7470
0
    if (argc < 1) {
7471
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7472
0
        return NULL;
7473
0
    }
7474
7475
0
    argvlist = parse_arglist(argv, &argc);
7476
0
    if (argvlist == NULL) {
7477
0
        return NULL;
7478
0
    }
7479
0
    if (!argvlist[0][0]) {
7480
0
        PyErr_SetString(PyExc_ValueError,
7481
0
            "execv() arg 2 first element cannot be empty");
7482
0
        free_string_array(argvlist, argc);
7483
0
        return NULL;
7484
0
    }
7485
7486
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7487
0
        free_string_array(argvlist, argc);
7488
0
        return NULL;
7489
0
    }
7490
7491
0
    _Py_BEGIN_SUPPRESS_IPH
7492
#ifdef HAVE_WEXECV
7493
    _wexecv(path->wide, argvlist);
7494
#else
7495
0
    execv(path->narrow, argvlist);
7496
0
#endif
7497
0
    _Py_END_SUPPRESS_IPH
7498
7499
    /* If we get here it's definitely an error */
7500
7501
0
    posix_error();
7502
0
    free_string_array(argvlist, argc);
7503
0
    return NULL;
7504
0
}
7505
7506
7507
/*[clinic input]
7508
os.execve
7509
7510
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7511
        Path of executable file.
7512
    argv: object
7513
        Tuple or list of strings.
7514
    env: object
7515
        Dictionary of strings mapping to strings.
7516
7517
Execute an executable path with arguments, replacing current process.
7518
[clinic start generated code]*/
7519
7520
static PyObject *
7521
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7522
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7523
0
{
7524
0
    EXECV_CHAR **argvlist = NULL;
7525
0
    EXECV_CHAR **envlist;
7526
0
    Py_ssize_t argc, envc;
7527
7528
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7529
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7530
0
        PyErr_SetString(PyExc_RuntimeError,
7531
0
                        "exec not supported for isolated subinterpreters");
7532
0
        return NULL;
7533
0
    }
7534
7535
    /* execve has three arguments: (path, argv, env), where
7536
       argv is a list or tuple of strings and env is a dictionary
7537
       like posix.environ. */
7538
7539
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7540
0
        PyErr_SetString(PyExc_TypeError,
7541
0
                        "execve: argv must be a tuple or list");
7542
0
        goto fail_0;
7543
0
    }
7544
0
    argc = PySequence_Size(argv);
7545
0
    if (argc < 1) {
7546
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7547
0
        return NULL;
7548
0
    }
7549
7550
0
    if (!PyMapping_Check(env)) {
7551
0
        PyErr_SetString(PyExc_TypeError,
7552
0
                        "execve: environment must be a mapping object");
7553
0
        goto fail_0;
7554
0
    }
7555
7556
0
    argvlist = parse_arglist(argv, &argc);
7557
0
    if (argvlist == NULL) {
7558
0
        goto fail_0;
7559
0
    }
7560
0
    if (!argvlist[0][0]) {
7561
0
        PyErr_SetString(PyExc_ValueError,
7562
0
            "execve: argv first element cannot be empty");
7563
0
        goto fail_0;
7564
0
    }
7565
7566
0
    envlist = parse_envlist(env, &envc);
7567
0
    if (envlist == NULL)
7568
0
        goto fail_0;
7569
7570
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7571
0
        goto fail_1;
7572
0
    }
7573
7574
0
    _Py_BEGIN_SUPPRESS_IPH
7575
0
#ifdef HAVE_FEXECVE
7576
0
    if (path->is_fd)
7577
0
        fexecve(path->fd, argvlist, envlist);
7578
0
    else
7579
0
#endif
7580
#ifdef HAVE_WEXECV
7581
        _wexecve(path->wide, argvlist, envlist);
7582
#else
7583
0
        execve(path->narrow, argvlist, envlist);
7584
0
#endif
7585
0
    _Py_END_SUPPRESS_IPH
7586
7587
    /* If we get here it's definitely an error */
7588
7589
0
    posix_path_error(path);
7590
0
  fail_1:
7591
0
    free_string_array(envlist, envc);
7592
0
  fail_0:
7593
0
    if (argvlist)
7594
0
        free_string_array(argvlist, argc);
7595
0
    return NULL;
7596
0
}
7597
7598
#endif /* HAVE_EXECV */
7599
7600
#ifdef HAVE_POSIX_SPAWN
7601
7602
enum posix_spawn_file_actions_identifier {
7603
    POSIX_SPAWN_OPEN,
7604
    POSIX_SPAWN_CLOSE,
7605
    POSIX_SPAWN_DUP2
7606
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7607
    ,POSIX_SPAWN_CLOSEFROM
7608
#endif
7609
};
7610
7611
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7612
static int
7613
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7614
#endif
7615
7616
static int
7617
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7618
                        int resetids, int setsid, PyObject *setsigmask,
7619
                        PyObject *setsigdef, PyObject *scheduler,
7620
                        posix_spawnattr_t *attrp)
7621
0
{
7622
0
    assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
7623
0
    long all_flags = 0;
7624
7625
0
    errno = posix_spawnattr_init(attrp);
7626
0
    if (errno) {
7627
0
        posix_error();
7628
0
        return -1;
7629
0
    }
7630
7631
0
    if (setpgroup && setpgroup != Py_None) {
7632
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7633
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7634
0
            goto fail;
7635
0
        }
7636
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7637
0
        if (errno) {
7638
0
            posix_error();
7639
0
            goto fail;
7640
0
        }
7641
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7642
0
    }
7643
7644
0
    if (resetids) {
7645
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7646
0
    }
7647
7648
0
    if (setsid) {
7649
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7650
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7651
#endif
7652
0
#ifdef POSIX_SPAWN_SETSID
7653
0
        all_flags |= POSIX_SPAWN_SETSID;
7654
#elif defined(POSIX_SPAWN_SETSID_NP)
7655
        all_flags |= POSIX_SPAWN_SETSID_NP;
7656
#else
7657
        argument_unavailable_error(func_name, "setsid");
7658
        return -1;
7659
#endif
7660
7661
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7662
        } else {
7663
            argument_unavailable_error(func_name, "setsid");
7664
            return -1;
7665
        }
7666
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7667
7668
0
    }
7669
7670
0
#ifdef HAVE_SIGSET_T
7671
0
   if (setsigmask) {
7672
0
        sigset_t set;
7673
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7674
0
            goto fail;
7675
0
        }
7676
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7677
0
        if (errno) {
7678
0
            posix_error();
7679
0
            goto fail;
7680
0
        }
7681
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7682
0
    }
7683
7684
0
    if (setsigdef) {
7685
0
        sigset_t set;
7686
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7687
0
            goto fail;
7688
0
        }
7689
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7690
0
        if (errno) {
7691
0
            posix_error();
7692
0
            goto fail;
7693
0
        }
7694
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7695
0
    }
7696
#else
7697
    if (setsigmask || setsigdef) {
7698
        PyErr_SetString(PyExc_NotImplementedError,
7699
                        "sigset is not supported on this platform");
7700
        goto fail;
7701
    }
7702
#endif
7703
7704
0
    if (scheduler && scheduler != Py_None) {
7705
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7706
0
        PyObject *py_schedpolicy;
7707
0
        PyObject *schedparam_obj;
7708
0
        struct sched_param schedparam;
7709
7710
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7711
0
                        ";A scheduler tuple must have two elements",
7712
0
                        &py_schedpolicy, &schedparam_obj)) {
7713
0
            goto fail;
7714
0
        }
7715
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7716
0
            goto fail;
7717
0
        }
7718
0
        if (py_schedpolicy != Py_None) {
7719
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7720
7721
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7722
0
                goto fail;
7723
0
            }
7724
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7725
0
            if (errno) {
7726
0
                posix_error();
7727
0
                goto fail;
7728
0
            }
7729
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7730
0
        }
7731
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7732
0
        if (errno) {
7733
0
            posix_error();
7734
0
            goto fail;
7735
0
        }
7736
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7737
#else
7738
        PyErr_SetString(PyExc_NotImplementedError,
7739
                "The scheduler option is not supported in this system.");
7740
        goto fail;
7741
#endif
7742
0
    }
7743
7744
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7745
0
    if (errno) {
7746
0
        posix_error();
7747
0
        goto fail;
7748
0
    }
7749
7750
0
    return 0;
7751
7752
0
fail:
7753
0
    (void)posix_spawnattr_destroy(attrp);
7754
0
    return -1;
7755
0
}
7756
7757
static int
7758
parse_file_actions(PyObject *file_actions,
7759
                   posix_spawn_file_actions_t *file_actionsp,
7760
                   PyObject *temp_buffer)
7761
0
{
7762
0
    PyObject *seq;
7763
0
    PyObject *file_action = NULL;
7764
0
    PyObject *tag_obj;
7765
7766
0
    seq = PySequence_Fast(file_actions,
7767
0
                          "file_actions must be a sequence or None");
7768
0
    if (seq == NULL) {
7769
0
        return -1;
7770
0
    }
7771
7772
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7773
0
    if (errno) {
7774
0
        posix_error();
7775
0
        Py_DECREF(seq);
7776
0
        return -1;
7777
0
    }
7778
7779
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7780
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7781
0
        Py_INCREF(file_action);
7782
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7783
0
            PyErr_SetString(PyExc_TypeError,
7784
0
                "Each file_actions element must be a non-empty tuple");
7785
0
            goto fail;
7786
0
        }
7787
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7788
0
        if (tag == -1 && PyErr_Occurred()) {
7789
0
            goto fail;
7790
0
        }
7791
7792
        /* Populate the file_actions object */
7793
0
        switch (tag) {
7794
0
            case POSIX_SPAWN_OPEN: {
7795
0
                int fd, oflag;
7796
0
                PyObject *path;
7797
0
                unsigned long mode;
7798
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7799
0
                        ";A open file_action tuple must have 5 elements",
7800
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7801
0
                        &oflag, &mode))
7802
0
                {
7803
0
                    goto fail;
7804
0
                }
7805
0
                if (PyList_Append(temp_buffer, path)) {
7806
0
                    Py_DECREF(path);
7807
0
                    goto fail;
7808
0
                }
7809
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7810
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7811
0
                if (errno) {
7812
0
                    posix_error();
7813
0
                    Py_DECREF(path);
7814
0
                    goto fail;
7815
0
                }
7816
0
                Py_DECREF(path);
7817
0
                break;
7818
0
            }
7819
0
            case POSIX_SPAWN_CLOSE: {
7820
0
                int fd;
7821
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7822
0
                        ";A close file_action tuple must have 2 elements",
7823
0
                        &tag_obj, &fd))
7824
0
                {
7825
0
                    goto fail;
7826
0
                }
7827
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7828
0
                if (errno) {
7829
0
                    posix_error();
7830
0
                    goto fail;
7831
0
                }
7832
0
                break;
7833
0
            }
7834
0
            case POSIX_SPAWN_DUP2: {
7835
0
                int fd1, fd2;
7836
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7837
0
                        ";A dup2 file_action tuple must have 3 elements",
7838
0
                        &tag_obj, &fd1, &fd2))
7839
0
                {
7840
0
                    goto fail;
7841
0
                }
7842
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7843
0
                                                         fd1, fd2);
7844
0
                if (errno) {
7845
0
                    posix_error();
7846
0
                    goto fail;
7847
0
                }
7848
0
                break;
7849
0
            }
7850
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7851
            case POSIX_SPAWN_CLOSEFROM: {
7852
                int fd;
7853
                if (!PyArg_ParseTuple(file_action, "Oi"
7854
                        ";A closefrom file_action tuple must have 2 elements",
7855
                        &tag_obj, &fd))
7856
                {
7857
                    goto fail;
7858
                }
7859
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7860
                                                                 fd);
7861
                if (errno) {
7862
                    posix_error();
7863
                    goto fail;
7864
                }
7865
                break;
7866
            }
7867
#endif
7868
0
            default: {
7869
0
                PyErr_SetString(PyExc_TypeError,
7870
0
                                "Unknown file_actions identifier");
7871
0
                goto fail;
7872
0
            }
7873
0
        }
7874
0
        Py_DECREF(file_action);
7875
0
    }
7876
7877
0
    Py_DECREF(seq);
7878
0
    return 0;
7879
7880
0
fail:
7881
0
    Py_DECREF(seq);
7882
0
    Py_DECREF(file_action);
7883
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7884
0
    return -1;
7885
0
}
7886
7887
7888
static PyObject *
7889
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7890
               PyObject *env, PyObject *file_actions,
7891
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7892
               PyObject *setsigdef, PyObject *scheduler)
7893
0
{
7894
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7895
0
    EXECV_CHAR **argvlist = NULL;
7896
0
    EXECV_CHAR **envlist = NULL;
7897
0
    posix_spawn_file_actions_t file_actions_buf;
7898
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7899
0
    posix_spawnattr_t attr;
7900
0
    posix_spawnattr_t *attrp = NULL;
7901
0
    Py_ssize_t argc, envc;
7902
0
    PyObject *result = NULL;
7903
0
    PyObject *temp_buffer = NULL;
7904
0
    pid_t pid;
7905
0
    int err_code;
7906
7907
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7908
       argv is a list or tuple of strings and env is a dictionary
7909
       like posix.environ. */
7910
7911
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7912
0
        PyErr_Format(PyExc_TypeError,
7913
0
                     "%s: argv must be a tuple or list", func_name);
7914
0
        goto exit;
7915
0
    }
7916
0
    argc = PySequence_Size(argv);
7917
0
    if (argc < 1) {
7918
0
        PyErr_Format(PyExc_ValueError,
7919
0
                     "%s: argv must not be empty", func_name);
7920
0
        goto exit;
7921
0
    }
7922
7923
0
    if (!PyMapping_Check(env) && env != Py_None) {
7924
0
        PyErr_Format(PyExc_TypeError,
7925
0
                     "%s: environment must be a mapping object or None", func_name);
7926
0
        goto exit;
7927
0
    }
7928
7929
0
    if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7930
0
        PyErr_Format(PyExc_TypeError,
7931
0
                     "%s: scheduler must be a tuple or None", func_name);
7932
0
        goto exit;
7933
0
    }
7934
7935
0
    argvlist = parse_arglist(argv, &argc);
7936
0
    if (argvlist == NULL) {
7937
0
        goto exit;
7938
0
    }
7939
0
    if (!argvlist[0][0]) {
7940
0
        PyErr_Format(PyExc_ValueError,
7941
0
                     "%s: argv first element cannot be empty", func_name);
7942
0
        goto exit;
7943
0
    }
7944
7945
#ifdef USE_DARWIN_NS_GET_ENVIRON
7946
    // There is no environ global in this situation.
7947
    char **environ = NULL;
7948
#endif
7949
7950
0
    if (env == Py_None) {
7951
#ifdef USE_DARWIN_NS_GET_ENVIRON
7952
        environ = *_NSGetEnviron();
7953
#endif
7954
0
        envlist = environ;
7955
0
    } else {
7956
0
        envlist = parse_envlist(env, &envc);
7957
0
        if (envlist == NULL) {
7958
0
            goto exit;
7959
0
        }
7960
0
    }
7961
7962
0
    if (file_actions != NULL && file_actions != Py_None) {
7963
        /* There is a bug in old versions of glibc that makes some of the
7964
         * helper functions for manipulating file actions not copy the provided
7965
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7966
         * copy the value of path for some old versions of glibc (<2.20).
7967
         * The use of temp_buffer here is a workaround that keeps the
7968
         * python objects that own the buffers alive until posix_spawn gets called.
7969
         * Check https://bugs.python.org/issue33630 and
7970
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7971
0
        temp_buffer = PyList_New(0);
7972
0
        if (!temp_buffer) {
7973
0
            goto exit;
7974
0
        }
7975
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7976
0
            goto exit;
7977
0
        }
7978
0
        file_actionsp = &file_actions_buf;
7979
0
    }
7980
7981
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7982
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7983
0
        goto exit;
7984
0
    }
7985
0
    attrp = &attr;
7986
7987
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7988
0
        goto exit;
7989
0
    }
7990
7991
0
    _Py_BEGIN_SUPPRESS_IPH
7992
0
#ifdef HAVE_POSIX_SPAWNP
7993
0
    if (use_posix_spawnp) {
7994
0
        err_code = posix_spawnp(&pid, path->narrow,
7995
0
                                file_actionsp, attrp, argvlist, envlist);
7996
0
    }
7997
0
    else
7998
0
#endif /* HAVE_POSIX_SPAWNP */
7999
0
    {
8000
0
        err_code = posix_spawn(&pid, path->narrow,
8001
0
                               file_actionsp, attrp, argvlist, envlist);
8002
0
    }
8003
0
    _Py_END_SUPPRESS_IPH
8004
8005
0
    if (err_code) {
8006
0
        errno = err_code;
8007
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8008
0
        goto exit;
8009
0
    }
8010
#ifdef _Py_MEMORY_SANITIZER
8011
    __msan_unpoison(&pid, sizeof(pid));
8012
#endif
8013
0
    result = PyLong_FromPid(pid);
8014
8015
0
exit:
8016
0
    if (file_actionsp) {
8017
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
8018
0
    }
8019
0
    if (attrp) {
8020
0
        (void)posix_spawnattr_destroy(attrp);
8021
0
    }
8022
0
    if (envlist && envlist != environ) {
8023
0
        free_string_array(envlist, envc);
8024
0
    }
8025
0
    if (argvlist) {
8026
0
        free_string_array(argvlist, argc);
8027
0
    }
8028
0
    Py_XDECREF(temp_buffer);
8029
0
    return result;
8030
0
}
8031
8032
8033
/*[clinic input]
8034
8035
os.posix_spawn
8036
    path: path_t
8037
        Path of executable file.
8038
    argv: object
8039
        Tuple or list of strings.
8040
    env: object
8041
        Dictionary of strings mapping to strings.
8042
    /
8043
    *
8044
    file_actions: object(c_default='NULL') = ()
8045
        A sequence of file action tuples.
8046
    setpgroup: object(c_default='NULL') = None
8047
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8048
    resetids: bool = False
8049
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8050
    setsid: bool = False
8051
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8052
    setsigmask: object(c_default='NULL') = ()
8053
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8054
    setsigdef: object(c_default='NULL') = ()
8055
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8056
    scheduler: object(c_default='NULL') = None
8057
        A tuple with the scheduler policy (optional) and parameters.
8058
8059
Execute the program specified by path in a new process.
8060
[clinic start generated code]*/
8061
8062
static PyObject *
8063
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8064
                    PyObject *env, PyObject *file_actions,
8065
                    PyObject *setpgroup, int resetids, int setsid,
8066
                    PyObject *setsigmask, PyObject *setsigdef,
8067
                    PyObject *scheduler)
8068
/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/
8069
0
{
8070
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8071
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8072
0
                          scheduler);
8073
0
}
8074
 #endif /* HAVE_POSIX_SPAWN */
8075
8076
8077
8078
#ifdef HAVE_POSIX_SPAWNP
8079
/*[clinic input]
8080
8081
os.posix_spawnp
8082
    path: path_t
8083
        Path of executable file.
8084
    argv: object
8085
        Tuple or list of strings.
8086
    env: object
8087
        Dictionary of strings mapping to strings.
8088
    /
8089
    *
8090
    file_actions: object(c_default='NULL') = ()
8091
        A sequence of file action tuples.
8092
    setpgroup: object(c_default='NULL') = None
8093
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8094
    resetids: bool = False
8095
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8096
    setsid: bool = False
8097
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8098
    setsigmask: object(c_default='NULL') = ()
8099
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8100
    setsigdef: object(c_default='NULL') = ()
8101
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8102
    scheduler: object(c_default='NULL') = None
8103
        A tuple with the scheduler policy (optional) and parameters.
8104
8105
Execute the program specified by path in a new process.
8106
[clinic start generated code]*/
8107
8108
static PyObject *
8109
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8110
                     PyObject *env, PyObject *file_actions,
8111
                     PyObject *setpgroup, int resetids, int setsid,
8112
                     PyObject *setsigmask, PyObject *setsigdef,
8113
                     PyObject *scheduler)
8114
/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/
8115
0
{
8116
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8117
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8118
0
                          scheduler);
8119
0
}
8120
#endif /* HAVE_POSIX_SPAWNP */
8121
8122
#ifdef HAVE_RTPSPAWN
8123
static intptr_t
8124
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8125
               const char  *envp[])
8126
{
8127
     RTP_ID rtpid;
8128
     int status;
8129
     pid_t res;
8130
     int async_err = 0;
8131
8132
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8133
        uStackSize=0 cannot be used, the default stack size is too small for
8134
        Python. */
8135
     if (envp) {
8136
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8137
                          100, 0x1000000, 0, VX_FP_TASK);
8138
     }
8139
     else {
8140
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8141
                          100, 0x1000000, 0, VX_FP_TASK);
8142
     }
8143
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8144
         do {
8145
             res = waitpid((pid_t)rtpid, &status, 0);
8146
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8147
8148
         if (res < 0)
8149
             return RTP_ID_ERROR;
8150
         return ((intptr_t)status);
8151
     }
8152
     return ((intptr_t)rtpid);
8153
}
8154
#endif
8155
8156
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8157
/*[clinic input]
8158
os.spawnv
8159
8160
    mode: int
8161
        Mode of process creation.
8162
    path: path_t
8163
        Path of executable file.
8164
    argv: object
8165
        Tuple or list of strings.
8166
    /
8167
8168
Execute the program specified by path in a new process.
8169
[clinic start generated code]*/
8170
8171
static PyObject *
8172
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8173
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8174
{
8175
    EXECV_CHAR **argvlist;
8176
    int i;
8177
    Py_ssize_t argc;
8178
    intptr_t spawnval;
8179
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8180
8181
    /* spawnv has three arguments: (mode, path, argv), where
8182
       argv is a list or tuple of strings. */
8183
8184
    if (PyList_Check(argv)) {
8185
        argc = PyList_Size(argv);
8186
        getitem = PyList_GetItem;
8187
    }
8188
    else if (PyTuple_Check(argv)) {
8189
        argc = PyTuple_Size(argv);
8190
        getitem = PyTuple_GetItem;
8191
    }
8192
    else {
8193
        PyErr_SetString(PyExc_TypeError,
8194
                        "spawnv() arg 2 must be a tuple or list");
8195
        return NULL;
8196
    }
8197
    if (argc == 0) {
8198
        PyErr_SetString(PyExc_ValueError,
8199
            "spawnv() arg 2 cannot be empty");
8200
        return NULL;
8201
    }
8202
8203
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8204
    if (argvlist == NULL) {
8205
        return PyErr_NoMemory();
8206
    }
8207
    for (i = 0; i < argc; i++) {
8208
        if (!fsconvert_strdup((*getitem)(argv, i),
8209
                              &argvlist[i])) {
8210
            free_string_array(argvlist, i);
8211
            PyErr_SetString(
8212
                PyExc_TypeError,
8213
                "spawnv() arg 2 must contain only strings");
8214
            return NULL;
8215
        }
8216
        if (i == 0 && !argvlist[0][0]) {
8217
            free_string_array(argvlist, i + 1);
8218
            PyErr_SetString(
8219
                PyExc_ValueError,
8220
                "spawnv() arg 2 first element cannot be empty");
8221
            return NULL;
8222
        }
8223
    }
8224
    argvlist[argc] = NULL;
8225
8226
#if !defined(HAVE_RTPSPAWN)
8227
    if (mode == _OLD_P_OVERLAY)
8228
        mode = _P_OVERLAY;
8229
#endif
8230
8231
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8232
                    Py_None) < 0) {
8233
        free_string_array(argvlist, argc);
8234
        return NULL;
8235
    }
8236
8237
    Py_BEGIN_ALLOW_THREADS
8238
    _Py_BEGIN_SUPPRESS_IPH
8239
#ifdef HAVE_WSPAWNV
8240
    spawnval = _wspawnv(mode, path->wide, argvlist);
8241
#elif defined(HAVE_RTPSPAWN)
8242
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8243
#else
8244
    spawnval = _spawnv(mode, path->narrow, argvlist);
8245
#endif
8246
    _Py_END_SUPPRESS_IPH
8247
    Py_END_ALLOW_THREADS
8248
8249
    int saved_errno = errno;
8250
    free_string_array(argvlist, argc);
8251
8252
    if (spawnval == -1) {
8253
        errno = saved_errno;
8254
        posix_error();
8255
        return NULL;
8256
    }
8257
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8258
}
8259
8260
/*[clinic input]
8261
os.spawnve
8262
8263
    mode: int
8264
        Mode of process creation.
8265
    path: path_t
8266
        Path of executable file.
8267
    argv: object
8268
        Tuple or list of strings.
8269
    env: object
8270
        Dictionary of strings mapping to strings.
8271
    /
8272
8273
Execute the program specified by path in a new process.
8274
[clinic start generated code]*/
8275
8276
static PyObject *
8277
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8278
                PyObject *env)
8279
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8280
{
8281
    EXECV_CHAR **argvlist;
8282
    EXECV_CHAR **envlist;
8283
    PyObject *res = NULL;
8284
    Py_ssize_t argc, i, envc;
8285
    intptr_t spawnval;
8286
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8287
    Py_ssize_t lastarg = 0;
8288
8289
    /* spawnve has four arguments: (mode, path, argv, env), where
8290
       argv is a list or tuple of strings and env is a dictionary
8291
       like posix.environ. */
8292
8293
    if (PyList_Check(argv)) {
8294
        argc = PyList_Size(argv);
8295
        getitem = PyList_GetItem;
8296
    }
8297
    else if (PyTuple_Check(argv)) {
8298
        argc = PyTuple_Size(argv);
8299
        getitem = PyTuple_GetItem;
8300
    }
8301
    else {
8302
        PyErr_SetString(PyExc_TypeError,
8303
                        "spawnve() arg 2 must be a tuple or list");
8304
        goto fail_0;
8305
    }
8306
    if (argc == 0) {
8307
        PyErr_SetString(PyExc_ValueError,
8308
            "spawnve() arg 2 cannot be empty");
8309
        goto fail_0;
8310
    }
8311
    if (!PyMapping_Check(env)) {
8312
        PyErr_SetString(PyExc_TypeError,
8313
                        "spawnve() arg 3 must be a mapping object");
8314
        goto fail_0;
8315
    }
8316
8317
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8318
    if (argvlist == NULL) {
8319
        PyErr_NoMemory();
8320
        goto fail_0;
8321
    }
8322
    for (i = 0; i < argc; i++) {
8323
        if (!fsconvert_strdup((*getitem)(argv, i),
8324
                              &argvlist[i]))
8325
        {
8326
            lastarg = i;
8327
            goto fail_1;
8328
        }
8329
        if (i == 0 && !argvlist[0][0]) {
8330
            lastarg = i + 1;
8331
            PyErr_SetString(
8332
                PyExc_ValueError,
8333
                "spawnv() arg 2 first element cannot be empty");
8334
            goto fail_1;
8335
        }
8336
    }
8337
    lastarg = argc;
8338
    argvlist[argc] = NULL;
8339
8340
    envlist = parse_envlist(env, &envc);
8341
    if (envlist == NULL)
8342
        goto fail_1;
8343
8344
#if !defined(HAVE_RTPSPAWN)
8345
    if (mode == _OLD_P_OVERLAY)
8346
        mode = _P_OVERLAY;
8347
#endif
8348
8349
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8350
        goto fail_2;
8351
    }
8352
8353
    Py_BEGIN_ALLOW_THREADS
8354
    _Py_BEGIN_SUPPRESS_IPH
8355
#ifdef HAVE_WSPAWNV
8356
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8357
#elif defined(HAVE_RTPSPAWN)
8358
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8359
                           (const char **)envlist);
8360
#else
8361
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8362
#endif
8363
    _Py_END_SUPPRESS_IPH
8364
    Py_END_ALLOW_THREADS
8365
8366
    if (spawnval == -1)
8367
        (void) posix_error();
8368
    else
8369
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8370
8371
  fail_2:
8372
    while (--envc >= 0) {
8373
        PyMem_Free(envlist[envc]);
8374
    }
8375
    PyMem_Free(envlist);
8376
  fail_1:
8377
    free_string_array(argvlist, lastarg);
8378
  fail_0:
8379
    return res;
8380
}
8381
8382
#endif /* HAVE_SPAWNV */
8383
8384
#ifdef HAVE_FORK
8385
8386
/* Helper function to validate arguments.
8387
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8388
   If obj is non-NULL it must be callable.  */
8389
static int
8390
check_null_or_callable(PyObject *obj, const char* obj_name)
8391
90
{
8392
90
    if (obj && !PyCallable_Check(obj)) {
8393
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8394
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8395
0
        return -1;
8396
0
    }
8397
90
    return 0;
8398
90
}
8399
8400
/*[clinic input]
8401
os.register_at_fork
8402
8403
    *
8404
    before: object=NULL
8405
        A callable to be called in the parent before the fork() syscall.
8406
    after_in_child: object=NULL
8407
        A callable to be called in the child after fork().
8408
    after_in_parent: object=NULL
8409
        A callable to be called in the parent after fork().
8410
8411
Register callables to be called when forking a new process.
8412
8413
'before' callbacks are called in reverse order.
8414
'after_in_child' and 'after_in_parent' callbacks are called in order.
8415
8416
[clinic start generated code]*/
8417
8418
static PyObject *
8419
os_register_at_fork_impl(PyObject *module, PyObject *before,
8420
                         PyObject *after_in_child, PyObject *after_in_parent)
8421
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8422
30
{
8423
30
    PyInterpreterState *interp;
8424
8425
30
    if (!before && !after_in_child && !after_in_parent) {
8426
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8427
0
        return NULL;
8428
0
    }
8429
30
    if (check_null_or_callable(before, "before") ||
8430
30
        check_null_or_callable(after_in_child, "after_in_child") ||
8431
30
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8432
0
        return NULL;
8433
0
    }
8434
30
    interp = _PyInterpreterState_GET();
8435
8436
30
    if (register_at_forker(&interp->before_forkers, before)) {
8437
0
        return NULL;
8438
0
    }
8439
30
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8440
0
        return NULL;
8441
0
    }
8442
30
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8443
0
        return NULL;
8444
0
    }
8445
30
    Py_RETURN_NONE;
8446
30
}
8447
#endif /* HAVE_FORK */
8448
8449
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8450
// Common code to raise a warning if we detect there is more than one thread
8451
// running in the process. Best effort, silent if unable to count threads.
8452
// Constraint: Quick. Never overcounts. Never leaves an error set.
8453
//
8454
// This MUST only be called from the parent process after
8455
// PyOS_AfterFork_Parent().
8456
static int
8457
warn_about_fork_with_threads(
8458
    const char* name,  // Name of the API to use in the warning message.
8459
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8460
)
8461
0
{
8462
    // It's not safe to issue the warning while the world is stopped, because
8463
    // other threads might be holding locks that we need, which would deadlock.
8464
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8465
8466
0
    Py_ssize_t num_python_threads = num_os_threads;
8467
0
    if (num_python_threads <= 0) {
8468
        // Fall back to just the number our threading module knows about.
8469
        // An incomplete view of the world, but better than nothing.
8470
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8471
0
        if (!threading) {
8472
0
            PyErr_Clear();
8473
0
            return 0;
8474
0
        }
8475
0
        PyObject *threading_active =
8476
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8477
0
        if (!threading_active) {
8478
0
            PyErr_Clear();
8479
0
            Py_DECREF(threading);
8480
0
            return 0;
8481
0
        }
8482
0
        PyObject *threading_limbo =
8483
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8484
0
        if (!threading_limbo) {
8485
0
            PyErr_Clear();
8486
0
            Py_DECREF(threading);
8487
0
            Py_DECREF(threading_active);
8488
0
            return 0;
8489
0
        }
8490
0
        Py_DECREF(threading);
8491
        // Duplicating what threading.active_count() does but without holding
8492
        // threading._active_limbo_lock so our count could be inaccurate if
8493
        // these dicts are mid-update from another thread.  Not a big deal.
8494
        // Worst case if someone replaced threading._active or threading._limbo
8495
        // with non-dicts, we get -1 from *Length() below and undercount.
8496
        // Nobody should, but we're best effort so we clear errors and move on.
8497
0
        num_python_threads = (PyMapping_Length(threading_active)
8498
0
                              + PyMapping_Length(threading_limbo));
8499
0
        PyErr_Clear();
8500
0
        Py_DECREF(threading_active);
8501
0
        Py_DECREF(threading_limbo);
8502
0
    }
8503
0
    if (num_python_threads > 1) {
8504
0
        return PyErr_WarnFormat(
8505
0
                PyExc_DeprecationWarning, 1,
8506
0
#ifdef HAVE_GETPID
8507
0
                "This process (pid=%d) is multi-threaded, "
8508
#else
8509
                "This process is multi-threaded, "
8510
#endif
8511
0
                "use of %s() may lead to deadlocks in the child.",
8512
0
#ifdef HAVE_GETPID
8513
0
                getpid(),
8514
0
#endif
8515
0
                name);
8516
0
    }
8517
0
    return 0;
8518
0
}
8519
8520
// If this returns <= 0, we were unable to successfully use any OS APIs.
8521
// Returns a positive number of threads otherwise.
8522
static Py_ssize_t get_number_of_os_threads(void)
8523
0
{
8524
    // TODO: Consider making an `os` module API to return the current number
8525
    // of threads in the process. That'd presumably use this platform code but
8526
    // raise an error rather than using the inaccurate fallback.
8527
0
    Py_ssize_t num_python_threads = 0;
8528
#if defined(__APPLE__) && defined(HAVE_GETPID)
8529
    mach_port_t macos_self = mach_task_self();
8530
    mach_port_t macos_task;
8531
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8532
        thread_array_t macos_threads;
8533
        mach_msg_type_number_t macos_n_threads;
8534
        if (task_threads(macos_task, &macos_threads,
8535
                         &macos_n_threads) == KERN_SUCCESS) {
8536
            num_python_threads = macos_n_threads;
8537
        }
8538
    }
8539
#elif defined(__linux__)
8540
    // Linux /proc/self/stat 20th field is the number of threads.
8541
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8542
0
    if (proc_stat) {
8543
0
        size_t n;
8544
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8545
        // observed on the author's workstation.
8546
0
        char stat_line[160];
8547
0
        n = fread(&stat_line, 1, 159, proc_stat);
8548
0
        stat_line[n] = '\0';
8549
0
        fclose(proc_stat);
8550
8551
0
        char *saveptr = NULL;
8552
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8553
0
        unsigned int idx;
8554
0
        for (idx = 19; idx && field; --idx) {
8555
0
            field = strtok_r(NULL, " ", &saveptr);
8556
0
        }
8557
0
        if (idx == 0 && field) {  // found the 20th field
8558
0
            num_python_threads = atoi(field);  // 0 on error
8559
0
        }
8560
0
    }
8561
0
#endif
8562
0
    return num_python_threads;
8563
0
}
8564
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8565
8566
#ifdef HAVE_FORK1
8567
/*[clinic input]
8568
os.fork1
8569
8570
Fork a child process with a single multiplexed (i.e., not bound) thread.
8571
8572
Return 0 to child process and PID of child to parent process.
8573
[clinic start generated code]*/
8574
8575
static PyObject *
8576
os_fork1_impl(PyObject *module)
8577
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8578
{
8579
    pid_t pid;
8580
8581
    PyInterpreterState *interp = _PyInterpreterState_GET();
8582
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8583
        PyErr_SetString(PyExc_PythonFinalizationError,
8584
                        "can't fork at interpreter shutdown");
8585
        return NULL;
8586
    }
8587
    if (!_Py_IsMainInterpreter(interp)) {
8588
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8589
        return NULL;
8590
    }
8591
    PyOS_BeforeFork();
8592
    pid = fork1();
8593
    int saved_errno = errno;
8594
    if (pid == 0) {
8595
        /* child: this clobbers and resets the import lock. */
8596
        PyOS_AfterFork_Child();
8597
    } else {
8598
        // Called before AfterFork_Parent in case those hooks start threads.
8599
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8600
        /* parent: release the import lock. */
8601
        PyOS_AfterFork_Parent();
8602
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8603
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8604
            return NULL;
8605
        }
8606
    }
8607
    if (pid == -1) {
8608
        errno = saved_errno;
8609
        return posix_error();
8610
    }
8611
    return PyLong_FromPid(pid);
8612
}
8613
#endif /* HAVE_FORK1 */
8614
8615
8616
#ifdef HAVE_FORK
8617
/*[clinic input]
8618
os.fork
8619
8620
Fork a child process.
8621
8622
Return 0 to child process and PID of child to parent process.
8623
[clinic start generated code]*/
8624
8625
static PyObject *
8626
os_fork_impl(PyObject *module)
8627
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8628
0
{
8629
0
    pid_t pid;
8630
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8631
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8632
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8633
0
                        "can't fork at interpreter shutdown");
8634
0
        return NULL;
8635
0
    }
8636
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8637
0
        PyErr_SetString(PyExc_RuntimeError,
8638
0
                        "fork not supported for isolated subinterpreters");
8639
0
        return NULL;
8640
0
    }
8641
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8642
0
        return NULL;
8643
0
    }
8644
0
    PyOS_BeforeFork();
8645
0
    pid = fork();
8646
0
    int saved_errno = errno;
8647
0
    if (pid == 0) {
8648
        /* child: this clobbers and resets the import lock. */
8649
0
        PyOS_AfterFork_Child();
8650
0
    } else {
8651
        // Called before AfterFork_Parent in case those hooks start threads.
8652
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8653
        /* parent: release the import lock. */
8654
0
        PyOS_AfterFork_Parent();
8655
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8656
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8657
0
            return NULL;
8658
0
    }
8659
0
    if (pid == -1) {
8660
0
        errno = saved_errno;
8661
0
        return posix_error();
8662
0
    }
8663
0
    return PyLong_FromPid(pid);
8664
0
}
8665
#endif /* HAVE_FORK */
8666
8667
8668
#ifdef HAVE_SCHED_H
8669
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8670
/*[clinic input]
8671
os.sched_get_priority_max
8672
8673
    policy: int
8674
8675
Get the maximum scheduling priority for policy.
8676
[clinic start generated code]*/
8677
8678
static PyObject *
8679
os_sched_get_priority_max_impl(PyObject *module, int policy)
8680
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8681
0
{
8682
    /* make sure that errno is cleared before the call */
8683
0
    errno = 0;
8684
0
    int max = sched_get_priority_max(policy);
8685
0
    if (max == -1 && errno)
8686
0
        return posix_error();
8687
0
    return PyLong_FromLong(max);
8688
0
}
8689
8690
8691
/*[clinic input]
8692
os.sched_get_priority_min
8693
8694
    policy: int
8695
8696
Get the minimum scheduling priority for policy.
8697
[clinic start generated code]*/
8698
8699
static PyObject *
8700
os_sched_get_priority_min_impl(PyObject *module, int policy)
8701
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8702
0
{
8703
    /* make sure that errno is cleared before the call */
8704
0
    errno = 0;
8705
0
    int min = sched_get_priority_min(policy);
8706
0
    if (min == -1 && errno)
8707
0
        return posix_error();
8708
0
    return PyLong_FromLong(min);
8709
0
}
8710
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8711
8712
8713
#ifdef HAVE_SCHED_SETSCHEDULER
8714
/*[clinic input]
8715
os.sched_getscheduler
8716
    pid: pid_t
8717
    /
8718
8719
Get the scheduling policy for the process identified by pid.
8720
8721
Passing 0 for pid returns the scheduling policy for the calling process.
8722
[clinic start generated code]*/
8723
8724
static PyObject *
8725
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8726
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8727
0
{
8728
0
    int policy;
8729
8730
0
    policy = sched_getscheduler(pid);
8731
0
    if (policy < 0)
8732
0
        return posix_error();
8733
0
    return PyLong_FromLong(policy);
8734
0
}
8735
#endif /* HAVE_SCHED_SETSCHEDULER */
8736
8737
8738
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8739
/*[clinic input]
8740
class os.sched_param "PyObject *" "SchedParamType"
8741
8742
@classmethod
8743
os.sched_param.__new__
8744
8745
    sched_priority: object
8746
        A scheduling parameter.
8747
8748
Currently has only one field: sched_priority
8749
[clinic start generated code]*/
8750
8751
static PyObject *
8752
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8753
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8754
0
{
8755
0
    PyObject *res;
8756
8757
0
    res = PyStructSequence_New(type);
8758
0
    if (!res)
8759
0
        return NULL;
8760
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8761
0
    return res;
8762
0
}
8763
8764
static PyObject *
8765
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8766
0
{
8767
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8768
0
}
8769
8770
static PyMethodDef os_sched_param_reduce_method = {
8771
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8772
};
8773
8774
PyDoc_VAR(os_sched_param__doc__);
8775
8776
static PyStructSequence_Field sched_param_fields[] = {
8777
    {"sched_priority", "the scheduling priority"},
8778
    {0}
8779
};
8780
8781
static PyStructSequence_Desc sched_param_desc = {
8782
    MODNAME ".sched_param", /* name */
8783
    os_sched_param__doc__, /* doc */
8784
    sched_param_fields,
8785
    1
8786
};
8787
8788
static int
8789
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8790
0
{
8791
0
    long priority;
8792
8793
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8794
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8795
0
        return 0;
8796
0
    }
8797
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8798
0
    if (priority == -1 && PyErr_Occurred())
8799
0
        return 0;
8800
0
    if (priority > INT_MAX || priority < INT_MIN) {
8801
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8802
0
        return 0;
8803
0
    }
8804
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8805
0
    return 1;
8806
0
}
8807
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8808
8809
8810
#ifdef HAVE_SCHED_SETSCHEDULER
8811
/*[clinic input]
8812
os.sched_setscheduler
8813
8814
    pid: pid_t
8815
    policy: int
8816
    param as param_obj: object
8817
    /
8818
8819
Set the scheduling policy for the process identified by pid.
8820
8821
If pid is 0, the calling process is changed.
8822
param is an instance of sched_param.
8823
[clinic start generated code]*/
8824
8825
static PyObject *
8826
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8827
                           PyObject *param_obj)
8828
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8829
0
{
8830
0
    struct sched_param param;
8831
0
    if (!convert_sched_param(module, param_obj, &param)) {
8832
0
        return NULL;
8833
0
    }
8834
8835
    /*
8836
    ** sched_setscheduler() returns 0 in Linux, but the previous
8837
    ** scheduling policy under Solaris/Illumos, and others.
8838
    ** On error, -1 is returned in all Operating Systems.
8839
    */
8840
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8841
0
        return posix_error();
8842
0
    Py_RETURN_NONE;
8843
0
}
8844
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8845
8846
8847
#ifdef HAVE_SCHED_SETPARAM
8848
/*[clinic input]
8849
os.sched_getparam
8850
    pid: pid_t
8851
    /
8852
8853
Returns scheduling parameters for the process identified by pid.
8854
8855
If pid is 0, returns parameters for the calling process.
8856
Return value is an instance of sched_param.
8857
[clinic start generated code]*/
8858
8859
static PyObject *
8860
os_sched_getparam_impl(PyObject *module, pid_t pid)
8861
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8862
0
{
8863
0
    struct sched_param param;
8864
0
    PyObject *result;
8865
0
    PyObject *priority;
8866
8867
0
    if (sched_getparam(pid, &param))
8868
0
        return posix_error();
8869
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8870
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8871
0
    if (!result)
8872
0
        return NULL;
8873
0
    priority = PyLong_FromLong(param.sched_priority);
8874
0
    if (!priority) {
8875
0
        Py_DECREF(result);
8876
0
        return NULL;
8877
0
    }
8878
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8879
0
    return result;
8880
0
}
8881
8882
8883
/*[clinic input]
8884
os.sched_setparam
8885
    pid: pid_t
8886
    param as param_obj: object
8887
    /
8888
8889
Set scheduling parameters for the process identified by pid.
8890
8891
If pid is 0, sets parameters for the calling process.
8892
param should be an instance of sched_param.
8893
[clinic start generated code]*/
8894
8895
static PyObject *
8896
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8897
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8898
0
{
8899
0
    struct sched_param param;
8900
0
    if (!convert_sched_param(module, param_obj, &param)) {
8901
0
        return NULL;
8902
0
    }
8903
8904
0
    if (sched_setparam(pid, &param))
8905
0
        return posix_error();
8906
0
    Py_RETURN_NONE;
8907
0
}
8908
#endif /* HAVE_SCHED_SETPARAM */
8909
8910
8911
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8912
/*[clinic input]
8913
@permit_long_summary
8914
os.sched_rr_get_interval -> double
8915
    pid: pid_t
8916
    /
8917
8918
Return the round-robin quantum for the process identified by pid, in seconds.
8919
8920
Value returned is a float.
8921
[clinic start generated code]*/
8922
8923
static double
8924
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8925
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8926
0
{
8927
0
    struct timespec interval;
8928
0
    if (sched_rr_get_interval(pid, &interval)) {
8929
0
        posix_error();
8930
0
        return -1.0;
8931
0
    }
8932
#ifdef _Py_MEMORY_SANITIZER
8933
    __msan_unpoison(&interval, sizeof(interval));
8934
#endif
8935
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8936
0
}
8937
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8938
8939
8940
/*[clinic input]
8941
os.sched_yield
8942
8943
Voluntarily relinquish the CPU.
8944
[clinic start generated code]*/
8945
8946
static PyObject *
8947
os_sched_yield_impl(PyObject *module)
8948
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8949
0
{
8950
0
    int result;
8951
0
    Py_BEGIN_ALLOW_THREADS
8952
0
    result = sched_yield();
8953
0
    Py_END_ALLOW_THREADS
8954
0
    if (result < 0) {
8955
0
        return posix_error();
8956
0
    }
8957
0
    Py_RETURN_NONE;
8958
0
}
8959
8960
#ifdef HAVE_SCHED_SETAFFINITY
8961
/* The minimum number of CPUs allocated in a cpu_set_t */
8962
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8963
8964
/*[clinic input]
8965
os.sched_setaffinity
8966
    pid: pid_t
8967
    mask : object
8968
    /
8969
8970
Set the CPU affinity of the process identified by pid to mask.
8971
8972
mask should be an iterable of integers identifying CPUs.
8973
[clinic start generated code]*/
8974
8975
static PyObject *
8976
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8977
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8978
0
{
8979
0
    int ncpus;
8980
0
    size_t setsize;
8981
0
    cpu_set_t *cpu_set = NULL;
8982
0
    PyObject *iterator = NULL, *item;
8983
8984
0
    iterator = PyObject_GetIter(mask);
8985
0
    if (iterator == NULL)
8986
0
        return NULL;
8987
8988
0
    ncpus = NCPUS_START;
8989
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8990
0
    cpu_set = CPU_ALLOC(ncpus);
8991
0
    if (cpu_set == NULL) {
8992
0
        PyErr_NoMemory();
8993
0
        goto error;
8994
0
    }
8995
0
    CPU_ZERO_S(setsize, cpu_set);
8996
8997
0
    while ((item = PyIter_Next(iterator))) {
8998
0
        long cpu;
8999
0
        if (!PyIndex_Check(item)) {
9000
0
            PyErr_Format(PyExc_TypeError,
9001
0
                        "expected an iterator of ints, "
9002
0
                        "but iterator yielded %R",
9003
0
                        Py_TYPE(item));
9004
0
            Py_DECREF(item);
9005
0
            goto error;
9006
0
        }
9007
0
        cpu = PyLong_AsLong(item);
9008
0
        Py_DECREF(item);
9009
0
        if (cpu < 0) {
9010
0
            if (!PyErr_Occurred())
9011
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9012
0
            goto error;
9013
0
        }
9014
0
        if (cpu > INT_MAX - 1) {
9015
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9016
0
            goto error;
9017
0
        }
9018
0
        if (cpu >= ncpus) {
9019
            /* Grow CPU mask to fit the CPU number */
9020
0
            int newncpus = ncpus;
9021
0
            cpu_set_t *newmask;
9022
0
            size_t newsetsize;
9023
0
            while (newncpus <= cpu) {
9024
0
                if (newncpus > INT_MAX / 2)
9025
0
                    newncpus = cpu + 1;
9026
0
                else
9027
0
                    newncpus = newncpus * 2;
9028
0
            }
9029
0
            newmask = CPU_ALLOC(newncpus);
9030
0
            if (newmask == NULL) {
9031
0
                PyErr_NoMemory();
9032
0
                goto error;
9033
0
            }
9034
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9035
0
            CPU_ZERO_S(newsetsize, newmask);
9036
0
            memcpy(newmask, cpu_set, setsize);
9037
0
            CPU_FREE(cpu_set);
9038
0
            setsize = newsetsize;
9039
0
            cpu_set = newmask;
9040
0
            ncpus = newncpus;
9041
0
        }
9042
0
        CPU_SET_S(cpu, setsize, cpu_set);
9043
0
    }
9044
0
    if (PyErr_Occurred()) {
9045
0
        goto error;
9046
0
    }
9047
0
    Py_CLEAR(iterator);
9048
9049
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9050
0
        posix_error();
9051
0
        goto error;
9052
0
    }
9053
0
    CPU_FREE(cpu_set);
9054
0
    Py_RETURN_NONE;
9055
9056
0
error:
9057
0
    if (cpu_set)
9058
0
        CPU_FREE(cpu_set);
9059
0
    Py_XDECREF(iterator);
9060
0
    return NULL;
9061
0
}
9062
9063
9064
/*[clinic input]
9065
@permit_long_summary
9066
os.sched_getaffinity
9067
    pid: pid_t
9068
    /
9069
9070
Return the affinity of the process identified by pid (or the current process if zero).
9071
9072
The affinity is returned as a set of CPU identifiers.
9073
[clinic start generated code]*/
9074
9075
static PyObject *
9076
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9077
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9078
0
{
9079
0
    int ncpus = NCPUS_START;
9080
0
    size_t setsize;
9081
0
    cpu_set_t *mask;
9082
9083
0
    while (1) {
9084
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9085
0
        mask = CPU_ALLOC(ncpus);
9086
0
        if (mask == NULL) {
9087
0
            return PyErr_NoMemory();
9088
0
        }
9089
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9090
0
            break;
9091
0
        }
9092
0
        CPU_FREE(mask);
9093
0
        if (errno != EINVAL) {
9094
0
            return posix_error();
9095
0
        }
9096
0
        if (ncpus > INT_MAX / 2) {
9097
0
            PyErr_SetString(PyExc_OverflowError,
9098
0
                            "could not allocate a large enough CPU set");
9099
0
            return NULL;
9100
0
        }
9101
0
        ncpus *= 2;
9102
0
    }
9103
9104
0
    PyObject *res = PySet_New(NULL);
9105
0
    if (res == NULL) {
9106
0
        goto error;
9107
0
    }
9108
9109
0
    int cpu = 0;
9110
0
    int count = CPU_COUNT_S(setsize, mask);
9111
0
    for (; count; cpu++) {
9112
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9113
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9114
0
            --count;
9115
0
            if (cpu_num == NULL) {
9116
0
                goto error;
9117
0
            }
9118
0
            if (PySet_Add(res, cpu_num)) {
9119
0
                Py_DECREF(cpu_num);
9120
0
                goto error;
9121
0
            }
9122
0
            Py_DECREF(cpu_num);
9123
0
        }
9124
0
    }
9125
0
    CPU_FREE(mask);
9126
0
    return res;
9127
9128
0
error:
9129
0
    if (mask) {
9130
0
        CPU_FREE(mask);
9131
0
    }
9132
0
    Py_XDECREF(res);
9133
0
    return NULL;
9134
0
}
9135
#endif /* HAVE_SCHED_SETAFFINITY */
9136
9137
#endif /* HAVE_SCHED_H */
9138
9139
9140
#ifdef HAVE_POSIX_OPENPT
9141
/*[clinic input]
9142
os.posix_openpt -> int
9143
9144
    oflag: int
9145
    /
9146
9147
Open and return a file descriptor for a master pseudo-terminal device.
9148
9149
Performs a posix_openpt() C function call. The oflag argument is used to
9150
set file status flags and file access modes as specified in the manual page
9151
of posix_openpt() of your system.
9152
[clinic start generated code]*/
9153
9154
static int
9155
os_posix_openpt_impl(PyObject *module, int oflag)
9156
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
9157
0
{
9158
0
    int fd;
9159
9160
0
#if defined(O_CLOEXEC)
9161
0
    oflag |= O_CLOEXEC;
9162
0
#endif
9163
9164
0
    fd = posix_openpt(oflag);
9165
0
    if (fd == -1) {
9166
0
        posix_error();
9167
0
        return -1;
9168
0
    }
9169
9170
    // Just in case, likely a no-op given O_CLOEXEC above.
9171
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9172
0
        close(fd);
9173
0
        return -1;
9174
0
    }
9175
9176
0
    return fd;
9177
0
}
9178
#endif /* HAVE_POSIX_OPENPT */
9179
9180
#ifdef HAVE_GRANTPT
9181
/*[clinic input]
9182
os.grantpt
9183
9184
    fd: fildes
9185
        File descriptor of a master pseudo-terminal device.
9186
    /
9187
9188
Grant access to the slave pseudo-terminal device.
9189
9190
Performs a grantpt() C function call.
9191
[clinic start generated code]*/
9192
9193
static PyObject *
9194
os_grantpt_impl(PyObject *module, int fd)
9195
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9196
0
{
9197
0
    int ret;
9198
0
    int saved_errno;
9199
0
    PyOS_sighandler_t sig_saved;
9200
9201
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9202
9203
0
    ret = grantpt(fd);
9204
0
    if (ret == -1)
9205
0
        saved_errno = errno;
9206
9207
0
    PyOS_setsig(SIGCHLD, sig_saved);
9208
9209
0
    if (ret == -1) {
9210
0
        errno = saved_errno;
9211
0
        return posix_error();
9212
0
    }
9213
9214
0
    Py_RETURN_NONE;
9215
0
}
9216
#endif /* HAVE_GRANTPT */
9217
9218
#ifdef HAVE_UNLOCKPT
9219
/*[clinic input]
9220
os.unlockpt
9221
9222
    fd: fildes
9223
        File descriptor of a master pseudo-terminal device.
9224
    /
9225
9226
Unlock a pseudo-terminal master/slave pair.
9227
9228
Performs an unlockpt() C function call.
9229
[clinic start generated code]*/
9230
9231
static PyObject *
9232
os_unlockpt_impl(PyObject *module, int fd)
9233
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9234
0
{
9235
0
    if (unlockpt(fd) == -1)
9236
0
        return posix_error();
9237
9238
0
    Py_RETURN_NONE;
9239
0
}
9240
#endif /* HAVE_UNLOCKPT */
9241
9242
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9243
static PyObject *
9244
py_ptsname(int fd)
9245
0
{
9246
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9247
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9248
0
    errno = 0;
9249
0
    char *name = ptsname(fd);
9250
0
    if (name == NULL) {
9251
0
        return posix_error();
9252
0
    }
9253
0
    return PyUnicode_DecodeFSDefault(name);
9254
0
}
9255
9256
/*[clinic input]
9257
os.ptsname
9258
9259
    fd: fildes
9260
        File descriptor of a master pseudo-terminal device.
9261
    /
9262
9263
Return the name of the slave pseudo-terminal device.
9264
9265
If the ptsname_r() C function is available, it is called;
9266
otherwise, performs a ptsname() C function call.
9267
[clinic start generated code]*/
9268
9269
static PyObject *
9270
os_ptsname_impl(PyObject *module, int fd)
9271
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9272
0
{
9273
0
#ifdef HAVE_PTSNAME_R
9274
0
    int ret;
9275
0
    char name[MAXPATHLEN+1];
9276
9277
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9278
0
        ret = ptsname_r(fd, name, sizeof(name));
9279
0
    }
9280
0
    else {
9281
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9282
0
        return py_ptsname(fd);
9283
0
    }
9284
0
    if (ret != 0) {
9285
0
        errno = ret;
9286
0
        return posix_error();
9287
0
    }
9288
9289
0
    return PyUnicode_DecodeFSDefault(name);
9290
#else
9291
    return py_ptsname(fd);
9292
#endif /* HAVE_PTSNAME_R */
9293
0
}
9294
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9295
9296
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9297
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9298
#  define DEV_PTY_FILE "/dev/ptc"
9299
#  define HAVE_DEV_PTMX
9300
#else
9301
#  define DEV_PTY_FILE "/dev/ptmx"
9302
#endif
9303
9304
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9305
#ifdef HAVE_PTY_H
9306
#include <pty.h>
9307
#elif defined(HAVE_LIBUTIL_H)
9308
#include <libutil.h>
9309
#elif defined(HAVE_UTIL_H)
9310
#include <util.h>
9311
#endif /* HAVE_PTY_H */
9312
#ifdef HAVE_UTMP_H
9313
#include <utmp.h>
9314
#endif /* HAVE_UTMP_H */
9315
#ifdef HAVE_STROPTS_H
9316
#include <stropts.h>
9317
#endif
9318
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9319
9320
9321
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9322
/*[clinic input]
9323
os.openpty
9324
9325
Open a pseudo-terminal.
9326
9327
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9328
for both the master and slave ends.
9329
[clinic start generated code]*/
9330
9331
static PyObject *
9332
os_openpty_impl(PyObject *module)
9333
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9334
0
{
9335
0
    int master_fd = -1, slave_fd = -1;
9336
#ifndef HAVE_OPENPTY
9337
    char * slave_name;
9338
#endif
9339
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9340
    PyOS_sighandler_t sig_saved;
9341
#if defined(__sun) && defined(__SVR4)
9342
    extern char *ptsname(int fildes);
9343
#endif
9344
#endif
9345
9346
0
#ifdef HAVE_OPENPTY
9347
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9348
0
        goto posix_error;
9349
9350
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9351
0
        goto error;
9352
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9353
0
        goto error;
9354
9355
#elif defined(HAVE__GETPTY)
9356
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9357
    if (slave_name == NULL)
9358
        goto posix_error;
9359
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9360
        goto error;
9361
9362
    slave_fd = _Py_open(slave_name, O_RDWR);
9363
    if (slave_fd < 0)
9364
        goto error;
9365
9366
#else
9367
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9368
    if (master_fd < 0)
9369
        goto posix_error;
9370
9371
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9372
9373
    /* change permission of slave */
9374
    if (grantpt(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
    /* unlock slave */
9382
    if (unlockpt(master_fd) < 0) {
9383
        int saved_errno = errno;
9384
        PyOS_setsig(SIGCHLD, sig_saved);
9385
        errno = saved_errno;
9386
        goto posix_error;
9387
    }
9388
9389
    PyOS_setsig(SIGCHLD, sig_saved);
9390
9391
    slave_name = ptsname(master_fd); /* get name of slave */
9392
    if (slave_name == NULL)
9393
        goto posix_error;
9394
9395
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9396
    if (slave_fd == -1)
9397
        goto error;
9398
9399
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9400
        goto posix_error;
9401
9402
#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC)
9403
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9404
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9405
#ifndef __hpux
9406
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9407
#endif /* __hpux */
9408
#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
9409
#endif /* HAVE_OPENPTY */
9410
9411
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9412
9413
0
posix_error:
9414
0
    posix_error();
9415
0
error:
9416
0
    if (master_fd != -1)
9417
0
        close(master_fd);
9418
0
    if (slave_fd != -1)
9419
0
        close(slave_fd);
9420
0
    return NULL;
9421
0
}
9422
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9423
9424
9425
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9426
#define HAVE_FALLBACK_LOGIN_TTY 1
9427
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9428
9429
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9430
/*[clinic input]
9431
os.login_tty
9432
9433
    fd: fildes
9434
    /
9435
9436
Prepare the tty of which fd is a file descriptor for a new login session.
9437
9438
Make the calling process a session leader; make the tty the
9439
controlling tty, the stdin, the stdout, and the stderr of the
9440
calling process; close fd.
9441
[clinic start generated code]*/
9442
9443
static PyObject *
9444
os_login_tty_impl(PyObject *module, int fd)
9445
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
9446
0
{
9447
0
#ifdef HAVE_LOGIN_TTY
9448
0
    if (login_tty(fd) == -1) {
9449
0
        return posix_error();
9450
0
    }
9451
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9452
    /* Establish a new session. */
9453
    if (setsid() == -1) {
9454
        return posix_error();
9455
    }
9456
9457
    /* The tty becomes the controlling terminal. */
9458
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9459
        return posix_error();
9460
    }
9461
9462
    /* The tty becomes stdin/stdout/stderr */
9463
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9464
        return posix_error();
9465
    }
9466
    if (fd > 2) {
9467
        close(fd);
9468
    }
9469
#endif /* HAVE_LOGIN_TTY */
9470
0
    Py_RETURN_NONE;
9471
0
}
9472
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9473
9474
9475
#ifdef HAVE_FORKPTY
9476
/*[clinic input]
9477
os.forkpty
9478
9479
Fork a new process with a new pseudo-terminal as controlling tty.
9480
9481
Returns a tuple of (pid, master_fd).
9482
Like fork(), return pid of 0 to the child process,
9483
and pid of child to the parent process.
9484
To both, return fd of newly opened pseudo-terminal.
9485
The master_fd is non-inheritable.
9486
[clinic start generated code]*/
9487
9488
static PyObject *
9489
os_forkpty_impl(PyObject *module)
9490
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9491
0
{
9492
0
    int master_fd = -1;
9493
0
    pid_t pid;
9494
9495
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9496
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9497
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9498
0
                        "can't fork at interpreter shutdown");
9499
0
        return NULL;
9500
0
    }
9501
0
    if (!_Py_IsMainInterpreter(interp)) {
9502
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9503
0
        return NULL;
9504
0
    }
9505
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9506
0
        return NULL;
9507
0
    }
9508
0
    PyOS_BeforeFork();
9509
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9510
0
    if (pid == 0) {
9511
        /* child: this clobbers and resets the import lock. */
9512
0
        PyOS_AfterFork_Child();
9513
0
    } else {
9514
        // Called before AfterFork_Parent in case those hooks start threads.
9515
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9516
        /* parent: release the import lock. */
9517
0
        PyOS_AfterFork_Parent();
9518
        /* set O_CLOEXEC on master_fd */
9519
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9520
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9521
0
                                   "non-inheritable in forkpty()");
9522
0
        }
9523
9524
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9525
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9526
0
            return NULL;
9527
0
    }
9528
0
    if (pid == -1) {
9529
0
        return posix_error();
9530
0
    }
9531
9532
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9533
0
}
9534
#endif /* HAVE_FORKPTY */
9535
9536
9537
#ifdef HAVE_GETEGID
9538
/*[clinic input]
9539
os.getegid
9540
9541
Return the current process's effective group id.
9542
[clinic start generated code]*/
9543
9544
static PyObject *
9545
os_getegid_impl(PyObject *module)
9546
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9547
36
{
9548
36
    return _PyLong_FromGid(getegid());
9549
36
}
9550
#endif /* HAVE_GETEGID */
9551
9552
9553
#ifdef HAVE_GETEUID
9554
/*[clinic input]
9555
os.geteuid
9556
9557
Return the current process's effective user id.
9558
[clinic start generated code]*/
9559
9560
static PyObject *
9561
os_geteuid_impl(PyObject *module)
9562
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9563
36
{
9564
36
    return _PyLong_FromUid(geteuid());
9565
36
}
9566
#endif /* HAVE_GETEUID */
9567
9568
9569
#ifdef HAVE_GETGID
9570
/*[clinic input]
9571
os.getgid
9572
9573
Return the current process's group id.
9574
[clinic start generated code]*/
9575
9576
static PyObject *
9577
os_getgid_impl(PyObject *module)
9578
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9579
36
{
9580
36
    return _PyLong_FromGid(getgid());
9581
36
}
9582
#endif /* HAVE_GETGID */
9583
9584
9585
#if defined(HAVE_GETPID)
9586
/*[clinic input]
9587
os.getpid
9588
9589
Return the current process id.
9590
[clinic start generated code]*/
9591
9592
static PyObject *
9593
os_getpid_impl(PyObject *module)
9594
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9595
3.87k
{
9596
3.87k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9597
3.87k
    return PyLong_FromPid(getpid());
9598
#else
9599
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9600
#endif
9601
3.87k
}
9602
#endif /* defined(HAVE_GETPID) */
9603
9604
#ifdef NGROUPS_MAX
9605
0
#define MAX_GROUPS NGROUPS_MAX
9606
#else
9607
    /* defined to be 16 on Solaris7, so this should be a small number */
9608
#define MAX_GROUPS 64
9609
#endif
9610
9611
#ifdef HAVE_GETGROUPLIST
9612
9613
#ifdef __APPLE__
9614
/*[clinic input]
9615
os.getgrouplist
9616
9617
    user: str
9618
        username to lookup
9619
    group as basegid: int
9620
        base group id of the user
9621
    /
9622
9623
Returns a list of groups to which a user belongs.
9624
[clinic start generated code]*/
9625
9626
static PyObject *
9627
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9628
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9629
#else
9630
/*[clinic input]
9631
os.getgrouplist
9632
9633
    user: str
9634
        username to lookup
9635
    group as basegid: gid_t
9636
        base group id of the user
9637
    /
9638
9639
Returns a list of groups to which a user belongs.
9640
[clinic start generated code]*/
9641
9642
static PyObject *
9643
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9644
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9645
#endif
9646
0
{
9647
0
    int i, ngroups;
9648
0
    PyObject *list;
9649
#ifdef __APPLE__
9650
    int *groups;
9651
#else
9652
0
    gid_t *groups;
9653
0
#endif
9654
9655
    /*
9656
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9657
     * number of supplemental groups a users can belong to.
9658
     * We have to increment it by one because
9659
     * getgrouplist() returns both the supplemental groups
9660
     * and the primary group, i.e. all of the groups the
9661
     * user belongs to.
9662
     */
9663
0
    ngroups = 1 + MAX_GROUPS;
9664
9665
0
    while (1) {
9666
#ifdef __APPLE__
9667
        groups = PyMem_New(int, ngroups);
9668
#else
9669
0
        groups = PyMem_New(gid_t, ngroups);
9670
0
#endif
9671
0
        if (groups == NULL) {
9672
0
            return PyErr_NoMemory();
9673
0
        }
9674
9675
0
        int old_ngroups = ngroups;
9676
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9677
            /* Success */
9678
0
            break;
9679
0
        }
9680
9681
        /* getgrouplist() fails if the group list is too small */
9682
0
        PyMem_Free(groups);
9683
9684
0
        if (ngroups > old_ngroups) {
9685
            /* If the group list is too small, the glibc implementation of
9686
               getgrouplist() sets ngroups to the total number of groups and
9687
               returns -1. */
9688
0
        }
9689
0
        else {
9690
            /* Double the group list size */
9691
0
            if (ngroups > INT_MAX / 2) {
9692
0
                return PyErr_NoMemory();
9693
0
            }
9694
0
            ngroups *= 2;
9695
0
        }
9696
9697
        /* Retry getgrouplist() with a larger group list */
9698
0
    }
9699
9700
#ifdef _Py_MEMORY_SANITIZER
9701
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9702
    __msan_unpoison(&ngroups, sizeof(ngroups));
9703
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9704
#endif
9705
9706
0
    list = PyList_New(ngroups);
9707
0
    if (list == NULL) {
9708
0
        PyMem_Free(groups);
9709
0
        return NULL;
9710
0
    }
9711
9712
0
    for (i = 0; i < ngroups; i++) {
9713
#ifdef __APPLE__
9714
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9715
#else
9716
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9717
0
#endif
9718
0
        if (o == NULL) {
9719
0
            Py_DECREF(list);
9720
0
            PyMem_Free(groups);
9721
0
            return NULL;
9722
0
        }
9723
0
        PyList_SET_ITEM(list, i, o);
9724
0
    }
9725
9726
0
    PyMem_Free(groups);
9727
9728
0
    return list;
9729
0
}
9730
#endif /* HAVE_GETGROUPLIST */
9731
9732
9733
#ifdef HAVE_GETGROUPS
9734
/*[clinic input]
9735
os.getgroups
9736
9737
Return list of supplemental group IDs for the process.
9738
[clinic start generated code]*/
9739
9740
static PyObject *
9741
os_getgroups_impl(PyObject *module)
9742
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9743
0
{
9744
    // Call getgroups with length 0 to get the actual number of groups
9745
0
    int n = getgroups(0, NULL);
9746
0
    if (n < 0) {
9747
0
        return posix_error();
9748
0
    }
9749
9750
0
    if (n == 0) {
9751
0
        return PyList_New(0);
9752
0
    }
9753
9754
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9755
0
    if (grouplist == NULL) {
9756
0
        return PyErr_NoMemory();
9757
0
    }
9758
9759
0
    n = getgroups(n, grouplist);
9760
0
    if (n == -1) {
9761
0
        posix_error();
9762
0
        PyMem_Free(grouplist);
9763
0
        return NULL;
9764
0
    }
9765
9766
0
    PyObject *result = PyList_New(n);
9767
0
    if (result == NULL) {
9768
0
        goto error;
9769
0
    }
9770
9771
0
    for (int i = 0; i < n; ++i) {
9772
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9773
0
        if (group == NULL) {
9774
0
            goto error;
9775
0
        }
9776
0
        PyList_SET_ITEM(result, i, group);
9777
0
    }
9778
0
    PyMem_Free(grouplist);
9779
9780
0
    return result;
9781
9782
0
error:
9783
0
    PyMem_Free(grouplist);
9784
0
    Py_XDECREF(result);
9785
0
    return NULL;
9786
0
}
9787
#endif /* HAVE_GETGROUPS */
9788
9789
#ifdef HAVE_INITGROUPS
9790
#ifdef __APPLE__
9791
/*[clinic input]
9792
os.initgroups
9793
9794
    username as oname: unicode_fs_encoded
9795
    gid: int
9796
    /
9797
9798
Initialize the group access list.
9799
9800
Call the system initgroups() to initialize the group access list with all of
9801
the groups of which the specified username is a member, plus the specified
9802
group id.
9803
[clinic start generated code]*/
9804
9805
static PyObject *
9806
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9807
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9808
#else
9809
/*[clinic input]
9810
os.initgroups
9811
9812
    username as oname: unicode_fs_encoded
9813
    gid: gid_t
9814
    /
9815
9816
Initialize the group access list.
9817
9818
Call the system initgroups() to initialize the group access list with all of
9819
the groups of which the specified username is a member, plus the specified
9820
group id.
9821
[clinic start generated code]*/
9822
9823
static PyObject *
9824
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9825
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9826
#endif
9827
0
{
9828
0
    const char *username = PyBytes_AS_STRING(oname);
9829
9830
0
    if (initgroups(username, gid) == -1)
9831
0
        return PyErr_SetFromErrno(PyExc_OSError);
9832
9833
0
    Py_RETURN_NONE;
9834
0
}
9835
#endif /* HAVE_INITGROUPS */
9836
9837
9838
#ifdef HAVE_GETPGID
9839
/*[clinic input]
9840
os.getpgid
9841
9842
    pid: pid_t
9843
9844
Call the system call getpgid(), and return the result.
9845
[clinic start generated code]*/
9846
9847
static PyObject *
9848
os_getpgid_impl(PyObject *module, pid_t pid)
9849
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9850
0
{
9851
0
    pid_t pgid = getpgid(pid);
9852
0
    if (pgid < 0)
9853
0
        return posix_error();
9854
0
    return PyLong_FromPid(pgid);
9855
0
}
9856
#endif /* HAVE_GETPGID */
9857
9858
9859
#ifdef HAVE_GETPGRP
9860
/*[clinic input]
9861
os.getpgrp
9862
9863
Return the current process group id.
9864
[clinic start generated code]*/
9865
9866
static PyObject *
9867
os_getpgrp_impl(PyObject *module)
9868
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9869
0
{
9870
#ifdef GETPGRP_HAVE_ARG
9871
    return PyLong_FromPid(getpgrp(0));
9872
#else /* GETPGRP_HAVE_ARG */
9873
0
    return PyLong_FromPid(getpgrp());
9874
0
#endif /* GETPGRP_HAVE_ARG */
9875
0
}
9876
#endif /* HAVE_GETPGRP */
9877
9878
9879
#ifdef HAVE_SETPGRP
9880
/*[clinic input]
9881
os.setpgrp
9882
9883
Make the current process the leader of its process group.
9884
[clinic start generated code]*/
9885
9886
static PyObject *
9887
os_setpgrp_impl(PyObject *module)
9888
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9889
0
{
9890
#ifdef SETPGRP_HAVE_ARG
9891
    if (setpgrp(0, 0) < 0)
9892
#else /* SETPGRP_HAVE_ARG */
9893
0
    if (setpgrp() < 0)
9894
0
#endif /* SETPGRP_HAVE_ARG */
9895
0
        return posix_error();
9896
0
    Py_RETURN_NONE;
9897
0
}
9898
#endif /* HAVE_SETPGRP */
9899
9900
#ifdef HAVE_GETPPID
9901
9902
#ifdef MS_WINDOWS
9903
#include <winternl.h>
9904
#include <ProcessSnapshot.h>
9905
9906
// The structure definition in winternl.h may be incomplete.
9907
// This structure is the full version from the MSDN documentation.
9908
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9909
    NTSTATUS ExitStatus;
9910
    PVOID PebBaseAddress;
9911
    ULONG_PTR AffinityMask;
9912
    LONG BasePriority;
9913
    ULONG_PTR UniqueProcessId;
9914
    ULONG_PTR InheritedFromUniqueProcessId;
9915
} PROCESS_BASIC_INFORMATION_FULL;
9916
9917
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9918
    IN    HANDLE           ProcessHandle,
9919
    IN    PROCESSINFOCLASS ProcessInformationClass,
9920
    OUT   PVOID            ProcessInformation,
9921
    IN    ULONG            ProcessInformationLength,
9922
    OUT   PULONG           ReturnLength OPTIONAL);
9923
9924
// This function returns the process ID of the parent process.
9925
// Returns 0 on failure.
9926
static ULONG
9927
win32_getppid_fast(void)
9928
{
9929
    NTSTATUS status;
9930
    HMODULE ntdll;
9931
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9932
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9933
    static ULONG cached_ppid = 0;
9934
9935
    if (cached_ppid) {
9936
        // No need to query the kernel again.
9937
        return cached_ppid;
9938
    }
9939
9940
    ntdll = GetModuleHandleW(L"ntdll.dll");
9941
    if (!ntdll) {
9942
        return 0;
9943
    }
9944
9945
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9946
    if (!pNtQueryInformationProcess) {
9947
        return 0;
9948
    }
9949
9950
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9951
                                        ProcessBasicInformation,
9952
                                        &basic_information,
9953
                                        sizeof(basic_information),
9954
                                        NULL);
9955
9956
    if (!NT_SUCCESS(status)) {
9957
        return 0;
9958
    }
9959
9960
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9961
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9962
    // zero and (ULONG) -1.
9963
9964
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9965
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9966
    {
9967
        return 0;
9968
    }
9969
9970
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9971
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9972
    // process. This process ID will be correctly returned even if the parent process has
9973
    // exited or been terminated.
9974
9975
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9976
    return cached_ppid;
9977
}
9978
9979
static PyObject*
9980
win32_getppid(void)
9981
{
9982
    DWORD error;
9983
    PyObject* result = NULL;
9984
    HANDLE process = GetCurrentProcess();
9985
    HPSS snapshot = NULL;
9986
    ULONG pid;
9987
9988
    pid = win32_getppid_fast();
9989
    if (pid != 0) {
9990
        return PyLong_FromUnsignedLong(pid);
9991
    }
9992
9993
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9994
9995
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9996
    if (error != ERROR_SUCCESS) {
9997
        return PyErr_SetFromWindowsErr(error);
9998
    }
9999
10000
    PSS_PROCESS_INFORMATION info;
10001
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
10002
                             sizeof(info));
10003
    if (error == ERROR_SUCCESS) {
10004
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
10005
    }
10006
    else {
10007
        result = PyErr_SetFromWindowsErr(error);
10008
    }
10009
10010
    PssFreeSnapshot(process, snapshot);
10011
    return result;
10012
}
10013
#endif /*MS_WINDOWS*/
10014
10015
10016
/*[clinic input]
10017
os.getppid
10018
10019
Return the parent's process id.
10020
10021
If the parent process has already exited, Windows machines will still
10022
return its id; others systems will return the id of the 'init' process (1).
10023
[clinic start generated code]*/
10024
10025
static PyObject *
10026
os_getppid_impl(PyObject *module)
10027
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
10028
0
{
10029
#ifdef MS_WINDOWS
10030
    return win32_getppid();
10031
#else
10032
0
    return PyLong_FromPid(getppid());
10033
0
#endif
10034
0
}
10035
#endif /* HAVE_GETPPID */
10036
10037
10038
#ifdef HAVE_GETLOGIN
10039
/*[clinic input]
10040
os.getlogin
10041
10042
Return the actual login name.
10043
[clinic start generated code]*/
10044
10045
static PyObject *
10046
os_getlogin_impl(PyObject *module)
10047
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10048
0
{
10049
0
    PyObject *result = NULL;
10050
#ifdef MS_WINDOWS
10051
    wchar_t user_name[UNLEN + 1];
10052
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10053
10054
    if (GetUserNameW(user_name, &num_chars)) {
10055
        /* num_chars is the number of unicode chars plus null terminator */
10056
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10057
    }
10058
    else
10059
        result = PyErr_SetFromWindowsErr(GetLastError());
10060
#elif defined (HAVE_GETLOGIN_R)
10061
# if defined (HAVE_MAXLOGNAME)
10062
    char name[MAXLOGNAME + 1];
10063
# elif defined (HAVE_UT_NAMESIZE)
10064
    char name[UT_NAMESIZE + 1];
10065
# else
10066
    char name[256];
10067
# endif
10068
0
    int err = getlogin_r(name, sizeof(name));
10069
0
    if (err) {
10070
0
        int old_errno = errno;
10071
0
        errno = err;
10072
0
        posix_error();
10073
0
        errno = old_errno;
10074
0
    }
10075
0
    else {
10076
0
        result = PyUnicode_DecodeFSDefault(name);
10077
0
    }
10078
#else
10079
    char *name;
10080
    int old_errno = errno;
10081
10082
    errno = 0;
10083
    name = getlogin();
10084
    if (name == NULL) {
10085
        if (errno)
10086
            posix_error();
10087
        else
10088
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10089
    }
10090
    else
10091
        result = PyUnicode_DecodeFSDefault(name);
10092
    errno = old_errno;
10093
#endif
10094
0
    return result;
10095
0
}
10096
#endif /* HAVE_GETLOGIN */
10097
10098
10099
#ifdef HAVE_GETUID
10100
/*[clinic input]
10101
os.getuid
10102
10103
Return the current process's user id.
10104
[clinic start generated code]*/
10105
10106
static PyObject *
10107
os_getuid_impl(PyObject *module)
10108
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10109
36
{
10110
36
    return _PyLong_FromUid(getuid());
10111
36
}
10112
#endif /* HAVE_GETUID */
10113
10114
10115
#ifdef MS_WINDOWS
10116
#define HAVE_KILL
10117
#endif /* MS_WINDOWS */
10118
10119
#ifdef HAVE_KILL
10120
/*[clinic input]
10121
os.kill
10122
10123
    pid: pid_t
10124
    signal: Py_ssize_t
10125
    /
10126
10127
Kill a process with a signal.
10128
[clinic start generated code]*/
10129
10130
static PyObject *
10131
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10132
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10133
0
{
10134
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10135
0
        return NULL;
10136
0
    }
10137
0
#ifndef MS_WINDOWS
10138
0
    if (kill(pid, (int)signal) == -1) {
10139
0
        return posix_error();
10140
0
    }
10141
10142
    // Check immediately if the signal was sent to the current process.
10143
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10144
    // is cheap.
10145
0
    if (PyErr_CheckSignals()) {
10146
0
        return NULL;
10147
0
    }
10148
10149
0
    Py_RETURN_NONE;
10150
#else /* !MS_WINDOWS */
10151
    DWORD sig = (DWORD)signal;
10152
10153
#ifdef HAVE_WINDOWS_CONSOLE_IO
10154
    /* Console processes which share a common console can be sent CTRL+C or
10155
       CTRL+BREAK events, provided they handle said events. */
10156
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10157
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10158
            return PyErr_SetFromWindowsErr(0);
10159
        }
10160
        Py_RETURN_NONE;
10161
    }
10162
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10163
10164
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10165
       attempt to open and terminate the process. */
10166
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10167
    if (handle == NULL) {
10168
        return PyErr_SetFromWindowsErr(0);
10169
    }
10170
10171
    BOOL res = TerminateProcess(handle, sig);
10172
    CloseHandle(handle);
10173
    if (res == 0) {
10174
        return PyErr_SetFromWindowsErr(0);
10175
    }
10176
10177
    Py_RETURN_NONE;
10178
#endif /* !MS_WINDOWS */
10179
0
}
10180
#endif /* HAVE_KILL */
10181
10182
10183
#ifdef HAVE_KILLPG
10184
/*[clinic input]
10185
os.killpg
10186
10187
    pgid: pid_t
10188
    signal: int
10189
    /
10190
10191
Kill a process group with a signal.
10192
[clinic start generated code]*/
10193
10194
static PyObject *
10195
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10196
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10197
0
{
10198
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10199
0
        return NULL;
10200
0
    }
10201
    /* XXX some man pages make the `pgid` parameter an int, others
10202
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10203
       take the same type. Moreover, pid_t is always at least as wide as
10204
       int (else compilation of this module fails), which is safe. */
10205
0
    if (killpg(pgid, signal) == -1)
10206
0
        return posix_error();
10207
0
    Py_RETURN_NONE;
10208
0
}
10209
#endif /* HAVE_KILLPG */
10210
10211
10212
#ifdef HAVE_PLOCK
10213
#ifdef HAVE_SYS_LOCK_H
10214
#include <sys/lock.h>
10215
#endif
10216
10217
/*[clinic input]
10218
os.plock
10219
    op: int
10220
    /
10221
10222
Lock program segments into memory.");
10223
[clinic start generated code]*/
10224
10225
static PyObject *
10226
os_plock_impl(PyObject *module, int op)
10227
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10228
{
10229
    if (plock(op) == -1)
10230
        return posix_error();
10231
    Py_RETURN_NONE;
10232
}
10233
#endif /* HAVE_PLOCK */
10234
10235
10236
#ifdef HAVE_SETUID
10237
/*[clinic input]
10238
os.setuid
10239
10240
    uid: uid_t
10241
    /
10242
10243
Set the current process's user id.
10244
[clinic start generated code]*/
10245
10246
static PyObject *
10247
os_setuid_impl(PyObject *module, uid_t uid)
10248
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10249
0
{
10250
0
    if (setuid(uid) < 0)
10251
0
        return posix_error();
10252
0
    Py_RETURN_NONE;
10253
0
}
10254
#endif /* HAVE_SETUID */
10255
10256
10257
#ifdef HAVE_SETEUID
10258
/*[clinic input]
10259
os.seteuid
10260
10261
    euid: uid_t
10262
    /
10263
10264
Set the current process's effective user id.
10265
[clinic start generated code]*/
10266
10267
static PyObject *
10268
os_seteuid_impl(PyObject *module, uid_t euid)
10269
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10270
0
{
10271
0
    if (seteuid(euid) < 0)
10272
0
        return posix_error();
10273
0
    Py_RETURN_NONE;
10274
0
}
10275
#endif /* HAVE_SETEUID */
10276
10277
10278
#ifdef HAVE_SETEGID
10279
/*[clinic input]
10280
os.setegid
10281
10282
    egid: gid_t
10283
    /
10284
10285
Set the current process's effective group id.
10286
[clinic start generated code]*/
10287
10288
static PyObject *
10289
os_setegid_impl(PyObject *module, gid_t egid)
10290
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10291
0
{
10292
0
    if (setegid(egid) < 0)
10293
0
        return posix_error();
10294
0
    Py_RETURN_NONE;
10295
0
}
10296
#endif /* HAVE_SETEGID */
10297
10298
10299
#ifdef HAVE_SETREUID
10300
/*[clinic input]
10301
os.setreuid
10302
10303
    ruid: uid_t
10304
    euid: uid_t
10305
    /
10306
10307
Set the current process's real and effective user ids.
10308
[clinic start generated code]*/
10309
10310
static PyObject *
10311
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10312
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10313
0
{
10314
0
    if (setreuid(ruid, euid) < 0) {
10315
0
        return posix_error();
10316
0
    } else {
10317
0
        Py_RETURN_NONE;
10318
0
    }
10319
0
}
10320
#endif /* HAVE_SETREUID */
10321
10322
10323
#ifdef HAVE_SETREGID
10324
/*[clinic input]
10325
os.setregid
10326
10327
    rgid: gid_t
10328
    egid: gid_t
10329
    /
10330
10331
Set the current process's real and effective group ids.
10332
[clinic start generated code]*/
10333
10334
static PyObject *
10335
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10336
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10337
0
{
10338
0
    if (setregid(rgid, egid) < 0)
10339
0
        return posix_error();
10340
0
    Py_RETURN_NONE;
10341
0
}
10342
#endif /* HAVE_SETREGID */
10343
10344
10345
#ifdef HAVE_SETGID
10346
/*[clinic input]
10347
os.setgid
10348
    gid: gid_t
10349
    /
10350
10351
Set the current process's group id.
10352
[clinic start generated code]*/
10353
10354
static PyObject *
10355
os_setgid_impl(PyObject *module, gid_t gid)
10356
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10357
0
{
10358
0
    if (setgid(gid) < 0)
10359
0
        return posix_error();
10360
0
    Py_RETURN_NONE;
10361
0
}
10362
#endif /* HAVE_SETGID */
10363
10364
10365
#ifdef HAVE_SETGROUPS
10366
/*[clinic input]
10367
os.setgroups
10368
10369
    groups: object
10370
    /
10371
10372
Set the groups of the current process to list.
10373
[clinic start generated code]*/
10374
10375
static PyObject *
10376
os_setgroups(PyObject *module, PyObject *groups)
10377
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10378
0
{
10379
0
    if (!PySequence_Check(groups)) {
10380
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10381
0
        return NULL;
10382
0
    }
10383
0
    Py_ssize_t len = PySequence_Size(groups);
10384
0
    if (len < 0) {
10385
0
        return NULL;
10386
0
    }
10387
0
    if (len > MAX_GROUPS) {
10388
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10389
0
        return NULL;
10390
0
    }
10391
10392
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10393
0
    if (grouplist == NULL) {
10394
0
        PyErr_NoMemory();
10395
0
        return NULL;
10396
0
    }
10397
0
    for (Py_ssize_t i = 0; i < len; i++) {
10398
0
        PyObject *elem;
10399
0
        elem = PySequence_GetItem(groups, i);
10400
0
        if (!elem) {
10401
0
            PyMem_Free(grouplist);
10402
0
            return NULL;
10403
0
        }
10404
0
        if (!PyIndex_Check(elem)) {
10405
0
            PyErr_SetString(PyExc_TypeError,
10406
0
                            "groups must be integers");
10407
0
            Py_DECREF(elem);
10408
0
            PyMem_Free(grouplist);
10409
0
            return NULL;
10410
0
        } else {
10411
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10412
0
                Py_DECREF(elem);
10413
0
                PyMem_Free(grouplist);
10414
0
                return NULL;
10415
0
            }
10416
0
        }
10417
0
        Py_DECREF(elem);
10418
0
    }
10419
10420
0
    if (setgroups(len, grouplist) < 0) {
10421
0
        posix_error();
10422
0
        PyMem_Free(grouplist);
10423
0
        return NULL;
10424
0
    }
10425
0
    PyMem_Free(grouplist);
10426
0
    Py_RETURN_NONE;
10427
0
}
10428
#endif /* HAVE_SETGROUPS */
10429
10430
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10431
static PyObject *
10432
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10433
0
{
10434
0
    PyObject *result;
10435
0
    PyObject *struct_rusage;
10436
10437
0
    if (pid == -1)
10438
0
        return posix_error();
10439
10440
    // If wait succeeded but no child was ready to report status, ru will not
10441
    // have been populated.
10442
0
    if (pid == 0) {
10443
0
        memset(ru, 0, sizeof(*ru));
10444
0
    }
10445
10446
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10447
0
    if (struct_rusage == NULL)
10448
0
        return NULL;
10449
10450
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10451
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10452
0
    Py_DECREF(struct_rusage);
10453
0
    if (!result)
10454
0
        return NULL;
10455
10456
0
    int pos = 0;
10457
10458
0
#ifndef doubletime
10459
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10460
0
#endif
10461
10462
0
#define SET_RESULT(CALL)                                     \
10463
0
    do {                                                     \
10464
0
        PyObject *item = (CALL);                             \
10465
0
        if (item == NULL) {                                  \
10466
0
            Py_DECREF(result);                               \
10467
0
            return NULL;                                     \
10468
0
        }                                                    \
10469
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10470
0
    } while(0)
10471
10472
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10473
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10474
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10475
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10476
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10477
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10478
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10479
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10480
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10481
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10482
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10483
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10484
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10485
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10486
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10487
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10488
0
#undef SET_RESULT
10489
10490
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10491
0
}
10492
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10493
10494
10495
#ifdef HAVE_WAIT3
10496
/*[clinic input]
10497
os.wait3
10498
10499
    options: int
10500
Wait for completion of a child process.
10501
10502
Returns a tuple of information about the child process:
10503
  (pid, status, rusage)
10504
[clinic start generated code]*/
10505
10506
static PyObject *
10507
os_wait3_impl(PyObject *module, int options)
10508
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10509
0
{
10510
0
    pid_t pid;
10511
0
    struct rusage ru;
10512
0
    int async_err = 0;
10513
0
    WAIT_TYPE status;
10514
0
    WAIT_STATUS_INT(status) = 0;
10515
10516
0
    do {
10517
0
        Py_BEGIN_ALLOW_THREADS
10518
0
        pid = wait3(&status, options, &ru);
10519
0
        Py_END_ALLOW_THREADS
10520
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10521
0
    if (pid < 0)
10522
0
        return (!async_err) ? posix_error() : NULL;
10523
10524
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10525
0
}
10526
#endif /* HAVE_WAIT3 */
10527
10528
10529
#ifdef HAVE_WAIT4
10530
/*[clinic input]
10531
10532
os.wait4
10533
10534
    pid: pid_t
10535
    options: int
10536
10537
Wait for completion of a specific child process.
10538
10539
Returns a tuple of information about the child process:
10540
  (pid, status, rusage)
10541
[clinic start generated code]*/
10542
10543
static PyObject *
10544
os_wait4_impl(PyObject *module, pid_t pid, int options)
10545
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10546
0
{
10547
0
    pid_t res;
10548
0
    struct rusage ru;
10549
0
    int async_err = 0;
10550
0
    WAIT_TYPE status;
10551
0
    WAIT_STATUS_INT(status) = 0;
10552
10553
0
    do {
10554
0
        Py_BEGIN_ALLOW_THREADS
10555
0
        res = wait4(pid, &status, options, &ru);
10556
0
        Py_END_ALLOW_THREADS
10557
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10558
0
    if (res < 0)
10559
0
        return (!async_err) ? posix_error() : NULL;
10560
10561
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10562
0
}
10563
#endif /* HAVE_WAIT4 */
10564
10565
10566
#if defined(HAVE_WAITID)
10567
/*[clinic input]
10568
os.waitid
10569
10570
    idtype: idtype_t
10571
        Must be one of be P_PID, P_PGID or P_ALL.
10572
    id: id_t
10573
        The id to wait on.
10574
    options: int
10575
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10576
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10577
    /
10578
10579
Returns the result of waiting for a process or processes.
10580
10581
Returns either waitid_result or None if WNOHANG is specified and there are
10582
no children in a waitable state.
10583
[clinic start generated code]*/
10584
10585
static PyObject *
10586
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10587
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10588
0
{
10589
0
    PyObject *result;
10590
0
    int res;
10591
0
    int async_err = 0;
10592
0
    siginfo_t si;
10593
0
    si.si_pid = 0;
10594
10595
0
    do {
10596
0
        Py_BEGIN_ALLOW_THREADS
10597
0
        res = waitid(idtype, id, &si, options);
10598
0
        Py_END_ALLOW_THREADS
10599
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10600
0
    if (res < 0)
10601
0
        return (!async_err) ? posix_error() : NULL;
10602
10603
0
    if (si.si_pid == 0)
10604
0
        Py_RETURN_NONE;
10605
10606
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10607
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10608
0
    if (!result)
10609
0
        return NULL;
10610
10611
0
    int pos = 0;
10612
10613
0
#define SET_RESULT(CALL)                                     \
10614
0
    do {                                                     \
10615
0
        PyObject *item = (CALL);                             \
10616
0
        if (item == NULL) {                                  \
10617
0
            Py_DECREF(result);                               \
10618
0
            return NULL;                                     \
10619
0
        }                                                    \
10620
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10621
0
    } while(0)
10622
10623
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10624
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10625
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10626
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10627
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10628
10629
0
#undef SET_RESULT
10630
10631
0
    return result;
10632
0
}
10633
#endif /* defined(HAVE_WAITID) */
10634
10635
10636
#if defined(HAVE_WAITPID)
10637
/*[clinic input]
10638
os.waitpid
10639
    pid: pid_t
10640
    options: int
10641
    /
10642
10643
Wait for completion of a given child process.
10644
10645
Returns a tuple of information regarding the child process:
10646
    (pid, status)
10647
10648
The options argument is ignored on Windows.
10649
[clinic start generated code]*/
10650
10651
static PyObject *
10652
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10653
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10654
0
{
10655
0
    pid_t res;
10656
0
    int async_err = 0;
10657
0
    WAIT_TYPE status;
10658
0
    WAIT_STATUS_INT(status) = 0;
10659
10660
0
    do {
10661
0
        Py_BEGIN_ALLOW_THREADS
10662
0
        res = waitpid(pid, &status, options);
10663
0
        Py_END_ALLOW_THREADS
10664
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10665
0
    if (res < 0)
10666
0
        return (!async_err) ? posix_error() : NULL;
10667
10668
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10669
0
}
10670
#elif defined(HAVE_CWAIT)
10671
/* MS C has a variant of waitpid() that's usable for most purposes. */
10672
/*[clinic input]
10673
os.waitpid
10674
    pid: intptr_t
10675
    options: int
10676
    /
10677
10678
Wait for completion of a given process.
10679
10680
Returns a tuple of information regarding the process:
10681
    (pid, status << 8)
10682
10683
The options argument is ignored on Windows.
10684
[clinic start generated code]*/
10685
10686
static PyObject *
10687
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10688
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10689
{
10690
    int status;
10691
    intptr_t res;
10692
    int async_err = 0;
10693
10694
    do {
10695
        Py_BEGIN_ALLOW_THREADS
10696
        _Py_BEGIN_SUPPRESS_IPH
10697
        res = _cwait(&status, pid, options);
10698
        _Py_END_SUPPRESS_IPH
10699
        Py_END_ALLOW_THREADS
10700
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10701
    if (res < 0)
10702
        return (!async_err) ? posix_error() : NULL;
10703
10704
    unsigned long long ustatus = (unsigned int)status;
10705
10706
    /* shift the status left a byte so this is more like the POSIX waitpid */
10707
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10708
}
10709
#endif
10710
10711
10712
#ifdef HAVE_WAIT
10713
/*[clinic input]
10714
os.wait
10715
10716
Wait for completion of a child process.
10717
10718
Returns a tuple of information about the child process:
10719
    (pid, status)
10720
[clinic start generated code]*/
10721
10722
static PyObject *
10723
os_wait_impl(PyObject *module)
10724
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10725
0
{
10726
0
    pid_t pid;
10727
0
    int async_err = 0;
10728
0
    WAIT_TYPE status;
10729
0
    WAIT_STATUS_INT(status) = 0;
10730
10731
0
    do {
10732
0
        Py_BEGIN_ALLOW_THREADS
10733
0
        pid = wait(&status);
10734
0
        Py_END_ALLOW_THREADS
10735
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10736
0
    if (pid < 0)
10737
0
        return (!async_err) ? posix_error() : NULL;
10738
10739
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10740
0
}
10741
#endif /* HAVE_WAIT */
10742
10743
10744
// This system call always crashes on older Android versions.
10745
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10746
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10747
/*[clinic input]
10748
os.pidfd_open
10749
  pid: pid_t
10750
  flags: unsigned_int = 0
10751
10752
Return a file descriptor referring to the process *pid*.
10753
10754
The descriptor can be used to perform process management without races and
10755
signals.
10756
[clinic start generated code]*/
10757
10758
static PyObject *
10759
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10760
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10761
4
{
10762
4
    int fd = syscall(__NR_pidfd_open, pid, flags);
10763
4
    if (fd < 0) {
10764
0
        return posix_error();
10765
0
    }
10766
4
    return PyLong_FromLong(fd);
10767
4
}
10768
#endif
10769
10770
10771
#ifdef HAVE_SETNS
10772
/*[clinic input]
10773
os.setns
10774
  fd: fildes
10775
    A file descriptor to a namespace.
10776
  nstype: int = 0
10777
    Type of namespace.
10778
10779
Move the calling thread into different namespaces.
10780
[clinic start generated code]*/
10781
10782
static PyObject *
10783
os_setns_impl(PyObject *module, int fd, int nstype)
10784
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10785
0
{
10786
0
    int res;
10787
10788
0
    Py_BEGIN_ALLOW_THREADS
10789
0
    res = setns(fd, nstype);
10790
0
    Py_END_ALLOW_THREADS
10791
10792
0
    if (res != 0) {
10793
0
        return posix_error();
10794
0
    }
10795
10796
0
    Py_RETURN_NONE;
10797
0
}
10798
#endif
10799
10800
10801
#ifdef HAVE_UNSHARE
10802
/*[clinic input]
10803
os.unshare
10804
  flags: int
10805
    Namespaces to be unshared.
10806
10807
Disassociate parts of a process (or thread) execution context.
10808
[clinic start generated code]*/
10809
10810
static PyObject *
10811
os_unshare_impl(PyObject *module, int flags)
10812
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10813
0
{
10814
0
    int res;
10815
10816
0
    Py_BEGIN_ALLOW_THREADS
10817
0
    res = unshare(flags);
10818
0
    Py_END_ALLOW_THREADS
10819
10820
0
    if (res != 0) {
10821
0
        return posix_error();
10822
0
    }
10823
10824
0
    Py_RETURN_NONE;
10825
0
}
10826
#endif
10827
10828
10829
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10830
/*[clinic input]
10831
os.readlink
10832
10833
    path: path_t
10834
    *
10835
    dir_fd: dir_fd(requires='readlinkat') = None
10836
10837
Return a string representing the path to which the symbolic link points.
10838
10839
If dir_fd is not None, it should be a file descriptor open to a directory,
10840
and path should be relative; path will then be relative to that directory.
10841
10842
dir_fd may not be implemented on your platform.  If it is unavailable,
10843
using it will raise a NotImplementedError.
10844
[clinic start generated code]*/
10845
10846
static PyObject *
10847
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10848
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10849
6
{
10850
6
#if defined(HAVE_READLINK)
10851
6
    char buffer[MAXPATHLEN+1];
10852
6
    ssize_t length;
10853
6
#ifdef HAVE_READLINKAT
10854
6
    int readlinkat_unavailable = 0;
10855
6
#endif
10856
10857
6
    Py_BEGIN_ALLOW_THREADS
10858
6
#ifdef HAVE_READLINKAT
10859
6
    if (dir_fd != DEFAULT_DIR_FD) {
10860
0
        if (HAVE_READLINKAT_RUNTIME) {
10861
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10862
0
        } else {
10863
0
            readlinkat_unavailable = 1;
10864
0
        }
10865
0
    } else
10866
6
#endif
10867
6
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10868
6
    Py_END_ALLOW_THREADS
10869
10870
6
#ifdef HAVE_READLINKAT
10871
6
    if (readlinkat_unavailable) {
10872
0
        argument_unavailable_error(NULL, "dir_fd");
10873
0
        return NULL;
10874
0
    }
10875
6
#endif
10876
10877
6
    if (length < 0) {
10878
0
        return path_error(path);
10879
0
    }
10880
6
    buffer[length] = '\0';
10881
10882
6
    if (PyUnicode_Check(path->object))
10883
6
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10884
0
    else
10885
0
        return PyBytes_FromStringAndSize(buffer, length);
10886
#elif defined(MS_WINDOWS)
10887
    DWORD n_bytes_returned;
10888
    DWORD io_result = 0;
10889
    HANDLE reparse_point_handle;
10890
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10891
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10892
    PyObject *result = NULL;
10893
10894
    /* First get a handle to the reparse point */
10895
    Py_BEGIN_ALLOW_THREADS
10896
    reparse_point_handle = CreateFileW(
10897
        path->wide,
10898
        0,
10899
        0,
10900
        0,
10901
        OPEN_EXISTING,
10902
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10903
        0);
10904
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10905
        /* New call DeviceIoControl to read the reparse point */
10906
        io_result = DeviceIoControl(
10907
            reparse_point_handle,
10908
            FSCTL_GET_REPARSE_POINT,
10909
            0, 0, /* in buffer */
10910
            target_buffer, sizeof(target_buffer),
10911
            &n_bytes_returned,
10912
            0 /* we're not using OVERLAPPED_IO */
10913
            );
10914
        CloseHandle(reparse_point_handle);
10915
    }
10916
    Py_END_ALLOW_THREADS
10917
10918
    if (io_result == 0) {
10919
        return path_error(path);
10920
    }
10921
10922
    wchar_t *name = NULL;
10923
    Py_ssize_t nameLen = 0;
10924
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10925
    {
10926
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10927
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10928
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10929
    }
10930
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10931
    {
10932
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10933
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10934
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10935
    }
10936
    else
10937
    {
10938
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10939
    }
10940
    if (name) {
10941
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10942
            /* Our buffer is mutable, so this is okay */
10943
            name[1] = L'\\';
10944
        }
10945
        result = PyUnicode_FromWideChar(name, nameLen);
10946
        if (result && PyBytes_Check(path->object)) {
10947
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10948
        }
10949
    }
10950
    return result;
10951
#endif
10952
6
}
10953
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10954
10955
#if defined(MS_WINDOWS)
10956
10957
/* Remove the last portion of the path - return 0 on success */
10958
static int
10959
_dirnameW(WCHAR *path)
10960
{
10961
    WCHAR *ptr;
10962
    size_t length = wcsnlen_s(path, MAX_PATH);
10963
    if (length == MAX_PATH) {
10964
        return -1;
10965
    }
10966
10967
    /* walk the path from the end until a backslash is encountered */
10968
    for(ptr = path + length; ptr != path; ptr--) {
10969
        if (*ptr == L'\\' || *ptr == L'/') {
10970
            break;
10971
        }
10972
    }
10973
    *ptr = 0;
10974
    return 0;
10975
}
10976
10977
#endif
10978
10979
#ifdef HAVE_SYMLINK
10980
10981
#if defined(MS_WINDOWS)
10982
10983
/* Is this path absolute? */
10984
static int
10985
_is_absW(const WCHAR *path)
10986
{
10987
    return path[0] == L'\\' || path[0] == L'/' ||
10988
        (path[0] && path[1] == L':');
10989
}
10990
10991
/* join root and rest with a backslash - return 0 on success */
10992
static int
10993
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10994
{
10995
    if (_is_absW(rest)) {
10996
        return wcscpy_s(dest_path, MAX_PATH, rest);
10997
    }
10998
10999
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
11000
        return -1;
11001
    }
11002
11003
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
11004
        return -1;
11005
    }
11006
11007
    return wcscat_s(dest_path, MAX_PATH, rest);
11008
}
11009
11010
/* Return True if the path at src relative to dest is a directory */
11011
static int
11012
_check_dirW(LPCWSTR src, LPCWSTR dest)
11013
{
11014
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11015
    WCHAR dest_parent[MAX_PATH];
11016
    WCHAR src_resolved[MAX_PATH] = L"";
11017
11018
    /* dest_parent = os.path.dirname(dest) */
11019
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11020
        _dirnameW(dest_parent)) {
11021
        return 0;
11022
    }
11023
    /* src_resolved = os.path.join(dest_parent, src) */
11024
    if (_joinW(src_resolved, dest_parent, src)) {
11025
        return 0;
11026
    }
11027
    return (
11028
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11029
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11030
    );
11031
}
11032
#endif
11033
11034
11035
/*[clinic input]
11036
os.symlink
11037
    src: path_t
11038
    dst: path_t
11039
    target_is_directory: bool = False
11040
    *
11041
    dir_fd: dir_fd(requires='symlinkat')=None
11042
11043
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
11044
11045
Create a symbolic link pointing to src named dst.
11046
11047
target_is_directory is required on Windows if the target is to be
11048
  interpreted as a directory.  (On Windows, symlink requires
11049
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
11050
  target_is_directory is ignored on non-Windows platforms.
11051
11052
If dir_fd is not None, it should be a file descriptor open to a directory,
11053
  and path should be relative; path will then be relative to that directory.
11054
dir_fd may not be implemented on your platform.
11055
  If it is unavailable, using it will raise a NotImplementedError.
11056
11057
[clinic start generated code]*/
11058
11059
static PyObject *
11060
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11061
                int target_is_directory, int dir_fd)
11062
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
11063
0
{
11064
#ifdef MS_WINDOWS
11065
    DWORD result;
11066
    DWORD flags = 0;
11067
11068
    /* Assumed true, set to false if detected to not be available. */
11069
    static int windows_has_symlink_unprivileged_flag = TRUE;
11070
#else
11071
0
    int result;
11072
0
#ifdef HAVE_SYMLINKAT
11073
0
    int symlinkat_unavailable = 0;
11074
0
#endif
11075
0
#endif
11076
11077
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11078
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11079
0
        return NULL;
11080
0
    }
11081
11082
#ifdef MS_WINDOWS
11083
11084
    if (windows_has_symlink_unprivileged_flag) {
11085
        /* Allow non-admin symlinks if system allows it. */
11086
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11087
    }
11088
11089
    Py_BEGIN_ALLOW_THREADS
11090
    _Py_BEGIN_SUPPRESS_IPH
11091
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11092
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11093
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11094
    }
11095
11096
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11097
    _Py_END_SUPPRESS_IPH
11098
    Py_END_ALLOW_THREADS
11099
11100
    if (windows_has_symlink_unprivileged_flag && !result &&
11101
        ERROR_INVALID_PARAMETER == GetLastError()) {
11102
11103
        Py_BEGIN_ALLOW_THREADS
11104
        _Py_BEGIN_SUPPRESS_IPH
11105
        /* This error might be caused by
11106
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11107
        Try again, and update windows_has_symlink_unprivileged_flag if we
11108
        are successful this time.
11109
11110
        NOTE: There is a risk of a race condition here if there are other
11111
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11112
        another process (or thread) changes that condition in between our
11113
        calls to CreateSymbolicLink.
11114
        */
11115
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11116
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11117
        _Py_END_SUPPRESS_IPH
11118
        Py_END_ALLOW_THREADS
11119
11120
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11121
            windows_has_symlink_unprivileged_flag = FALSE;
11122
        }
11123
    }
11124
11125
    if (!result)
11126
        return path_error2(src, dst);
11127
11128
#else
11129
11130
0
    Py_BEGIN_ALLOW_THREADS
11131
0
#ifdef HAVE_SYMLINKAT
11132
0
    if (dir_fd != DEFAULT_DIR_FD) {
11133
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11134
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11135
0
        } else {
11136
0
            symlinkat_unavailable = 1;
11137
0
        }
11138
0
    } else
11139
0
#endif
11140
0
        result = symlink(src->narrow, dst->narrow);
11141
0
    Py_END_ALLOW_THREADS
11142
11143
0
#ifdef HAVE_SYMLINKAT
11144
0
    if (symlinkat_unavailable) {
11145
0
          argument_unavailable_error(NULL, "dir_fd");
11146
0
          return NULL;
11147
0
    }
11148
0
#endif
11149
11150
0
    if (result)
11151
0
        return path_error2(src, dst);
11152
0
#endif
11153
11154
0
    Py_RETURN_NONE;
11155
0
}
11156
#endif /* HAVE_SYMLINK */
11157
11158
11159
static PyStructSequence_Field times_result_fields[] = {
11160
    {"user",    "user time"},
11161
    {"system",   "system time"},
11162
    {"children_user",    "user time of children"},
11163
    {"children_system",    "system time of children"},
11164
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11165
    {NULL}
11166
};
11167
11168
PyDoc_STRVAR(times_result__doc__,
11169
"times_result: Result from os.times().\n\n\
11170
This object may be accessed either as a tuple of\n\
11171
  (user, system, children_user, children_system, elapsed),\n\
11172
or via the attributes user, system, children_user, children_system,\n\
11173
and elapsed.\n\
11174
\n\
11175
See os.times for more information.");
11176
11177
static PyStructSequence_Desc times_result_desc = {
11178
    MODNAME ".times_result", /* name */
11179
    times_result__doc__, /* doc */
11180
    times_result_fields,
11181
    5
11182
};
11183
11184
static PyObject *
11185
build_times_result(PyObject *module, double user, double system,
11186
    double children_user, double children_system,
11187
    double elapsed)
11188
0
{
11189
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11190
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11191
0
    if (value == NULL)
11192
0
        return NULL;
11193
11194
0
#define SET(i, field) \
11195
0
    { \
11196
0
    PyObject *o = PyFloat_FromDouble(field); \
11197
0
    if (!o) { \
11198
0
        Py_DECREF(value); \
11199
0
        return NULL; \
11200
0
    } \
11201
0
    PyStructSequence_SET_ITEM(value, i, o); \
11202
0
    } \
11203
0
11204
0
    SET(0, user);
11205
0
    SET(1, system);
11206
0
    SET(2, children_user);
11207
0
    SET(3, children_system);
11208
0
    SET(4, elapsed);
11209
11210
0
#undef SET
11211
11212
0
    return value;
11213
0
}
11214
11215
11216
/*[clinic input]
11217
os.times
11218
11219
Return a collection containing process timing information.
11220
11221
The object returned behaves like a named tuple with these fields:
11222
  (utime, stime, cutime, cstime, elapsed_time)
11223
All fields are floating-point numbers.
11224
[clinic start generated code]*/
11225
11226
static PyObject *
11227
os_times_impl(PyObject *module)
11228
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11229
0
{
11230
#ifdef MS_WINDOWS
11231
    FILETIME create, exit, kernel, user;
11232
    HANDLE hProc;
11233
    hProc = GetCurrentProcess();
11234
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11235
    /* The fields of a FILETIME structure are the hi and lo part
11236
       of a 64-bit value expressed in 100 nanosecond units.
11237
       1e7 is one second in such units; 1e-7 the inverse.
11238
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11239
    */
11240
    return build_times_result(module,
11241
        (double)(user.dwHighDateTime*429.4967296 +
11242
                 user.dwLowDateTime*1e-7),
11243
        (double)(kernel.dwHighDateTime*429.4967296 +
11244
                 kernel.dwLowDateTime*1e-7),
11245
        (double)0,
11246
        (double)0,
11247
        (double)0);
11248
#else /* MS_WINDOWS */
11249
0
    _posixstate *state = get_posix_state(module);
11250
0
    long ticks_per_second = state->ticks_per_second;
11251
11252
0
    struct tms process;
11253
0
    clock_t elapsed;
11254
0
    errno = 0;
11255
0
    elapsed = times(&process);
11256
0
    if (elapsed == (clock_t) -1) {
11257
0
        return posix_error();
11258
0
    }
11259
11260
0
    return build_times_result(module,
11261
0
        (double)process.tms_utime / ticks_per_second,
11262
0
        (double)process.tms_stime / ticks_per_second,
11263
0
        (double)process.tms_cutime / ticks_per_second,
11264
0
        (double)process.tms_cstime / ticks_per_second,
11265
0
        (double)elapsed / ticks_per_second);
11266
0
#endif /* MS_WINDOWS */
11267
0
}
11268
11269
11270
#if defined(HAVE_TIMERFD_CREATE)
11271
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11272
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11273
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11274
11275
static PyObject *
11276
build_itimerspec(const struct itimerspec* curr_value)
11277
0
{
11278
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11279
0
                                                          curr_value->it_value.tv_nsec);
11280
0
    PyObject *value = PyFloat_FromDouble(_value);
11281
0
    if (value == NULL) {
11282
0
        return NULL;
11283
0
    }
11284
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11285
0
                                                   curr_value->it_interval.tv_nsec);
11286
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11287
0
    if (interval == NULL) {
11288
0
        Py_DECREF(value);
11289
0
        return NULL;
11290
0
    }
11291
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
11292
0
    Py_DECREF(interval);
11293
0
    Py_DECREF(value);
11294
0
    return tuple;
11295
0
}
11296
11297
static PyObject *
11298
build_itimerspec_ns(const struct itimerspec* curr_value)
11299
0
{
11300
0
    PyTime_t value, interval;
11301
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11302
0
        return NULL;
11303
0
    }
11304
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11305
0
        return NULL;
11306
0
    }
11307
0
    return Py_BuildValue("LL", value, interval);
11308
0
}
11309
11310
/*[clinic input]
11311
os.timerfd_create
11312
11313
    clockid: int
11314
        A valid clock ID constant as timer file descriptor.
11315
11316
        time.CLOCK_REALTIME
11317
        time.CLOCK_MONOTONIC
11318
        time.CLOCK_BOOTTIME
11319
    /
11320
    *
11321
    flags: int = 0
11322
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11323
11324
        os.TFD_NONBLOCK
11325
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11326
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11327
11328
        os.TFD_CLOEXEC
11329
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11330
11331
Create and return a timer file descriptor.
11332
[clinic start generated code]*/
11333
11334
static PyObject *
11335
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11336
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11337
11338
0
{
11339
0
    int fd;
11340
0
    Py_BEGIN_ALLOW_THREADS
11341
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11342
0
    fd = timerfd_create(clockid, flags);
11343
0
    Py_END_ALLOW_THREADS
11344
0
    if (fd == -1) {
11345
0
        return PyErr_SetFromErrno(PyExc_OSError);
11346
0
    }
11347
0
    return PyLong_FromLong(fd);
11348
0
}
11349
11350
/*[clinic input]
11351
os.timerfd_settime
11352
11353
    fd: fildes
11354
        A timer file descriptor.
11355
    /
11356
    *
11357
    flags: int = 0
11358
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11359
    initial as initial_double: double = 0.0
11360
        The initial expiration time, in seconds.
11361
    interval as interval_double: double = 0.0
11362
        The timer's interval, in seconds.
11363
11364
Alter a timer file descriptor's internal timer in seconds.
11365
[clinic start generated code]*/
11366
11367
static PyObject *
11368
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11369
                        double initial_double, double interval_double)
11370
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11371
0
{
11372
0
    PyTime_t initial, interval;
11373
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11374
0
                                  &initial) < 0) {
11375
0
        return NULL;
11376
0
    }
11377
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11378
0
                                  &interval) < 0) {
11379
0
        return NULL;
11380
0
    }
11381
11382
0
    struct itimerspec new_value, old_value;
11383
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11384
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11385
0
        return NULL;
11386
0
    }
11387
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11388
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11389
0
        return NULL;
11390
0
    }
11391
11392
0
    int result;
11393
0
    Py_BEGIN_ALLOW_THREADS
11394
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11395
0
    Py_END_ALLOW_THREADS
11396
0
    if (result == -1) {
11397
0
        return PyErr_SetFromErrno(PyExc_OSError);
11398
0
    }
11399
0
    return build_itimerspec(&old_value);
11400
0
}
11401
11402
11403
/*[clinic input]
11404
os.timerfd_settime_ns
11405
11406
    fd: fildes
11407
        A timer file descriptor.
11408
    /
11409
    *
11410
    flags: int = 0
11411
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11412
    initial: long_long = 0
11413
        initial expiration timing in seconds.
11414
    interval: long_long = 0
11415
        interval for the timer in seconds.
11416
11417
Alter a timer file descriptor's internal timer in nanoseconds.
11418
[clinic start generated code]*/
11419
11420
static PyObject *
11421
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11422
                           long long initial, long long interval)
11423
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11424
0
{
11425
0
    struct itimerspec new_value;
11426
0
    struct itimerspec old_value;
11427
0
    int result;
11428
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11429
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11430
0
        return NULL;
11431
0
    }
11432
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11433
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11434
0
        return NULL;
11435
0
    }
11436
0
    Py_BEGIN_ALLOW_THREADS
11437
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11438
0
    Py_END_ALLOW_THREADS
11439
0
    if (result == -1) {
11440
0
        return PyErr_SetFromErrno(PyExc_OSError);
11441
0
    }
11442
0
    return build_itimerspec_ns(&old_value);
11443
0
}
11444
11445
/*[clinic input]
11446
@permit_long_summary
11447
os.timerfd_gettime
11448
11449
    fd: fildes
11450
        A timer file descriptor.
11451
    /
11452
11453
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11454
[clinic start generated code]*/
11455
11456
static PyObject *
11457
os_timerfd_gettime_impl(PyObject *module, int fd)
11458
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11459
0
{
11460
0
    struct itimerspec curr_value;
11461
0
    int result;
11462
0
    Py_BEGIN_ALLOW_THREADS
11463
0
    result = timerfd_gettime(fd, &curr_value);
11464
0
    Py_END_ALLOW_THREADS
11465
0
    if (result == -1) {
11466
0
        return PyErr_SetFromErrno(PyExc_OSError);
11467
0
    }
11468
0
    return build_itimerspec(&curr_value);
11469
0
}
11470
11471
11472
/*[clinic input]
11473
@permit_long_summary
11474
os.timerfd_gettime_ns
11475
11476
    fd: fildes
11477
        A timer file descriptor.
11478
    /
11479
11480
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11481
[clinic start generated code]*/
11482
11483
static PyObject *
11484
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11485
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11486
0
{
11487
0
    struct itimerspec curr_value;
11488
0
    int result;
11489
0
    Py_BEGIN_ALLOW_THREADS
11490
0
    result = timerfd_gettime(fd, &curr_value);
11491
0
    Py_END_ALLOW_THREADS
11492
0
    if (result == -1) {
11493
0
        return PyErr_SetFromErrno(PyExc_OSError);
11494
0
    }
11495
0
    return build_itimerspec_ns(&curr_value);
11496
0
}
11497
11498
#undef ONE_SECOND_IN_NS
11499
#undef EXTRACT_NSEC
11500
11501
#endif  /* HAVE_TIMERFD_CREATE */
11502
11503
#ifdef HAVE_GETSID
11504
/*[clinic input]
11505
os.getsid
11506
11507
    pid: pid_t
11508
    /
11509
11510
Call the system call getsid(pid) and return the result.
11511
[clinic start generated code]*/
11512
11513
static PyObject *
11514
os_getsid_impl(PyObject *module, pid_t pid)
11515
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11516
0
{
11517
0
    int sid;
11518
0
    sid = getsid(pid);
11519
0
    if (sid < 0)
11520
0
        return posix_error();
11521
0
    return PyLong_FromLong((long)sid);
11522
0
}
11523
#endif /* HAVE_GETSID */
11524
11525
11526
#ifdef HAVE_SETSID
11527
/*[clinic input]
11528
os.setsid
11529
11530
Call the system call setsid().
11531
[clinic start generated code]*/
11532
11533
static PyObject *
11534
os_setsid_impl(PyObject *module)
11535
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11536
0
{
11537
0
    if (setsid() < 0)
11538
0
        return posix_error();
11539
0
    Py_RETURN_NONE;
11540
0
}
11541
#endif /* HAVE_SETSID */
11542
11543
11544
#ifdef HAVE_SETPGID
11545
/*[clinic input]
11546
os.setpgid
11547
11548
    pid: pid_t
11549
    pgrp: pid_t
11550
    /
11551
11552
Call the system call setpgid(pid, pgrp).
11553
[clinic start generated code]*/
11554
11555
static PyObject *
11556
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11557
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11558
0
{
11559
0
    if (setpgid(pid, pgrp) < 0)
11560
0
        return posix_error();
11561
0
    Py_RETURN_NONE;
11562
0
}
11563
#endif /* HAVE_SETPGID */
11564
11565
11566
#ifdef HAVE_TCGETPGRP
11567
/*[clinic input]
11568
os.tcgetpgrp
11569
11570
    fd: int
11571
    /
11572
11573
Return the process group associated with the terminal specified by fd.
11574
[clinic start generated code]*/
11575
11576
static PyObject *
11577
os_tcgetpgrp_impl(PyObject *module, int fd)
11578
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11579
0
{
11580
0
    pid_t pgid = tcgetpgrp(fd);
11581
0
    if (pgid < 0)
11582
0
        return posix_error();
11583
0
    return PyLong_FromPid(pgid);
11584
0
}
11585
#endif /* HAVE_TCGETPGRP */
11586
11587
11588
#ifdef HAVE_TCSETPGRP
11589
/*[clinic input]
11590
os.tcsetpgrp
11591
11592
    fd: int
11593
    pgid: pid_t
11594
    /
11595
11596
Set the process group associated with the terminal specified by fd.
11597
[clinic start generated code]*/
11598
11599
static PyObject *
11600
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11601
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11602
0
{
11603
0
    if (tcsetpgrp(fd, pgid) < 0)
11604
0
        return posix_error();
11605
0
    Py_RETURN_NONE;
11606
0
}
11607
#endif /* HAVE_TCSETPGRP */
11608
11609
/* Functions acting on file descriptors */
11610
11611
#ifdef O_CLOEXEC
11612
extern int _Py_open_cloexec_works;
11613
#endif
11614
11615
11616
/*[clinic input]
11617
os.open -> int
11618
    path: path_t
11619
    flags: int
11620
    mode: int = 0o777
11621
    *
11622
    dir_fd: dir_fd(requires='openat') = None
11623
11624
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11625
11626
Open a file for low level IO.  Returns a file descriptor (integer).
11627
11628
If dir_fd is not None, it should be a file descriptor open to a directory,
11629
  and path should be relative; path will then be relative to that directory.
11630
dir_fd may not be implemented on your platform.
11631
  If it is unavailable, using it will raise a NotImplementedError.
11632
[clinic start generated code]*/
11633
11634
static int
11635
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11636
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11637
144k
{
11638
144k
    int fd;
11639
144k
    int async_err = 0;
11640
144k
#ifdef HAVE_OPENAT
11641
144k
    int openat_unavailable = 0;
11642
144k
#endif
11643
11644
144k
#ifdef O_CLOEXEC
11645
144k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11646
#elif !defined(MS_WINDOWS)
11647
    int *atomic_flag_works = NULL;
11648
#endif
11649
11650
#ifdef MS_WINDOWS
11651
    flags |= O_NOINHERIT;
11652
#elif defined(O_CLOEXEC)
11653
144k
    flags |= O_CLOEXEC;
11654
144k
#endif
11655
11656
144k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11657
0
        return -1;
11658
0
    }
11659
11660
144k
    _Py_BEGIN_SUPPRESS_IPH
11661
144k
    do {
11662
144k
        Py_BEGIN_ALLOW_THREADS
11663
#ifdef MS_WINDOWS
11664
        fd = _wopen(path->wide, flags, mode);
11665
#else
11666
144k
#ifdef HAVE_OPENAT
11667
144k
        if (dir_fd != DEFAULT_DIR_FD) {
11668
140k
            if (HAVE_OPENAT_RUNTIME) {
11669
140k
                fd = openat(dir_fd, path->narrow, flags, mode);
11670
11671
140k
            } else {
11672
0
                openat_unavailable = 1;
11673
0
                fd = -1;
11674
0
            }
11675
140k
        } else
11676
4.03k
#endif /* HAVE_OPENAT */
11677
4.03k
            fd = open(path->narrow, flags, mode);
11678
144k
#endif /* !MS_WINDOWS */
11679
144k
        Py_END_ALLOW_THREADS
11680
144k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11681
144k
    _Py_END_SUPPRESS_IPH
11682
11683
144k
#ifdef HAVE_OPENAT
11684
144k
    if (openat_unavailable) {
11685
0
        argument_unavailable_error(NULL, "dir_fd");
11686
0
        return -1;
11687
0
    }
11688
144k
#endif
11689
11690
144k
    if (fd < 0) {
11691
0
        if (!async_err)
11692
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11693
0
        return -1;
11694
0
    }
11695
11696
144k
#ifndef MS_WINDOWS
11697
144k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11698
0
        close(fd);
11699
0
        return -1;
11700
0
    }
11701
144k
#endif
11702
11703
144k
    return fd;
11704
144k
}
11705
11706
11707
/*[clinic input]
11708
os.close
11709
11710
    fd: int
11711
11712
Close a file descriptor.
11713
[clinic start generated code]*/
11714
11715
static PyObject *
11716
os_close_impl(PyObject *module, int fd)
11717
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11718
144k
{
11719
144k
    int res;
11720
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11721
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11722
     * for more details.
11723
     */
11724
144k
    Py_BEGIN_ALLOW_THREADS
11725
144k
    _Py_BEGIN_SUPPRESS_IPH
11726
144k
    res = close(fd);
11727
144k
    _Py_END_SUPPRESS_IPH
11728
144k
    Py_END_ALLOW_THREADS
11729
144k
    if (res < 0)
11730
0
        return posix_error();
11731
144k
    Py_RETURN_NONE;
11732
144k
}
11733
11734
/*[clinic input]
11735
os.closerange
11736
11737
    fd_low: int
11738
    fd_high: int
11739
    /
11740
11741
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11742
[clinic start generated code]*/
11743
11744
static PyObject *
11745
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11746
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11747
0
{
11748
0
    Py_BEGIN_ALLOW_THREADS
11749
0
    _Py_closerange(fd_low, fd_high - 1);
11750
0
    Py_END_ALLOW_THREADS
11751
0
    Py_RETURN_NONE;
11752
0
}
11753
11754
11755
/*[clinic input]
11756
os.dup -> int
11757
11758
    fd: int
11759
    /
11760
11761
Return a duplicate of a file descriptor.
11762
[clinic start generated code]*/
11763
11764
static int
11765
os_dup_impl(PyObject *module, int fd)
11766
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11767
0
{
11768
0
    return _Py_dup(fd);
11769
0
}
11770
11771
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11772
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11773
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11774
/*[clinic input]
11775
os.dup2 -> int
11776
    fd: int
11777
    fd2: int
11778
    inheritable: bool=True
11779
11780
Duplicate file descriptor.
11781
[clinic start generated code]*/
11782
11783
static int
11784
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11785
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11786
0
{
11787
0
    int res = 0;
11788
0
#if defined(HAVE_DUP3) && \
11789
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11790
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11791
0
    static int dup3_works = -1;
11792
0
#endif
11793
11794
    /* dup2() can fail with EINTR if the target FD is already open, because it
11795
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11796
     * upon close(), and therefore below.
11797
     */
11798
#ifdef MS_WINDOWS
11799
    Py_BEGIN_ALLOW_THREADS
11800
    _Py_BEGIN_SUPPRESS_IPH
11801
    res = dup2(fd, fd2);
11802
    _Py_END_SUPPRESS_IPH
11803
    Py_END_ALLOW_THREADS
11804
    if (res < 0) {
11805
        posix_error();
11806
        return -1;
11807
    }
11808
    res = fd2; // msvcrt dup2 returns 0 on success.
11809
11810
    /* Character files like console cannot be make non-inheritable */
11811
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11812
        close(fd2);
11813
        return -1;
11814
    }
11815
11816
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11817
    Py_BEGIN_ALLOW_THREADS
11818
    if (!inheritable)
11819
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11820
    else
11821
        res = dup2(fd, fd2);
11822
    Py_END_ALLOW_THREADS
11823
    if (res < 0) {
11824
        posix_error();
11825
        return -1;
11826
    }
11827
11828
#else
11829
11830
0
#ifdef HAVE_DUP3
11831
0
    if (!inheritable && dup3_works != 0) {
11832
0
        Py_BEGIN_ALLOW_THREADS
11833
0
        res = dup3(fd, fd2, O_CLOEXEC);
11834
0
        Py_END_ALLOW_THREADS
11835
0
        if (res < 0) {
11836
0
            if (dup3_works == -1)
11837
0
                dup3_works = (errno != ENOSYS);
11838
0
            if (dup3_works) {
11839
0
                posix_error();
11840
0
                return -1;
11841
0
            }
11842
0
        }
11843
0
    }
11844
11845
0
    if (inheritable || dup3_works == 0)
11846
0
    {
11847
0
#endif
11848
0
        Py_BEGIN_ALLOW_THREADS
11849
0
        res = dup2(fd, fd2);
11850
0
        Py_END_ALLOW_THREADS
11851
0
        if (res < 0) {
11852
0
            posix_error();
11853
0
            return -1;
11854
0
        }
11855
11856
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11857
0
            close(fd2);
11858
0
            return -1;
11859
0
        }
11860
0
#ifdef HAVE_DUP3
11861
0
    }
11862
0
#endif
11863
11864
0
#endif
11865
11866
0
    return res;
11867
0
}
11868
#endif
11869
11870
11871
#ifdef HAVE_LOCKF
11872
/*[clinic input]
11873
os.lockf
11874
11875
    fd: int
11876
        An open file descriptor.
11877
    command: int
11878
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11879
    length: Py_off_t
11880
        The number of bytes to lock, starting at the current position.
11881
    /
11882
11883
Apply, test or remove a POSIX lock on an open file descriptor.
11884
11885
[clinic start generated code]*/
11886
11887
static PyObject *
11888
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11889
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11890
0
{
11891
0
    int res;
11892
11893
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11894
0
        return NULL;
11895
0
    }
11896
11897
0
    Py_BEGIN_ALLOW_THREADS
11898
0
    res = lockf(fd, command, length);
11899
0
    Py_END_ALLOW_THREADS
11900
11901
0
    if (res < 0)
11902
0
        return posix_error();
11903
11904
0
    Py_RETURN_NONE;
11905
0
}
11906
#endif /* HAVE_LOCKF */
11907
11908
11909
/*[clinic input]
11910
@permit_long_docstring_body
11911
os.lseek -> Py_off_t
11912
11913
    fd: int
11914
        An open file descriptor, as returned by os.open().
11915
    position: Py_off_t
11916
        Position, interpreted relative to 'whence'.
11917
    whence as how: int
11918
        The relative position to seek from. Valid values are:
11919
        - SEEK_SET: seek from the start of the file.
11920
        - SEEK_CUR: seek from the current file position.
11921
        - SEEK_END: seek from the end of the file.
11922
    /
11923
11924
Set the position of a file descriptor.  Return the new position.
11925
11926
The return value is the number of bytes relative to the beginning of the file.
11927
[clinic start generated code]*/
11928
11929
static Py_off_t
11930
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11931
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11932
0
{
11933
0
    Py_off_t result;
11934
11935
0
#ifdef SEEK_SET
11936
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11937
0
    switch (how) {
11938
0
        case 0: how = SEEK_SET; break;
11939
0
        case 1: how = SEEK_CUR; break;
11940
0
        case 2: how = SEEK_END; break;
11941
0
    }
11942
0
#endif /* SEEK_END */
11943
11944
0
    Py_BEGIN_ALLOW_THREADS
11945
0
    _Py_BEGIN_SUPPRESS_IPH
11946
#ifdef MS_WINDOWS
11947
    result = _lseeki64(fd, position, how);
11948
#else
11949
0
    result = lseek(fd, position, how);
11950
0
#endif
11951
0
    _Py_END_SUPPRESS_IPH
11952
0
    Py_END_ALLOW_THREADS
11953
0
    if (result < 0)
11954
0
        posix_error();
11955
11956
0
    return result;
11957
0
}
11958
11959
11960
/*[clinic input]
11961
os.read
11962
    fd: int
11963
    length: Py_ssize_t
11964
    /
11965
11966
Read from a file descriptor.  Returns a bytes object.
11967
[clinic start generated code]*/
11968
11969
static PyObject *
11970
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11971
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11972
0
{
11973
0
    if (length < 0) {
11974
0
        errno = EINVAL;
11975
0
        return posix_error();
11976
0
    }
11977
11978
0
    length = Py_MIN(length, _PY_READ_MAX);
11979
11980
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11981
0
    if (writer == NULL) {
11982
0
        return NULL;
11983
0
    }
11984
11985
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11986
0
    if (n == -1) {
11987
0
        PyBytesWriter_Discard(writer);
11988
0
        return NULL;
11989
0
    }
11990
11991
0
    return PyBytesWriter_FinishWithSize(writer, n);
11992
0
}
11993
11994
/*[clinic input]
11995
@permit_long_docstring_body
11996
os.readinto -> Py_ssize_t
11997
    fd: int
11998
    buffer: Py_buffer(accept={rwbuffer})
11999
    /
12000
12001
Read into a buffer object from a file descriptor.
12002
12003
The buffer should be mutable and bytes-like. On success, returns the number of
12004
bytes read. Less bytes may be read than the size of the buffer. The underlying
12005
system call will be retried when interrupted by a signal, unless the signal
12006
handler raises an exception. Other errors will not be retried and an error will
12007
be raised.
12008
12009
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
12010
(which can be used to check for errors without reading data). Never returns
12011
negative.
12012
[clinic start generated code]*/
12013
12014
static Py_ssize_t
12015
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12016
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
12017
0
{
12018
0
    assert(buffer->len >= 0);
12019
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12020
    /* Ensure negative is never returned without an error. Simplifies calling
12021
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12022
        error. */
12023
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12024
0
    return result;
12025
0
}
12026
12027
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12028
                                || defined(__APPLE__))) \
12029
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12030
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12031
static int
12032
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12033
0
{
12034
0
    Py_ssize_t i, j;
12035
12036
0
    *iov = PyMem_New(struct iovec, cnt);
12037
0
    if (*iov == NULL) {
12038
0
        PyErr_NoMemory();
12039
0
        return -1;
12040
0
    }
12041
12042
0
    *buf = PyMem_New(Py_buffer, cnt);
12043
0
    if (*buf == NULL) {
12044
0
        PyMem_Free(*iov);
12045
0
        PyErr_NoMemory();
12046
0
        return -1;
12047
0
    }
12048
12049
0
    for (i = 0; i < cnt; i++) {
12050
0
        PyObject *item = PySequence_GetItem(seq, i);
12051
0
        if (item == NULL)
12052
0
            goto fail;
12053
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12054
0
            Py_DECREF(item);
12055
0
            goto fail;
12056
0
        }
12057
0
        Py_DECREF(item);
12058
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12059
0
        (*iov)[i].iov_len = (*buf)[i].len;
12060
0
    }
12061
0
    return 0;
12062
12063
0
fail:
12064
0
    PyMem_Free(*iov);
12065
0
    for (j = 0; j < i; j++) {
12066
0
        PyBuffer_Release(&(*buf)[j]);
12067
0
    }
12068
0
    PyMem_Free(*buf);
12069
0
    return -1;
12070
0
}
12071
12072
static void
12073
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12074
0
{
12075
0
    int i;
12076
0
    PyMem_Free(iov);
12077
0
    for (i = 0; i < cnt; i++) {
12078
0
        PyBuffer_Release(&buf[i]);
12079
0
    }
12080
0
    PyMem_Free(buf);
12081
0
}
12082
#endif
12083
12084
12085
#ifdef HAVE_READV
12086
/*[clinic input]
12087
os.readv -> Py_ssize_t
12088
12089
    fd: int
12090
    buffers: object
12091
    /
12092
12093
Read from a file descriptor fd into an iterable of buffers.
12094
12095
The buffers should be mutable buffers accepting bytes.
12096
readv will transfer data into each buffer until it is full
12097
and then move on to the next buffer in the sequence to hold
12098
the rest of the data.
12099
12100
readv returns the total number of bytes read,
12101
which may be less than the total capacity of all the buffers.
12102
[clinic start generated code]*/
12103
12104
static Py_ssize_t
12105
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12106
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12107
0
{
12108
0
    Py_ssize_t cnt, n;
12109
0
    int async_err = 0;
12110
0
    struct iovec *iov;
12111
0
    Py_buffer *buf;
12112
12113
0
    if (!PySequence_Check(buffers)) {
12114
0
        PyErr_SetString(PyExc_TypeError,
12115
0
            "readv() arg 2 must be a sequence");
12116
0
        return -1;
12117
0
    }
12118
12119
0
    cnt = PySequence_Size(buffers);
12120
0
    if (cnt < 0)
12121
0
        return -1;
12122
12123
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12124
0
        return -1;
12125
12126
0
    do {
12127
0
        Py_BEGIN_ALLOW_THREADS
12128
0
        n = readv(fd, iov, cnt);
12129
0
        Py_END_ALLOW_THREADS
12130
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12131
12132
0
    int saved_errno = errno;
12133
0
    iov_cleanup(iov, buf, cnt);
12134
0
    if (n < 0) {
12135
0
        if (!async_err) {
12136
0
            errno = saved_errno;
12137
0
            posix_error();
12138
0
        }
12139
0
        return -1;
12140
0
    }
12141
12142
0
    return n;
12143
0
}
12144
#endif /* HAVE_READV */
12145
12146
12147
#ifdef HAVE_PREAD
12148
/*[clinic input]
12149
@permit_long_summary
12150
os.pread
12151
12152
    fd: int
12153
    length: Py_ssize_t
12154
    offset: Py_off_t
12155
    /
12156
12157
Read a number of bytes from a file descriptor starting at a particular offset.
12158
12159
Read length bytes from file descriptor fd, starting at offset bytes from
12160
the beginning of the file.  The file offset remains unchanged.
12161
[clinic start generated code]*/
12162
12163
static PyObject *
12164
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12165
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12166
0
{
12167
0
    Py_ssize_t n;
12168
0
    int async_err = 0;
12169
12170
0
    if (length < 0) {
12171
0
        errno = EINVAL;
12172
0
        return posix_error();
12173
0
    }
12174
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12175
0
    if (writer == NULL) {
12176
0
        return NULL;
12177
0
    }
12178
12179
0
    do {
12180
0
        Py_BEGIN_ALLOW_THREADS
12181
0
        _Py_BEGIN_SUPPRESS_IPH
12182
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12183
0
        _Py_END_SUPPRESS_IPH
12184
0
        Py_END_ALLOW_THREADS
12185
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12186
12187
0
    if (n < 0) {
12188
0
        if (!async_err) {
12189
0
            posix_error();
12190
0
        }
12191
0
        PyBytesWriter_Discard(writer);
12192
0
        return NULL;
12193
0
    }
12194
0
    return PyBytesWriter_FinishWithSize(writer, n);
12195
0
}
12196
#endif /* HAVE_PREAD */
12197
12198
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12199
/*[clinic input]
12200
@permit_long_docstring_body
12201
os.preadv -> Py_ssize_t
12202
12203
    fd: int
12204
    buffers: object
12205
    offset: Py_off_t
12206
    flags: int = 0
12207
    /
12208
12209
Reads from a file descriptor into a number of mutable bytes-like objects.
12210
12211
Combines the functionality of readv() and pread(). As readv(), it will
12212
transfer data into each buffer until it is full and then move on to the next
12213
buffer in the sequence to hold the rest of the data. Its fourth argument,
12214
specifies the file offset at which the input operation is to be performed. It
12215
will return the total number of bytes read (which can be less than the total
12216
capacity of all the objects).
12217
12218
The flags argument contains a bitwise OR of zero or more of the following flags:
12219
12220
- RWF_HIPRI
12221
- RWF_NOWAIT
12222
- RWF_DONTCACHE
12223
12224
Using non-zero flags requires Linux 4.6 or newer.
12225
[clinic start generated code]*/
12226
12227
static Py_ssize_t
12228
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12229
               int flags)
12230
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
12231
0
{
12232
0
    Py_ssize_t cnt, n;
12233
0
    int async_err = 0;
12234
0
    struct iovec *iov;
12235
0
    Py_buffer *buf;
12236
12237
0
    if (!PySequence_Check(buffers)) {
12238
0
        PyErr_SetString(PyExc_TypeError,
12239
0
            "preadv2() arg 2 must be a sequence");
12240
0
        return -1;
12241
0
    }
12242
12243
0
    cnt = PySequence_Size(buffers);
12244
0
    if (cnt < 0) {
12245
0
        return -1;
12246
0
    }
12247
12248
#ifndef HAVE_PREADV2
12249
    if(flags != 0) {
12250
        argument_unavailable_error("preadv2", "flags");
12251
        return -1;
12252
    }
12253
#endif
12254
12255
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12256
0
        return -1;
12257
0
    }
12258
0
#ifdef HAVE_PREADV2
12259
0
    do {
12260
0
        Py_BEGIN_ALLOW_THREADS
12261
0
        _Py_BEGIN_SUPPRESS_IPH
12262
0
        n = preadv2(fd, iov, cnt, offset, flags);
12263
0
        _Py_END_SUPPRESS_IPH
12264
0
        Py_END_ALLOW_THREADS
12265
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12266
#else
12267
    do {
12268
#if defined(__APPLE__) && defined(__clang__)
12269
/* This entire function will be removed from the module dict when the API
12270
 * is not available.
12271
 */
12272
#pragma clang diagnostic push
12273
#pragma clang diagnostic ignored "-Wunguarded-availability"
12274
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12275
#endif
12276
        Py_BEGIN_ALLOW_THREADS
12277
        _Py_BEGIN_SUPPRESS_IPH
12278
        n = preadv(fd, iov, cnt, offset);
12279
        _Py_END_SUPPRESS_IPH
12280
        Py_END_ALLOW_THREADS
12281
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12282
12283
#if defined(__APPLE__) && defined(__clang__)
12284
#pragma clang diagnostic pop
12285
#endif
12286
12287
#endif
12288
12289
0
    int saved_errno = errno;
12290
0
    iov_cleanup(iov, buf, cnt);
12291
0
    if (n < 0) {
12292
0
        if (!async_err) {
12293
0
            errno = saved_errno;
12294
0
            posix_error();
12295
0
        }
12296
0
        return -1;
12297
0
    }
12298
12299
0
    return n;
12300
0
}
12301
#endif /* HAVE_PREADV */
12302
12303
12304
/*[clinic input]
12305
os.write -> Py_ssize_t
12306
12307
    fd: int
12308
    data: Py_buffer
12309
    /
12310
12311
Write a bytes object to a file descriptor.
12312
[clinic start generated code]*/
12313
12314
static Py_ssize_t
12315
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12316
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12317
2
{
12318
2
    return _Py_write(fd, data->buf, data->len);
12319
2
}
12320
12321
#ifdef HAVE_SENDFILE
12322
#ifdef __APPLE__
12323
/*[clinic input]
12324
os.sendfile
12325
12326
    out_fd: int
12327
    in_fd: int
12328
    offset: Py_off_t
12329
    count as sbytes: Py_off_t
12330
    headers: object(c_default="NULL") = ()
12331
    trailers: object(c_default="NULL") = ()
12332
    flags: int = 0
12333
12334
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12335
[clinic start generated code]*/
12336
12337
static PyObject *
12338
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12339
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12340
                 int flags)
12341
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12342
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12343
/*[clinic input]
12344
os.sendfile
12345
12346
    out_fd: int
12347
    in_fd: int
12348
    offset: Py_off_t
12349
    count: Py_ssize_t(allow_negative=False)
12350
    headers: object(c_default="NULL") = ()
12351
    trailers: object(c_default="NULL") = ()
12352
    flags: int = 0
12353
12354
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12355
[clinic start generated code]*/
12356
12357
static PyObject *
12358
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12359
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12360
                 int flags)
12361
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12362
#else
12363
/*[clinic input]
12364
os.sendfile
12365
12366
    out_fd: int
12367
    in_fd: int
12368
    offset as offobj: object
12369
    count: Py_ssize_t(allow_negative=False)
12370
12371
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12372
[clinic start generated code]*/
12373
12374
static PyObject *
12375
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12376
                 Py_ssize_t count)
12377
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12378
#endif
12379
0
{
12380
0
    Py_ssize_t ret;
12381
0
    int async_err = 0;
12382
12383
#ifdef __APPLE__
12384
    if(sbytes < 0) {
12385
        PyErr_SetString(PyExc_ValueError,
12386
                        "count cannot be negative");
12387
        return NULL;
12388
    }
12389
#else
12390
0
    assert(count >= 0);
12391
0
#endif
12392
12393
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12394
#ifndef __APPLE__
12395
    off_t sbytes;
12396
#endif
12397
    Py_buffer *hbuf, *tbuf;
12398
    struct sf_hdtr sf;
12399
12400
    sf.headers = NULL;
12401
    sf.trailers = NULL;
12402
12403
    if (headers != NULL) {
12404
        if (!PySequence_Check(headers)) {
12405
            PyErr_SetString(PyExc_TypeError,
12406
                "sendfile() headers must be a sequence");
12407
            return NULL;
12408
        } else {
12409
            Py_ssize_t i = PySequence_Size(headers);
12410
            if (i < 0)
12411
                return NULL;
12412
            if (i > INT_MAX) {
12413
                PyErr_SetString(PyExc_OverflowError,
12414
                    "sendfile() header is too large");
12415
                return NULL;
12416
            }
12417
            if (i > 0) {
12418
                sf.hdr_cnt = (int)i;
12419
                if (iov_setup(&(sf.headers), &hbuf,
12420
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12421
                    return NULL;
12422
#ifdef __APPLE__
12423
                for (i = 0; i < sf.hdr_cnt; i++) {
12424
                    Py_ssize_t blen = sf.headers[i].iov_len;
12425
# define OFF_T_MAX 0x7fffffffffffffff
12426
                    if (sbytes >= OFF_T_MAX - blen) {
12427
                        PyErr_SetString(PyExc_OverflowError,
12428
                            "sendfile() header is too large");
12429
                        return NULL;
12430
                    }
12431
                    sbytes += blen;
12432
                }
12433
#endif
12434
            }
12435
        }
12436
    }
12437
    if (trailers != NULL) {
12438
        if (!PySequence_Check(trailers)) {
12439
            PyErr_SetString(PyExc_TypeError,
12440
                "sendfile() trailers must be a sequence");
12441
            return NULL;
12442
        } else {
12443
            Py_ssize_t i = PySequence_Size(trailers);
12444
            if (i < 0)
12445
                return NULL;
12446
            if (i > INT_MAX) {
12447
                PyErr_SetString(PyExc_OverflowError,
12448
                    "sendfile() trailer is too large");
12449
                return NULL;
12450
            }
12451
            if (i > 0) {
12452
                sf.trl_cnt = (int)i;
12453
                if (iov_setup(&(sf.trailers), &tbuf,
12454
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12455
                    return NULL;
12456
            }
12457
        }
12458
    }
12459
12460
    _Py_BEGIN_SUPPRESS_IPH
12461
    do {
12462
        Py_BEGIN_ALLOW_THREADS
12463
#ifdef __APPLE__
12464
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12465
#else
12466
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12467
#endif
12468
        Py_END_ALLOW_THREADS
12469
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12470
    _Py_END_SUPPRESS_IPH
12471
12472
    int saved_errno = errno;
12473
    if (sf.headers != NULL)
12474
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12475
    if (sf.trailers != NULL)
12476
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12477
12478
    if (ret < 0) {
12479
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12480
            if (sbytes != 0) {
12481
                // some data has been sent
12482
                goto done;
12483
            }
12484
            // no data has been sent; upper application is supposed
12485
            // to retry on EAGAIN or EBUSY
12486
        }
12487
        if (!async_err) {
12488
            errno = saved_errno;
12489
            posix_error();
12490
        }
12491
        return NULL;
12492
    }
12493
    goto done;
12494
12495
done:
12496
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12497
        return PyLong_FromLong(sbytes);
12498
    #else
12499
        return PyLong_FromLongLong(sbytes);
12500
    #endif
12501
12502
#else
12503
0
#ifdef __linux__
12504
0
    if (offobj == Py_None) {
12505
0
        do {
12506
0
            Py_BEGIN_ALLOW_THREADS
12507
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12508
0
            Py_END_ALLOW_THREADS
12509
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12510
0
        if (ret < 0)
12511
0
            return (!async_err) ? posix_error() : NULL;
12512
0
        return PyLong_FromSsize_t(ret);
12513
0
    }
12514
0
#endif
12515
0
    off_t offset;
12516
0
    if (!Py_off_t_converter(offobj, &offset))
12517
0
        return NULL;
12518
12519
#if defined(__sun) && defined(__SVR4)
12520
    // On Solaris, sendfile raises EINVAL rather than returning 0
12521
    // when the offset is equal or bigger than the in_fd size.
12522
    struct stat st;
12523
12524
    do {
12525
        Py_BEGIN_ALLOW_THREADS
12526
        ret = fstat(in_fd, &st);
12527
        Py_END_ALLOW_THREADS
12528
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12529
    if (ret < 0)
12530
        return (!async_err) ? posix_error() : NULL;
12531
12532
    if (offset >= st.st_size) {
12533
        return PyLong_FromLong(0);
12534
    }
12535
12536
    // On illumos specifically sendfile() may perform a partial write but
12537
    // return -1/an error (in one confirmed case the destination socket
12538
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12539
    // code to check if the offset parameter was modified by sendfile().
12540
    //
12541
    // We need this variable to track said change.
12542
    off_t original_offset = offset;
12543
#endif
12544
12545
0
    do {
12546
0
        Py_BEGIN_ALLOW_THREADS
12547
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12548
#if defined(__sun) && defined(__SVR4)
12549
        // This handles illumos-specific sendfile() partial write behavior,
12550
        // see a comment above for more details.
12551
        if (ret < 0 && offset != original_offset) {
12552
            ret = offset - original_offset;
12553
        }
12554
#endif
12555
0
        Py_END_ALLOW_THREADS
12556
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12557
0
    if (ret < 0)
12558
0
        return (!async_err) ? posix_error() : NULL;
12559
0
    return PyLong_FromSsize_t(ret);
12560
0
#endif
12561
0
}
12562
#endif /* HAVE_SENDFILE */
12563
12564
12565
#if defined(__APPLE__)
12566
/*[clinic input]
12567
os._fcopyfile
12568
12569
    in_fd: int
12570
    out_fd: int
12571
    flags: int
12572
    /
12573
12574
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12575
[clinic start generated code]*/
12576
12577
static PyObject *
12578
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12579
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12580
{
12581
    int ret;
12582
12583
    Py_BEGIN_ALLOW_THREADS
12584
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12585
    Py_END_ALLOW_THREADS
12586
    if (ret < 0)
12587
        return posix_error();
12588
    Py_RETURN_NONE;
12589
}
12590
#endif
12591
12592
12593
/*[clinic input]
12594
os.fstat
12595
12596
    fd : int
12597
12598
Perform a stat system call on the given file descriptor.
12599
12600
Like stat(), but for an open file descriptor.
12601
Equivalent to os.stat(fd).
12602
[clinic start generated code]*/
12603
12604
static PyObject *
12605
os_fstat_impl(PyObject *module, int fd)
12606
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12607
144k
{
12608
144k
    STRUCT_STAT st;
12609
144k
    int res;
12610
144k
    int async_err = 0;
12611
12612
144k
    do {
12613
144k
        Py_BEGIN_ALLOW_THREADS
12614
144k
        res = FSTAT(fd, &st);
12615
144k
        Py_END_ALLOW_THREADS
12616
144k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12617
144k
    if (res != 0) {
12618
#ifdef MS_WINDOWS
12619
        return PyErr_SetFromWindowsErr(0);
12620
#else
12621
0
        return (!async_err) ? posix_error() : NULL;
12622
0
#endif
12623
0
    }
12624
12625
144k
    return _pystat_fromstructstat(module, &st);
12626
144k
}
12627
12628
12629
/*[clinic input]
12630
os.isatty -> bool
12631
    fd: int
12632
    /
12633
12634
Return True if the fd is connected to a terminal.
12635
12636
Return True if the file descriptor is an open file descriptor
12637
connected to the slave end of a terminal.
12638
[clinic start generated code]*/
12639
12640
static int
12641
os_isatty_impl(PyObject *module, int fd)
12642
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12643
0
{
12644
0
    int return_value;
12645
0
    Py_BEGIN_ALLOW_THREADS
12646
0
    _Py_BEGIN_SUPPRESS_IPH
12647
0
    return_value = isatty(fd);
12648
0
    _Py_END_SUPPRESS_IPH
12649
0
    Py_END_ALLOW_THREADS
12650
0
    return return_value;
12651
0
}
12652
12653
12654
#ifdef HAVE_PIPE
12655
/*[clinic input]
12656
os.pipe
12657
12658
Create a pipe.
12659
12660
Returns a tuple of two file descriptors:
12661
  (read_fd, write_fd)
12662
[clinic start generated code]*/
12663
12664
static PyObject *
12665
os_pipe_impl(PyObject *module)
12666
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12667
0
{
12668
0
    int fds[2];
12669
#ifdef MS_WINDOWS
12670
    HANDLE read, write;
12671
    SECURITY_ATTRIBUTES attr;
12672
    BOOL ok;
12673
#else
12674
0
    int res;
12675
0
#endif
12676
12677
#ifdef MS_WINDOWS
12678
    attr.nLength = sizeof(attr);
12679
    attr.lpSecurityDescriptor = NULL;
12680
    attr.bInheritHandle = FALSE;
12681
12682
    Py_BEGIN_ALLOW_THREADS
12683
    ok = CreatePipe(&read, &write, &attr, 0);
12684
    if (ok) {
12685
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12686
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12687
        if (fds[0] == -1 || fds[1] == -1) {
12688
            CloseHandle(read);
12689
            CloseHandle(write);
12690
            ok = 0;
12691
        }
12692
    }
12693
    Py_END_ALLOW_THREADS
12694
12695
    if (!ok)
12696
        return PyErr_SetFromWindowsErr(0);
12697
#else
12698
12699
0
#ifdef HAVE_PIPE2
12700
0
    Py_BEGIN_ALLOW_THREADS
12701
0
    res = pipe2(fds, O_CLOEXEC);
12702
0
    Py_END_ALLOW_THREADS
12703
12704
0
    if (res != 0 && errno == ENOSYS)
12705
0
    {
12706
0
#endif
12707
0
        Py_BEGIN_ALLOW_THREADS
12708
0
        res = pipe(fds);
12709
0
        Py_END_ALLOW_THREADS
12710
12711
0
        if (res == 0) {
12712
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12713
0
                close(fds[0]);
12714
0
                close(fds[1]);
12715
0
                return NULL;
12716
0
            }
12717
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12718
0
                close(fds[0]);
12719
0
                close(fds[1]);
12720
0
                return NULL;
12721
0
            }
12722
0
        }
12723
0
#ifdef HAVE_PIPE2
12724
0
    }
12725
0
#endif
12726
12727
0
    if (res != 0)
12728
0
        return PyErr_SetFromErrno(PyExc_OSError);
12729
0
#endif /* !MS_WINDOWS */
12730
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12731
0
}
12732
#endif  /* HAVE_PIPE */
12733
12734
12735
#ifdef HAVE_PIPE2
12736
/*[clinic input]
12737
os.pipe2
12738
12739
    flags: int
12740
    /
12741
12742
Create a pipe with flags set atomically.
12743
12744
Returns a tuple of two file descriptors:
12745
  (read_fd, write_fd)
12746
12747
flags can be constructed by ORing together one or more of these values:
12748
O_NONBLOCK, O_CLOEXEC.
12749
[clinic start generated code]*/
12750
12751
static PyObject *
12752
os_pipe2_impl(PyObject *module, int flags)
12753
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12754
0
{
12755
0
    int fds[2];
12756
0
    int res;
12757
12758
0
    res = pipe2(fds, flags);
12759
0
    if (res != 0)
12760
0
        return posix_error();
12761
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12762
0
}
12763
#endif /* HAVE_PIPE2 */
12764
12765
12766
#ifdef HAVE_WRITEV
12767
/*[clinic input]
12768
os.writev -> Py_ssize_t
12769
    fd: int
12770
    buffers: object
12771
    /
12772
12773
Iterate over buffers, and write the contents of each to a file descriptor.
12774
12775
Returns the total number of bytes written.
12776
buffers must be a sequence of bytes-like objects.
12777
[clinic start generated code]*/
12778
12779
static Py_ssize_t
12780
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12781
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12782
0
{
12783
0
    Py_ssize_t cnt;
12784
0
    Py_ssize_t result;
12785
0
    int async_err = 0;
12786
0
    struct iovec *iov;
12787
0
    Py_buffer *buf;
12788
12789
0
    if (!PySequence_Check(buffers)) {
12790
0
        PyErr_SetString(PyExc_TypeError,
12791
0
            "writev() arg 2 must be a sequence");
12792
0
        return -1;
12793
0
    }
12794
0
    cnt = PySequence_Size(buffers);
12795
0
    if (cnt < 0)
12796
0
        return -1;
12797
12798
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12799
0
        return -1;
12800
0
    }
12801
12802
0
    do {
12803
0
        Py_BEGIN_ALLOW_THREADS
12804
0
        result = writev(fd, iov, cnt);
12805
0
        Py_END_ALLOW_THREADS
12806
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12807
12808
0
    if (result < 0 && !async_err)
12809
0
        posix_error();
12810
12811
0
    iov_cleanup(iov, buf, cnt);
12812
0
    return result;
12813
0
}
12814
#endif /* HAVE_WRITEV */
12815
12816
12817
#ifdef HAVE_PWRITE
12818
/*[clinic input]
12819
os.pwrite -> Py_ssize_t
12820
12821
    fd: int
12822
    buffer: Py_buffer
12823
    offset: Py_off_t
12824
    /
12825
12826
Write bytes to a file descriptor starting at a particular offset.
12827
12828
Write buffer to fd, starting at offset bytes from the beginning of
12829
the file.  Returns the number of bytes written.  Does not change the
12830
current file offset.
12831
[clinic start generated code]*/
12832
12833
static Py_ssize_t
12834
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12835
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12836
0
{
12837
0
    Py_ssize_t size;
12838
0
    int async_err = 0;
12839
12840
0
    do {
12841
0
        Py_BEGIN_ALLOW_THREADS
12842
0
        _Py_BEGIN_SUPPRESS_IPH
12843
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12844
0
        _Py_END_SUPPRESS_IPH
12845
0
        Py_END_ALLOW_THREADS
12846
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12847
12848
0
    if (size < 0 && !async_err)
12849
0
        posix_error();
12850
0
    return size;
12851
0
}
12852
#endif /* HAVE_PWRITE */
12853
12854
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12855
/*[clinic input]
12856
@permit_long_summary
12857
@permit_long_docstring_body
12858
os.pwritev -> Py_ssize_t
12859
12860
    fd: int
12861
    buffers: object
12862
    offset: Py_off_t
12863
    flags: int = 0
12864
    /
12865
12866
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12867
12868
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12869
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12870
buffer is written before proceeding to second, and so on. The operating system may
12871
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12872
This function writes the contents of each object to the file descriptor and returns
12873
the total number of bytes written.
12874
12875
The flags argument contains a bitwise OR of zero or more of the following flags:
12876
12877
- RWF_DSYNC
12878
- RWF_SYNC
12879
- RWF_APPEND
12880
- RWF_DONTCACHE
12881
- RWF_ATOMIC
12882
12883
Using non-zero flags requires Linux 4.7 or newer.
12884
[clinic start generated code]*/
12885
12886
static Py_ssize_t
12887
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12888
                int flags)
12889
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=7de72245873f56bf]*/
12890
0
{
12891
0
    Py_ssize_t cnt;
12892
0
    Py_ssize_t result;
12893
0
    int async_err = 0;
12894
0
    struct iovec *iov;
12895
0
    Py_buffer *buf;
12896
12897
0
    if (!PySequence_Check(buffers)) {
12898
0
        PyErr_SetString(PyExc_TypeError,
12899
0
            "pwritev() arg 2 must be a sequence");
12900
0
        return -1;
12901
0
    }
12902
12903
0
    cnt = PySequence_Size(buffers);
12904
0
    if (cnt < 0) {
12905
0
        return -1;
12906
0
    }
12907
12908
#ifndef HAVE_PWRITEV2
12909
    if(flags != 0) {
12910
        argument_unavailable_error("pwritev2", "flags");
12911
        return -1;
12912
    }
12913
#endif
12914
12915
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12916
0
        return -1;
12917
0
    }
12918
0
#ifdef HAVE_PWRITEV2
12919
0
    do {
12920
0
        Py_BEGIN_ALLOW_THREADS
12921
0
        _Py_BEGIN_SUPPRESS_IPH
12922
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12923
0
        _Py_END_SUPPRESS_IPH
12924
0
        Py_END_ALLOW_THREADS
12925
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12926
#else
12927
12928
#if defined(__APPLE__) && defined(__clang__)
12929
/* This entire function will be removed from the module dict when the API
12930
 * is not available.
12931
 */
12932
#pragma clang diagnostic push
12933
#pragma clang diagnostic ignored "-Wunguarded-availability"
12934
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12935
#endif
12936
    do {
12937
        Py_BEGIN_ALLOW_THREADS
12938
        _Py_BEGIN_SUPPRESS_IPH
12939
        result = pwritev(fd, iov, cnt, offset);
12940
        _Py_END_SUPPRESS_IPH
12941
        Py_END_ALLOW_THREADS
12942
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12943
12944
#if defined(__APPLE__) && defined(__clang__)
12945
#pragma clang diagnostic pop
12946
#endif
12947
12948
#endif
12949
12950
0
    if (result < 0) {
12951
0
        if (!async_err) {
12952
0
            posix_error();
12953
0
        }
12954
0
        result = -1;
12955
0
    }
12956
0
    iov_cleanup(iov, buf, cnt);
12957
12958
0
    return result;
12959
0
}
12960
#endif /* HAVE_PWRITEV */
12961
12962
#ifdef HAVE_COPY_FILE_RANGE
12963
/*[clinic input]
12964
12965
os.copy_file_range
12966
    src: int
12967
        Source file descriptor.
12968
    dst: int
12969
        Destination file descriptor.
12970
    count: Py_ssize_t(allow_negative=False)
12971
        Number of bytes to copy.
12972
    offset_src: object = None
12973
        Starting offset in src.
12974
    offset_dst: object = None
12975
        Starting offset in dst.
12976
12977
Copy count bytes from one file descriptor to another.
12978
12979
If offset_src is None, then src is read from the current position;
12980
respectively for offset_dst.
12981
[clinic start generated code]*/
12982
12983
static PyObject *
12984
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12985
                        PyObject *offset_src, PyObject *offset_dst)
12986
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12987
0
{
12988
0
    off_t offset_src_val, offset_dst_val;
12989
0
    off_t *p_offset_src = NULL;
12990
0
    off_t *p_offset_dst = NULL;
12991
0
    Py_ssize_t ret;
12992
0
    int async_err = 0;
12993
    /* The flags argument is provided to allow
12994
     * for future extensions and currently must be to 0. */
12995
0
    int flags = 0;
12996
12997
12998
0
    if (offset_src != Py_None) {
12999
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13000
0
            return NULL;
13001
0
        }
13002
0
        p_offset_src = &offset_src_val;
13003
0
    }
13004
13005
0
    if (offset_dst != Py_None) {
13006
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13007
0
            return NULL;
13008
0
        }
13009
0
        p_offset_dst = &offset_dst_val;
13010
0
    }
13011
13012
0
    do {
13013
0
        Py_BEGIN_ALLOW_THREADS
13014
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13015
0
        Py_END_ALLOW_THREADS
13016
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13017
13018
0
    if (ret < 0) {
13019
0
        return (!async_err) ? posix_error() : NULL;
13020
0
    }
13021
13022
0
    return PyLong_FromSsize_t(ret);
13023
0
}
13024
#endif /* HAVE_COPY_FILE_RANGE*/
13025
13026
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13027
/*[clinic input]
13028
13029
os.splice
13030
    src: int
13031
        Source file descriptor.
13032
    dst: int
13033
        Destination file descriptor.
13034
    count: Py_ssize_t(allow_negative=False)
13035
        Number of bytes to copy.
13036
    offset_src: object = None
13037
        Starting offset in src.
13038
    offset_dst: object = None
13039
        Starting offset in dst.
13040
    flags: unsigned_int = 0
13041
        Flags to modify the semantics of the call.
13042
13043
Transfer count bytes from one pipe to a descriptor or vice versa.
13044
13045
If offset_src is None, then src is read from the current position;
13046
respectively for offset_dst. The offset associated to the file
13047
descriptor that refers to a pipe must be None.
13048
[clinic start generated code]*/
13049
13050
static PyObject *
13051
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13052
               PyObject *offset_src, PyObject *offset_dst,
13053
               unsigned int flags)
13054
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13055
0
{
13056
0
    off_t offset_src_val, offset_dst_val;
13057
0
    off_t *p_offset_src = NULL;
13058
0
    off_t *p_offset_dst = NULL;
13059
0
    Py_ssize_t ret;
13060
0
    int async_err = 0;
13061
13062
13063
0
    if (offset_src != Py_None) {
13064
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13065
0
            return NULL;
13066
0
        }
13067
0
        p_offset_src = &offset_src_val;
13068
0
    }
13069
13070
0
    if (offset_dst != Py_None) {
13071
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13072
0
            return NULL;
13073
0
        }
13074
0
        p_offset_dst = &offset_dst_val;
13075
0
    }
13076
13077
0
    do {
13078
0
        Py_BEGIN_ALLOW_THREADS
13079
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13080
0
        Py_END_ALLOW_THREADS
13081
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13082
13083
0
    if (ret < 0) {
13084
0
        return (!async_err) ? posix_error() : NULL;
13085
0
    }
13086
13087
0
    return PyLong_FromSsize_t(ret);
13088
0
}
13089
#endif /* HAVE_SPLICE*/
13090
13091
#ifdef HAVE_MKFIFO
13092
/*[clinic input]
13093
os.mkfifo
13094
13095
    path: path_t
13096
    mode: int=0o666
13097
    *
13098
    dir_fd: dir_fd(requires='mkfifoat')=None
13099
13100
Create a "fifo" (a POSIX named pipe).
13101
13102
If dir_fd is not None, it should be a file descriptor open to a directory,
13103
  and path should be relative; path will then be relative to that directory.
13104
dir_fd may not be implemented on your platform.
13105
  If it is unavailable, using it will raise a NotImplementedError.
13106
[clinic start generated code]*/
13107
13108
static PyObject *
13109
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13110
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
13111
0
{
13112
0
    int result;
13113
0
    int async_err = 0;
13114
0
#ifdef HAVE_MKFIFOAT
13115
0
    int mkfifoat_unavailable = 0;
13116
0
#endif
13117
13118
0
    do {
13119
0
        Py_BEGIN_ALLOW_THREADS
13120
0
#ifdef HAVE_MKFIFOAT
13121
0
        if (dir_fd != DEFAULT_DIR_FD) {
13122
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13123
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13124
13125
0
            } else {
13126
0
                mkfifoat_unavailable = 1;
13127
0
                result = 0;
13128
0
            }
13129
0
        } else
13130
0
#endif
13131
0
            result = mkfifo(path->narrow, mode);
13132
0
        Py_END_ALLOW_THREADS
13133
0
    } while (result != 0 && errno == EINTR &&
13134
0
             !(async_err = PyErr_CheckSignals()));
13135
13136
0
#ifdef HAVE_MKFIFOAT
13137
0
    if (mkfifoat_unavailable) {
13138
0
        argument_unavailable_error(NULL, "dir_fd");
13139
0
        return NULL;
13140
0
    }
13141
0
#endif
13142
13143
0
    if (result != 0)
13144
0
        return (!async_err) ? posix_error() : NULL;
13145
13146
0
    Py_RETURN_NONE;
13147
0
}
13148
#endif /* HAVE_MKFIFO */
13149
13150
13151
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13152
/*[clinic input]
13153
@permit_long_docstring_body
13154
os.mknod
13155
13156
    path: path_t
13157
    mode: int=0o600
13158
    device: dev_t=0
13159
    *
13160
    dir_fd: dir_fd(requires='mknodat')=None
13161
13162
Create a node in the file system.
13163
13164
Create a node in the file system (file, device special file or named pipe)
13165
at path.  mode specifies both the permissions to use and the
13166
type of node to be created, being combined (bitwise OR) with one of
13167
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
13168
device defines the newly created device special file (probably using
13169
os.makedev()).  Otherwise device is ignored.
13170
13171
If dir_fd is not None, it should be a file descriptor open to a directory,
13172
  and path should be relative; path will then be relative to that directory.
13173
dir_fd may not be implemented on your platform.
13174
  If it is unavailable, using it will raise a NotImplementedError.
13175
[clinic start generated code]*/
13176
13177
static PyObject *
13178
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13179
              int dir_fd)
13180
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
13181
0
{
13182
0
    int result;
13183
0
    int async_err = 0;
13184
0
#ifdef HAVE_MKNODAT
13185
0
    int mknodat_unavailable = 0;
13186
0
#endif
13187
13188
0
    do {
13189
0
        Py_BEGIN_ALLOW_THREADS
13190
0
#ifdef HAVE_MKNODAT
13191
0
        if (dir_fd != DEFAULT_DIR_FD) {
13192
0
            if (HAVE_MKNODAT_RUNTIME) {
13193
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13194
13195
0
            } else {
13196
0
                mknodat_unavailable = 1;
13197
0
                result = 0;
13198
0
            }
13199
0
        } else
13200
0
#endif
13201
0
            result = mknod(path->narrow, mode, device);
13202
0
        Py_END_ALLOW_THREADS
13203
0
    } while (result != 0 && errno == EINTR &&
13204
0
             !(async_err = PyErr_CheckSignals()));
13205
0
#ifdef HAVE_MKNODAT
13206
0
    if (mknodat_unavailable) {
13207
0
        argument_unavailable_error(NULL, "dir_fd");
13208
0
        return NULL;
13209
0
    }
13210
0
#endif
13211
0
    if (result != 0)
13212
0
        return (!async_err) ? posix_error() : NULL;
13213
13214
0
    Py_RETURN_NONE;
13215
0
}
13216
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13217
13218
13219
#ifdef HAVE_DEVICE_MACROS
13220
static PyObject *
13221
major_minor_conv(unsigned int value)
13222
0
{
13223
0
#ifdef NODEV
13224
0
    if (value == (unsigned int)NODEV) {
13225
0
        return PyLong_FromLong((int)NODEV);
13226
0
    }
13227
0
#endif
13228
0
    return PyLong_FromUnsignedLong(value);
13229
0
}
13230
13231
static int
13232
major_minor_check(dev_t value)
13233
0
{
13234
0
#ifdef NODEV
13235
0
    if (value == NODEV) {
13236
0
        return 1;
13237
0
    }
13238
0
#endif
13239
0
    return (dev_t)(unsigned int)value == value;
13240
0
}
13241
13242
/*[clinic input]
13243
os.major
13244
13245
    device: dev_t
13246
    /
13247
13248
Extracts a device major number from a raw device number.
13249
[clinic start generated code]*/
13250
13251
static PyObject *
13252
os_major_impl(PyObject *module, dev_t device)
13253
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13254
0
{
13255
0
    return major_minor_conv(major(device));
13256
0
}
13257
13258
13259
/*[clinic input]
13260
os.minor
13261
13262
    device: dev_t
13263
    /
13264
13265
Extracts a device minor number from a raw device number.
13266
[clinic start generated code]*/
13267
13268
static PyObject *
13269
os_minor_impl(PyObject *module, dev_t device)
13270
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13271
0
{
13272
0
    return major_minor_conv(minor(device));
13273
0
}
13274
13275
13276
/*[clinic input]
13277
os.makedev -> dev_t
13278
13279
    major: dev_t
13280
    minor: dev_t
13281
    /
13282
13283
Composes a raw device number from the major and minor device numbers.
13284
[clinic start generated code]*/
13285
13286
static dev_t
13287
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13288
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13289
0
{
13290
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13291
0
        PyErr_SetString(PyExc_OverflowError,
13292
0
                        "Python int too large to convert to C unsigned int");
13293
0
        return (dev_t)-1;
13294
0
    }
13295
0
    return makedev(major, minor);
13296
0
}
13297
#endif /* HAVE_DEVICE_MACROS */
13298
13299
13300
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13301
/*[clinic input]
13302
os.ftruncate
13303
13304
    fd: int
13305
    length: Py_off_t
13306
    /
13307
13308
Truncate a file, specified by file descriptor, to a specific length.
13309
[clinic start generated code]*/
13310
13311
static PyObject *
13312
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13313
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13314
0
{
13315
0
    int result;
13316
0
    int async_err = 0;
13317
13318
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13319
0
        return NULL;
13320
0
    }
13321
13322
0
    do {
13323
0
        Py_BEGIN_ALLOW_THREADS
13324
0
        _Py_BEGIN_SUPPRESS_IPH
13325
#ifdef MS_WINDOWS
13326
        result = _chsize_s(fd, length);
13327
#else
13328
0
        result = ftruncate(fd, length);
13329
0
#endif
13330
0
        _Py_END_SUPPRESS_IPH
13331
0
        Py_END_ALLOW_THREADS
13332
0
    } while (result != 0 && errno == EINTR &&
13333
0
             !(async_err = PyErr_CheckSignals()));
13334
0
    if (result != 0)
13335
0
        return (!async_err) ? posix_error() : NULL;
13336
0
    Py_RETURN_NONE;
13337
0
}
13338
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13339
13340
13341
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13342
/*[clinic input]
13343
os.truncate
13344
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13345
    length: Py_off_t
13346
13347
Truncate a file, specified by path, to a specific length.
13348
13349
On some platforms, path may also be specified as an open file descriptor.
13350
  If this functionality is unavailable, using it raises an exception.
13351
[clinic start generated code]*/
13352
13353
static PyObject *
13354
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13355
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
13356
0
{
13357
0
    int result;
13358
#ifdef MS_WINDOWS
13359
    int fd;
13360
#endif
13361
13362
0
    if (path->is_fd)
13363
0
        return os_ftruncate_impl(module, path->fd, length);
13364
13365
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13366
0
        return NULL;
13367
0
    }
13368
13369
0
    Py_BEGIN_ALLOW_THREADS
13370
0
    _Py_BEGIN_SUPPRESS_IPH
13371
#ifdef MS_WINDOWS
13372
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13373
    if (fd < 0)
13374
        result = -1;
13375
    else {
13376
        result = _chsize_s(fd, length);
13377
        close(fd);
13378
        if (result < 0)
13379
            errno = result;
13380
    }
13381
#else
13382
0
    result = truncate(path->narrow, length);
13383
0
#endif
13384
0
    _Py_END_SUPPRESS_IPH
13385
0
    Py_END_ALLOW_THREADS
13386
0
    if (result < 0)
13387
0
        return posix_path_error(path);
13388
13389
0
    Py_RETURN_NONE;
13390
0
}
13391
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13392
13393
13394
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13395
   OSs, support was dropped in WASI preview2. */
13396
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13397
/*[clinic input]
13398
os.posix_fallocate
13399
13400
    fd: int
13401
    offset: Py_off_t
13402
    length: Py_off_t
13403
    /
13404
13405
Ensure a file has allocated at least a particular number of bytes on disk.
13406
13407
Ensure that the file specified by fd encompasses a range of bytes
13408
starting at offset bytes from the beginning and continuing for length bytes.
13409
[clinic start generated code]*/
13410
13411
static PyObject *
13412
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13413
                        Py_off_t length)
13414
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
13415
0
{
13416
0
    int result;
13417
0
    int async_err = 0;
13418
13419
0
    do {
13420
0
        Py_BEGIN_ALLOW_THREADS
13421
0
        result = posix_fallocate(fd, offset, length);
13422
0
        Py_END_ALLOW_THREADS
13423
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13424
13425
0
    if (result == 0)
13426
0
        Py_RETURN_NONE;
13427
13428
0
    if (async_err)
13429
0
        return NULL;
13430
13431
0
    errno = result;
13432
0
    return posix_error();
13433
0
}
13434
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13435
13436
13437
#if defined(HAVE_POSIX_FADVISE)
13438
/*[clinic input]
13439
os.posix_fadvise
13440
13441
    fd: int
13442
    offset: Py_off_t
13443
    length: Py_off_t
13444
    advice: int
13445
    /
13446
13447
Announce an intention to access data in a specific pattern.
13448
13449
Announce an intention to access data in a specific pattern, thus allowing
13450
the kernel to make optimizations.
13451
The advice applies to the region of the file specified by fd starting at
13452
offset and continuing for length bytes.
13453
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13454
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13455
POSIX_FADV_DONTNEED.
13456
[clinic start generated code]*/
13457
13458
static PyObject *
13459
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13460
                      Py_off_t length, int advice)
13461
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13462
0
{
13463
0
    int result;
13464
0
    int async_err = 0;
13465
13466
0
    do {
13467
0
        Py_BEGIN_ALLOW_THREADS
13468
0
        result = posix_fadvise(fd, offset, length, advice);
13469
0
        Py_END_ALLOW_THREADS
13470
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13471
13472
0
    if (result == 0)
13473
0
        Py_RETURN_NONE;
13474
13475
0
    if (async_err)
13476
0
        return NULL;
13477
13478
0
    errno = result;
13479
0
    return posix_error();
13480
0
}
13481
#endif /* HAVE_POSIX_FADVISE */
13482
13483
13484
#ifdef MS_WINDOWS
13485
static PyObject*
13486
win32_putenv(PyObject *name, PyObject *value)
13487
{
13488
    /* Search from index 1 because on Windows starting '=' is allowed for
13489
       defining hidden environment variables. */
13490
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13491
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13492
    {
13493
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13494
        return NULL;
13495
    }
13496
    PyObject *unicode;
13497
    if (value != NULL) {
13498
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13499
    }
13500
    else {
13501
        unicode = PyUnicode_FromFormat("%U=", name);
13502
    }
13503
    if (unicode == NULL) {
13504
        return NULL;
13505
    }
13506
13507
    Py_ssize_t size;
13508
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13509
    Py_DECREF(unicode);
13510
13511
    if (env == NULL) {
13512
        return NULL;
13513
    }
13514
    if (size > _MAX_ENV) {
13515
        PyErr_Format(PyExc_ValueError,
13516
                     "the environment variable is longer than %u characters",
13517
                     _MAX_ENV);
13518
        PyMem_Free(env);
13519
        return NULL;
13520
    }
13521
    if (wcslen(env) != (size_t)size) {
13522
        PyErr_SetString(PyExc_ValueError,
13523
                        "embedded null character");
13524
        PyMem_Free(env);
13525
        return NULL;
13526
    }
13527
13528
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13529
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13530
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13531
13532
       Prefer _wputenv() to be compatible with C libraries using CRT
13533
       variables and CRT functions using these variables (ex: getenv()). */
13534
    int err = _wputenv(env);
13535
13536
    if (err) {
13537
        posix_error();
13538
        PyMem_Free(env);
13539
        return NULL;
13540
    }
13541
    PyMem_Free(env);
13542
13543
    Py_RETURN_NONE;
13544
}
13545
#endif
13546
13547
13548
#ifdef MS_WINDOWS
13549
/*[clinic input]
13550
os.putenv
13551
13552
    name: unicode
13553
    value: unicode
13554
    /
13555
13556
Change or add an environment variable.
13557
[clinic start generated code]*/
13558
13559
static PyObject *
13560
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13561
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13562
{
13563
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13564
        return NULL;
13565
    }
13566
    return win32_putenv(name, value);
13567
}
13568
#else
13569
/*[clinic input]
13570
os.putenv
13571
13572
    name: unicode_fs_encoded
13573
    value: unicode_fs_encoded
13574
    /
13575
13576
Change or add an environment variable.
13577
[clinic start generated code]*/
13578
13579
static PyObject *
13580
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13581
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13582
0
{
13583
0
    const char *name_string = PyBytes_AS_STRING(name);
13584
0
    const char *value_string = PyBytes_AS_STRING(value);
13585
13586
0
    if (strchr(name_string, '=') != NULL) {
13587
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13588
0
        return NULL;
13589
0
    }
13590
13591
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13592
0
        return NULL;
13593
0
    }
13594
13595
0
    if (setenv(name_string, value_string, 1)) {
13596
0
        return posix_error();
13597
0
    }
13598
0
    Py_RETURN_NONE;
13599
0
}
13600
#endif  /* !defined(MS_WINDOWS) */
13601
13602
13603
#ifdef MS_WINDOWS
13604
/*[clinic input]
13605
os.unsetenv
13606
    name: unicode
13607
    /
13608
13609
Delete an environment variable.
13610
[clinic start generated code]*/
13611
13612
static PyObject *
13613
os_unsetenv_impl(PyObject *module, PyObject *name)
13614
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13615
{
13616
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13617
        return NULL;
13618
    }
13619
    return win32_putenv(name, NULL);
13620
}
13621
#else
13622
/*[clinic input]
13623
os.unsetenv
13624
    name: unicode_fs_encoded
13625
    /
13626
13627
Delete an environment variable.
13628
[clinic start generated code]*/
13629
13630
static PyObject *
13631
os_unsetenv_impl(PyObject *module, PyObject *name)
13632
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13633
0
{
13634
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13635
0
        return NULL;
13636
0
    }
13637
#ifdef HAVE_BROKEN_UNSETENV
13638
    unsetenv(PyBytes_AS_STRING(name));
13639
#else
13640
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13641
0
    if (err) {
13642
0
        return posix_error();
13643
0
    }
13644
0
#endif
13645
13646
0
    Py_RETURN_NONE;
13647
0
}
13648
#endif /* !MS_WINDOWS */
13649
13650
13651
#ifdef HAVE_CLEARENV
13652
/*[clinic input]
13653
os._clearenv
13654
[clinic start generated code]*/
13655
13656
static PyObject *
13657
os__clearenv_impl(PyObject *module)
13658
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13659
0
{
13660
0
    errno = 0;
13661
0
    int err = clearenv();
13662
0
    if (err) {
13663
0
        return posix_error();
13664
0
    }
13665
0
    Py_RETURN_NONE;
13666
0
}
13667
#endif
13668
13669
13670
/*[clinic input]
13671
os.strerror
13672
13673
    code: int
13674
    /
13675
13676
Translate an error code to a message string.
13677
[clinic start generated code]*/
13678
13679
static PyObject *
13680
os_strerror_impl(PyObject *module, int code)
13681
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13682
0
{
13683
0
    char *message = strerror(code);
13684
0
    if (message == NULL) {
13685
0
        PyErr_SetString(PyExc_ValueError,
13686
0
                        "strerror() argument out of range");
13687
0
        return NULL;
13688
0
    }
13689
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13690
0
}
13691
13692
13693
#ifdef HAVE_SYS_WAIT_H
13694
#ifdef WCOREDUMP
13695
/*[clinic input]
13696
os.WCOREDUMP -> bool
13697
13698
    status: int
13699
    /
13700
13701
Return True if the process returning status was dumped to a core file.
13702
[clinic start generated code]*/
13703
13704
static int
13705
os_WCOREDUMP_impl(PyObject *module, int status)
13706
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13707
0
{
13708
0
    WAIT_TYPE wait_status;
13709
0
    WAIT_STATUS_INT(wait_status) = status;
13710
0
    return WCOREDUMP(wait_status);
13711
0
}
13712
#endif /* WCOREDUMP */
13713
13714
13715
#ifdef WIFCONTINUED
13716
/*[clinic input]
13717
os.WIFCONTINUED -> bool
13718
13719
    status: int
13720
13721
Return True if a particular process was continued from a job control stop.
13722
13723
Return True if the process returning status was continued from a
13724
job control stop.
13725
[clinic start generated code]*/
13726
13727
static int
13728
os_WIFCONTINUED_impl(PyObject *module, int status)
13729
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13730
0
{
13731
0
    WAIT_TYPE wait_status;
13732
0
    WAIT_STATUS_INT(wait_status) = status;
13733
0
    return WIFCONTINUED(wait_status);
13734
0
}
13735
#endif /* WIFCONTINUED */
13736
13737
13738
#ifdef WIFSTOPPED
13739
/*[clinic input]
13740
os.WIFSTOPPED -> bool
13741
13742
    status: int
13743
13744
Return True if the process returning status was stopped.
13745
[clinic start generated code]*/
13746
13747
static int
13748
os_WIFSTOPPED_impl(PyObject *module, int status)
13749
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13750
0
{
13751
0
    WAIT_TYPE wait_status;
13752
0
    WAIT_STATUS_INT(wait_status) = status;
13753
0
    return WIFSTOPPED(wait_status);
13754
0
}
13755
#endif /* WIFSTOPPED */
13756
13757
13758
#ifdef WIFSIGNALED
13759
/*[clinic input]
13760
os.WIFSIGNALED -> bool
13761
13762
    status: int
13763
13764
Return True if the process returning status was terminated by a signal.
13765
[clinic start generated code]*/
13766
13767
static int
13768
os_WIFSIGNALED_impl(PyObject *module, int status)
13769
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13770
0
{
13771
0
    WAIT_TYPE wait_status;
13772
0
    WAIT_STATUS_INT(wait_status) = status;
13773
0
    return WIFSIGNALED(wait_status);
13774
0
}
13775
#endif /* WIFSIGNALED */
13776
13777
13778
#ifdef WIFEXITED
13779
/*[clinic input]
13780
@permit_long_summary
13781
os.WIFEXITED -> bool
13782
13783
    status: int
13784
13785
Return True if the process returning status exited via the exit() system call.
13786
[clinic start generated code]*/
13787
13788
static int
13789
os_WIFEXITED_impl(PyObject *module, int status)
13790
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13791
0
{
13792
0
    WAIT_TYPE wait_status;
13793
0
    WAIT_STATUS_INT(wait_status) = status;
13794
0
    return WIFEXITED(wait_status);
13795
0
}
13796
#endif /* WIFEXITED */
13797
13798
13799
#ifdef WEXITSTATUS
13800
/*[clinic input]
13801
os.WEXITSTATUS -> int
13802
13803
    status: int
13804
13805
Return the process return code from status.
13806
[clinic start generated code]*/
13807
13808
static int
13809
os_WEXITSTATUS_impl(PyObject *module, int status)
13810
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13811
0
{
13812
0
    WAIT_TYPE wait_status;
13813
0
    WAIT_STATUS_INT(wait_status) = status;
13814
0
    return WEXITSTATUS(wait_status);
13815
0
}
13816
#endif /* WEXITSTATUS */
13817
13818
13819
#ifdef WTERMSIG
13820
/*[clinic input]
13821
@permit_long_summary
13822
os.WTERMSIG -> int
13823
13824
    status: int
13825
13826
Return the signal that terminated the process that provided the status value.
13827
[clinic start generated code]*/
13828
13829
static int
13830
os_WTERMSIG_impl(PyObject *module, int status)
13831
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13832
0
{
13833
0
    WAIT_TYPE wait_status;
13834
0
    WAIT_STATUS_INT(wait_status) = status;
13835
0
    return WTERMSIG(wait_status);
13836
0
}
13837
#endif /* WTERMSIG */
13838
13839
13840
#ifdef WSTOPSIG
13841
/*[clinic input]
13842
os.WSTOPSIG -> int
13843
13844
    status: int
13845
13846
Return the signal that stopped the process that provided the status value.
13847
[clinic start generated code]*/
13848
13849
static int
13850
os_WSTOPSIG_impl(PyObject *module, int status)
13851
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13852
0
{
13853
0
    WAIT_TYPE wait_status;
13854
0
    WAIT_STATUS_INT(wait_status) = status;
13855
0
    return WSTOPSIG(wait_status);
13856
0
}
13857
#endif /* WSTOPSIG */
13858
#endif /* HAVE_SYS_WAIT_H */
13859
13860
13861
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13862
#ifdef _SCO_DS
13863
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13864
   needed definitions in sys/statvfs.h */
13865
#define _SVID3
13866
#endif
13867
#include <sys/statvfs.h>
13868
13869
#ifdef __APPLE__
13870
/* On macOS struct statvfs uses 32-bit integers for block counts,
13871
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13872
 * os.statvfs is implemented in terms of statfs(2).
13873
 */
13874
13875
static PyObject*
13876
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13877
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13878
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13879
    if (v == NULL) {
13880
        return NULL;
13881
    }
13882
13883
    long flags = 0;
13884
    if (st.f_flags & MNT_RDONLY) {
13885
        flags |= ST_RDONLY;
13886
    }
13887
    if (st.f_flags & MNT_NOSUID) {
13888
        flags |= ST_NOSUID;
13889
    }
13890
13891
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13892
13893
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13894
    do {                                                 \
13895
        PyObject *obj = (EXPR);                          \
13896
        if (obj == NULL) {                               \
13897
            Py_DECREF((SEQ));                            \
13898
            return NULL;                                 \
13899
        }                                                \
13900
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13901
    } while (0)
13902
13903
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13904
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13905
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13906
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13907
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13908
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13909
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13910
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13911
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13912
13913
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13914
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13915
13916
#undef SET_ITEM
13917
13918
    return v;
13919
}
13920
13921
#else
13922
13923
13924
13925
static PyObject*
13926
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13927
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13928
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13929
0
    if (v == NULL)
13930
0
        return NULL;
13931
13932
0
    int pos = 0;
13933
13934
0
#define SET_RESULT(CALL)                                     \
13935
0
    do {                                                     \
13936
0
        PyObject *item = (CALL);                             \
13937
0
        if (item == NULL) {                                  \
13938
0
            Py_DECREF(v);                                    \
13939
0
            return NULL;                                     \
13940
0
        }                                                    \
13941
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13942
0
    } while(0)
13943
13944
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13945
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13946
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13947
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13948
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13949
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13950
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13951
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13952
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13953
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13954
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13955
#else
13956
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13957
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13958
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13959
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13960
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13961
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13962
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13963
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13964
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13965
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13966
#endif
13967
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13968
 * (issue #32390). */
13969
#if defined(_AIX) && defined(_ALL_SOURCE)
13970
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13971
#else
13972
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13973
0
#endif
13974
13975
0
#undef SET_RESULT
13976
13977
0
    return v;
13978
0
}
13979
13980
#endif
13981
13982
13983
/*[clinic input]
13984
os.fstatvfs
13985
    fd: int
13986
    /
13987
13988
Perform an fstatvfs system call on the given fd.
13989
13990
Equivalent to statvfs(fd).
13991
[clinic start generated code]*/
13992
13993
static PyObject *
13994
os_fstatvfs_impl(PyObject *module, int fd)
13995
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13996
0
{
13997
0
    int result;
13998
0
    int async_err = 0;
13999
#ifdef __APPLE__
14000
    struct statfs st;
14001
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
14002
     * the former uses 32-bit values for block counts.
14003
     */
14004
    do {
14005
        Py_BEGIN_ALLOW_THREADS
14006
        result = fstatfs(fd, &st);
14007
        Py_END_ALLOW_THREADS
14008
    } while (result != 0 && errno == EINTR &&
14009
             !(async_err = PyErr_CheckSignals()));
14010
    if (result != 0)
14011
        return (!async_err) ? posix_error() : NULL;
14012
14013
    return _pystatvfs_fromstructstatfs(module, st);
14014
#else
14015
0
    struct statvfs st;
14016
14017
0
    do {
14018
0
        Py_BEGIN_ALLOW_THREADS
14019
0
        result = fstatvfs(fd, &st);
14020
0
        Py_END_ALLOW_THREADS
14021
0
    } while (result != 0 && errno == EINTR &&
14022
0
             !(async_err = PyErr_CheckSignals()));
14023
0
    if (result != 0)
14024
0
        return (!async_err) ? posix_error() : NULL;
14025
14026
0
    return _pystatvfs_fromstructstatvfs(module, st);
14027
0
#endif
14028
0
}
14029
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14030
14031
14032
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14033
#include <sys/statvfs.h>
14034
/*[clinic input]
14035
os.statvfs
14036
14037
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14038
14039
Perform a statvfs system call on the given path.
14040
14041
path may always be specified as a string.
14042
On some platforms, path may also be specified as an open file descriptor.
14043
  If this functionality is unavailable, using it raises an exception.
14044
[clinic start generated code]*/
14045
14046
static PyObject *
14047
os_statvfs_impl(PyObject *module, path_t *path)
14048
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
14049
0
{
14050
0
    int result;
14051
14052
#ifdef __APPLE__
14053
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14054
     * the former uses 32-bit values for block counts.
14055
     */
14056
    struct statfs st;
14057
14058
    Py_BEGIN_ALLOW_THREADS
14059
    if (path->is_fd) {
14060
        result = fstatfs(path->fd, &st);
14061
    }
14062
    else
14063
        result = statfs(path->narrow, &st);
14064
    Py_END_ALLOW_THREADS
14065
14066
    if (result) {
14067
        return path_error(path);
14068
    }
14069
14070
    return _pystatvfs_fromstructstatfs(module, st);
14071
14072
#else
14073
0
    struct statvfs st;
14074
14075
0
    Py_BEGIN_ALLOW_THREADS
14076
0
#ifdef HAVE_FSTATVFS
14077
0
    if (path->is_fd) {
14078
0
        result = fstatvfs(path->fd, &st);
14079
0
    }
14080
0
    else
14081
0
#endif
14082
0
        result = statvfs(path->narrow, &st);
14083
0
    Py_END_ALLOW_THREADS
14084
14085
0
    if (result) {
14086
0
        return path_error(path);
14087
0
    }
14088
14089
0
    return _pystatvfs_fromstructstatvfs(module, st);
14090
0
#endif
14091
0
}
14092
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14093
14094
14095
#ifdef MS_WINDOWS
14096
/*[clinic input]
14097
os._getdiskusage
14098
14099
    path: path_t
14100
14101
Return disk usage statistics about the given path as a (total, free) tuple.
14102
[clinic start generated code]*/
14103
14104
static PyObject *
14105
os__getdiskusage_impl(PyObject *module, path_t *path)
14106
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
14107
{
14108
    BOOL retval;
14109
    ULARGE_INTEGER _, total, free;
14110
    DWORD err = 0;
14111
14112
    Py_BEGIN_ALLOW_THREADS
14113
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14114
    Py_END_ALLOW_THREADS
14115
    if (retval == 0) {
14116
        if (GetLastError() == ERROR_DIRECTORY) {
14117
            wchar_t *dir_path = NULL;
14118
14119
            dir_path = PyMem_New(wchar_t, path->length + 1);
14120
            if (dir_path == NULL) {
14121
                return PyErr_NoMemory();
14122
            }
14123
14124
            wcscpy_s(dir_path, path->length + 1, path->wide);
14125
14126
            if (_dirnameW(dir_path) != -1) {
14127
                Py_BEGIN_ALLOW_THREADS
14128
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14129
                Py_END_ALLOW_THREADS
14130
            }
14131
            /* Record the last error in case it's modified by PyMem_Free. */
14132
            err = GetLastError();
14133
            PyMem_Free(dir_path);
14134
            if (retval) {
14135
                goto success;
14136
            }
14137
        }
14138
        return PyErr_SetFromWindowsErr(err);
14139
    }
14140
14141
success:
14142
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14143
}
14144
#endif /* MS_WINDOWS */
14145
14146
14147
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14148
 * It maps strings representing configuration variable names to
14149
 * integer values, allowing those functions to be called with the
14150
 * magic names instead of polluting the module's namespace with tons of
14151
 * rarely-used constants.  There are three separate tables that use
14152
 * these definitions.
14153
 *
14154
 * This code is always included, even if none of the interfaces that
14155
 * need it are included.  The #if hackery needed to avoid it would be
14156
 * sufficiently pervasive that it's not worth the loss of readability.
14157
 */
14158
struct constdef {
14159
    const char *name;
14160
    int value;
14161
};
14162
14163
static int
14164
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14165
8
{
14166
8
    if (PyUnicode_Check(arg)) {
14167
8
        PyObject *table = PyObject_GetAttrString(module, tablename);
14168
8
        if (table == NULL) {
14169
0
            return 0;
14170
0
        }
14171
14172
8
        arg = PyObject_GetItem(table, arg);
14173
8
        Py_DECREF(table);
14174
8
        if (arg == NULL) {
14175
0
            PyErr_SetString(
14176
0
                PyExc_ValueError, "unrecognized configuration name");
14177
0
            return 0;
14178
0
        }
14179
8
    } else {
14180
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14181
0
    }
14182
14183
8
    int success = 0;
14184
8
    if (!PyIndex_Check(arg)) {
14185
0
        PyErr_SetString(PyExc_TypeError,
14186
0
            "configuration names must be strings or integers");
14187
8
    } else {
14188
8
        int value = PyLong_AsInt(arg);
14189
8
        if (!(value == -1 && PyErr_Occurred())) {
14190
8
            *valuep = value;
14191
8
            success = 1;
14192
8
        }
14193
8
    }
14194
8
    Py_DECREF(arg);
14195
8
    return success;
14196
8
}
14197
14198
14199
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14200
static struct constdef  posix_constants_pathconf[] = {
14201
#ifdef _PC_ABI_AIO_XFER_MAX
14202
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14203
#endif
14204
#ifdef _PC_ABI_ASYNC_IO
14205
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14206
#endif
14207
#ifdef _PC_ASYNC_IO
14208
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14209
#endif
14210
#ifdef _PC_CHOWN_RESTRICTED
14211
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14212
#endif
14213
#ifdef _PC_FILESIZEBITS
14214
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14215
#endif
14216
#ifdef _PC_LAST
14217
    {"PC_LAST", _PC_LAST},
14218
#endif
14219
#ifdef _PC_LINK_MAX
14220
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14221
#endif
14222
#ifdef _PC_MAX_CANON
14223
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14224
#endif
14225
#ifdef _PC_MAX_INPUT
14226
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14227
#endif
14228
#ifdef _PC_NAME_MAX
14229
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14230
#endif
14231
#ifdef _PC_NO_TRUNC
14232
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14233
#endif
14234
#ifdef _PC_PATH_MAX
14235
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14236
#endif
14237
#ifdef _PC_PIPE_BUF
14238
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14239
#endif
14240
#ifdef _PC_PRIO_IO
14241
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14242
#endif
14243
#ifdef _PC_SOCK_MAXBUF
14244
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14245
#endif
14246
#ifdef _PC_SYNC_IO
14247
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14248
#endif
14249
#ifdef _PC_VDISABLE
14250
    {"PC_VDISABLE",     _PC_VDISABLE},
14251
#endif
14252
#ifdef _PC_ACL_ENABLED
14253
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14254
#endif
14255
#ifdef _PC_MIN_HOLE_SIZE
14256
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14257
#endif
14258
#ifdef _PC_ALLOC_SIZE_MIN
14259
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14260
#endif
14261
#ifdef _PC_REC_INCR_XFER_SIZE
14262
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14263
#endif
14264
#ifdef _PC_REC_MAX_XFER_SIZE
14265
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14266
#endif
14267
#ifdef _PC_REC_MIN_XFER_SIZE
14268
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14269
#endif
14270
#ifdef _PC_REC_XFER_ALIGN
14271
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14272
#endif
14273
#ifdef _PC_SYMLINK_MAX
14274
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14275
#endif
14276
#ifdef _PC_XATTR_ENABLED
14277
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14278
#endif
14279
#ifdef _PC_XATTR_EXISTS
14280
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14281
#endif
14282
#ifdef _PC_TIMESTAMP_RESOLUTION
14283
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14284
#endif
14285
};
14286
#endif
14287
14288
14289
#ifdef HAVE_FPATHCONF
14290
/*[clinic input]
14291
os.fpathconf -> long
14292
14293
    fd: fildes
14294
    name: confname(table="pathconf_names")
14295
    /
14296
14297
Return the configuration limit name for the file descriptor fd.
14298
14299
If there is no limit, return -1.
14300
[clinic start generated code]*/
14301
14302
static long
14303
os_fpathconf_impl(PyObject *module, int fd, int name)
14304
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14305
0
{
14306
0
    long limit;
14307
14308
0
    errno = 0;
14309
0
    limit = fpathconf(fd, name);
14310
0
    if (limit == -1 && errno != 0)
14311
0
        posix_error();
14312
14313
0
    return limit;
14314
0
}
14315
#endif /* HAVE_FPATHCONF */
14316
14317
14318
#ifdef HAVE_PATHCONF
14319
/*[clinic input]
14320
os.pathconf -> long
14321
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14322
    name: confname(table="pathconf_names")
14323
14324
Return the configuration limit name for the file or directory path.
14325
14326
If there is no limit, return -1.
14327
On some platforms, path may also be specified as an open file descriptor.
14328
  If this functionality is unavailable, using it raises an exception.
14329
[clinic start generated code]*/
14330
14331
static long
14332
os_pathconf_impl(PyObject *module, path_t *path, int name)
14333
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
14334
0
{
14335
0
    long limit;
14336
14337
0
    errno = 0;
14338
0
#ifdef HAVE_FPATHCONF
14339
0
    if (path->is_fd) {
14340
0
        limit = fpathconf(path->fd, name);
14341
0
    }
14342
0
    else
14343
0
#endif
14344
0
        limit = pathconf(path->narrow, name);
14345
0
    if (limit == -1 && errno != 0) {
14346
0
        if (errno == EINVAL)
14347
            /* could be a path or name problem */
14348
0
            posix_error();
14349
0
        else
14350
0
            path_error(path);
14351
0
    }
14352
14353
0
    return limit;
14354
0
}
14355
#endif /* HAVE_PATHCONF */
14356
14357
#ifdef HAVE_CONFSTR
14358
static struct constdef posix_constants_confstr[] = {
14359
#ifdef _CS_ARCHITECTURE
14360
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14361
#endif
14362
#ifdef _CS_GNU_LIBC_VERSION
14363
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14364
#endif
14365
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14366
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14367
#endif
14368
#ifdef _CS_HOSTNAME
14369
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14370
#endif
14371
#ifdef _CS_HW_PROVIDER
14372
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14373
#endif
14374
#ifdef _CS_HW_SERIAL
14375
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14376
#endif
14377
#ifdef _CS_INITTAB_NAME
14378
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14379
#endif
14380
#ifdef _CS_LFS64_CFLAGS
14381
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14382
#endif
14383
#ifdef _CS_LFS64_LDFLAGS
14384
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14385
#endif
14386
#ifdef _CS_LFS64_LIBS
14387
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14388
#endif
14389
#ifdef _CS_LFS64_LINTFLAGS
14390
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14391
#endif
14392
#ifdef _CS_LFS_CFLAGS
14393
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14394
#endif
14395
#ifdef _CS_LFS_LDFLAGS
14396
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14397
#endif
14398
#ifdef _CS_LFS_LIBS
14399
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14400
#endif
14401
#ifdef _CS_LFS_LINTFLAGS
14402
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14403
#endif
14404
#ifdef _CS_MACHINE
14405
    {"CS_MACHINE",      _CS_MACHINE},
14406
#endif
14407
#ifdef _CS_PATH
14408
    {"CS_PATH", _CS_PATH},
14409
#endif
14410
#ifdef _CS_RELEASE
14411
    {"CS_RELEASE",      _CS_RELEASE},
14412
#endif
14413
#ifdef _CS_SRPC_DOMAIN
14414
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14415
#endif
14416
#ifdef _CS_SYSNAME
14417
    {"CS_SYSNAME",      _CS_SYSNAME},
14418
#endif
14419
#ifdef _CS_VERSION
14420
    {"CS_VERSION",      _CS_VERSION},
14421
#endif
14422
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14423
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14424
#endif
14425
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14426
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14427
#endif
14428
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14429
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14430
#endif
14431
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14432
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14433
#endif
14434
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14435
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14436
#endif
14437
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14438
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14439
#endif
14440
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14441
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14442
#endif
14443
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14444
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14445
#endif
14446
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14447
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14448
#endif
14449
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14450
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14451
#endif
14452
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14453
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14454
#endif
14455
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14456
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14457
#endif
14458
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14459
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14460
#endif
14461
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14462
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14463
#endif
14464
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14465
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14466
#endif
14467
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14468
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14469
#endif
14470
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14471
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14472
#endif
14473
#ifdef _MIPS_CS_BASE
14474
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14475
#endif
14476
#ifdef _MIPS_CS_HOSTID
14477
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14478
#endif
14479
#ifdef _MIPS_CS_HW_NAME
14480
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14481
#endif
14482
#ifdef _MIPS_CS_NUM_PROCESSORS
14483
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14484
#endif
14485
#ifdef _MIPS_CS_OSREL_MAJ
14486
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14487
#endif
14488
#ifdef _MIPS_CS_OSREL_MIN
14489
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14490
#endif
14491
#ifdef _MIPS_CS_OSREL_PATCH
14492
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14493
#endif
14494
#ifdef _MIPS_CS_OS_NAME
14495
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14496
#endif
14497
#ifdef _MIPS_CS_OS_PROVIDER
14498
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14499
#endif
14500
#ifdef _MIPS_CS_PROCESSORS
14501
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14502
#endif
14503
#ifdef _MIPS_CS_SERIAL
14504
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14505
#endif
14506
#ifdef _MIPS_CS_VENDOR
14507
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14508
#endif
14509
};
14510
14511
14512
/*[clinic input]
14513
os.confstr
14514
14515
    name: confname(table="confstr_names")
14516
    /
14517
14518
Return a string-valued system configuration variable.
14519
[clinic start generated code]*/
14520
14521
static PyObject *
14522
os_confstr_impl(PyObject *module, int name)
14523
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14524
4
{
14525
4
    PyObject *result = NULL;
14526
4
    char buffer[255];
14527
4
    size_t len;
14528
14529
4
    errno = 0;
14530
4
    len = confstr(name, buffer, sizeof(buffer));
14531
4
    if (len == 0) {
14532
0
        if (errno) {
14533
0
            posix_error();
14534
0
            return NULL;
14535
0
        }
14536
0
        else {
14537
0
            Py_RETURN_NONE;
14538
0
        }
14539
0
    }
14540
14541
4
    if (len >= sizeof(buffer)) {
14542
0
        size_t len2;
14543
0
        char *buf = PyMem_Malloc(len);
14544
0
        if (buf == NULL)
14545
0
            return PyErr_NoMemory();
14546
0
        len2 = confstr(name, buf, len);
14547
0
        assert(len == len2);
14548
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14549
0
        PyMem_Free(buf);
14550
0
    }
14551
4
    else
14552
4
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14553
4
    return result;
14554
4
}
14555
#endif /* HAVE_CONFSTR */
14556
14557
14558
#ifdef HAVE_SYSCONF
14559
static struct constdef posix_constants_sysconf[] = {
14560
#ifdef _SC_2_CHAR_TERM
14561
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14562
#endif
14563
#ifdef _SC_2_C_BIND
14564
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14565
#endif
14566
#ifdef _SC_2_C_DEV
14567
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14568
#endif
14569
#ifdef _SC_2_C_VERSION
14570
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14571
#endif
14572
#ifdef _SC_2_FORT_DEV
14573
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14574
#endif
14575
#ifdef _SC_2_FORT_RUN
14576
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14577
#endif
14578
#ifdef _SC_2_LOCALEDEF
14579
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14580
#endif
14581
#ifdef _SC_2_SW_DEV
14582
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14583
#endif
14584
#ifdef _SC_2_UPE
14585
    {"SC_2_UPE",        _SC_2_UPE},
14586
#endif
14587
#ifdef _SC_2_VERSION
14588
    {"SC_2_VERSION",    _SC_2_VERSION},
14589
#endif
14590
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14591
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14592
#endif
14593
#ifdef _SC_ACL
14594
    {"SC_ACL",  _SC_ACL},
14595
#endif
14596
#ifdef _SC_AIO_LISTIO_MAX
14597
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14598
#endif
14599
#ifdef _SC_AIO_MAX
14600
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14601
#endif
14602
#ifdef _SC_AIO_PRIO_DELTA_MAX
14603
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14604
#endif
14605
#ifdef _SC_ARG_MAX
14606
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14607
#endif
14608
#ifdef _SC_ASYNCHRONOUS_IO
14609
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14610
#endif
14611
#ifdef _SC_ATEXIT_MAX
14612
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14613
#endif
14614
#ifdef _SC_AUDIT
14615
    {"SC_AUDIT",        _SC_AUDIT},
14616
#endif
14617
#ifdef _SC_AVPHYS_PAGES
14618
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14619
#endif
14620
#ifdef _SC_BC_BASE_MAX
14621
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14622
#endif
14623
#ifdef _SC_BC_DIM_MAX
14624
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14625
#endif
14626
#ifdef _SC_BC_SCALE_MAX
14627
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14628
#endif
14629
#ifdef _SC_BC_STRING_MAX
14630
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14631
#endif
14632
#ifdef _SC_CAP
14633
    {"SC_CAP",  _SC_CAP},
14634
#endif
14635
#ifdef _SC_CHARCLASS_NAME_MAX
14636
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14637
#endif
14638
#ifdef _SC_CHAR_BIT
14639
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14640
#endif
14641
#ifdef _SC_CHAR_MAX
14642
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14643
#endif
14644
#ifdef _SC_CHAR_MIN
14645
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14646
#endif
14647
#ifdef _SC_CHILD_MAX
14648
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14649
#endif
14650
#ifdef _SC_CLK_TCK
14651
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14652
#endif
14653
#ifdef _SC_COHER_BLKSZ
14654
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14655
#endif
14656
#ifdef _SC_COLL_WEIGHTS_MAX
14657
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14658
#endif
14659
#ifdef _SC_DCACHE_ASSOC
14660
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14661
#endif
14662
#ifdef _SC_DCACHE_BLKSZ
14663
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14664
#endif
14665
#ifdef _SC_DCACHE_LINESZ
14666
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14667
#endif
14668
#ifdef _SC_DCACHE_SZ
14669
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14670
#endif
14671
#ifdef _SC_DCACHE_TBLKSZ
14672
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14673
#endif
14674
#ifdef _SC_DELAYTIMER_MAX
14675
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14676
#endif
14677
#ifdef _SC_EQUIV_CLASS_MAX
14678
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14679
#endif
14680
#ifdef _SC_EXPR_NEST_MAX
14681
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14682
#endif
14683
#ifdef _SC_FSYNC
14684
    {"SC_FSYNC",        _SC_FSYNC},
14685
#endif
14686
#ifdef _SC_GETGR_R_SIZE_MAX
14687
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14688
#endif
14689
#ifdef _SC_GETPW_R_SIZE_MAX
14690
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14691
#endif
14692
#ifdef _SC_ICACHE_ASSOC
14693
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14694
#endif
14695
#ifdef _SC_ICACHE_BLKSZ
14696
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14697
#endif
14698
#ifdef _SC_ICACHE_LINESZ
14699
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14700
#endif
14701
#ifdef _SC_ICACHE_SZ
14702
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14703
#endif
14704
#ifdef _SC_INF
14705
    {"SC_INF",  _SC_INF},
14706
#endif
14707
#ifdef _SC_INT_MAX
14708
    {"SC_INT_MAX",      _SC_INT_MAX},
14709
#endif
14710
#ifdef _SC_INT_MIN
14711
    {"SC_INT_MIN",      _SC_INT_MIN},
14712
#endif
14713
#ifdef _SC_IOV_MAX
14714
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14715
#endif
14716
#ifdef _SC_IP_SECOPTS
14717
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14718
#endif
14719
#ifdef _SC_JOB_CONTROL
14720
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14721
#endif
14722
#ifdef _SC_KERN_POINTERS
14723
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14724
#endif
14725
#ifdef _SC_KERN_SIM
14726
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14727
#endif
14728
#ifdef _SC_LINE_MAX
14729
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14730
#endif
14731
#ifdef _SC_LOGIN_NAME_MAX
14732
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14733
#endif
14734
#ifdef _SC_LOGNAME_MAX
14735
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14736
#endif
14737
#ifdef _SC_LONG_BIT
14738
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14739
#endif
14740
#ifdef _SC_MAC
14741
    {"SC_MAC",  _SC_MAC},
14742
#endif
14743
#ifdef _SC_MAPPED_FILES
14744
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14745
#endif
14746
#ifdef _SC_MAXPID
14747
    {"SC_MAXPID",       _SC_MAXPID},
14748
#endif
14749
#ifdef _SC_MB_LEN_MAX
14750
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14751
#endif
14752
#ifdef _SC_MEMLOCK
14753
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14754
#endif
14755
#ifdef _SC_MEMLOCK_RANGE
14756
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14757
#endif
14758
#ifdef _SC_MEMORY_PROTECTION
14759
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14760
#endif
14761
#ifdef _SC_MESSAGE_PASSING
14762
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14763
#endif
14764
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14765
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14766
#endif
14767
#ifdef _SC_MQ_OPEN_MAX
14768
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14769
#endif
14770
#ifdef _SC_MQ_PRIO_MAX
14771
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14772
#endif
14773
#ifdef _SC_NACLS_MAX
14774
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14775
#endif
14776
#ifdef _SC_NGROUPS_MAX
14777
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14778
#endif
14779
#ifdef _SC_NL_ARGMAX
14780
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14781
#endif
14782
#ifdef _SC_NL_LANGMAX
14783
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14784
#endif
14785
#ifdef _SC_NL_MSGMAX
14786
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14787
#endif
14788
#ifdef _SC_NL_NMAX
14789
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14790
#endif
14791
#ifdef _SC_NL_SETMAX
14792
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14793
#endif
14794
#ifdef _SC_NL_TEXTMAX
14795
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14796
#endif
14797
#ifdef _SC_NPROCESSORS_CONF
14798
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14799
#endif
14800
#ifdef _SC_NPROCESSORS_ONLN
14801
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14802
#endif
14803
#ifdef _SC_NPROC_CONF
14804
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14805
#endif
14806
#ifdef _SC_NPROC_ONLN
14807
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14808
#endif
14809
#ifdef _SC_NZERO
14810
    {"SC_NZERO",        _SC_NZERO},
14811
#endif
14812
#ifdef _SC_OPEN_MAX
14813
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14814
#endif
14815
#ifdef _SC_PAGESIZE
14816
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14817
#endif
14818
#ifdef _SC_PAGE_SIZE
14819
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14820
#endif
14821
#ifdef _SC_AIX_REALMEM
14822
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14823
#endif
14824
#ifdef _SC_PASS_MAX
14825
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14826
#endif
14827
#ifdef _SC_PHYS_PAGES
14828
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14829
#endif
14830
#ifdef _SC_PII
14831
    {"SC_PII",  _SC_PII},
14832
#endif
14833
#ifdef _SC_PII_INTERNET
14834
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14835
#endif
14836
#ifdef _SC_PII_INTERNET_DGRAM
14837
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14838
#endif
14839
#ifdef _SC_PII_INTERNET_STREAM
14840
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14841
#endif
14842
#ifdef _SC_PII_OSI
14843
    {"SC_PII_OSI",      _SC_PII_OSI},
14844
#endif
14845
#ifdef _SC_PII_OSI_CLTS
14846
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14847
#endif
14848
#ifdef _SC_PII_OSI_COTS
14849
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14850
#endif
14851
#ifdef _SC_PII_OSI_M
14852
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14853
#endif
14854
#ifdef _SC_PII_SOCKET
14855
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14856
#endif
14857
#ifdef _SC_PII_XTI
14858
    {"SC_PII_XTI",      _SC_PII_XTI},
14859
#endif
14860
#ifdef _SC_POLL
14861
    {"SC_POLL", _SC_POLL},
14862
#endif
14863
#ifdef _SC_PRIORITIZED_IO
14864
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14865
#endif
14866
#ifdef _SC_PRIORITY_SCHEDULING
14867
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14868
#endif
14869
#ifdef _SC_REALTIME_SIGNALS
14870
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14871
#endif
14872
#ifdef _SC_RE_DUP_MAX
14873
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14874
#endif
14875
#ifdef _SC_RTSIG_MAX
14876
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14877
#endif
14878
#ifdef _SC_SAVED_IDS
14879
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14880
#endif
14881
#ifdef _SC_SCHAR_MAX
14882
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14883
#endif
14884
#ifdef _SC_SCHAR_MIN
14885
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14886
#endif
14887
#ifdef _SC_SELECT
14888
    {"SC_SELECT",       _SC_SELECT},
14889
#endif
14890
#ifdef _SC_SEMAPHORES
14891
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14892
#endif
14893
#ifdef _SC_SEM_NSEMS_MAX
14894
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14895
#endif
14896
#ifdef _SC_SEM_VALUE_MAX
14897
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14898
#endif
14899
#ifdef _SC_SHARED_MEMORY_OBJECTS
14900
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14901
#endif
14902
#ifdef _SC_SHRT_MAX
14903
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14904
#endif
14905
#ifdef _SC_SHRT_MIN
14906
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14907
#endif
14908
#ifdef _SC_SIGQUEUE_MAX
14909
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14910
#endif
14911
#ifdef _SC_SIGRT_MAX
14912
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14913
#endif
14914
#ifdef _SC_SIGRT_MIN
14915
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14916
#endif
14917
#ifdef _SC_SOFTPOWER
14918
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14919
#endif
14920
#ifdef _SC_SPLIT_CACHE
14921
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14922
#endif
14923
#ifdef _SC_SSIZE_MAX
14924
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14925
#endif
14926
#ifdef _SC_STACK_PROT
14927
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14928
#endif
14929
#ifdef _SC_STREAM_MAX
14930
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14931
#endif
14932
#ifdef _SC_SYNCHRONIZED_IO
14933
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14934
#endif
14935
#ifdef _SC_THREADS
14936
    {"SC_THREADS",      _SC_THREADS},
14937
#endif
14938
#ifdef _SC_THREAD_ATTR_STACKADDR
14939
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14940
#endif
14941
#ifdef _SC_THREAD_ATTR_STACKSIZE
14942
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14943
#endif
14944
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14945
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14946
#endif
14947
#ifdef _SC_THREAD_KEYS_MAX
14948
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14949
#endif
14950
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14951
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14952
#endif
14953
#ifdef _SC_THREAD_PRIO_INHERIT
14954
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14955
#endif
14956
#ifdef _SC_THREAD_PRIO_PROTECT
14957
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14958
#endif
14959
#ifdef _SC_THREAD_PROCESS_SHARED
14960
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14961
#endif
14962
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14963
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14964
#endif
14965
#ifdef _SC_THREAD_STACK_MIN
14966
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14967
#endif
14968
#ifdef _SC_THREAD_THREADS_MAX
14969
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14970
#endif
14971
#ifdef _SC_TIMERS
14972
    {"SC_TIMERS",       _SC_TIMERS},
14973
#endif
14974
#ifdef _SC_TIMER_MAX
14975
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14976
#endif
14977
#ifdef _SC_TTY_NAME_MAX
14978
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14979
#endif
14980
#ifdef _SC_TZNAME_MAX
14981
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14982
#endif
14983
#ifdef _SC_T_IOV_MAX
14984
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14985
#endif
14986
#ifdef _SC_UCHAR_MAX
14987
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14988
#endif
14989
#ifdef _SC_UINT_MAX
14990
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14991
#endif
14992
#ifdef _SC_UIO_MAXIOV
14993
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14994
#endif
14995
#ifdef _SC_ULONG_MAX
14996
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14997
#endif
14998
#ifdef _SC_USHRT_MAX
14999
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
15000
#endif
15001
#ifdef _SC_VERSION
15002
    {"SC_VERSION",      _SC_VERSION},
15003
#endif
15004
#ifdef _SC_WORD_BIT
15005
    {"SC_WORD_BIT",     _SC_WORD_BIT},
15006
#endif
15007
#ifdef _SC_XBS5_ILP32_OFF32
15008
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15009
#endif
15010
#ifdef _SC_XBS5_ILP32_OFFBIG
15011
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15012
#endif
15013
#ifdef _SC_XBS5_LP64_OFF64
15014
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15015
#endif
15016
#ifdef _SC_XBS5_LPBIG_OFFBIG
15017
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15018
#endif
15019
#ifdef _SC_XOPEN_CRYPT
15020
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15021
#endif
15022
#ifdef _SC_XOPEN_ENH_I18N
15023
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15024
#endif
15025
#ifdef _SC_XOPEN_LEGACY
15026
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15027
#endif
15028
#ifdef _SC_XOPEN_REALTIME
15029
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15030
#endif
15031
#ifdef _SC_XOPEN_REALTIME_THREADS
15032
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15033
#endif
15034
#ifdef _SC_XOPEN_SHM
15035
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15036
#endif
15037
#ifdef _SC_XOPEN_UNIX
15038
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15039
#endif
15040
#ifdef _SC_XOPEN_VERSION
15041
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15042
#endif
15043
#ifdef _SC_XOPEN_XCU_VERSION
15044
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15045
#endif
15046
#ifdef _SC_XOPEN_XPG2
15047
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15048
#endif
15049
#ifdef _SC_XOPEN_XPG3
15050
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15051
#endif
15052
#ifdef _SC_XOPEN_XPG4
15053
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15054
#endif
15055
#ifdef _SC_MINSIGSTKSZ
15056
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15057
#endif
15058
};
15059
15060
15061
/*[clinic input]
15062
os.sysconf -> long
15063
    name: confname(table="sysconf_names")
15064
    /
15065
15066
Return an integer-valued system configuration variable.
15067
[clinic start generated code]*/
15068
15069
static long
15070
os_sysconf_impl(PyObject *module, int name)
15071
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15072
4
{
15073
4
    long value;
15074
15075
4
    errno = 0;
15076
4
    value = sysconf(name);
15077
4
    if (value == -1 && errno != 0)
15078
0
        posix_error();
15079
4
    return value;
15080
4
}
15081
#endif /* HAVE_SYSCONF */
15082
15083
15084
static int
15085
setup_confname_table(struct constdef *table, size_t tablesize,
15086
                     const char *tablename, PyObject *module)
15087
108
{
15088
108
    PyObject *d = PyDict_New();
15089
108
    if (d == NULL)
15090
0
        return -1;
15091
15092
6.62k
    for (size_t i=0; i < tablesize; ++i) {
15093
6.51k
        PyObject *o = PyLong_FromLong(table[i].value);
15094
6.51k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15095
0
            Py_XDECREF(o);
15096
0
            Py_DECREF(d);
15097
0
            return -1;
15098
0
        }
15099
6.51k
        Py_DECREF(o);
15100
6.51k
    }
15101
108
    return PyModule_Add(module, tablename, d);
15102
108
}
15103
15104
/* Return -1 on failure, 0 on success. */
15105
static int
15106
setup_confname_tables(PyObject *module)
15107
36
{
15108
36
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15109
36
    if (setup_confname_table(posix_constants_pathconf,
15110
36
                             sizeof(posix_constants_pathconf)
15111
36
                               / sizeof(struct constdef),
15112
36
                             "pathconf_names", module))
15113
0
        return -1;
15114
36
#endif
15115
36
#ifdef HAVE_CONFSTR
15116
36
    if (setup_confname_table(posix_constants_confstr,
15117
36
                             sizeof(posix_constants_confstr)
15118
36
                               / sizeof(struct constdef),
15119
36
                             "confstr_names", module))
15120
0
        return -1;
15121
36
#endif
15122
36
#ifdef HAVE_SYSCONF
15123
36
    if (setup_confname_table(posix_constants_sysconf,
15124
36
                             sizeof(posix_constants_sysconf)
15125
36
                               / sizeof(struct constdef),
15126
36
                             "sysconf_names", module))
15127
0
        return -1;
15128
36
#endif
15129
36
    return 0;
15130
36
}
15131
15132
15133
/*[clinic input]
15134
os.abort
15135
15136
Abort the interpreter immediately.
15137
15138
This function 'dumps core' or otherwise fails in the hardest way possible
15139
on the hosting operating system.  This function never returns.
15140
[clinic start generated code]*/
15141
15142
static PyObject *
15143
os_abort_impl(PyObject *module)
15144
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
15145
0
{
15146
0
    abort();
15147
    /*NOTREACHED*/
15148
#ifndef __clang__
15149
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15150
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15151
       is smarter and emits a warning on the return. */
15152
    Py_FatalError("abort() called from Python code didn't abort!");
15153
    return NULL;
15154
#endif
15155
0
}
15156
15157
#ifdef MS_WINDOWS
15158
/* Grab ShellExecute dynamically from shell32 */
15159
static int has_ShellExecute = -1;
15160
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15161
                                              LPCWSTR, INT);
15162
static int
15163
check_ShellExecute(void)
15164
{
15165
    HINSTANCE hShell32;
15166
15167
    /* only recheck */
15168
    if (-1 == has_ShellExecute) {
15169
        Py_BEGIN_ALLOW_THREADS
15170
        /* Security note: this call is not vulnerable to "DLL hijacking".
15171
           SHELL32 is part of "KnownDLLs" and so Windows always load
15172
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15173
           in the DLL search path. */
15174
        hShell32 = LoadLibraryW(L"SHELL32");
15175
        if (hShell32) {
15176
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15177
                                            "ShellExecuteW");
15178
            has_ShellExecute = Py_ShellExecuteW != NULL;
15179
        } else {
15180
            has_ShellExecute = 0;
15181
        }
15182
        Py_END_ALLOW_THREADS
15183
    }
15184
    return has_ShellExecute;
15185
}
15186
15187
15188
/*[clinic input]
15189
os.startfile
15190
    filepath: path_t
15191
    operation: Py_UNICODE = NULL
15192
    arguments: Py_UNICODE = NULL
15193
    cwd: path_t(nullable=True) = None
15194
    show_cmd: int = 1
15195
15196
Start a file with its associated application.
15197
15198
When "operation" is not specified or "open", this acts like
15199
double-clicking the file in Explorer, or giving the file name as an
15200
argument to the DOS "start" command: the file is opened with whatever
15201
application (if any) its extension is associated.
15202
When another "operation" is given, it specifies what should be done with
15203
the file.  A typical operation is "print".
15204
15205
"arguments" is passed to the application, but should be omitted if the
15206
file is a document.
15207
15208
"cwd" is the working directory for the operation. If "filepath" is
15209
relative, it will be resolved against this directory. This argument
15210
should usually be an absolute path.
15211
15212
"show_cmd" can be used to override the recommended visibility option.
15213
See the Windows ShellExecute documentation for values.
15214
15215
startfile returns as soon as the associated application is launched.
15216
There is no option to wait for the application to close, and no way
15217
to retrieve the application's exit status.
15218
15219
The filepath is relative to the current directory.  If you want to use
15220
an absolute path, make sure the first character is not a slash ("/");
15221
the underlying Win32 ShellExecute function doesn't work if it is.
15222
[clinic start generated code]*/
15223
15224
static PyObject *
15225
os_startfile_impl(PyObject *module, path_t *filepath,
15226
                  const wchar_t *operation, const wchar_t *arguments,
15227
                  path_t *cwd, int show_cmd)
15228
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15229
{
15230
    HINSTANCE rc;
15231
15232
    if(!check_ShellExecute()) {
15233
        /* If the OS doesn't have ShellExecute, return a
15234
           NotImplementedError. */
15235
        return PyErr_Format(PyExc_NotImplementedError,
15236
            "startfile not available on this platform");
15237
    }
15238
15239
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15240
        return NULL;
15241
    }
15242
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15243
                    arguments, cwd->object ? cwd->object : Py_None,
15244
                    show_cmd) < 0) {
15245
        return NULL;
15246
    }
15247
15248
    Py_BEGIN_ALLOW_THREADS
15249
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15250
                          arguments, cwd->wide, show_cmd);
15251
    Py_END_ALLOW_THREADS
15252
15253
    if (rc <= (HINSTANCE)32) {
15254
        win32_error_object("startfile", filepath->object);
15255
        return NULL;
15256
    }
15257
    Py_RETURN_NONE;
15258
}
15259
#endif /* MS_WINDOWS */
15260
15261
15262
#ifdef HAVE_GETLOADAVG
15263
/*[clinic input]
15264
os.getloadavg
15265
15266
Return average recent system load information.
15267
15268
Return the number of processes in the system run queue averaged over
15269
the last 1, 5, and 15 minutes as a tuple of three floats.
15270
Raises OSError if the load average was unobtainable.
15271
[clinic start generated code]*/
15272
15273
static PyObject *
15274
os_getloadavg_impl(PyObject *module)
15275
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15276
0
{
15277
0
    double loadavg[3];
15278
0
    if (getloadavg(loadavg, 3)!=3) {
15279
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15280
0
        return NULL;
15281
0
    } else
15282
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15283
0
}
15284
#endif /* HAVE_GETLOADAVG */
15285
15286
15287
/*[clinic input]
15288
os.device_encoding
15289
    fd: int
15290
15291
Return a string describing the encoding of a terminal's file descriptor.
15292
15293
The file descriptor must be attached to a terminal.
15294
If the device is not a terminal, return None.
15295
[clinic start generated code]*/
15296
15297
static PyObject *
15298
os_device_encoding_impl(PyObject *module, int fd)
15299
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15300
0
{
15301
0
    return _Py_device_encoding(fd);
15302
0
}
15303
15304
15305
#ifdef HAVE_SETRESUID
15306
/*[clinic input]
15307
os.setresuid
15308
15309
    ruid: uid_t
15310
    euid: uid_t
15311
    suid: uid_t
15312
    /
15313
15314
Set the current process's real, effective, and saved user ids.
15315
[clinic start generated code]*/
15316
15317
static PyObject *
15318
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15319
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15320
0
{
15321
0
    if (setresuid(ruid, euid, suid) < 0)
15322
0
        return posix_error();
15323
0
    Py_RETURN_NONE;
15324
0
}
15325
#endif /* HAVE_SETRESUID */
15326
15327
15328
#ifdef HAVE_SETRESGID
15329
/*[clinic input]
15330
os.setresgid
15331
15332
    rgid: gid_t
15333
    egid: gid_t
15334
    sgid: gid_t
15335
    /
15336
15337
Set the current process's real, effective, and saved group ids.
15338
[clinic start generated code]*/
15339
15340
static PyObject *
15341
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15342
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15343
0
{
15344
0
    if (setresgid(rgid, egid, sgid) < 0)
15345
0
        return posix_error();
15346
0
    Py_RETURN_NONE;
15347
0
}
15348
#endif /* HAVE_SETRESGID */
15349
15350
15351
#ifdef HAVE_GETRESUID
15352
/*[clinic input]
15353
os.getresuid
15354
15355
Return a tuple of the current process's real, effective, and saved user ids.
15356
[clinic start generated code]*/
15357
15358
static PyObject *
15359
os_getresuid_impl(PyObject *module)
15360
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
15361
0
{
15362
0
    uid_t ruid, euid, suid;
15363
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15364
0
        return posix_error();
15365
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15366
0
                                  _PyLong_FromUid(euid),
15367
0
                                  _PyLong_FromUid(suid));
15368
0
}
15369
#endif /* HAVE_GETRESUID */
15370
15371
15372
#ifdef HAVE_GETRESGID
15373
/*[clinic input]
15374
@permit_long_summary
15375
os.getresgid
15376
15377
Return a tuple of the current process's real, effective, and saved group ids.
15378
[clinic start generated code]*/
15379
15380
static PyObject *
15381
os_getresgid_impl(PyObject *module)
15382
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15383
0
{
15384
0
    gid_t rgid, egid, sgid;
15385
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15386
0
        return posix_error();
15387
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15388
0
                                  _PyLong_FromGid(egid),
15389
0
                                  _PyLong_FromGid(sgid));
15390
0
}
15391
#endif /* HAVE_GETRESGID */
15392
15393
15394
#ifdef USE_XATTRS
15395
/*[clinic input]
15396
os.getxattr
15397
15398
    path: path_t(allow_fd=True)
15399
    attribute: path_t
15400
    *
15401
    follow_symlinks: bool = True
15402
15403
Return the value of extended attribute attribute on path.
15404
15405
path may be either a string, a path-like object, or an open file descriptor.
15406
If follow_symlinks is False, and the last element of the path is a symbolic
15407
  link, getxattr will examine the symbolic link itself instead of the file
15408
  the link points to.
15409
15410
[clinic start generated code]*/
15411
15412
static PyObject *
15413
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15414
                 int follow_symlinks)
15415
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
15416
0
{
15417
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
15418
0
        return NULL;
15419
15420
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15421
0
        return NULL;
15422
0
    }
15423
15424
0
    for (Py_ssize_t i = 0; ; i++) {
15425
0
        ssize_t result;
15426
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15427
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15428
0
        if (!buffer_size) {
15429
0
            path_error(path);
15430
0
            return NULL;
15431
0
        }
15432
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15433
0
        if (writer == NULL) {
15434
0
            return NULL;
15435
0
        }
15436
0
        void *ptr = PyBytesWriter_GetData(writer);
15437
15438
0
        Py_BEGIN_ALLOW_THREADS;
15439
0
        if (path->is_fd)
15440
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15441
0
        else if (follow_symlinks)
15442
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15443
0
        else
15444
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15445
0
        Py_END_ALLOW_THREADS;
15446
15447
0
        if (result < 0) {
15448
0
            PyBytesWriter_Discard(writer);
15449
0
            if (errno == ERANGE) {
15450
0
                continue;
15451
0
            }
15452
0
            path_error(path);
15453
0
            return NULL;
15454
0
        }
15455
15456
0
        return PyBytesWriter_FinishWithSize(writer, result);
15457
0
    }
15458
0
}
15459
15460
15461
/*[clinic input]
15462
@permit_long_docstring_body
15463
os.setxattr
15464
15465
    path: path_t(allow_fd=True)
15466
    attribute: path_t
15467
    value: Py_buffer
15468
    flags: int = 0
15469
    *
15470
    follow_symlinks: bool = True
15471
15472
Set extended attribute attribute on path to value.
15473
15474
path may be either a string, a path-like object,  or an open file descriptor.
15475
If follow_symlinks is False, and the last element of the path is a symbolic
15476
  link, setxattr will modify the symbolic link itself instead of the file
15477
  the link points to.
15478
15479
[clinic start generated code]*/
15480
15481
static PyObject *
15482
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15483
                 Py_buffer *value, int flags, int follow_symlinks)
15484
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15485
0
{
15486
0
    ssize_t result;
15487
15488
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
15489
0
        return NULL;
15490
15491
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15492
0
                    value->buf, value->len, flags) < 0) {
15493
0
        return NULL;
15494
0
    }
15495
15496
0
    Py_BEGIN_ALLOW_THREADS;
15497
0
    if (path->is_fd)
15498
0
        result = fsetxattr(path->fd, attribute->narrow,
15499
0
                           value->buf, value->len, flags);
15500
0
    else if (follow_symlinks)
15501
0
        result = setxattr(path->narrow, attribute->narrow,
15502
0
                           value->buf, value->len, flags);
15503
0
    else
15504
0
        result = lsetxattr(path->narrow, attribute->narrow,
15505
0
                           value->buf, value->len, flags);
15506
0
    Py_END_ALLOW_THREADS;
15507
15508
0
    if (result) {
15509
0
        path_error(path);
15510
0
        return NULL;
15511
0
    }
15512
15513
0
    Py_RETURN_NONE;
15514
0
}
15515
15516
15517
/*[clinic input]
15518
os.removexattr
15519
15520
    path: path_t(allow_fd=True)
15521
    attribute: path_t
15522
    *
15523
    follow_symlinks: bool = True
15524
15525
Remove extended attribute attribute on path.
15526
15527
path may be either a string, a path-like object, or an open file descriptor.
15528
If follow_symlinks is False, and the last element of the path is a symbolic
15529
  link, removexattr will modify the symbolic link itself instead of the file
15530
  the link points to.
15531
15532
[clinic start generated code]*/
15533
15534
static PyObject *
15535
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15536
                    int follow_symlinks)
15537
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15538
0
{
15539
0
    ssize_t result;
15540
15541
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
15542
0
        return NULL;
15543
15544
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15545
0
        return NULL;
15546
0
    }
15547
15548
0
    Py_BEGIN_ALLOW_THREADS;
15549
0
    if (path->is_fd)
15550
0
        result = fremovexattr(path->fd, attribute->narrow);
15551
0
    else if (follow_symlinks)
15552
0
        result = removexattr(path->narrow, attribute->narrow);
15553
0
    else
15554
0
        result = lremovexattr(path->narrow, attribute->narrow);
15555
0
    Py_END_ALLOW_THREADS;
15556
15557
0
    if (result) {
15558
0
        return path_error(path);
15559
0
    }
15560
15561
0
    Py_RETURN_NONE;
15562
0
}
15563
15564
15565
/*[clinic input]
15566
@permit_long_docstring_body
15567
os.listxattr
15568
15569
    path: path_t(allow_fd=True, nullable=True) = None
15570
    *
15571
    follow_symlinks: bool = True
15572
15573
Return a list of extended attributes on path.
15574
15575
path may be either None, a string, a path-like object, or an open file descriptor.
15576
if path is None, listxattr will examine the current directory.
15577
If follow_symlinks is False, and the last element of the path is a symbolic
15578
  link, listxattr will examine the symbolic link itself instead of the file
15579
  the link points to.
15580
[clinic start generated code]*/
15581
15582
static PyObject *
15583
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15584
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15585
0
{
15586
0
    Py_ssize_t i;
15587
0
    PyObject *result = NULL;
15588
0
    const char *name;
15589
0
    char *buffer = NULL;
15590
15591
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
15592
0
        goto exit;
15593
15594
0
    if (PySys_Audit("os.listxattr", "(O)",
15595
0
                    path->object ? path->object : Py_None) < 0) {
15596
0
        return NULL;
15597
0
    }
15598
15599
0
    name = path->narrow ? path->narrow : ".";
15600
15601
0
    for (i = 0; ; i++) {
15602
0
        const char *start, *trace, *end;
15603
0
        ssize_t length;
15604
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15605
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15606
0
        if (!buffer_size) {
15607
            /* ERANGE */
15608
0
            path_error(path);
15609
0
            break;
15610
0
        }
15611
0
        buffer = PyMem_Malloc(buffer_size);
15612
0
        if (!buffer) {
15613
0
            PyErr_NoMemory();
15614
0
            break;
15615
0
        }
15616
15617
0
        Py_BEGIN_ALLOW_THREADS;
15618
0
        if (path->is_fd)
15619
0
            length = flistxattr(path->fd, buffer, buffer_size);
15620
0
        else if (follow_symlinks)
15621
0
            length = listxattr(name, buffer, buffer_size);
15622
0
        else
15623
0
            length = llistxattr(name, buffer, buffer_size);
15624
0
        Py_END_ALLOW_THREADS;
15625
15626
0
        if (length < 0) {
15627
0
            if (errno == ERANGE) {
15628
0
                PyMem_Free(buffer);
15629
0
                buffer = NULL;
15630
0
                continue;
15631
0
            }
15632
0
            path_error(path);
15633
0
            break;
15634
0
        }
15635
15636
0
        result = PyList_New(0);
15637
0
        if (!result) {
15638
0
            goto exit;
15639
0
        }
15640
15641
0
        end = buffer + length;
15642
0
        for (trace = start = buffer; trace != end; trace++) {
15643
0
            if (!*trace) {
15644
0
                int error;
15645
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15646
0
                                                                 trace - start);
15647
0
                if (!attribute) {
15648
0
                    Py_SETREF(result, NULL);
15649
0
                    goto exit;
15650
0
                }
15651
0
                error = PyList_Append(result, attribute);
15652
0
                Py_DECREF(attribute);
15653
0
                if (error) {
15654
0
                    Py_SETREF(result, NULL);
15655
0
                    goto exit;
15656
0
                }
15657
0
                start = trace + 1;
15658
0
            }
15659
0
        }
15660
0
    break;
15661
0
    }
15662
0
exit:
15663
0
    if (buffer)
15664
0
        PyMem_Free(buffer);
15665
0
    return result;
15666
0
}
15667
#endif /* USE_XATTRS */
15668
15669
15670
/*[clinic input]
15671
@permit_long_summary
15672
os.urandom
15673
15674
    size: Py_ssize_t(allow_negative=False)
15675
    /
15676
15677
Return a bytes object containing random bytes suitable for cryptographic use.
15678
[clinic start generated code]*/
15679
15680
static PyObject *
15681
os_urandom_impl(PyObject *module, Py_ssize_t size)
15682
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15683
0
{
15684
0
    if (size < 0) {
15685
0
        return PyErr_Format(PyExc_ValueError,
15686
0
                            "negative argument not allowed");
15687
0
    }
15688
15689
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15690
0
    if (writer == NULL) {
15691
0
        return NULL;
15692
0
    }
15693
15694
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15695
0
    if (result == -1) {
15696
0
        PyBytesWriter_Discard(writer);
15697
0
        return NULL;
15698
0
    }
15699
0
    return PyBytesWriter_Finish(writer);
15700
0
}
15701
15702
#ifdef HAVE_MEMFD_CREATE
15703
/*[clinic input]
15704
os.memfd_create
15705
15706
    name: unicode_fs_encoded
15707
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15708
15709
[clinic start generated code]*/
15710
15711
static PyObject *
15712
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15713
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15714
0
{
15715
0
    int fd;
15716
0
    const char *bytes = PyBytes_AS_STRING(name);
15717
0
    Py_BEGIN_ALLOW_THREADS
15718
0
    fd = memfd_create(bytes, flags);
15719
0
    Py_END_ALLOW_THREADS
15720
0
    if (fd == -1) {
15721
0
        return PyErr_SetFromErrno(PyExc_OSError);
15722
0
    }
15723
0
    return PyLong_FromLong(fd);
15724
0
}
15725
#endif
15726
15727
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15728
/*[clinic input]
15729
os.eventfd
15730
15731
    initval: unsigned_int
15732
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15733
15734
Creates and returns an event notification file descriptor.
15735
[clinic start generated code]*/
15736
15737
static PyObject *
15738
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15739
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15740
15741
0
{
15742
    /* initval is limited to uint32_t, internal counter is uint64_t */
15743
0
    int fd;
15744
0
    Py_BEGIN_ALLOW_THREADS
15745
0
    fd = eventfd(initval, flags);
15746
0
    Py_END_ALLOW_THREADS
15747
0
    if (fd == -1) {
15748
0
        return PyErr_SetFromErrno(PyExc_OSError);
15749
0
    }
15750
0
    return PyLong_FromLong(fd);
15751
0
}
15752
15753
/*[clinic input]
15754
os.eventfd_read
15755
15756
    fd: fildes
15757
15758
Read eventfd value
15759
[clinic start generated code]*/
15760
15761
static PyObject *
15762
os_eventfd_read_impl(PyObject *module, int fd)
15763
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15764
0
{
15765
0
    eventfd_t value;
15766
0
    int result;
15767
0
    Py_BEGIN_ALLOW_THREADS
15768
0
    result = eventfd_read(fd, &value);
15769
0
    Py_END_ALLOW_THREADS
15770
0
    if (result == -1) {
15771
0
        return PyErr_SetFromErrno(PyExc_OSError);
15772
0
    }
15773
0
    return PyLong_FromUnsignedLongLong(value);
15774
0
}
15775
15776
/*[clinic input]
15777
os.eventfd_write
15778
15779
    fd: fildes
15780
    value: unsigned_long_long
15781
15782
Write eventfd value.
15783
[clinic start generated code]*/
15784
15785
static PyObject *
15786
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15787
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15788
0
{
15789
0
    int result;
15790
0
    Py_BEGIN_ALLOW_THREADS
15791
0
    result = eventfd_write(fd, value);
15792
0
    Py_END_ALLOW_THREADS
15793
0
    if (result == -1) {
15794
0
        return PyErr_SetFromErrno(PyExc_OSError);
15795
0
    }
15796
0
    Py_RETURN_NONE;
15797
0
}
15798
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15799
15800
/* Terminal size querying */
15801
15802
PyDoc_STRVAR(TerminalSize_docstring,
15803
    "A tuple of (columns, lines) for holding terminal window size");
15804
15805
static PyStructSequence_Field TerminalSize_fields[] = {
15806
    {"columns", "width of the terminal window in characters"},
15807
    {"lines", "height of the terminal window in characters"},
15808
    {NULL, NULL}
15809
};
15810
15811
static PyStructSequence_Desc TerminalSize_desc = {
15812
    "os.terminal_size",
15813
    TerminalSize_docstring,
15814
    TerminalSize_fields,
15815
    2,
15816
};
15817
15818
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15819
/*[clinic input]
15820
os.get_terminal_size
15821
15822
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15823
    /
15824
15825
Return the size of the terminal window as (columns, lines).
15826
15827
The optional argument fd (default standard output) specifies
15828
which file descriptor should be queried.
15829
15830
If the file descriptor is not connected to a terminal, an OSError
15831
is thrown.
15832
15833
This function will only be defined if an implementation is
15834
available for this system.
15835
15836
shutil.get_terminal_size is the high-level function which should
15837
normally be used, os.get_terminal_size is the low-level implementation.
15838
[clinic start generated code]*/
15839
15840
static PyObject *
15841
os_get_terminal_size_impl(PyObject *module, int fd)
15842
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15843
0
{
15844
0
    int columns, lines;
15845
0
    PyObject *termsize;
15846
15847
    /* Under some conditions stdout may not be connected and
15848
     * fileno(stdout) may point to an invalid file descriptor. For example
15849
     * GUI apps don't have valid standard streams by default.
15850
     *
15851
     * If this happens, and the optional fd argument is not present,
15852
     * the ioctl below will fail returning EBADF. This is what we want.
15853
     */
15854
15855
0
#ifdef TERMSIZE_USE_IOCTL
15856
0
    {
15857
0
        struct winsize w;
15858
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15859
0
            return PyErr_SetFromErrno(PyExc_OSError);
15860
0
        columns = w.ws_col;
15861
0
        lines = w.ws_row;
15862
0
    }
15863
0
#endif /* TERMSIZE_USE_IOCTL */
15864
15865
#ifdef TERMSIZE_USE_CONIO
15866
    {
15867
        HANDLE handle;
15868
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15869
        handle = _Py_get_osfhandle(fd);
15870
        if (handle == INVALID_HANDLE_VALUE)
15871
            return NULL;
15872
15873
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15874
            return PyErr_SetFromWindowsErr(0);
15875
15876
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15877
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15878
    }
15879
#endif /* TERMSIZE_USE_CONIO */
15880
15881
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15882
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15883
0
    if (termsize == NULL)
15884
0
        return NULL;
15885
15886
0
    int pos = 0;
15887
15888
0
#define SET_TERMSIZE(CALL)                                   \
15889
0
    do {                                                     \
15890
0
        PyObject *item = (CALL);                             \
15891
0
        if (item == NULL) {                                  \
15892
0
            Py_DECREF(termsize);                             \
15893
0
            return NULL;                                     \
15894
0
        }                                                    \
15895
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15896
0
    } while(0)
15897
15898
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15899
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15900
0
#undef SET_TERMSIZE
15901
15902
0
    return termsize;
15903
0
}
15904
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15905
15906
/*[clinic input]
15907
os.cpu_count
15908
15909
Return the number of logical CPUs in the system.
15910
15911
Return None if indeterminable.
15912
[clinic start generated code]*/
15913
15914
static PyObject *
15915
os_cpu_count_impl(PyObject *module)
15916
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15917
0
{
15918
0
    const PyConfig *config = _Py_GetConfig();
15919
0
    if (config->cpu_count > 0) {
15920
0
        return PyLong_FromLong(config->cpu_count);
15921
0
    }
15922
15923
0
    int ncpu = 0;
15924
#ifdef MS_WINDOWS
15925
# ifdef MS_WINDOWS_DESKTOP
15926
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15927
# else
15928
    ncpu = 0;
15929
# endif
15930
15931
#elif defined(__hpux)
15932
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15933
15934
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15935
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15936
15937
#elif defined(__VXWORKS__)
15938
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15939
15940
#elif defined(__DragonFly__) || \
15941
      defined(__OpenBSD__)   || \
15942
      defined(__FreeBSD__)   || \
15943
      defined(__NetBSD__)    || \
15944
      defined(__APPLE__)
15945
    ncpu = 0;
15946
    size_t len = sizeof(ncpu);
15947
    int mib[2] = {CTL_HW, HW_NCPU};
15948
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15949
        ncpu = 0;
15950
    }
15951
#endif
15952
15953
0
    if (ncpu < 1) {
15954
0
        Py_RETURN_NONE;
15955
0
    }
15956
0
    return PyLong_FromLong(ncpu);
15957
0
}
15958
15959
15960
/*[clinic input]
15961
os.get_inheritable -> bool
15962
15963
    fd: int
15964
    /
15965
15966
Get the close-on-exe flag of the specified file descriptor.
15967
[clinic start generated code]*/
15968
15969
static int
15970
os_get_inheritable_impl(PyObject *module, int fd)
15971
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15972
0
{
15973
0
    int return_value;
15974
0
    _Py_BEGIN_SUPPRESS_IPH
15975
0
    return_value = _Py_get_inheritable(fd);
15976
0
    _Py_END_SUPPRESS_IPH
15977
0
    return return_value;
15978
0
}
15979
15980
15981
/*[clinic input]
15982
os.set_inheritable
15983
    fd: int
15984
    inheritable: int
15985
    /
15986
15987
Set the inheritable flag of the specified file descriptor.
15988
[clinic start generated code]*/
15989
15990
static PyObject *
15991
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15992
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15993
0
{
15994
0
    int result;
15995
15996
0
    _Py_BEGIN_SUPPRESS_IPH
15997
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15998
0
    _Py_END_SUPPRESS_IPH
15999
0
    if (result < 0)
16000
0
        return NULL;
16001
0
    Py_RETURN_NONE;
16002
0
}
16003
16004
16005
#ifdef MS_WINDOWS
16006
#ifndef HANDLE_FLAG_INHERIT
16007
#define HANDLE_FLAG_INHERIT 0x00000001
16008
#endif
16009
16010
/*[clinic input]
16011
os.get_handle_inheritable -> bool
16012
    handle: intptr_t
16013
    /
16014
16015
Get the close-on-exe flag of the specified file descriptor.
16016
[clinic start generated code]*/
16017
16018
static int
16019
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16020
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16021
{
16022
    DWORD flags;
16023
16024
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16025
        PyErr_SetFromWindowsErr(0);
16026
        return -1;
16027
    }
16028
16029
    return flags & HANDLE_FLAG_INHERIT;
16030
}
16031
16032
16033
/*[clinic input]
16034
os.set_handle_inheritable
16035
    handle: intptr_t
16036
    inheritable: bool
16037
    /
16038
16039
Set the inheritable flag of the specified handle.
16040
[clinic start generated code]*/
16041
16042
static PyObject *
16043
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16044
                               int inheritable)
16045
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16046
{
16047
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16048
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16049
        PyErr_SetFromWindowsErr(0);
16050
        return NULL;
16051
    }
16052
    Py_RETURN_NONE;
16053
}
16054
#endif /* MS_WINDOWS */
16055
16056
/*[clinic input]
16057
os.get_blocking -> bool
16058
    fd: int
16059
    /
16060
16061
Get the blocking mode of the file descriptor.
16062
16063
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16064
[clinic start generated code]*/
16065
16066
static int
16067
os_get_blocking_impl(PyObject *module, int fd)
16068
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16069
0
{
16070
0
    int blocking;
16071
16072
0
    _Py_BEGIN_SUPPRESS_IPH
16073
0
    blocking = _Py_get_blocking(fd);
16074
0
    _Py_END_SUPPRESS_IPH
16075
0
    return blocking;
16076
0
}
16077
16078
/*[clinic input]
16079
os.set_blocking
16080
    fd: int
16081
    blocking: bool
16082
    /
16083
16084
Set the blocking mode of the specified file descriptor.
16085
16086
Set the O_NONBLOCK flag if blocking is False,
16087
clear the O_NONBLOCK flag otherwise.
16088
[clinic start generated code]*/
16089
16090
static PyObject *
16091
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16092
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16093
0
{
16094
0
    int result;
16095
16096
0
    _Py_BEGIN_SUPPRESS_IPH
16097
0
    result = _Py_set_blocking(fd, blocking);
16098
0
    _Py_END_SUPPRESS_IPH
16099
0
    if (result < 0)
16100
0
        return NULL;
16101
0
    Py_RETURN_NONE;
16102
0
}
16103
16104
16105
/*[clinic input]
16106
class os.DirEntry "DirEntry *" "DirEntryType"
16107
[clinic start generated code]*/
16108
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16109
16110
typedef struct {
16111
    PyObject_HEAD
16112
    PyObject *name;
16113
    PyObject *path;
16114
    PyObject *stat;
16115
    PyObject *lstat;
16116
#ifdef MS_WINDOWS
16117
    struct _Py_stat_struct win32_lstat;
16118
    uint64_t win32_file_index;
16119
    uint64_t win32_file_index_high;
16120
    int got_file_index;
16121
#else /* POSIX */
16122
#ifdef HAVE_DIRENT_D_TYPE
16123
    unsigned char d_type;
16124
#endif
16125
    ino_t d_ino;
16126
    int dir_fd;
16127
#endif
16128
} DirEntry;
16129
16130
163k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16131
16132
static void
16133
DirEntry_dealloc(PyObject *op)
16134
163k
{
16135
163k
    DirEntry *entry = DirEntry_CAST(op);
16136
163k
    PyTypeObject *tp = Py_TYPE(entry);
16137
163k
    Py_XDECREF(entry->name);
16138
163k
    Py_XDECREF(entry->path);
16139
163k
    Py_XDECREF(entry->stat);
16140
163k
    Py_XDECREF(entry->lstat);
16141
163k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16142
163k
    free_func(entry);
16143
163k
    Py_DECREF(tp);
16144
163k
}
16145
16146
/* Forward reference */
16147
static int
16148
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16149
                   int follow_symlinks, unsigned short mode_bits);
16150
16151
/*[clinic input]
16152
os.DirEntry.is_symlink -> bool
16153
    defining_class: defining_class
16154
    /
16155
16156
Return True if the entry is a symbolic link; cached per entry.
16157
[clinic start generated code]*/
16158
16159
static int
16160
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16161
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16162
0
{
16163
#ifdef MS_WINDOWS
16164
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16165
#elif defined(HAVE_DIRENT_D_TYPE)
16166
    /* POSIX */
16167
0
    if (self->d_type != DT_UNKNOWN)
16168
0
        return self->d_type == DT_LNK;
16169
0
    else
16170
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16171
#else
16172
    /* POSIX without d_type */
16173
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16174
#endif
16175
0
}
16176
16177
/*[clinic input]
16178
os.DirEntry.is_junction -> bool
16179
16180
Return True if the entry is a junction; cached per entry.
16181
[clinic start generated code]*/
16182
16183
static int
16184
os_DirEntry_is_junction_impl(DirEntry *self)
16185
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16186
0
{
16187
#ifdef MS_WINDOWS
16188
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16189
#else
16190
0
    return 0;
16191
0
#endif
16192
0
}
16193
16194
static PyObject *
16195
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16196
140k
{
16197
140k
    int result;
16198
140k
    STRUCT_STAT st;
16199
140k
    PyObject *ub;
16200
16201
#ifdef MS_WINDOWS
16202
    if (!PyUnicode_FSDecoder(self->path, &ub))
16203
        return NULL;
16204
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16205
    Py_DECREF(ub);
16206
#else /* POSIX */
16207
140k
    if (!PyUnicode_FSConverter(self->path, &ub))
16208
0
        return NULL;
16209
140k
    const char *path = PyBytes_AS_STRING(ub);
16210
140k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16211
140k
#ifdef HAVE_FSTATAT
16212
140k
      if (HAVE_FSTATAT_RUNTIME) {
16213
140k
        Py_BEGIN_ALLOW_THREADS
16214
140k
        result = fstatat(self->dir_fd, path, &st,
16215
140k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16216
140k
        Py_END_ALLOW_THREADS
16217
140k
      } else
16218
16219
0
#endif /* HAVE_FSTATAT */
16220
0
      {
16221
0
        Py_DECREF(ub);
16222
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16223
0
        return NULL;
16224
0
      }
16225
140k
    }
16226
0
    else
16227
0
#endif
16228
0
    {
16229
0
        Py_BEGIN_ALLOW_THREADS
16230
0
        if (follow_symlinks) {
16231
0
            result = STAT(path, &st);
16232
0
        }
16233
0
        else {
16234
0
            result = LSTAT(path, &st);
16235
0
        }
16236
0
        Py_END_ALLOW_THREADS
16237
0
    }
16238
16239
140k
    int saved_errno = errno;
16240
#if defined(MS_WINDOWS)
16241
    PyMem_Free(path);
16242
#else
16243
140k
    Py_DECREF(ub);
16244
140k
#endif
16245
16246
140k
    if (result != 0) {
16247
0
        errno = saved_errno;
16248
0
        path_object_error(self->path);
16249
0
        return NULL;
16250
0
    }
16251
16252
140k
    return _pystat_fromstructstat(module, &st);
16253
140k
}
16254
16255
static PyObject *
16256
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16257
140k
{
16258
140k
    if (!self->lstat) {
16259
140k
        PyObject *module = PyType_GetModule(defining_class);
16260
#ifdef MS_WINDOWS
16261
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16262
#else /* POSIX */
16263
140k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16264
140k
#endif
16265
140k
    }
16266
140k
    return Py_XNewRef(self->lstat);
16267
140k
}
16268
16269
/*[clinic input]
16270
os.DirEntry.stat
16271
    defining_class: defining_class
16272
    /
16273
    *
16274
    follow_symlinks: bool = True
16275
16276
Return stat_result object for the entry; cached per entry.
16277
[clinic start generated code]*/
16278
16279
static PyObject *
16280
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16281
                      int follow_symlinks)
16282
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16283
140k
{
16284
140k
    if (!follow_symlinks) {
16285
140k
        return DirEntry_get_lstat(defining_class, self);
16286
140k
    }
16287
16288
0
    if (!self->stat) {
16289
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16290
0
        if (result == -1) {
16291
0
            return NULL;
16292
0
        }
16293
0
        if (result) {
16294
0
            PyObject *module = PyType_GetModule(defining_class);
16295
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16296
0
        }
16297
0
        else {
16298
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16299
0
        }
16300
0
    }
16301
16302
0
    return Py_XNewRef(self->stat);
16303
0
}
16304
16305
/* Set exception and return -1 on error, 0 for False, 1 for True */
16306
static int
16307
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16308
                   int follow_symlinks, unsigned short mode_bits)
16309
163k
{
16310
163k
    PyObject *stat = NULL;
16311
163k
    PyObject *st_mode = NULL;
16312
163k
    long mode;
16313
163k
    int result;
16314
163k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16315
163k
    int is_symlink;
16316
163k
    int need_stat;
16317
163k
#endif
16318
#ifdef MS_WINDOWS
16319
    unsigned long dir_bits;
16320
#endif
16321
16322
#ifdef MS_WINDOWS
16323
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16324
    need_stat = follow_symlinks && is_symlink;
16325
#elif defined(HAVE_DIRENT_D_TYPE)
16326
163k
    is_symlink = self->d_type == DT_LNK;
16327
163k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16328
163k
#endif
16329
16330
163k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16331
163k
    if (need_stat) {
16332
0
#endif
16333
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16334
0
        if (!stat) {
16335
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16336
                /* If file doesn't exist (anymore), then return False
16337
                   (i.e., say it's not a file/directory) */
16338
0
                PyErr_Clear();
16339
0
                return 0;
16340
0
            }
16341
0
            goto error;
16342
0
        }
16343
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16344
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16345
0
        if (!st_mode)
16346
0
            goto error;
16347
16348
0
        mode = PyLong_AsLong(st_mode);
16349
0
        if (mode == -1 && PyErr_Occurred())
16350
0
            goto error;
16351
0
        Py_CLEAR(st_mode);
16352
0
        Py_CLEAR(stat);
16353
0
        result = (mode & S_IFMT) == mode_bits;
16354
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16355
0
    }
16356
163k
    else if (is_symlink) {
16357
0
        assert(mode_bits != S_IFLNK);
16358
0
        result = 0;
16359
0
    }
16360
163k
    else {
16361
163k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16362
#ifdef MS_WINDOWS
16363
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16364
        if (mode_bits == S_IFDIR)
16365
            result = dir_bits != 0;
16366
        else
16367
            result = dir_bits == 0;
16368
#else /* POSIX */
16369
163k
        if (mode_bits == S_IFDIR)
16370
163k
            result = self->d_type == DT_DIR;
16371
0
        else
16372
0
            result = self->d_type == DT_REG;
16373
163k
#endif
16374
163k
    }
16375
163k
#endif
16376
16377
163k
    return result;
16378
16379
0
error:
16380
0
    Py_XDECREF(st_mode);
16381
0
    Py_XDECREF(stat);
16382
0
    return -1;
16383
163k
}
16384
16385
/*[clinic input]
16386
os.DirEntry.is_dir -> bool
16387
    defining_class: defining_class
16388
    /
16389
    *
16390
    follow_symlinks: bool = True
16391
16392
Return True if the entry is a directory; cached per entry.
16393
[clinic start generated code]*/
16394
16395
static int
16396
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16397
                        int follow_symlinks)
16398
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16399
163k
{
16400
163k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16401
163k
}
16402
16403
/*[clinic input]
16404
os.DirEntry.is_file -> bool
16405
    defining_class: defining_class
16406
    /
16407
    *
16408
    follow_symlinks: bool = True
16409
16410
Return True if the entry is a file; cached per entry.
16411
[clinic start generated code]*/
16412
16413
static int
16414
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16415
                         int follow_symlinks)
16416
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16417
0
{
16418
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16419
0
}
16420
16421
/*[clinic input]
16422
os.DirEntry.inode
16423
16424
Return inode of the entry; cached per entry.
16425
[clinic start generated code]*/
16426
16427
static PyObject *
16428
os_DirEntry_inode_impl(DirEntry *self)
16429
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16430
0
{
16431
#ifdef MS_WINDOWS
16432
    if (!self->got_file_index) {
16433
        PyObject *unicode;
16434
        STRUCT_STAT stat;
16435
        int result;
16436
16437
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16438
            return NULL;
16439
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16440
        Py_DECREF(unicode);
16441
        result = LSTAT(path, &stat);
16442
16443
        int saved_errno = errno;
16444
        PyMem_Free(path);
16445
16446
        if (result != 0) {
16447
            errno = saved_errno;
16448
            return path_object_error(self->path);
16449
        }
16450
16451
        self->win32_file_index = stat.st_ino;
16452
        self->win32_file_index_high = stat.st_ino_high;
16453
        self->got_file_index = 1;
16454
    }
16455
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16456
#else /* POSIX */
16457
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16458
0
                  "DirEntry.d_ino is larger than unsigned long long");
16459
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16460
0
#endif
16461
0
}
16462
16463
static PyObject *
16464
DirEntry_repr(PyObject *op)
16465
0
{
16466
0
    DirEntry *self = DirEntry_CAST(op);
16467
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16468
0
}
16469
16470
/*[clinic input]
16471
os.DirEntry.__fspath__
16472
16473
Returns the path for the entry.
16474
[clinic start generated code]*/
16475
16476
static PyObject *
16477
os_DirEntry___fspath___impl(DirEntry *self)
16478
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16479
0
{
16480
0
    return Py_NewRef(self->path);
16481
0
}
16482
16483
static PyMemberDef DirEntry_members[] = {
16484
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16485
     "the entry's base filename, relative to scandir() \"path\" argument"},
16486
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16487
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16488
    {NULL}
16489
};
16490
16491
#include "clinic/posixmodule.c.h"
16492
16493
static PyMethodDef DirEntry_methods[] = {
16494
    OS_DIRENTRY_IS_DIR_METHODDEF
16495
    OS_DIRENTRY_IS_FILE_METHODDEF
16496
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16497
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16498
    OS_DIRENTRY_STAT_METHODDEF
16499
    OS_DIRENTRY_INODE_METHODDEF
16500
    OS_DIRENTRY___FSPATH___METHODDEF
16501
    {"__class_getitem__",       Py_GenericAlias,
16502
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16503
    {NULL}
16504
};
16505
16506
static PyType_Slot DirEntryType_slots[] = {
16507
    {Py_tp_dealloc, DirEntry_dealloc},
16508
    {Py_tp_repr, DirEntry_repr},
16509
    {Py_tp_methods, DirEntry_methods},
16510
    {Py_tp_members, DirEntry_members},
16511
    {0, 0},
16512
};
16513
16514
static PyType_Spec DirEntryType_spec = {
16515
    .name = MODNAME ".DirEntry",
16516
    .basicsize = sizeof(DirEntry),
16517
    .flags = (
16518
        Py_TPFLAGS_DEFAULT
16519
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16520
        | Py_TPFLAGS_IMMUTABLETYPE
16521
    ),
16522
    .slots = DirEntryType_slots
16523
};
16524
16525
16526
#ifdef MS_WINDOWS
16527
16528
static wchar_t *
16529
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16530
{
16531
    Py_ssize_t path_len;
16532
    Py_ssize_t size;
16533
    wchar_t *result;
16534
    wchar_t ch;
16535
16536
    if (!path_wide) { /* Default arg: "." */
16537
        path_wide = L".";
16538
        path_len = 1;
16539
    }
16540
    else {
16541
        path_len = wcslen(path_wide);
16542
    }
16543
16544
    /* The +1's are for the path separator and the NUL */
16545
    size = path_len + 1 + wcslen(filename) + 1;
16546
    result = PyMem_New(wchar_t, size);
16547
    if (!result) {
16548
        PyErr_NoMemory();
16549
        return NULL;
16550
    }
16551
    wcscpy(result, path_wide);
16552
    if (path_len > 0) {
16553
        ch = result[path_len - 1];
16554
        if (ch != SEP && ch != ALTSEP && ch != L':')
16555
            result[path_len++] = SEP;
16556
        wcscpy(result + path_len, filename);
16557
    }
16558
    return result;
16559
}
16560
16561
static PyObject *
16562
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16563
{
16564
    DirEntry *entry;
16565
    BY_HANDLE_FILE_INFORMATION file_info;
16566
    ULONG reparse_tag;
16567
    wchar_t *joined_path;
16568
16569
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16570
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16571
    if (!entry)
16572
        return NULL;
16573
    entry->name = NULL;
16574
    entry->path = NULL;
16575
    entry->stat = NULL;
16576
    entry->lstat = NULL;
16577
    entry->got_file_index = 0;
16578
16579
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16580
    if (!entry->name)
16581
        goto error;
16582
    int return_bytes = path->wide && PyBytes_Check(path->object);
16583
    if (return_bytes) {
16584
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16585
        if (!entry->name)
16586
            goto error;
16587
    }
16588
16589
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16590
    if (!joined_path)
16591
        goto error;
16592
16593
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16594
    PyMem_Free(joined_path);
16595
    if (!entry->path)
16596
        goto error;
16597
    if (return_bytes) {
16598
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16599
        if (!entry->path)
16600
            goto error;
16601
    }
16602
16603
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16604
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16605
16606
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16607
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16608
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16609
16610
    return (PyObject *)entry;
16611
16612
error:
16613
    Py_DECREF(entry);
16614
    return NULL;
16615
}
16616
16617
#else /* POSIX */
16618
16619
static char *
16620
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16621
0
{
16622
0
    Py_ssize_t path_len;
16623
0
    Py_ssize_t size;
16624
0
    char *result;
16625
16626
0
    if (!path_narrow) { /* Default arg: "." */
16627
0
        path_narrow = ".";
16628
0
        path_len = 1;
16629
0
    }
16630
0
    else {
16631
0
        path_len = strlen(path_narrow);
16632
0
    }
16633
16634
0
    if (filename_len == -1)
16635
0
        filename_len = strlen(filename);
16636
16637
    /* The +1's are for the path separator and the NUL */
16638
0
    size = path_len + 1 + filename_len + 1;
16639
0
    result = PyMem_New(char, size);
16640
0
    if (!result) {
16641
0
        PyErr_NoMemory();
16642
0
        return NULL;
16643
0
    }
16644
0
    strcpy(result, path_narrow);
16645
0
    if (path_len > 0 && result[path_len - 1] != '/')
16646
0
        result[path_len++] = '/';
16647
0
    strcpy(result + path_len, filename);
16648
0
    return result;
16649
0
}
16650
16651
static PyObject *
16652
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16653
                         Py_ssize_t name_len, ino_t d_ino
16654
#ifdef HAVE_DIRENT_D_TYPE
16655
                         , unsigned char d_type
16656
#endif
16657
                         )
16658
163k
{
16659
163k
    DirEntry *entry;
16660
163k
    char *joined_path;
16661
16662
163k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16663
163k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16664
163k
    if (!entry)
16665
0
        return NULL;
16666
163k
    entry->name = NULL;
16667
163k
    entry->path = NULL;
16668
163k
    entry->stat = NULL;
16669
163k
    entry->lstat = NULL;
16670
16671
163k
    if (path->is_fd) {
16672
163k
        entry->dir_fd = path->fd;
16673
163k
        joined_path = NULL;
16674
163k
    }
16675
0
    else {
16676
0
        entry->dir_fd = DEFAULT_DIR_FD;
16677
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16678
0
        if (!joined_path)
16679
0
            goto error;
16680
0
    }
16681
16682
163k
    if (!path->narrow || !PyBytes_Check(path->object)) {
16683
163k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16684
163k
        if (joined_path)
16685
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16686
163k
    }
16687
0
    else {
16688
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16689
0
        if (joined_path)
16690
0
            entry->path = PyBytes_FromString(joined_path);
16691
0
    }
16692
163k
    PyMem_Free(joined_path);
16693
163k
    if (!entry->name)
16694
0
        goto error;
16695
16696
163k
    if (path->is_fd) {
16697
163k
        entry->path = Py_NewRef(entry->name);
16698
163k
    }
16699
0
    else if (!entry->path)
16700
0
        goto error;
16701
16702
163k
#ifdef HAVE_DIRENT_D_TYPE
16703
163k
    entry->d_type = d_type;
16704
163k
#endif
16705
163k
    entry->d_ino = d_ino;
16706
16707
163k
    return (PyObject *)entry;
16708
16709
0
error:
16710
0
    Py_XDECREF(entry);
16711
0
    return NULL;
16712
163k
}
16713
16714
#endif
16715
16716
16717
typedef struct {
16718
    PyObject_HEAD
16719
    path_t path;
16720
#ifdef MS_WINDOWS
16721
    HANDLE handle;
16722
    WIN32_FIND_DATAW file_data;
16723
    int first_time;
16724
#else /* POSIX */
16725
    DIR *dirp;
16726
#endif
16727
#ifdef HAVE_FDOPENDIR
16728
    int fd;
16729
#endif
16730
} ScandirIterator;
16731
16732
595k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16733
16734
#ifdef MS_WINDOWS
16735
16736
static int
16737
ScandirIterator_is_closed(ScandirIterator *iterator)
16738
{
16739
    return iterator->handle == INVALID_HANDLE_VALUE;
16740
}
16741
16742
static void
16743
ScandirIterator_closedir(ScandirIterator *iterator)
16744
{
16745
    HANDLE handle = iterator->handle;
16746
16747
    if (handle == INVALID_HANDLE_VALUE)
16748
        return;
16749
16750
    iterator->handle = INVALID_HANDLE_VALUE;
16751
    Py_BEGIN_ALLOW_THREADS
16752
    FindClose(handle);
16753
    Py_END_ALLOW_THREADS
16754
}
16755
16756
static PyObject *
16757
ScandirIterator_iternext(PyObject *op)
16758
{
16759
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16760
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16761
    BOOL success;
16762
    PyObject *entry;
16763
16764
    /* Happens if the iterator is iterated twice, or closed explicitly */
16765
    if (iterator->handle == INVALID_HANDLE_VALUE)
16766
        return NULL;
16767
16768
    while (1) {
16769
        if (!iterator->first_time) {
16770
            Py_BEGIN_ALLOW_THREADS
16771
            success = FindNextFileW(iterator->handle, file_data);
16772
            Py_END_ALLOW_THREADS
16773
            if (!success) {
16774
                /* Error or no more files */
16775
                if (GetLastError() != ERROR_NO_MORE_FILES)
16776
                    path_error(&iterator->path);
16777
                break;
16778
            }
16779
        }
16780
        iterator->first_time = 0;
16781
16782
        /* Skip over . and .. */
16783
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16784
            wcscmp(file_data->cFileName, L"..") != 0)
16785
        {
16786
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16787
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16788
            if (!entry)
16789
                break;
16790
            return entry;
16791
        }
16792
16793
        /* Loop till we get a non-dot directory or finish iterating */
16794
    }
16795
16796
    /* Error or no more files */
16797
    ScandirIterator_closedir(iterator);
16798
    return NULL;
16799
}
16800
16801
#else /* POSIX */
16802
16803
static int
16804
ScandirIterator_is_closed(ScandirIterator *iterator)
16805
144k
{
16806
144k
    return !iterator->dirp;
16807
144k
}
16808
16809
static void
16810
ScandirIterator_closedir(ScandirIterator *iterator)
16811
288k
{
16812
288k
    DIR *dirp = iterator->dirp;
16813
16814
288k
    if (!dirp)
16815
144k
        return;
16816
16817
144k
    iterator->dirp = NULL;
16818
144k
    Py_BEGIN_ALLOW_THREADS
16819
144k
#ifdef HAVE_FDOPENDIR
16820
144k
    if (iterator->path.is_fd) {
16821
144k
        rewinddir(dirp);
16822
144k
    }
16823
144k
#endif
16824
144k
    closedir(dirp);
16825
144k
    Py_END_ALLOW_THREADS
16826
144k
    return;
16827
288k
}
16828
16829
static PyObject *
16830
ScandirIterator_iternext(PyObject *op)
16831
307k
{
16832
307k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16833
307k
    struct dirent *direntp;
16834
307k
    Py_ssize_t name_len;
16835
307k
    int is_dot;
16836
307k
    PyObject *entry;
16837
16838
    /* Happens if the iterator is iterated twice, or closed explicitly */
16839
307k
    if (!iterator->dirp)
16840
0
        return NULL;
16841
16842
595k
    while (1) {
16843
595k
        errno = 0;
16844
595k
        Py_BEGIN_ALLOW_THREADS
16845
595k
        direntp = readdir(iterator->dirp);
16846
595k
        Py_END_ALLOW_THREADS
16847
16848
595k
        if (!direntp) {
16849
            /* Error or no more files */
16850
144k
            if (errno != 0)
16851
0
                path_error(&iterator->path);
16852
144k
            break;
16853
144k
        }
16854
16855
        /* Skip over . and .. */
16856
451k
        name_len = NAMLEN(direntp);
16857
451k
        is_dot = direntp->d_name[0] == '.' &&
16858
289k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16859
451k
        if (!is_dot) {
16860
163k
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16861
163k
            entry = DirEntry_from_posix_info(module,
16862
163k
                                             &iterator->path, direntp->d_name,
16863
163k
                                             name_len, direntp->d_ino
16864
163k
#ifdef HAVE_DIRENT_D_TYPE
16865
163k
                                             , direntp->d_type
16866
163k
#endif
16867
163k
                                            );
16868
163k
            if (!entry)
16869
0
                break;
16870
163k
            return entry;
16871
163k
        }
16872
16873
        /* Loop till we get a non-dot directory or finish iterating */
16874
451k
    }
16875
16876
    /* Error or no more files */
16877
144k
    ScandirIterator_closedir(iterator);
16878
144k
    return NULL;
16879
307k
}
16880
16881
#endif
16882
16883
static PyObject *
16884
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16885
0
{
16886
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16887
0
    ScandirIterator_closedir(self);
16888
0
    Py_RETURN_NONE;
16889
0
}
16890
16891
static PyObject *
16892
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16893
144k
{
16894
144k
    return Py_NewRef(self);
16895
144k
}
16896
16897
static PyObject *
16898
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16899
144k
{
16900
144k
    ScandirIterator *self = ScandirIterator_CAST(op);
16901
144k
    ScandirIterator_closedir(self);
16902
144k
    Py_RETURN_NONE;
16903
144k
}
16904
16905
static void
16906
ScandirIterator_finalize(PyObject *op)
16907
144k
{
16908
144k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16909
    /* Save the current exception, if any. */
16910
144k
    PyObject *exc = PyErr_GetRaisedException();
16911
16912
144k
    if (!ScandirIterator_is_closed(iterator)) {
16913
0
        ScandirIterator_closedir(iterator);
16914
16915
0
        if (PyErr_ResourceWarning(op, 1,
16916
0
                                  "unclosed scandir iterator %R", iterator))
16917
0
        {
16918
            /* Spurious errors can appear at shutdown */
16919
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16920
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16921
0
                                       "scandir iterator %R", iterator);
16922
0
            }
16923
0
        }
16924
0
    }
16925
16926
144k
    path_cleanup(&iterator->path);
16927
16928
    /* Restore the saved exception. */
16929
144k
    PyErr_SetRaisedException(exc);
16930
144k
}
16931
16932
static void
16933
ScandirIterator_dealloc(PyObject *op)
16934
144k
{
16935
144k
    PyTypeObject *tp = Py_TYPE(op);
16936
144k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16937
0
        return;
16938
16939
144k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16940
144k
    free_func(op);
16941
144k
    Py_DECREF(tp);
16942
144k
}
16943
16944
static PyMethodDef ScandirIterator_methods[] = {
16945
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16946
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16947
    {"close", ScandirIterator_close, METH_NOARGS},
16948
    {NULL}
16949
};
16950
16951
static PyType_Slot ScandirIteratorType_slots[] = {
16952
    {Py_tp_dealloc, ScandirIterator_dealloc},
16953
    {Py_tp_finalize, ScandirIterator_finalize},
16954
    {Py_tp_iter, PyObject_SelfIter},
16955
    {Py_tp_iternext, ScandirIterator_iternext},
16956
    {Py_tp_methods, ScandirIterator_methods},
16957
    {0, 0},
16958
};
16959
16960
static PyType_Spec ScandirIteratorType_spec = {
16961
    .name = MODNAME ".ScandirIterator",
16962
    .basicsize = sizeof(ScandirIterator),
16963
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16964
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16965
    .flags = (
16966
        Py_TPFLAGS_DEFAULT
16967
        | Py_TPFLAGS_HAVE_FINALIZE
16968
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16969
        | Py_TPFLAGS_IMMUTABLETYPE
16970
    ),
16971
    .slots = ScandirIteratorType_slots
16972
};
16973
16974
/*[clinic input]
16975
os.scandir
16976
16977
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16978
16979
Return an iterator of DirEntry objects for given path.
16980
16981
path can be specified as either str, bytes, or a path-like object.  If path
16982
is bytes, the names of yielded DirEntry objects will also be bytes; in
16983
all other circumstances they will be str.
16984
16985
If path is None, uses the path='.'.
16986
[clinic start generated code]*/
16987
16988
static PyObject *
16989
os_scandir_impl(PyObject *module, path_t *path)
16990
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16991
144k
{
16992
144k
    ScandirIterator *iterator;
16993
#ifdef MS_WINDOWS
16994
    wchar_t *path_strW;
16995
#else
16996
144k
    const char *path_str;
16997
144k
#ifdef HAVE_FDOPENDIR
16998
144k
    int fd = -1;
16999
144k
#endif
17000
144k
#endif
17001
17002
144k
    if (PySys_Audit("os.scandir", "O",
17003
144k
                    path->object ? path->object : Py_None) < 0) {
17004
0
        return NULL;
17005
0
    }
17006
17007
144k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
17008
144k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
17009
144k
    if (!iterator)
17010
0
        return NULL;
17011
17012
#ifdef MS_WINDOWS
17013
    iterator->handle = INVALID_HANDLE_VALUE;
17014
#else
17015
144k
    iterator->dirp = NULL;
17016
144k
#endif
17017
17018
    /* Move the ownership to iterator->path */
17019
144k
    memcpy(&iterator->path, path, sizeof(path_t));
17020
144k
    memset(path, 0, sizeof(path_t));
17021
17022
#ifdef MS_WINDOWS
17023
    iterator->first_time = 1;
17024
17025
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
17026
    if (!path_strW)
17027
        goto error;
17028
17029
    Py_BEGIN_ALLOW_THREADS
17030
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17031
    Py_END_ALLOW_THREADS
17032
17033
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17034
        path_error(&iterator->path);
17035
        PyMem_Free(path_strW);
17036
        goto error;
17037
    }
17038
    PyMem_Free(path_strW);
17039
#else /* POSIX */
17040
144k
    errno = 0;
17041
144k
#ifdef HAVE_FDOPENDIR
17042
144k
    if (iterator->path.is_fd) {
17043
144k
      if (HAVE_FDOPENDIR_RUNTIME) {
17044
        /* closedir() closes the FD, so we duplicate it */
17045
144k
        fd = _Py_dup(iterator->path.fd);
17046
144k
        if (fd == -1)
17047
0
            goto error;
17048
17049
144k
        Py_BEGIN_ALLOW_THREADS
17050
144k
        iterator->dirp = fdopendir(fd);
17051
144k
        Py_END_ALLOW_THREADS
17052
144k
      } else {
17053
0
        PyErr_SetString(PyExc_TypeError,
17054
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17055
0
        return NULL;
17056
0
      }
17057
144k
    }
17058
0
    else
17059
0
#endif
17060
0
    {
17061
0
        if (iterator->path.narrow)
17062
0
            path_str = iterator->path.narrow;
17063
0
        else
17064
0
            path_str = ".";
17065
17066
0
        Py_BEGIN_ALLOW_THREADS
17067
0
        iterator->dirp = opendir(path_str);
17068
0
        Py_END_ALLOW_THREADS
17069
0
    }
17070
17071
144k
    if (!iterator->dirp) {
17072
0
        path_error(&iterator->path);
17073
0
#ifdef HAVE_FDOPENDIR
17074
0
        if (fd != -1) {
17075
0
            Py_BEGIN_ALLOW_THREADS
17076
0
            close(fd);
17077
0
            Py_END_ALLOW_THREADS
17078
0
        }
17079
0
#endif
17080
0
        goto error;
17081
0
    }
17082
144k
#endif
17083
17084
144k
    return (PyObject *)iterator;
17085
17086
0
error:
17087
0
    Py_DECREF(iterator);
17088
0
    return NULL;
17089
144k
}
17090
17091
/*
17092
    Return the file system path representation of the object.
17093
17094
    If the object is str or bytes, then allow it to pass through with
17095
    an incremented refcount. If the object defines __fspath__(), then
17096
    return the result of that method. All other types raise a TypeError.
17097
*/
17098
PyObject *
17099
PyOS_FSPath(PyObject *path)
17100
1.35M
{
17101
    /* For error message reasons, this function is manually inlined in
17102
       path_converter(). */
17103
1.35M
    PyObject *func = NULL;
17104
1.35M
    PyObject *path_repr = NULL;
17105
17106
1.35M
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17107
1.35M
        return Py_NewRef(path);
17108
1.35M
    }
17109
17110
488
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17111
488
    if ((NULL == func) || (func == Py_None)) {
17112
0
        return PyErr_Format(PyExc_TypeError,
17113
0
                            "expected str, bytes or os.PathLike object, "
17114
0
                            "not %.200s",
17115
0
                            _PyType_Name(Py_TYPE(path)));
17116
0
    }
17117
17118
488
    path_repr = _PyObject_CallNoArgs(func);
17119
488
    Py_DECREF(func);
17120
488
    if (NULL == path_repr) {
17121
0
        return NULL;
17122
0
    }
17123
17124
488
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17125
0
        PyErr_Format(PyExc_TypeError,
17126
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17127
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17128
0
                     _PyType_Name(Py_TYPE(path_repr)));
17129
0
        Py_DECREF(path_repr);
17130
0
        return NULL;
17131
0
    }
17132
17133
488
    return path_repr;
17134
488
}
17135
17136
/*[clinic input]
17137
@permit_long_docstring_body
17138
os.fspath
17139
17140
    path: object
17141
17142
Return the file system path representation of the object.
17143
17144
If the object is str or bytes, then allow it to pass through as-is. If the
17145
object defines __fspath__(), then return the result of that method. All other
17146
types raise a TypeError.
17147
[clinic start generated code]*/
17148
17149
static PyObject *
17150
os_fspath_impl(PyObject *module, PyObject *path)
17151
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
17152
980k
{
17153
980k
    return PyOS_FSPath(path);
17154
980k
}
17155
17156
#ifdef HAVE_GETRANDOM_SYSCALL
17157
/*[clinic input]
17158
os.getrandom
17159
17160
    size: Py_ssize_t
17161
    flags: int=0
17162
17163
Obtain a series of random bytes.
17164
[clinic start generated code]*/
17165
17166
static PyObject *
17167
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17168
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17169
0
{
17170
0
    if (size < 0) {
17171
0
        errno = EINVAL;
17172
0
        return posix_error();
17173
0
    }
17174
17175
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17176
0
    if (writer == NULL) {
17177
0
        return NULL;
17178
0
    }
17179
0
    void *data = PyBytesWriter_GetData(writer);
17180
17181
0
    Py_ssize_t n;
17182
0
    while (1) {
17183
0
        n = syscall(SYS_getrandom, data, size, flags);
17184
0
        if (n < 0 && errno == EINTR) {
17185
0
            if (PyErr_CheckSignals() < 0) {
17186
0
                goto error;
17187
0
            }
17188
17189
            /* getrandom() was interrupted by a signal: retry */
17190
0
            continue;
17191
0
        }
17192
0
        break;
17193
0
    }
17194
17195
0
    if (n < 0) {
17196
0
        PyErr_SetFromErrno(PyExc_OSError);
17197
0
        goto error;
17198
0
    }
17199
17200
0
    return PyBytesWriter_FinishWithSize(writer, n);
17201
17202
0
error:
17203
0
    PyBytesWriter_Discard(writer);
17204
0
    return NULL;
17205
0
}
17206
#endif   /* HAVE_GETRANDOM_SYSCALL */
17207
17208
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17209
17210
/* bpo-36085: Helper functions for managing DLL search directories
17211
 * on win32
17212
 */
17213
17214
/*[clinic input]
17215
os._add_dll_directory
17216
17217
    path: path_t
17218
17219
Add a path to the DLL search path.
17220
17221
This search path is used when resolving dependencies for imported
17222
extension modules (the module itself is resolved through sys.path),
17223
and also by ctypes.
17224
17225
Returns an opaque value that may be passed to os.remove_dll_directory
17226
to remove this directory from the search path.
17227
[clinic start generated code]*/
17228
17229
static PyObject *
17230
os__add_dll_directory_impl(PyObject *module, path_t *path)
17231
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17232
{
17233
    DLL_DIRECTORY_COOKIE cookie = 0;
17234
    DWORD err = 0;
17235
17236
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17237
        return NULL;
17238
    }
17239
17240
    Py_BEGIN_ALLOW_THREADS
17241
    if (!(cookie = AddDllDirectory(path->wide))) {
17242
        err = GetLastError();
17243
    }
17244
    Py_END_ALLOW_THREADS
17245
17246
    if (err) {
17247
        return win32_error_object_err("add_dll_directory",
17248
                                      path->object, err);
17249
    }
17250
17251
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17252
}
17253
17254
/*[clinic input]
17255
os._remove_dll_directory
17256
17257
    cookie: object
17258
17259
Removes a path from the DLL search path.
17260
17261
The parameter is an opaque value that was returned from
17262
os.add_dll_directory. You can only remove directories that you added
17263
yourself.
17264
[clinic start generated code]*/
17265
17266
static PyObject *
17267
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17268
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17269
{
17270
    DLL_DIRECTORY_COOKIE cookieValue;
17271
    DWORD err = 0;
17272
17273
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17274
        PyErr_SetString(PyExc_TypeError,
17275
            "Provided cookie was not returned from os.add_dll_directory");
17276
        return NULL;
17277
    }
17278
17279
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17280
        cookie, "DLL directory cookie");
17281
17282
    Py_BEGIN_ALLOW_THREADS
17283
    if (!RemoveDllDirectory(cookieValue)) {
17284
        err = GetLastError();
17285
    }
17286
    Py_END_ALLOW_THREADS
17287
17288
    if (err) {
17289
        return win32_error_object_err("remove_dll_directory",
17290
                                      NULL, err);
17291
    }
17292
17293
    if (PyCapsule_SetName(cookie, NULL)) {
17294
        return NULL;
17295
    }
17296
17297
    Py_RETURN_NONE;
17298
}
17299
17300
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17301
17302
17303
/* Only check if WIFEXITED is available: expect that it comes
17304
   with WEXITSTATUS, WIFSIGNALED, etc.
17305
17306
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17307
   subprocess can safely call it during late Python finalization without
17308
   risking that used os attributes were set to None by finalize_modules(). */
17309
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17310
/*[clinic input]
17311
os.waitstatus_to_exitcode
17312
17313
    status as status_obj: object
17314
17315
Convert a wait status to an exit code.
17316
17317
On Unix:
17318
17319
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17320
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17321
* Otherwise, raise a ValueError.
17322
17323
On Windows, return status shifted right by 8 bits.
17324
17325
On Unix, if the process is being traced or if waitpid() was called with
17326
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
17327
This function must not be called if WIFSTOPPED(status) is true.
17328
[clinic start generated code]*/
17329
17330
static PyObject *
17331
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17332
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
17333
0
{
17334
0
#ifndef MS_WINDOWS
17335
0
    int status = PyLong_AsInt(status_obj);
17336
0
    if (status == -1 && PyErr_Occurred()) {
17337
0
        return NULL;
17338
0
    }
17339
17340
0
    WAIT_TYPE wait_status;
17341
0
    WAIT_STATUS_INT(wait_status) = status;
17342
0
    int exitcode;
17343
0
    if (WIFEXITED(wait_status)) {
17344
0
        exitcode = WEXITSTATUS(wait_status);
17345
        /* Sanity check to provide warranty on the function behavior.
17346
           It should not occur in practice */
17347
0
        if (exitcode < 0) {
17348
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17349
0
            return NULL;
17350
0
        }
17351
0
    }
17352
0
    else if (WIFSIGNALED(wait_status)) {
17353
0
        int signum = WTERMSIG(wait_status);
17354
        /* Sanity check to provide warranty on the function behavior.
17355
           It should not occurs in practice */
17356
0
        if (signum <= 0) {
17357
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17358
0
            return NULL;
17359
0
        }
17360
0
        exitcode = -signum;
17361
0
    } else if (WIFSTOPPED(wait_status)) {
17362
        /* Status only received if the process is being traced
17363
           or if waitpid() was called with WUNTRACED option. */
17364
0
        int signum = WSTOPSIG(wait_status);
17365
0
        PyErr_Format(PyExc_ValueError,
17366
0
                     "process stopped by delivery of signal %i",
17367
0
                     signum);
17368
0
        return NULL;
17369
0
    }
17370
0
    else {
17371
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17372
0
        return NULL;
17373
0
    }
17374
0
    return PyLong_FromLong(exitcode);
17375
#else
17376
    /* Windows implementation: see os.waitpid() implementation
17377
       which uses _cwait(). */
17378
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17379
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17380
        return NULL;
17381
    }
17382
17383
    unsigned long long exitcode = (status >> 8);
17384
    /* ExitProcess() accepts an UINT type:
17385
       reject exit code which doesn't fit in an UINT */
17386
    if (exitcode > UINT_MAX) {
17387
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17388
        return NULL;
17389
    }
17390
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17391
#endif
17392
0
}
17393
#endif
17394
17395
#if defined(MS_WINDOWS)
17396
/*[clinic input]
17397
os._supports_virtual_terminal
17398
17399
Checks if virtual terminal is supported in windows
17400
[clinic start generated code]*/
17401
17402
static PyObject *
17403
os__supports_virtual_terminal_impl(PyObject *module)
17404
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17405
{
17406
#ifdef HAVE_WINDOWS_CONSOLE_IO
17407
    DWORD mode = 0;
17408
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17409
    if (!GetConsoleMode(handle, &mode)) {
17410
        Py_RETURN_FALSE;
17411
    }
17412
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17413
#else
17414
    Py_RETURN_FALSE;
17415
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17416
}
17417
#endif
17418
17419
/*[clinic input]
17420
os._inputhook
17421
17422
Calls PyOS_InputHook dropping the GIL first
17423
[clinic start generated code]*/
17424
17425
static PyObject *
17426
os__inputhook_impl(PyObject *module)
17427
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17428
0
{
17429
0
     int result = 0;
17430
0
     if (PyOS_InputHook) {
17431
0
         Py_BEGIN_ALLOW_THREADS;
17432
0
         result = PyOS_InputHook();
17433
0
         Py_END_ALLOW_THREADS;
17434
0
     }
17435
0
     return PyLong_FromLong(result);
17436
0
}
17437
17438
/*[clinic input]
17439
os._is_inputhook_installed
17440
17441
Checks if PyOS_InputHook is set
17442
[clinic start generated code]*/
17443
17444
static PyObject *
17445
os__is_inputhook_installed_impl(PyObject *module)
17446
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17447
0
{
17448
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17449
0
}
17450
17451
/*[clinic input]
17452
os._create_environ
17453
17454
Create the environment dictionary.
17455
[clinic start generated code]*/
17456
17457
static PyObject *
17458
os__create_environ_impl(PyObject *module)
17459
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17460
0
{
17461
0
    return convertenviron();
17462
0
}
17463
17464
17465
#ifdef __EMSCRIPTEN__
17466
/*[clinic input]
17467
os._emscripten_debugger
17468
17469
Create a breakpoint for the JavaScript debugger. Emscripten only.
17470
[clinic start generated code]*/
17471
17472
static PyObject *
17473
os__emscripten_debugger_impl(PyObject *module)
17474
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17475
{
17476
    emscripten_debugger();
17477
    Py_RETURN_NONE;
17478
}
17479
17480
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17481
    console.warn(UTF8ToString(arg));
17482
});
17483
17484
/*[clinic input]
17485
os._emscripten_log
17486
   arg: str
17487
17488
Log something to the JS console. Emscripten only.
17489
[clinic start generated code]*/
17490
17491
static PyObject *
17492
os__emscripten_log_impl(PyObject *module, const char *arg)
17493
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17494
{
17495
    emscripten_log_impl_js(arg);
17496
    Py_RETURN_NONE;
17497
}
17498
#endif /* __EMSCRIPTEN__ */
17499
17500
17501
static PyMethodDef posix_methods[] = {
17502
    OS_STAT_METHODDEF
17503
    OS_STATX_METHODDEF
17504
    OS_ACCESS_METHODDEF
17505
    OS_TTYNAME_METHODDEF
17506
    OS_CHDIR_METHODDEF
17507
    OS_CHFLAGS_METHODDEF
17508
    OS_CHMOD_METHODDEF
17509
    OS_FCHMOD_METHODDEF
17510
    OS_LCHMOD_METHODDEF
17511
    OS_CHOWN_METHODDEF
17512
    OS_FCHOWN_METHODDEF
17513
    OS_LCHOWN_METHODDEF
17514
    OS_LCHFLAGS_METHODDEF
17515
    OS_CHROOT_METHODDEF
17516
    OS_CTERMID_METHODDEF
17517
    OS_GETCWD_METHODDEF
17518
    OS_GETCWDB_METHODDEF
17519
    OS_LINK_METHODDEF
17520
    OS_LISTDIR_METHODDEF
17521
    OS_LISTDRIVES_METHODDEF
17522
    OS_LISTMOUNTS_METHODDEF
17523
    OS_LISTVOLUMES_METHODDEF
17524
    OS_LSTAT_METHODDEF
17525
    OS_MKDIR_METHODDEF
17526
    OS_NICE_METHODDEF
17527
    OS_GETPRIORITY_METHODDEF
17528
    OS_SETPRIORITY_METHODDEF
17529
    OS_POSIX_SPAWN_METHODDEF
17530
    OS_POSIX_SPAWNP_METHODDEF
17531
    OS_READLINK_METHODDEF
17532
    OS_COPY_FILE_RANGE_METHODDEF
17533
    OS_SPLICE_METHODDEF
17534
    OS_RENAME_METHODDEF
17535
    OS_REPLACE_METHODDEF
17536
    OS_RMDIR_METHODDEF
17537
    OS_SYMLINK_METHODDEF
17538
    OS_SYSTEM_METHODDEF
17539
    OS_UMASK_METHODDEF
17540
    OS_UNAME_METHODDEF
17541
    OS_UNLINK_METHODDEF
17542
    OS_REMOVE_METHODDEF
17543
    OS_UTIME_METHODDEF
17544
    OS_TIMES_METHODDEF
17545
    OS__EXIT_METHODDEF
17546
    OS__FCOPYFILE_METHODDEF
17547
    OS_EXECV_METHODDEF
17548
    OS_EXECVE_METHODDEF
17549
    OS_SPAWNV_METHODDEF
17550
    OS_SPAWNVE_METHODDEF
17551
    OS_FORK1_METHODDEF
17552
    OS_FORK_METHODDEF
17553
    OS_REGISTER_AT_FORK_METHODDEF
17554
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17555
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17556
    OS_SCHED_GETPARAM_METHODDEF
17557
    OS_SCHED_GETSCHEDULER_METHODDEF
17558
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17559
    OS_SCHED_SETPARAM_METHODDEF
17560
    OS_SCHED_SETSCHEDULER_METHODDEF
17561
    OS_SCHED_YIELD_METHODDEF
17562
    OS_SCHED_SETAFFINITY_METHODDEF
17563
    OS_SCHED_GETAFFINITY_METHODDEF
17564
    OS_POSIX_OPENPT_METHODDEF
17565
    OS_GRANTPT_METHODDEF
17566
    OS_UNLOCKPT_METHODDEF
17567
    OS_PTSNAME_METHODDEF
17568
    OS_OPENPTY_METHODDEF
17569
    OS_LOGIN_TTY_METHODDEF
17570
    OS_FORKPTY_METHODDEF
17571
    OS_GETEGID_METHODDEF
17572
    OS_GETEUID_METHODDEF
17573
    OS_GETGID_METHODDEF
17574
    OS_GETGROUPLIST_METHODDEF
17575
    OS_GETGROUPS_METHODDEF
17576
    OS_GETPID_METHODDEF
17577
    OS_GETPGRP_METHODDEF
17578
    OS_GETPPID_METHODDEF
17579
    OS_GETUID_METHODDEF
17580
    OS_GETLOGIN_METHODDEF
17581
    OS_KILL_METHODDEF
17582
    OS_KILLPG_METHODDEF
17583
    OS_PLOCK_METHODDEF
17584
    OS_STARTFILE_METHODDEF
17585
    OS_SETUID_METHODDEF
17586
    OS_SETEUID_METHODDEF
17587
    OS_SETREUID_METHODDEF
17588
    OS_SETGID_METHODDEF
17589
    OS_SETEGID_METHODDEF
17590
    OS_SETREGID_METHODDEF
17591
    OS_SETGROUPS_METHODDEF
17592
    OS_INITGROUPS_METHODDEF
17593
    OS_GETPGID_METHODDEF
17594
    OS_SETPGRP_METHODDEF
17595
    OS_WAIT_METHODDEF
17596
    OS_WAIT3_METHODDEF
17597
    OS_WAIT4_METHODDEF
17598
    OS_WAITID_METHODDEF
17599
    OS_WAITPID_METHODDEF
17600
    OS_PIDFD_OPEN_METHODDEF
17601
    OS_GETSID_METHODDEF
17602
    OS_SETSID_METHODDEF
17603
    OS_SETPGID_METHODDEF
17604
    OS_TCGETPGRP_METHODDEF
17605
    OS_TCSETPGRP_METHODDEF
17606
    OS_OPEN_METHODDEF
17607
    OS_CLOSE_METHODDEF
17608
    OS_CLOSERANGE_METHODDEF
17609
    OS_DEVICE_ENCODING_METHODDEF
17610
    OS_DUP_METHODDEF
17611
    OS_DUP2_METHODDEF
17612
    OS_LOCKF_METHODDEF
17613
    OS_LSEEK_METHODDEF
17614
    OS_READ_METHODDEF
17615
    OS_READINTO_METHODDEF
17616
    OS_READV_METHODDEF
17617
    OS_PREAD_METHODDEF
17618
    OS_PREADV_METHODDEF
17619
    OS_WRITE_METHODDEF
17620
    OS_WRITEV_METHODDEF
17621
    OS_PWRITE_METHODDEF
17622
    OS_PWRITEV_METHODDEF
17623
    OS_SENDFILE_METHODDEF
17624
    OS_FSTAT_METHODDEF
17625
    OS_ISATTY_METHODDEF
17626
    OS_PIPE_METHODDEF
17627
    OS_PIPE2_METHODDEF
17628
    OS_MKFIFO_METHODDEF
17629
    OS_MKNOD_METHODDEF
17630
    OS_MAJOR_METHODDEF
17631
    OS_MINOR_METHODDEF
17632
    OS_MAKEDEV_METHODDEF
17633
    OS_FTRUNCATE_METHODDEF
17634
    OS_TRUNCATE_METHODDEF
17635
    OS_POSIX_FALLOCATE_METHODDEF
17636
    OS_POSIX_FADVISE_METHODDEF
17637
    OS_PUTENV_METHODDEF
17638
    OS_UNSETENV_METHODDEF
17639
    OS__CLEARENV_METHODDEF
17640
    OS_STRERROR_METHODDEF
17641
    OS_FCHDIR_METHODDEF
17642
    OS_FSYNC_METHODDEF
17643
    OS_SYNC_METHODDEF
17644
    OS_FDATASYNC_METHODDEF
17645
    OS_WCOREDUMP_METHODDEF
17646
    OS_WIFCONTINUED_METHODDEF
17647
    OS_WIFSTOPPED_METHODDEF
17648
    OS_WIFSIGNALED_METHODDEF
17649
    OS_WIFEXITED_METHODDEF
17650
    OS_WEXITSTATUS_METHODDEF
17651
    OS_WTERMSIG_METHODDEF
17652
    OS_WSTOPSIG_METHODDEF
17653
    OS_FSTATVFS_METHODDEF
17654
    OS_STATVFS_METHODDEF
17655
    OS_CONFSTR_METHODDEF
17656
    OS_SYSCONF_METHODDEF
17657
    OS_FPATHCONF_METHODDEF
17658
    OS_PATHCONF_METHODDEF
17659
    OS_ABORT_METHODDEF
17660
    OS__GETFULLPATHNAME_METHODDEF
17661
    OS__GETDISKUSAGE_METHODDEF
17662
    OS__GETFINALPATHNAME_METHODDEF
17663
    OS__FINDFIRSTFILE_METHODDEF
17664
    OS__GETVOLUMEPATHNAME_METHODDEF
17665
    OS__PATH_SPLITROOT_METHODDEF
17666
    OS__PATH_SPLITROOT_EX_METHODDEF
17667
    OS__PATH_NORMPATH_METHODDEF
17668
    OS_GETLOADAVG_METHODDEF
17669
    OS_URANDOM_METHODDEF
17670
    OS_SETRESUID_METHODDEF
17671
    OS_SETRESGID_METHODDEF
17672
    OS_GETRESUID_METHODDEF
17673
    OS_GETRESGID_METHODDEF
17674
17675
    OS_GETXATTR_METHODDEF
17676
    OS_SETXATTR_METHODDEF
17677
    OS_REMOVEXATTR_METHODDEF
17678
    OS_LISTXATTR_METHODDEF
17679
17680
    OS_GET_TERMINAL_SIZE_METHODDEF
17681
    OS_CPU_COUNT_METHODDEF
17682
    OS_GET_INHERITABLE_METHODDEF
17683
    OS_SET_INHERITABLE_METHODDEF
17684
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17685
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17686
    OS_GET_BLOCKING_METHODDEF
17687
    OS_SET_BLOCKING_METHODDEF
17688
    OS_SCANDIR_METHODDEF
17689
    OS_FSPATH_METHODDEF
17690
    OS_GETRANDOM_METHODDEF
17691
    OS_MEMFD_CREATE_METHODDEF
17692
    OS_EVENTFD_METHODDEF
17693
    OS_EVENTFD_READ_METHODDEF
17694
    OS_EVENTFD_WRITE_METHODDEF
17695
    OS__ADD_DLL_DIRECTORY_METHODDEF
17696
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17697
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17698
    OS_SETNS_METHODDEF
17699
    OS_UNSHARE_METHODDEF
17700
    OS_TIMERFD_CREATE_METHODDEF
17701
    OS_TIMERFD_SETTIME_METHODDEF
17702
    OS_TIMERFD_SETTIME_NS_METHODDEF
17703
    OS_TIMERFD_GETTIME_METHODDEF
17704
    OS_TIMERFD_GETTIME_NS_METHODDEF
17705
17706
    OS__PATH_ISDEVDRIVE_METHODDEF
17707
    OS__PATH_ISDIR_METHODDEF
17708
    OS__PATH_ISFILE_METHODDEF
17709
    OS__PATH_ISLINK_METHODDEF
17710
    OS__PATH_ISJUNCTION_METHODDEF
17711
    OS__PATH_EXISTS_METHODDEF
17712
    OS__PATH_LEXISTS_METHODDEF
17713
17714
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17715
    OS__INPUTHOOK_METHODDEF
17716
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17717
    OS__CREATE_ENVIRON_METHODDEF
17718
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17719
    OS__EMSCRIPTEN_LOG_METHODDEF
17720
    {NULL,              NULL}            /* Sentinel */
17721
};
17722
17723
static int
17724
all_ins(PyObject *m)
17725
36
{
17726
36
#ifdef F_OK
17727
36
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17728
36
#endif
17729
36
#ifdef R_OK
17730
36
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17731
36
#endif
17732
36
#ifdef W_OK
17733
36
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17734
36
#endif
17735
36
#ifdef X_OK
17736
36
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17737
36
#endif
17738
36
#ifdef NGROUPS_MAX
17739
36
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17740
36
#endif
17741
36
#ifdef TMP_MAX
17742
36
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17743
36
#endif
17744
36
#ifdef WCONTINUED
17745
36
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17746
36
#endif
17747
36
#ifdef WNOHANG
17748
36
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17749
36
#endif
17750
36
#ifdef WUNTRACED
17751
36
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17752
36
#endif
17753
36
#ifdef O_RDONLY
17754
36
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17755
36
#endif
17756
36
#ifdef O_WRONLY
17757
36
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17758
36
#endif
17759
36
#ifdef O_RDWR
17760
36
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17761
36
#endif
17762
36
#ifdef O_NDELAY
17763
36
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17764
36
#endif
17765
36
#ifdef O_NONBLOCK
17766
36
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17767
36
#endif
17768
36
#ifdef O_APPEND
17769
36
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17770
36
#endif
17771
36
#ifdef O_DSYNC
17772
36
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17773
36
#endif
17774
36
#ifdef O_RSYNC
17775
36
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17776
36
#endif
17777
36
#ifdef O_SYNC
17778
36
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17779
36
#endif
17780
36
#ifdef O_NOCTTY
17781
36
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17782
36
#endif
17783
36
#ifdef O_CREAT
17784
36
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17785
36
#endif
17786
36
#ifdef O_EXCL
17787
36
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17788
36
#endif
17789
36
#ifdef O_TRUNC
17790
36
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17791
36
#endif
17792
#ifdef O_BINARY
17793
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17794
#endif
17795
#ifdef O_TEXT
17796
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17797
#endif
17798
#ifdef O_XATTR
17799
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17800
#endif
17801
36
#ifdef O_LARGEFILE
17802
36
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17803
36
#endif
17804
36
#ifndef __GNU__
17805
#ifdef O_SHLOCK
17806
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17807
#endif
17808
#ifdef O_EXLOCK
17809
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17810
#endif
17811
36
#endif
17812
#ifdef O_EXEC
17813
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17814
#endif
17815
#ifdef O_SEARCH
17816
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17817
#endif
17818
36
#ifdef O_PATH
17819
36
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17820
36
#endif
17821
#ifdef O_TTY_INIT
17822
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17823
#endif
17824
36
#ifdef O_TMPFILE
17825
36
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17826
36
#endif
17827
36
#ifdef PRIO_PROCESS
17828
36
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17829
36
#endif
17830
36
#ifdef PRIO_PGRP
17831
36
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17832
36
#endif
17833
36
#ifdef PRIO_USER
17834
36
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17835
36
#endif
17836
#ifdef PRIO_DARWIN_THREAD
17837
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17838
#endif
17839
#ifdef PRIO_DARWIN_PROCESS
17840
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17841
#endif
17842
#ifdef PRIO_DARWIN_BG
17843
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17844
#endif
17845
#ifdef PRIO_DARWIN_NONUI
17846
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17847
#endif
17848
36
#ifdef O_CLOEXEC
17849
36
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17850
36
#endif
17851
36
#ifdef O_ACCMODE
17852
36
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17853
36
#endif
17854
#ifdef O_EVTONLY
17855
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17856
#endif
17857
36
#ifdef O_FSYNC
17858
36
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17859
36
#endif
17860
#ifdef O_SYMLINK
17861
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17862
#endif
17863
17864
36
#ifdef SEEK_HOLE
17865
36
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17866
36
#endif
17867
36
#ifdef SEEK_DATA
17868
36
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17869
36
#endif
17870
17871
/* MS Windows */
17872
#ifdef O_NOINHERIT
17873
    /* Don't inherit in child processes. */
17874
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17875
#endif
17876
#ifdef _O_SHORT_LIVED
17877
    /* Optimize for short life (keep in memory). */
17878
    /* MS forgot to define this one with a non-underscore form too. */
17879
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17880
#endif
17881
#ifdef O_TEMPORARY
17882
    /* Automatically delete when last handle is closed. */
17883
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17884
#endif
17885
#ifdef O_RANDOM
17886
    /* Optimize for random access. */
17887
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17888
#endif
17889
#ifdef O_SEQUENTIAL
17890
    /* Optimize for sequential access. */
17891
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17892
#endif
17893
17894
/* GNU extensions. */
17895
36
#ifdef O_ASYNC
17896
    /* Send a SIGIO signal whenever input or output
17897
       becomes available on file descriptor */
17898
36
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17899
36
#endif
17900
36
#ifdef O_DIRECT
17901
    /* Direct disk access. */
17902
36
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17903
36
#endif
17904
36
#ifdef O_DIRECTORY
17905
    /* Must be a directory.      */
17906
36
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17907
36
#endif
17908
36
#ifdef O_NOFOLLOW
17909
    /* Do not follow links.      */
17910
36
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17911
36
#endif
17912
#ifdef O_NOFOLLOW_ANY
17913
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17914
#endif
17915
#ifdef O_NOLINKS
17916
    /* Fails if link count of the named file is greater than 1 */
17917
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17918
#endif
17919
36
#ifdef O_NOATIME
17920
    /* Do not update the access time. */
17921
36
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17922
36
#endif
17923
17924
    /* These come from sysexits.h */
17925
36
#ifdef EX_OK
17926
36
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17927
36
#endif /* EX_OK */
17928
36
#ifdef EX_USAGE
17929
36
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17930
36
#endif /* EX_USAGE */
17931
36
#ifdef EX_DATAERR
17932
36
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17933
36
#endif /* EX_DATAERR */
17934
36
#ifdef EX_NOINPUT
17935
36
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17936
36
#endif /* EX_NOINPUT */
17937
36
#ifdef EX_NOUSER
17938
36
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17939
36
#endif /* EX_NOUSER */
17940
36
#ifdef EX_NOHOST
17941
36
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17942
36
#endif /* EX_NOHOST */
17943
36
#ifdef EX_UNAVAILABLE
17944
36
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17945
36
#endif /* EX_UNAVAILABLE */
17946
36
#ifdef EX_SOFTWARE
17947
36
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17948
36
#endif /* EX_SOFTWARE */
17949
36
#ifdef EX_OSERR
17950
36
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17951
36
#endif /* EX_OSERR */
17952
36
#ifdef EX_OSFILE
17953
36
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17954
36
#endif /* EX_OSFILE */
17955
36
#ifdef EX_CANTCREAT
17956
36
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17957
36
#endif /* EX_CANTCREAT */
17958
36
#ifdef EX_IOERR
17959
36
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17960
36
#endif /* EX_IOERR */
17961
36
#ifdef EX_TEMPFAIL
17962
36
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17963
36
#endif /* EX_TEMPFAIL */
17964
36
#ifdef EX_PROTOCOL
17965
36
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17966
36
#endif /* EX_PROTOCOL */
17967
36
#ifdef EX_NOPERM
17968
36
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17969
36
#endif /* EX_NOPERM */
17970
36
#ifdef EX_CONFIG
17971
36
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17972
36
#endif /* EX_CONFIG */
17973
#ifdef EX_NOTFOUND
17974
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17975
#endif /* EX_NOTFOUND */
17976
17977
    /* statvfs */
17978
36
#ifdef ST_RDONLY
17979
36
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17980
36
#endif /* ST_RDONLY */
17981
36
#ifdef ST_NOSUID
17982
36
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17983
36
#endif /* ST_NOSUID */
17984
17985
       /* GNU extensions */
17986
36
#ifdef ST_NODEV
17987
36
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17988
36
#endif /* ST_NODEV */
17989
36
#ifdef ST_NOEXEC
17990
36
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17991
36
#endif /* ST_NOEXEC */
17992
36
#ifdef ST_SYNCHRONOUS
17993
36
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17994
36
#endif /* ST_SYNCHRONOUS */
17995
36
#ifdef ST_MANDLOCK
17996
36
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17997
36
#endif /* ST_MANDLOCK */
17998
36
#ifdef ST_WRITE
17999
36
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
18000
36
#endif /* ST_WRITE */
18001
36
#ifdef ST_APPEND
18002
36
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
18003
36
#endif /* ST_APPEND */
18004
36
#ifdef ST_NOATIME
18005
36
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
18006
36
#endif /* ST_NOATIME */
18007
36
#ifdef ST_NODIRATIME
18008
36
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
18009
36
#endif /* ST_NODIRATIME */
18010
36
#ifdef ST_RELATIME
18011
36
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18012
36
#endif /* ST_RELATIME */
18013
18014
    /* FreeBSD sendfile() constants */
18015
#ifdef SF_NODISKIO
18016
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18017
#endif
18018
    /* is obsolete since the 11.x release */
18019
#ifdef SF_MNOWAIT
18020
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18021
#endif
18022
#ifdef SF_SYNC
18023
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18024
#endif
18025
#ifdef SF_NOCACHE
18026
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18027
#endif
18028
18029
36
#ifdef TFD_NONBLOCK
18030
36
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18031
36
#endif
18032
36
#ifdef TFD_CLOEXEC
18033
36
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18034
36
#endif
18035
36
#ifdef TFD_TIMER_ABSTIME
18036
36
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18037
36
#endif
18038
36
#ifdef TFD_TIMER_CANCEL_ON_SET
18039
36
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18040
36
#endif
18041
18042
    /* constants for posix_fadvise */
18043
36
#ifdef POSIX_FADV_NORMAL
18044
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18045
36
#endif
18046
36
#ifdef POSIX_FADV_SEQUENTIAL
18047
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18048
36
#endif
18049
36
#ifdef POSIX_FADV_RANDOM
18050
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18051
36
#endif
18052
36
#ifdef POSIX_FADV_NOREUSE
18053
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18054
36
#endif
18055
36
#ifdef POSIX_FADV_WILLNEED
18056
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18057
36
#endif
18058
36
#ifdef POSIX_FADV_DONTNEED
18059
36
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18060
36
#endif
18061
18062
    /* constants for waitid */
18063
36
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18064
36
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18065
36
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18066
36
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18067
36
#ifdef P_PIDFD
18068
36
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18069
36
#endif
18070
#ifdef PIDFD_NONBLOCK
18071
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18072
#endif
18073
36
#endif
18074
36
#ifdef WEXITED
18075
36
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18076
36
#endif
18077
36
#ifdef WNOWAIT
18078
36
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18079
36
#endif
18080
36
#ifdef WSTOPPED
18081
36
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18082
36
#endif
18083
36
#ifdef CLD_EXITED
18084
36
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18085
36
#endif
18086
36
#ifdef CLD_KILLED
18087
36
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18088
36
#endif
18089
36
#ifdef CLD_DUMPED
18090
36
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18091
36
#endif
18092
36
#ifdef CLD_TRAPPED
18093
36
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18094
36
#endif
18095
36
#ifdef CLD_STOPPED
18096
36
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18097
36
#endif
18098
36
#ifdef CLD_CONTINUED
18099
36
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18100
36
#endif
18101
18102
    /* constants for lockf */
18103
36
#ifdef F_LOCK
18104
36
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18105
36
#endif
18106
36
#ifdef F_TLOCK
18107
36
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18108
36
#endif
18109
36
#ifdef F_ULOCK
18110
36
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18111
36
#endif
18112
36
#ifdef F_TEST
18113
36
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18114
36
#endif
18115
18116
36
#ifdef RWF_DSYNC
18117
36
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18118
36
#endif
18119
36
#ifdef RWF_HIPRI
18120
36
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18121
36
#endif
18122
36
#ifdef RWF_SYNC
18123
36
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18124
36
#endif
18125
36
#ifdef RWF_NOWAIT
18126
36
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18127
36
#endif
18128
#ifdef RWF_DONTCACHE
18129
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18130
#endif
18131
#ifdef RWF_ATOMIC
18132
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18133
#endif
18134
36
#ifdef RWF_APPEND
18135
36
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18136
36
#endif
18137
18138
/* constants for splice */
18139
36
#if defined(HAVE_SPLICE) && defined(__linux__)
18140
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18141
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18142
36
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18143
36
#endif
18144
18145
/* constants for posix_spawn */
18146
36
#ifdef HAVE_POSIX_SPAWN
18147
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18148
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18149
36
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18150
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18151
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18152
#endif
18153
36
#endif
18154
18155
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18156
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18157
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18158
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18159
#endif
18160
#ifdef HAVE_SPAWNV
18161
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18162
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18163
#endif
18164
18165
36
#ifdef HAVE_SCHED_H
18166
36
#ifdef SCHED_OTHER
18167
36
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18168
36
#endif
18169
36
#ifdef SCHED_DEADLINE
18170
36
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18171
36
#endif
18172
36
#ifdef SCHED_FIFO
18173
36
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18174
36
#endif
18175
36
#ifdef SCHED_NORMAL
18176
36
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18177
36
#endif
18178
36
#ifdef SCHED_RR
18179
36
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18180
36
#endif
18181
#ifdef SCHED_SPORADIC
18182
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18183
#endif
18184
36
#ifdef SCHED_BATCH
18185
36
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18186
36
#endif
18187
36
#ifdef SCHED_IDLE
18188
36
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18189
36
#endif
18190
36
#ifdef SCHED_RESET_ON_FORK
18191
36
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18192
36
#endif
18193
#ifdef SCHED_SYS
18194
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18195
#endif
18196
#ifdef SCHED_IA
18197
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18198
#endif
18199
#ifdef SCHED_FSS
18200
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18201
#endif
18202
#ifdef SCHED_FX
18203
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18204
#endif
18205
18206
/* constants for namespaces */
18207
36
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18208
36
#ifdef CLONE_FS
18209
36
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18210
36
#endif
18211
36
#ifdef CLONE_FILES
18212
36
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18213
36
#endif
18214
36
#ifdef CLONE_NEWNS
18215
36
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18216
36
#endif
18217
36
#ifdef CLONE_NEWCGROUP
18218
36
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18219
36
#endif
18220
36
#ifdef CLONE_NEWUTS
18221
36
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18222
36
#endif
18223
36
#ifdef CLONE_NEWIPC
18224
36
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18225
36
#endif
18226
36
#ifdef CLONE_NEWUSER
18227
36
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18228
36
#endif
18229
36
#ifdef CLONE_NEWPID
18230
36
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18231
36
#endif
18232
36
#ifdef CLONE_NEWNET
18233
36
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18234
36
#endif
18235
#ifdef CLONE_NEWTIME
18236
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18237
#endif
18238
36
#ifdef CLONE_SYSVSEM
18239
36
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18240
36
#endif
18241
36
#ifdef CLONE_THREAD
18242
36
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18243
36
#endif
18244
36
#ifdef CLONE_SIGHAND
18245
36
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18246
36
#endif
18247
36
#ifdef CLONE_VM
18248
36
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18249
36
#endif
18250
36
#endif
18251
18252
36
#endif
18253
18254
36
#ifdef USE_XATTRS
18255
36
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18256
36
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18257
36
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18258
36
#endif
18259
18260
36
#if HAVE_DECL_RTLD_LAZY
18261
36
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18262
36
#endif
18263
36
#if HAVE_DECL_RTLD_NOW
18264
36
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18265
36
#endif
18266
36
#if HAVE_DECL_RTLD_GLOBAL
18267
36
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18268
36
#endif
18269
36
#if HAVE_DECL_RTLD_LOCAL
18270
36
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18271
36
#endif
18272
36
#if HAVE_DECL_RTLD_NODELETE
18273
36
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18274
36
#endif
18275
36
#if HAVE_DECL_RTLD_NOLOAD
18276
36
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18277
36
#endif
18278
36
#if HAVE_DECL_RTLD_DEEPBIND
18279
36
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18280
36
#endif
18281
#if HAVE_DECL_RTLD_MEMBER
18282
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18283
#endif
18284
18285
36
#ifdef HAVE_GETRANDOM_SYSCALL
18286
36
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18287
36
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18288
36
#endif
18289
36
#ifdef HAVE_MEMFD_CREATE
18290
36
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18291
36
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18292
36
#ifdef MFD_HUGETLB
18293
36
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18294
36
#endif
18295
36
#ifdef MFD_HUGE_SHIFT
18296
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18297
36
#endif
18298
36
#ifdef MFD_HUGE_MASK
18299
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18300
36
#endif
18301
36
#ifdef MFD_HUGE_64KB
18302
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18303
36
#endif
18304
36
#ifdef MFD_HUGE_512KB
18305
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18306
36
#endif
18307
36
#ifdef MFD_HUGE_1MB
18308
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18309
36
#endif
18310
36
#ifdef MFD_HUGE_2MB
18311
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18312
36
#endif
18313
36
#ifdef MFD_HUGE_8MB
18314
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18315
36
#endif
18316
36
#ifdef MFD_HUGE_16MB
18317
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18318
36
#endif
18319
36
#ifdef MFD_HUGE_32MB
18320
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18321
36
#endif
18322
36
#ifdef MFD_HUGE_256MB
18323
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18324
36
#endif
18325
36
#ifdef MFD_HUGE_512MB
18326
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18327
36
#endif
18328
36
#ifdef MFD_HUGE_1GB
18329
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18330
36
#endif
18331
36
#ifdef MFD_HUGE_2GB
18332
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18333
36
#endif
18334
36
#ifdef MFD_HUGE_16GB
18335
36
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18336
36
#endif
18337
36
#endif /* HAVE_MEMFD_CREATE */
18338
18339
36
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18340
36
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18341
36
#ifdef EFD_NONBLOCK
18342
36
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18343
36
#endif
18344
36
#ifdef EFD_SEMAPHORE
18345
36
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18346
36
#endif
18347
36
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18348
18349
36
#ifdef NODEV
18350
36
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18351
36
#endif
18352
18353
36
#ifdef AT_NO_AUTOMOUNT
18354
36
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18355
36
#endif
18356
18357
36
#ifdef HAVE_STATX
18358
36
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18359
36
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18360
36
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18361
36
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18362
36
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18363
36
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18364
36
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18365
36
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18366
36
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18367
36
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18368
36
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18369
36
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18370
36
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18371
#ifdef STATX_MNT_ID
18372
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18373
#endif
18374
#ifdef STATX_DIOALIGN
18375
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18376
#endif
18377
#ifdef STATX_MNT_ID_UNIQUE
18378
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18379
#endif
18380
#ifdef STATX_SUBVOL
18381
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18382
#endif
18383
#ifdef STATX_WRITE_ATOMIC
18384
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18385
#endif
18386
#ifdef STATX_DIO_READ_ALIGN
18387
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18388
#endif
18389
    /* STATX_ALL intentionally omitted because it is deprecated */
18390
36
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18391
36
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18392
36
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18393
    /* STATX_ATTR_* constants are in the stat module */
18394
36
#endif /* HAVE_STATX */
18395
18396
#if defined(__APPLE__)
18397
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18398
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18399
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18400
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18401
#endif
18402
18403
#ifdef MS_WINDOWS
18404
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18405
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18406
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18407
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18408
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18409
#endif
18410
18411
36
    return 0;
18412
36
}
18413
18414
18415
18416
#define PROBE(name, test) \
18417
   static int name(void)  \
18418
612
   {                      \
18419
612
      if (test) {        \
18420
612
          return 1;       \
18421
612
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
612
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_futimens
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_linkat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_openat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_renameat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18418
36
   {                      \
18419
36
      if (test) {        \
18420
36
          return 1;       \
18421
36
      } else {            \
18422
0
          return 0;       \
18423
0
      }                   \
18424
36
   }
18425
18426
#ifdef HAVE_FSTATAT
18427
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18428
#endif
18429
18430
#ifdef HAVE_FACCESSAT
18431
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18432
#endif
18433
18434
#ifdef HAVE_FCHMODAT
18435
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18436
#endif
18437
18438
#ifdef HAVE_FCHOWNAT
18439
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18440
#endif
18441
18442
#ifdef HAVE_LINKAT
18443
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18444
#endif
18445
18446
#ifdef HAVE_FDOPENDIR
18447
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18448
#endif
18449
18450
#ifdef HAVE_MKDIRAT
18451
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18452
#endif
18453
18454
#ifdef HAVE_MKFIFOAT
18455
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18456
#endif
18457
18458
#ifdef HAVE_MKNODAT
18459
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18460
#endif
18461
18462
#ifdef HAVE_RENAMEAT
18463
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18464
#endif
18465
18466
#ifdef HAVE_UNLINKAT
18467
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18468
#endif
18469
18470
#ifdef HAVE_OPENAT
18471
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18472
#endif
18473
18474
#ifdef HAVE_READLINKAT
18475
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18476
#endif
18477
18478
#ifdef HAVE_SYMLINKAT
18479
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18480
#endif
18481
18482
#ifdef HAVE_FUTIMENS
18483
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18484
#endif
18485
18486
#ifdef HAVE_UTIMENSAT
18487
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18488
#endif
18489
18490
#ifdef HAVE_PTSNAME_R
18491
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18492
#endif
18493
18494
18495
18496
static const struct have_function {
18497
    const char * const label;
18498
    int (*probe)(void);
18499
} have_functions[] = {
18500
18501
#ifdef HAVE_EVENTFD
18502
    {"HAVE_EVENTFD", NULL},
18503
#endif
18504
18505
#ifdef HAVE_TIMERFD_CREATE
18506
    {"HAVE_TIMERFD_CREATE", NULL},
18507
#endif
18508
18509
#ifdef HAVE_FACCESSAT
18510
    { "HAVE_FACCESSAT", probe_faccessat },
18511
#endif
18512
18513
#ifdef HAVE_FCHDIR
18514
    { "HAVE_FCHDIR", NULL },
18515
#endif
18516
18517
#ifdef HAVE_FCHMOD
18518
    { "HAVE_FCHMOD", NULL },
18519
#endif
18520
18521
#ifdef HAVE_FCHMODAT
18522
    { "HAVE_FCHMODAT", probe_fchmodat },
18523
#endif
18524
18525
#ifdef HAVE_FCHOWN
18526
    { "HAVE_FCHOWN", NULL },
18527
#endif
18528
18529
#ifdef HAVE_FCHOWNAT
18530
    { "HAVE_FCHOWNAT", probe_fchownat },
18531
#endif
18532
18533
#ifdef HAVE_FEXECVE
18534
    { "HAVE_FEXECVE", NULL },
18535
#endif
18536
18537
#ifdef HAVE_FDOPENDIR
18538
    { "HAVE_FDOPENDIR", probe_fdopendir },
18539
#endif
18540
18541
#ifdef HAVE_FPATHCONF
18542
    { "HAVE_FPATHCONF", NULL },
18543
#endif
18544
18545
#ifdef HAVE_FSTATAT
18546
    { "HAVE_FSTATAT", probe_fstatat },
18547
#endif
18548
18549
#ifdef HAVE_FSTATVFS
18550
    { "HAVE_FSTATVFS", NULL },
18551
#endif
18552
18553
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18554
    { "HAVE_FTRUNCATE", NULL },
18555
#endif
18556
18557
#ifdef HAVE_FUTIMENS
18558
    { "HAVE_FUTIMENS", probe_futimens },
18559
#endif
18560
18561
#ifdef HAVE_FUTIMES
18562
    { "HAVE_FUTIMES", NULL },
18563
#endif
18564
18565
#ifdef HAVE_FUTIMESAT
18566
    { "HAVE_FUTIMESAT", NULL },
18567
#endif
18568
18569
#ifdef HAVE_LINKAT
18570
    { "HAVE_LINKAT", probe_linkat },
18571
#endif
18572
18573
#ifdef HAVE_LCHFLAGS
18574
    { "HAVE_LCHFLAGS", NULL },
18575
#endif
18576
18577
#ifdef HAVE_LCHMOD
18578
    { "HAVE_LCHMOD", NULL },
18579
#endif
18580
18581
#ifdef HAVE_LCHOWN
18582
    { "HAVE_LCHOWN", NULL },
18583
#endif
18584
18585
#ifdef HAVE_LSTAT
18586
    { "HAVE_LSTAT", NULL },
18587
#endif
18588
18589
#ifdef HAVE_LUTIMES
18590
    { "HAVE_LUTIMES", NULL },
18591
#endif
18592
18593
#ifdef HAVE_MEMFD_CREATE
18594
    { "HAVE_MEMFD_CREATE", NULL },
18595
#endif
18596
18597
#ifdef HAVE_MKDIRAT
18598
    { "HAVE_MKDIRAT", probe_mkdirat },
18599
#endif
18600
18601
#ifdef HAVE_MKFIFOAT
18602
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18603
#endif
18604
18605
#ifdef HAVE_MKNODAT
18606
    { "HAVE_MKNODAT", probe_mknodat },
18607
#endif
18608
18609
#ifdef HAVE_OPENAT
18610
    { "HAVE_OPENAT", probe_openat },
18611
#endif
18612
18613
#ifdef HAVE_READLINKAT
18614
    { "HAVE_READLINKAT", probe_readlinkat },
18615
#endif
18616
18617
#ifdef HAVE_RENAMEAT
18618
    { "HAVE_RENAMEAT", probe_renameat },
18619
#endif
18620
18621
#ifdef HAVE_SYMLINKAT
18622
    { "HAVE_SYMLINKAT", probe_symlinkat },
18623
#endif
18624
18625
#ifdef HAVE_UNLINKAT
18626
    { "HAVE_UNLINKAT", probe_unlinkat },
18627
#endif
18628
18629
#ifdef HAVE_UTIMENSAT
18630
    { "HAVE_UTIMENSAT", probe_utimensat },
18631
#endif
18632
18633
#ifdef HAVE_PTSNAME_R
18634
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18635
#endif
18636
18637
#ifdef MS_WINDOWS
18638
    { "MS_WINDOWS", NULL },
18639
#endif
18640
18641
    { NULL, NULL }
18642
};
18643
18644
18645
static int
18646
posixmodule_exec(PyObject *m)
18647
36
{
18648
36
    _posixstate *state = get_posix_state(m);
18649
18650
36
#if defined(HAVE_PWRITEV)
18651
36
    if (HAVE_PWRITEV_RUNTIME) {} else {
18652
0
        PyObject* dct = PyModule_GetDict(m);
18653
18654
0
        if (dct == NULL) {
18655
0
            return -1;
18656
0
        }
18657
18658
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18659
0
            return -1;
18660
0
        }
18661
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18662
0
            return -1;
18663
0
        }
18664
0
    }
18665
36
#endif
18666
18667
36
#ifdef HAVE_STATX
18668
36
    if (statx == NULL) {
18669
0
        PyObject* dct = PyModule_GetDict(m);
18670
0
        if (dct == NULL) {
18671
0
            return -1;
18672
0
        }
18673
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18674
0
            return -1;
18675
0
        }
18676
0
    }
18677
36
    else {
18678
36
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18679
36
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18680
0
            return -1;
18681
0
        }
18682
36
    }
18683
36
#endif
18684
18685
    /* Initialize environ dictionary */
18686
36
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18687
0
        return -1;
18688
0
    }
18689
18690
36
    if (all_ins(m))
18691
0
        return -1;
18692
18693
36
    if (setup_confname_tables(m))
18694
0
        return -1;
18695
18696
36
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18697
0
        return -1;
18698
0
    }
18699
18700
36
#if defined(HAVE_WAITID)
18701
36
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18702
36
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18703
0
        return -1;
18704
0
    }
18705
36
#endif
18706
18707
36
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18708
36
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18709
36
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18710
36
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18711
36
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18712
0
        return -1;
18713
0
    }
18714
36
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18715
36
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18716
18717
36
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18718
36
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18719
0
        return -1;
18720
0
    }
18721
18722
36
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18723
36
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18724
36
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18725
0
        return -1;
18726
0
    }
18727
36
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18728
36
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18729
36
                          &os_sched_param_reduce_method) < 0)
18730
0
    {
18731
0
        return -1;
18732
0
    }
18733
36
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18734
36
#endif
18735
18736
    /* initialize TerminalSize_info */
18737
36
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18738
36
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18739
0
        return -1;
18740
0
    }
18741
18742
    /* initialize scandir types */
18743
36
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18744
36
    if (ScandirIteratorType == NULL) {
18745
0
        return -1;
18746
0
    }
18747
36
    state->ScandirIteratorType = ScandirIteratorType;
18748
18749
36
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18750
36
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18751
0
        return -1;
18752
0
    }
18753
18754
36
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18755
36
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18756
0
        return -1;
18757
0
    }
18758
18759
36
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18760
36
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18761
0
        return -1;
18762
0
    }
18763
18764
36
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18765
0
        return -1;
18766
36
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18767
36
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18768
36
    if (state->struct_rusage == NULL)
18769
0
        return -1;
18770
36
#endif
18771
36
    state->st_mode = PyUnicode_InternFromString("st_mode");
18772
36
    if (state->st_mode == NULL)
18773
0
        return -1;
18774
18775
    /* suppress "function not used" warnings */
18776
36
    {
18777
36
    int ignored;
18778
36
    fd_specified("", -1);
18779
36
    follow_symlinks_specified("", 1);
18780
36
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18781
36
    dir_fd_converter(Py_None, &ignored);
18782
36
    dir_fd_unavailable(Py_None, &ignored);
18783
36
    }
18784
18785
    /*
18786
     * provide list of locally available functions
18787
     * so os.py can populate support_* lists
18788
     */
18789
36
    PyObject *list = PyList_New(0);
18790
36
    if (!list) {
18791
0
        return -1;
18792
0
    }
18793
1.18k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18794
1.15k
        PyObject *unicode;
18795
1.15k
        if (trace->probe && !trace->probe()) continue;
18796
1.15k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18797
1.15k
        if (!unicode)
18798
0
            return -1;
18799
1.15k
        if (PyList_Append(list, unicode))
18800
0
            return -1;
18801
1.15k
        Py_DECREF(unicode);
18802
1.15k
    }
18803
18804
36
#ifndef MS_WINDOWS
18805
36
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18806
0
        PyErr_SetString(PyExc_RuntimeError,
18807
0
                        "cannot read ticks_per_second");
18808
0
        return -1;
18809
0
    }
18810
36
    assert(state->ticks_per_second >= 1);
18811
36
#endif
18812
18813
36
    return PyModule_Add(m, "_have_functions", list);
18814
36
}
18815
18816
18817
static PyModuleDef_Slot posixmodile_slots[] = {
18818
    {Py_mod_exec, posixmodule_exec},
18819
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18820
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18821
    {0, NULL}
18822
};
18823
18824
static struct PyModuleDef posixmodule = {
18825
    PyModuleDef_HEAD_INIT,
18826
    .m_name = MODNAME,
18827
    .m_doc = posix__doc__,
18828
    .m_size = sizeof(_posixstate),
18829
    .m_methods = posix_methods,
18830
    .m_slots = posixmodile_slots,
18831
    .m_traverse = _posix_traverse,
18832
    .m_clear = _posix_clear,
18833
    .m_free = _posix_free,
18834
};
18835
18836
PyMODINIT_FUNC
18837
INITFUNC(void)
18838
36
{
18839
36
    return PyModuleDef_Init(&posixmodule);
18840
36
}