Coverage Report

Created: 2026-03-08 06:40

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
542k
#  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
315k
#  define STAT stat
407
9.58k
#  define LSTAT lstat
408
167k
#  define FSTAT fstat
409
656k
#  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
163k
#  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
167k
#  define HAVE_FDOPENDIR_RUNTIME 1
608
0
#  define HAVE_MKDIRAT_RUNTIME 1
609
0
#  define HAVE_RENAMEAT_RUNTIME 1
610
189k
#  define HAVE_UNLINKAT_RUNTIME 1
611
163k
#  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
34
#  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
72
{
798
72
    if (func == NULL)  /* nothing to register? do nothing. */
799
40
        return 0;
800
32
    if (*lst == NULL) {
801
18
        *lst = PyList_New(0);
802
18
        if (*lst == NULL)
803
0
            return -1;
804
18
    }
805
32
    return PyList_Append(*lst, func);
806
32
}
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
408k
{
835
408k
    if (uid == (uid_t)-1)
836
0
        return PyLong_FromLong(-1);
837
408k
    return PyLong_FromUnsignedLong(uid);
838
408k
}
839
840
PyObject *
841
_PyLong_FromGid(gid_t gid)
842
408k
{
843
408k
    if (gid == (gid_t)-1)
844
0
        return PyLong_FromLong(-1);
845
408k
    return PyLong_FromUnsignedLong(gid);
846
408k
}
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
817k
{
1066
817k
#ifdef NODEV
1067
817k
    if (dev == NODEV) {
1068
34
        return PyLong_FromLongLong((long long)dev);
1069
34
    }
1070
817k
#endif
1071
817k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1072
817k
}
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.90M
#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
520k
{
1137
520k
    int overflow;
1138
520k
    long long_value;
1139
1140
520k
    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
520k
    PyObject *index = _PyNumber_Index(o);
1148
520k
    if (index == NULL) {
1149
0
        return 0;
1150
0
    }
1151
1152
520k
    assert(PyLong_Check(index));
1153
520k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1154
520k
    Py_DECREF(index);
1155
520k
    assert(!PyErr_Occurred());
1156
520k
    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
520k
    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
520k
    *p = (int)long_value;
1168
520k
    return 1;
1169
520k
}
1170
1171
static int
1172
dir_fd_converter(PyObject *o, void *p)
1173
368k
{
1174
368k
    if (o == Py_None) {
1175
15.5k
        *(int *)p = DEFAULT_DIR_FD;
1176
15.5k
        return 1;
1177
15.5k
    }
1178
353k
    else if (PyIndex_Check(o)) {
1179
353k
        return _fd_converter(o, (int *)p);
1180
353k
    }
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
368k
}
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
767k
{
1222
767k
    void *state = _PyModule_GetState(module);
1223
767k
    assert(state != NULL);
1224
767k
    return (_posixstate *)state;
1225
767k
}
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.25M
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1347
1.25M
     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
1.02M
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1357
1.02M
                      suppress_value_error, allow_fd)
1358
#endif
1359
1360
static void
1361
path_cleanup(path_t *path)
1362
1.41M
{
1363
1.41M
    wchar_t *wide = (wchar_t *)path->wide;
1364
1.41M
    path->wide = NULL;
1365
1.41M
    PyMem_Free(wide);
1366
1.41M
    Py_CLEAR(path->object);
1367
1.41M
    Py_CLEAR(path->cleanup);
1368
1.41M
}
1369
1370
static int
1371
path_converter(PyObject *o, void *p)
1372
1.25M
{
1373
1.25M
    path_t *path = (path_t *)p;
1374
1.25M
    PyObject *bytes = NULL;
1375
1.25M
    Py_ssize_t length = 0;
1376
1.25M
    int is_index, is_bytes, is_unicode;
1377
1.25M
    const char *narrow;
1378
1.25M
    PyObject *wo = NULL;
1379
1.25M
    wchar_t *wide = NULL;
1380
1381
1.25M
#define FORMAT_EXCEPTION(exc, fmt) \
1382
1.25M
    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.25M
    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.25M
    path->object = path->cleanup = NULL;
1395
    /* path->object owns a reference to the original object */
1396
1.25M
    Py_INCREF(o);
1397
1398
1.25M
    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.25M
    is_index = path->allow_fd && PyIndex_Check(o);
1408
1.25M
    is_bytes = PyBytes_Check(o);
1409
1.25M
    is_unicode = PyUnicode_Check(o);
1410
1411
1.25M
    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.25M
    if (is_unicode) {
1444
1.08M
        if (path->make_wide) {
1445
228k
            wide = PyUnicode_AsWideCharString(o, &length);
1446
228k
            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
228k
            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
228k
            path->wide = wide;
1462
228k
            path->narrow = NULL;
1463
228k
            path->fd = -1;
1464
228k
            wide = NULL;
1465
228k
            goto success_exit;
1466
228k
        }
1467
855k
        bytes = PyUnicode_EncodeFSDefault(o);
1468
855k
        if (!bytes) {
1469
0
            goto error_exit;
1470
0
        }
1471
855k
    }
1472
167k
    else if (is_bytes) {
1473
0
        bytes = Py_NewRef(o);
1474
0
    }
1475
167k
    else if (is_index) {
1476
167k
        if (!_fd_converter(o, &path->fd)) {
1477
0
            goto error_exit;
1478
0
        }
1479
167k
        path->wide = NULL;
1480
167k
        path->narrow = NULL;
1481
167k
        path->is_fd = true;
1482
167k
        goto success_exit;
1483
167k
    }
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
855k
    length = PyBytes_GET_SIZE(bytes);
1500
855k
    narrow = PyBytes_AS_STRING(bytes);
1501
855k
    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
855k
    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
855k
    else {
1534
855k
        path->wide = NULL;
1535
855k
        path->narrow = narrow;
1536
855k
        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
855k
        else {
1542
855k
            path->cleanup = bytes;
1543
855k
        }
1544
855k
    }
1545
855k
    path->fd = -1;
1546
1547
1.25M
 success_exit:
1548
1.25M
    path->value_error = 0;
1549
1.25M
    path->length = length;
1550
1.25M
    path->object = o;
1551
1.25M
    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
34
{
1585
34
    int dir_fd;
1586
34
    if (!dir_fd_converter(o, &dir_fd))
1587
0
        return 0;
1588
34
    if (dir_fd != DEFAULT_DIR_FD) {
1589
0
        argument_unavailable_error(NULL, "dir_fd");
1590
0
        return 0;
1591
0
    }
1592
34
    *(int *)p = dir_fd;
1593
34
    return 1;
1594
34
}
1595
1596
static int
1597
fd_specified(const char *function_name, int fd)
1598
34
{
1599
34
    if (fd == -1)
1600
34
        return 0;
1601
1602
0
    argument_unavailable_error(function_name, "fd");
1603
0
    return 1;
1604
34
}
1605
1606
static int
1607
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1608
34
{
1609
34
    if (follow_symlinks)
1610
34
        return 0;
1611
1612
0
    argument_unavailable_error(function_name, "follow_symlinks");
1613
0
    return 1;
1614
34
}
1615
1616
static int
1617
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1618
325k
{
1619
325k
    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
325k
    return 0;
1626
325k
}
1627
1628
static int
1629
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1630
325k
{
1631
325k
    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
325k
    return 0;
1638
325k
}
1639
1640
static int
1641
fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
1642
                               int follow_symlinks)
1643
325k
{
1644
325k
    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
325k
    return 0;
1651
325k
}
1652
1653
static int
1654
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1655
                                   int follow_symlinks)
1656
34
{
1657
34
    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
34
    return 0;
1664
34
}
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
34
{
1784
34
    PyObject *d;
1785
#ifdef MS_WINDOWS
1786
    wchar_t **e;
1787
#else
1788
34
    char **e;
1789
34
#endif
1790
1791
34
    d = PyDict_New();
1792
34
    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
34
    e = environ;
1806
34
#endif
1807
34
    if (e == NULL)
1808
0
        return d;
1809
1.19k
    for (; *e != NULL; e++) {
1810
1.15k
        PyObject *k;
1811
1.15k
        PyObject *v;
1812
#ifdef MS_WINDOWS
1813
        const wchar_t *p = wcschr(*e, L'=');
1814
#else
1815
1.15k
        const char *p = strchr(*e, '=');
1816
1.15k
#endif
1817
1.15k
        if (p == NULL)
1818
0
            continue;
1819
#ifdef MS_WINDOWS
1820
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1821
#else
1822
1.15k
        k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
1823
1.15k
#endif
1824
1.15k
        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.15k
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1832
1.15k
#endif
1833
1.15k
        if (v == NULL) {
1834
0
            Py_DECREF(k);
1835
0
            Py_DECREF(d);
1836
0
            return NULL;
1837
0
        }
1838
1.15k
        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.15k
        Py_DECREF(k);
1845
1.15k
        Py_DECREF(v);
1846
1.15k
    }
1847
34
    return d;
1848
34
}
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
247k
{
1899
247k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1900
247k
}
1901
1902
static PyObject *
1903
path_object_error(PyObject *path)
1904
247k
{
1905
#ifdef MS_WINDOWS
1906
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1907
                PyExc_OSError, 0, path);
1908
#else
1909
247k
    return posix_path_object_error(path);
1910
247k
#endif
1911
247k
}
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
247k
{
1927
247k
    return path_object_error(path->object);
1928
247k
}
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.67M
#define SEC_TO_NS (1000000000LL)
2638
static PyObject *
2639
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2640
1.22M
{
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.22M
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2646
1.22M
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2647
1.22M
    }
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.22M
#endif
2672
1.22M
}
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.22M
{
2678
1.22M
    assert(!PyErr_Occurred());
2679
1.22M
    assert(nsec < SEC_TO_NS);
2680
2681
1.22M
    if (s_index >= 0) {
2682
1.22M
        PyObject *s = _PyLong_FromTime_t(sec);
2683
1.22M
        if (s == NULL) {
2684
0
            return -1;
2685
0
        }
2686
1.22M
        PyStructSequence_SET_ITEM(v, s_index, s);
2687
1.22M
    }
2688
2689
1.22M
    if (f_index >= 0) {
2690
1.22M
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2691
1.22M
        if (float_s == NULL) {
2692
0
            return -1;
2693
0
        }
2694
1.22M
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2695
1.22M
    }
2696
2697
1.22M
    if (ns_index >= 0) {
2698
1.22M
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2699
1.22M
        if (ns_total == NULL) {
2700
0
            return -1;
2701
0
        }
2702
1.22M
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2703
1.22M
    }
2704
2705
1.22M
    assert(!PyErr_Occurred());
2706
1.22M
    return 0;
2707
1.22M
}
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
408k
{
2742
408k
    assert(!PyErr_Occurred());
2743
2744
408k
    _posixstate *state = get_posix_state(module);
2745
408k
    PyObject *StatResultType = state->StatResultType;
2746
408k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2747
408k
    if (v == NULL) {
2748
0
        return NULL;
2749
0
    }
2750
2751
408k
#define SET_ITEM(pos, expr) \
2752
4.08M
    do { \
2753
4.08M
        PyObject *obj = (expr); \
2754
4.08M
        if (obj == NULL) { \
2755
0
            goto error; \
2756
0
        } \
2757
4.08M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2758
4.08M
    } while (0)
2759
2760
408k
    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
408k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2766
408k
                  "stat.st_ino is larger than unsigned long long");
2767
408k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2768
408k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2769
408k
#endif
2770
408k
    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
408k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2776
408k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2777
408k
#endif
2778
408k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2779
408k
                  "stat.st_size is larger than long long");
2780
408k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2781
2782
    // Set st_atime, st_mtime and st_ctime
2783
408k
    unsigned long ansec, mnsec, cnsec;
2784
408k
#if defined(HAVE_STAT_TV_NSEC)
2785
408k
    ansec = st->st_atim.tv_nsec;
2786
408k
    mnsec = st->st_mtim.tv_nsec;
2787
408k
    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
408k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2800
0
        goto error;
2801
0
    }
2802
408k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2803
0
        goto error;
2804
0
    }
2805
408k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2806
0
        goto error;
2807
0
    }
2808
2809
408k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2810
408k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2811
408k
#endif
2812
408k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2813
408k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2814
408k
#endif
2815
408k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2816
408k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2817
408k
#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
408k
    assert(!PyErr_Occurred());
2853
408k
    return v;
2854
2855
0
error:
2856
0
    Py_DECREF(v);
2857
0
    return NULL;
2858
2859
408k
#undef SET_ITEM
2860
408k
}
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
325k
{
2869
325k
    STRUCT_STAT st;
2870
325k
    int result;
2871
2872
325k
#ifdef HAVE_FSTATAT
2873
325k
    int fstatat_unavailable = 0;
2874
325k
#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
325k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2882
325k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2883
325k
        fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
2884
0
        return NULL;
2885
2886
325k
    Py_BEGIN_ALLOW_THREADS
2887
325k
    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
325k
    else
2897
325k
#if defined(HAVE_LSTAT)
2898
325k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2899
9.58k
        result = LSTAT(path->narrow, &st);
2900
315k
    else
2901
315k
#endif /* HAVE_LSTAT */
2902
315k
#ifdef HAVE_FSTATAT
2903
315k
    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
315k
#endif /* HAVE_FSTATAT */
2913
315k
        result = STAT(path->narrow, &st);
2914
325k
#endif /* MS_WINDOWS */
2915
325k
    Py_END_ALLOW_THREADS
2916
2917
325k
#ifdef HAVE_FSTATAT
2918
325k
    if (fstatat_unavailable) {
2919
0
        argument_unavailable_error("stat", "dir_fd");
2920
0
        return NULL;
2921
0
    }
2922
325k
#endif
2923
2924
325k
    if (result != 0) {
2925
247k
        return path_error(path);
2926
247k
    }
2927
2928
78.1k
    return _pystat_fromstructstat(module, &st);
2929
325k
}
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.73k
    #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
167k
    #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
193k
    #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
3117
    converter = 'path_converter'
3118
3119
    def converter_init(self, *, allow_fd=False, make_wide=None,
3120
                       nonstrict=False, nullable=False,
3121
                       suppress_value_error=False):
3122
        # right now path_t doesn't support default values.
3123
        # to support a default value, you'll need to override initialize().
3124
        if self.default not in (unspecified, None):
3125
            fail("Can't specify a default to the path_t converter!")
3126
3127
        if self.c_default not in (None, 'Py_None'):
3128
            raise RuntimeError("Can't specify a c_default to the path_t converter!")
3129
3130
        self.nullable = nullable
3131
        self.nonstrict = nonstrict
3132
        self.make_wide = make_wide
3133
        self.suppress_value_error = suppress_value_error
3134
        self.allow_fd = allow_fd
3135
3136
    def pre_render(self):
3137
        def strify(value):
3138
            if isinstance(value, str):
3139
                return value
3140
            return str(int(bool(value)))
3141
3142
        # add self.py_name here when merging with posixmodule conversion
3143
        if self.make_wide is None:
3144
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3145
                self.function.name,
3146
                self.name,
3147
                strify(self.nullable),
3148
                strify(self.nonstrict),
3149
                strify(self.suppress_value_error),
3150
                strify(self.allow_fd),
3151
            )
3152
        else:
3153
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3154
                self.function.name,
3155
                self.name,
3156
                strify(self.nullable),
3157
                strify(self.nonstrict),
3158
                strify(self.make_wide),
3159
                strify(self.suppress_value_error),
3160
                strify(self.allow_fd),
3161
            )
3162
3163
    def cleanup(self):
3164
        return "path_cleanup(&" + self.name + ");\n"
3165
3166
3167
class dir_fd_converter(CConverter):
3168
    type = 'int'
3169
3170
    def converter_init(self, requires=None):
3171
        if self.default in (unspecified, None):
3172
            self.c_default = 'DEFAULT_DIR_FD'
3173
        if isinstance(requires, str):
3174
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3175
        else:
3176
            self.converter = 'dir_fd_converter'
3177
3178
class uid_t_converter(CConverter):
3179
    type = "uid_t"
3180
    converter = '_Py_Uid_Converter'
3181
3182
class gid_t_converter(CConverter):
3183
    type = "gid_t"
3184
    converter = '_Py_Gid_Converter'
3185
3186
class dev_t_converter(CConverter):
3187
    type = 'dev_t'
3188
    converter = '_Py_Dev_Converter'
3189
3190
class dev_t_return_converter(unsigned_long_return_converter):
3191
    type = 'dev_t'
3192
    conversion_fn = '_PyLong_FromDev'
3193
    unsigned_cast = '(dev_t)'
3194
3195
class pid_t_converter(CConverter):
3196
    type = 'pid_t'
3197
    format_unit = '" _Py_PARSE_PID "'
3198
3199
    def parse_arg(self, argname, displayname, *, limited_capi):
3200
        return self.format_code("""
3201
            {paramname} = PyLong_AsPid({argname});
3202
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3203
                goto exit;
3204
            }}}}
3205
            """, argname=argname)
3206
3207
class idtype_t_converter(CConverter):
3208
    type = 'idtype_t'
3209
    converter = 'idtype_t_converter'
3210
3211
class id_t_converter(CConverter):
3212
    type = 'id_t'
3213
    format_unit = '" _Py_PARSE_PID "'
3214
3215
    def parse_arg(self, argname, displayname, *, limited_capi):
3216
        return self.format_code("""
3217
            {paramname} = (id_t)PyLong_AsPid({argname});
3218
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3219
                goto exit;
3220
            }}}}
3221
            """, argname=argname)
3222
3223
class intptr_t_converter(CConverter):
3224
    type = 'intptr_t'
3225
    format_unit = '" _Py_PARSE_INTPTR "'
3226
3227
    def parse_arg(self, argname, displayname, *, limited_capi):
3228
        return self.format_code("""
3229
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3230
            if (!{paramname} && PyErr_Occurred()) {{{{
3231
                goto exit;
3232
            }}}}
3233
            """, argname=argname)
3234
3235
class Py_off_t_converter(CConverter):
3236
    type = 'Py_off_t'
3237
    converter = 'Py_off_t_converter'
3238
3239
class Py_off_t_return_converter(long_return_converter):
3240
    type = 'Py_off_t'
3241
    conversion_fn = 'PyLong_FromPy_off_t'
3242
3243
class confname_converter(CConverter):
3244
    type="int"
3245
    converter="conv_confname"
3246
3247
    def converter_init(self, *, table):
3248
        self.table = table
3249
3250
    def parse_arg(self, argname, displayname, *, limited_capi):
3251
        return self.format_code("""
3252
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3253
                goto exit;
3254
            }}}}
3255
        """, argname=argname, converter=self.converter, table=self.table)
3256
3257
[python start generated code]*/
3258
/*[python end generated code: output=da39a3ee5e6b4b0d input=d2759f2332cd39b3]*/
3259
3260
/*[clinic input]
3261
3262
os.stat
3263
3264
    path : path_t(allow_fd=True)
3265
        Path to be examined; can be string, bytes, a path-like object or
3266
        open-file-descriptor int.
3267
3268
    *
3269
3270
    dir_fd : dir_fd(requires='fstatat') = None
3271
        If not None, it should be a file descriptor open to a directory,
3272
        and path should be a relative string; path will then be relative to
3273
        that directory.
3274
3275
    follow_symlinks: bool = True
3276
        If False, and the last element of the path is a symbolic link,
3277
        stat will examine the symbolic link itself instead of the file
3278
        the link points to.
3279
3280
Perform a stat system call on the given path.
3281
3282
dir_fd and follow_symlinks may not be implemented
3283
  on your platform.  If they are unavailable, using them will raise a
3284
  NotImplementedError.
3285
3286
It's an error to use dir_fd or follow_symlinks when specifying path as
3287
  an open file descriptor.
3288
3289
[clinic start generated code]*/
3290
3291
static PyObject *
3292
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3293
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3294
315k
{
3295
315k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3296
315k
}
3297
3298
3299
/*[clinic input]
3300
@permit_long_summary
3301
os.lstat
3302
3303
    path : path_t
3304
3305
    *
3306
3307
    dir_fd : dir_fd(requires='fstatat') = None
3308
3309
Perform a stat system call on the given path, without following symbolic links.
3310
3311
Like stat(), but do not follow symbolic links.
3312
Equivalent to stat(path, follow_symlinks=False).
3313
[clinic start generated code]*/
3314
3315
static PyObject *
3316
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3317
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3318
9.58k
{
3319
9.58k
    int follow_symlinks = 0;
3320
9.58k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3321
9.58k
}
3322
3323
3324
#ifdef HAVE_STATX
3325
typedef struct {
3326
    PyObject_HEAD
3327
    dev_t rdev, dev;
3328
    struct statx stx;
3329
} Py_statx_result;
3330
3331
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3332
3333
#define M(attr, type, offset, doc) \
3334
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3335
#define MM(attr, type, member, doc) \
3336
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3337
#define MX(attr, type, member, doc) \
3338
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3339
3340
static PyMemberDef pystatx_result_members[] = {
3341
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3342
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3343
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3344
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3345
        "Mask of supported bits in stx_attributes"),
3346
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3347
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3348
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3349
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3350
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3351
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3352
    {NULL},
3353
};
3354
3355
#undef MX
3356
#undef MM
3357
#undef M
3358
3359
3360
#define STATX_GET_UINT(ATTR, MASK) \
3361
    static PyObject* \
3362
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3363
0
    { \
3364
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3365
0
        if (!(self->stx.stx_mask & MASK)) { \
3366
0
            Py_RETURN_NONE; \
3367
0
        } \
3368
0
        unsigned long value = self->stx.ATTR; \
3369
0
        return PyLong_FromUnsignedLong(value); \
3370
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
3371
3372
STATX_GET_UINT(stx_uid, STATX_UID)
3373
STATX_GET_UINT(stx_gid, STATX_GID)
3374
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3375
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3376
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3377
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3378
#endif
3379
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3380
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3381
#endif
3382
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3383
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3384
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3385
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3386
#endif
3387
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3388
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3389
#endif
3390
3391
3392
static PyObject*
3393
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3394
0
{
3395
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3396
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3397
0
        Py_RETURN_NONE;
3398
0
    }
3399
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3400
0
}
3401
3402
3403
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3404
    static PyObject* \
3405
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3406
0
    { \
3407
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3408
0
        if (!(self->stx.stx_mask & MASK)) { \
3409
0
            Py_RETURN_NONE; \
3410
0
        } \
3411
0
        unsigned long long value = self->stx.ATTR; \
3412
0
        return PyLong_FromUnsignedLongLong(value); \
3413
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
3414
3415
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3416
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3417
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3418
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3419
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3420
#endif
3421
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3422
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3423
#endif
3424
3425
3426
#define STATX_GET_DOUBLE(ATTR, MASK) \
3427
    static PyObject* \
3428
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3429
0
    { \
3430
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3431
0
        if (!(self->stx.stx_mask & MASK)) { \
3432
0
            Py_RETURN_NONE; \
3433
0
        } \
3434
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3435
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3436
0
        return PyFloat_FromDouble(sec); \
3437
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
3438
3439
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3440
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3441
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3442
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3443
3444
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3445
    static PyObject* \
3446
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3447
0
    { \
3448
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3449
0
        if (!(self->stx.stx_mask & MASK)) { \
3450
0
            Py_RETURN_NONE; \
3451
0
        } \
3452
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3453
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3454
0
        assert(state != NULL); \
3455
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3456
0
    }
3457
3458
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3459
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3460
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3461
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3462
3463
#define G(attr, doc) \
3464
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3465
3466
static PyGetSetDef pystatx_result_getset[] = {
3467
    G(stx_mode, "protection bits"),
3468
    G(stx_nlink, "number of hard links"),
3469
    G(stx_uid, "user ID of owner"),
3470
    G(stx_gid, "group ID of owner"),
3471
    G(stx_ino, "inode"),
3472
    G(stx_size, "total size, in bytes"),
3473
    G(stx_blocks, "number of blocks allocated"),
3474
    G(stx_atime, "time of last access"),
3475
    G(stx_atime_ns, "time of last access in nanoseconds"),
3476
    G(stx_btime, "time of creation"),
3477
    G(stx_btime_ns, "time of creation in nanoseconds"),
3478
    G(stx_ctime, "time of last change"),
3479
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3480
    G(stx_mtime, "time of last modification"),
3481
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3482
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3483
    G(stx_mnt_id, "mount ID"),
3484
#endif
3485
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3486
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3487
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3488
#endif
3489
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3490
    G(stx_subvol, "subvolume ID"),
3491
#endif
3492
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3493
    G(stx_atomic_write_unit_min,
3494
      "minimum size for direct I/O with torn-write protection"),
3495
    G(stx_atomic_write_unit_max,
3496
        "maximum size for direct I/O with torn-write protection"),
3497
    G(stx_atomic_write_segments_max,
3498
        "maximum iovecs for direct I/O with torn-write protection"),
3499
#endif
3500
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3501
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3502
#endif
3503
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3504
    G(stx_atomic_write_unit_max_opt,
3505
        "maximum optimized size for direct I/O with torn-write protection"),
3506
#endif
3507
    {NULL},
3508
};
3509
3510
#undef G
3511
3512
static PyObject *
3513
pystatx_result_repr(PyObject *op)
3514
0
{
3515
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3516
0
    if (writer == NULL) {
3517
0
        return NULL;
3518
0
    }
3519
0
#define WRITE_ASCII(s) \
3520
0
    do { \
3521
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3522
0
            goto error; \
3523
0
        } \
3524
0
    } while (0)
3525
3526
0
    WRITE_ASCII("os.statx_result(");
3527
3528
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3529
0
        if (i > 0) {
3530
0
            WRITE_ASCII(", ");
3531
0
        }
3532
3533
0
        PyMemberDef *d = &pystatx_result_members[i];
3534
0
        WRITE_ASCII(d->name);
3535
0
        WRITE_ASCII("=");
3536
3537
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3538
0
        if (o == NULL) {
3539
0
            goto error;
3540
0
        }
3541
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3542
0
            Py_DECREF(o);
3543
0
            goto error;
3544
0
        }
3545
0
        Py_DECREF(o);
3546
0
    }
3547
3548
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3549
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3550
0
        PyObject *o = d->get(op, d->closure);
3551
0
        if (o == NULL) {
3552
0
            goto error;
3553
0
        }
3554
0
        if (o == Py_None) {
3555
0
            continue;
3556
0
        }
3557
3558
0
        WRITE_ASCII(", ");
3559
0
        WRITE_ASCII(d->name);
3560
0
        WRITE_ASCII("=");
3561
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3562
0
            Py_DECREF(o);
3563
0
            goto error;
3564
0
        }
3565
0
        Py_DECREF(o);
3566
0
    }
3567
3568
0
    WRITE_ASCII(")");
3569
0
    return PyUnicodeWriter_Finish(writer);
3570
0
#undef WRITE_ASCII
3571
3572
0
error:
3573
0
    PyUnicodeWriter_Discard(writer);
3574
0
    return NULL;
3575
0
}
3576
3577
static int
3578
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3579
0
{
3580
0
    Py_VISIT(Py_TYPE(self));
3581
0
    return 0;
3582
0
}
3583
3584
static void
3585
pystatx_result_dealloc(PyObject *op)
3586
0
{
3587
0
    Py_statx_result *self = (Py_statx_result *) op;
3588
0
    PyTypeObject *tp = Py_TYPE(self);
3589
0
    PyObject_GC_UnTrack(self);
3590
0
    tp->tp_free(self);
3591
0
    Py_DECREF(tp);
3592
0
}
3593
3594
static PyType_Slot pystatx_result_slots[] = {
3595
    {Py_tp_repr, pystatx_result_repr},
3596
    {Py_tp_traverse, pystatx_result_traverse},
3597
    {Py_tp_dealloc, pystatx_result_dealloc},
3598
    {Py_tp_members, pystatx_result_members},
3599
    {Py_tp_getset, pystatx_result_getset},
3600
    {0, NULL},
3601
};
3602
3603
static PyType_Spec pystatx_result_spec = {
3604
    .name = "os.statx_result",
3605
    .basicsize = sizeof(Py_statx_result),
3606
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3607
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3608
    .slots = pystatx_result_slots,
3609
};
3610
3611
/*[clinic input]
3612
3613
os.statx
3614
3615
    path : path_t(allow_fd=True)
3616
        Path to be examined; can be string, bytes, a path-like object or
3617
        open-file-descriptor int.
3618
3619
    mask: unsigned_int(bitwise=True)
3620
        A bitmask of STATX_* constants defining the requested information.
3621
3622
    *
3623
3624
    flags: int = 0
3625
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3626
3627
    dir_fd : dir_fd = None
3628
        If not None, it should be a file descriptor open to a directory,
3629
        and path should be a relative string; path will then be relative to
3630
        that directory.
3631
3632
    follow_symlinks: bool = True
3633
        If False, and the last element of the path is a symbolic link,
3634
        statx will examine the symbolic link itself instead of the file
3635
        the link points to.
3636
3637
Perform a statx system call on the given path.
3638
3639
It's an error to use dir_fd or follow_symlinks when specifying path as
3640
  an open file descriptor.
3641
3642
[clinic start generated code]*/
3643
3644
static PyObject *
3645
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3646
              int dir_fd, int follow_symlinks)
3647
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3648
0
{
3649
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3650
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3651
0
        fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) {
3652
0
        return NULL;
3653
0
    }
3654
3655
    /* reject flags covered by kwargs, but allow unknown flags that may be
3656
       future AT_STATX_* extensions */
3657
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3658
0
        PyErr_Format(PyExc_ValueError,
3659
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3660
0
        return NULL;
3661
0
    }
3662
0
    if (flags & AT_EMPTY_PATH) {
3663
0
        PyErr_Format(PyExc_ValueError,
3664
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3665
0
        return NULL;
3666
0
    }
3667
3668
    /* Future bits may refer to members beyond the current size of struct
3669
       statx, so we need to mask them off to prevent memory corruption. */
3670
0
    mask &= _Py_STATX_KNOWN;
3671
3672
0
    _posixstate *state = get_posix_state(module);
3673
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3674
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3675
0
    if (v == NULL) {
3676
0
        return NULL;
3677
0
    }
3678
3679
0
    int result;
3680
0
    Py_BEGIN_ALLOW_THREADS
3681
0
    if (path->is_fd) {
3682
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3683
0
    }
3684
0
    else {
3685
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3686
0
    }
3687
0
    Py_END_ALLOW_THREADS
3688
3689
0
    if (result != 0) {
3690
0
        Py_DECREF(v);
3691
0
        return path_error(path);
3692
0
    }
3693
3694
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3695
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3696
3697
0
    assert(!PyErr_Occurred());
3698
0
    return (PyObject *)v;
3699
0
}
3700
#endif /* HAVE_STATX */
3701
3702
3703
/*[clinic input]
3704
os.access -> bool
3705
3706
    path: path_t
3707
        Path to be tested; can be string, bytes, or a path-like object.
3708
3709
    mode: int
3710
        Operating-system mode bitfield.  Can be F_OK to test existence,
3711
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3712
3713
    *
3714
3715
    dir_fd : dir_fd(requires='faccessat') = None
3716
        If not None, it should be a file descriptor open to a directory,
3717
        and path should be relative; path will then be relative to that
3718
        directory.
3719
3720
    effective_ids: bool = False
3721
        If True, access will use the effective uid/gid instead of
3722
        the real uid/gid.
3723
3724
    follow_symlinks: bool = True
3725
        If False, and the last element of the path is a symbolic link,
3726
        access will examine the symbolic link itself instead of the file
3727
        the link points to.
3728
3729
Use the real uid/gid to test for access to a path.
3730
3731
{parameters}
3732
dir_fd, effective_ids, and follow_symlinks may not be implemented
3733
  on your platform.  If they are unavailable, using them will raise a
3734
  NotImplementedError.
3735
3736
Note that most operations will use the effective uid/gid, therefore this
3737
  routine can be used in a suid/sgid environment to test if the invoking
3738
  user has the specified access to the path.
3739
3740
[clinic start generated code]*/
3741
3742
static int
3743
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3744
               int effective_ids, int follow_symlinks)
3745
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3746
0
{
3747
0
    int return_value;
3748
3749
#ifdef MS_WINDOWS
3750
    DWORD attr;
3751
#else
3752
0
    int result;
3753
0
#endif
3754
3755
0
#ifdef HAVE_FACCESSAT
3756
0
    int faccessat_unavailable = 0;
3757
0
#endif
3758
3759
#ifndef HAVE_FACCESSAT
3760
    if (follow_symlinks_specified("access", follow_symlinks))
3761
        return -1;
3762
3763
    if (effective_ids) {
3764
        argument_unavailable_error("access", "effective_ids");
3765
        return -1;
3766
    }
3767
#endif
3768
3769
#ifdef MS_WINDOWS
3770
    Py_BEGIN_ALLOW_THREADS
3771
    attr = GetFileAttributesW(path->wide);
3772
    Py_END_ALLOW_THREADS
3773
3774
    /*
3775
     * Access is possible if
3776
     *   * we didn't get a -1, and
3777
     *     * write access wasn't requested,
3778
     *     * or the file isn't read-only,
3779
     *     * or it's a directory.
3780
     * (Directories cannot be read-only on Windows.)
3781
    */
3782
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3783
            (!(mode & 2) ||
3784
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3785
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3786
#else
3787
3788
0
    Py_BEGIN_ALLOW_THREADS
3789
0
#ifdef HAVE_FACCESSAT
3790
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3791
0
        effective_ids ||
3792
0
        !follow_symlinks) {
3793
3794
0
        if (HAVE_FACCESSAT_RUNTIME) {
3795
0
            int flags = 0;
3796
0
            if (!follow_symlinks)
3797
0
                flags |= AT_SYMLINK_NOFOLLOW;
3798
0
            if (effective_ids)
3799
0
                flags |= AT_EACCESS;
3800
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3801
0
        } else {
3802
0
            faccessat_unavailable = 1;
3803
0
        }
3804
0
    }
3805
0
    else
3806
0
#endif
3807
0
        result = access(path->narrow, mode);
3808
0
    Py_END_ALLOW_THREADS
3809
3810
0
#ifdef HAVE_FACCESSAT
3811
0
    if (faccessat_unavailable) {
3812
0
        if (dir_fd != DEFAULT_DIR_FD) {
3813
0
            argument_unavailable_error("access", "dir_fd");
3814
0
            return -1;
3815
0
        }
3816
0
        if (follow_symlinks_specified("access", follow_symlinks))
3817
0
            return -1;
3818
3819
0
        if (effective_ids) {
3820
0
            argument_unavailable_error("access", "effective_ids");
3821
0
            return -1;
3822
0
        }
3823
        /* should be unreachable */
3824
0
        return -1;
3825
0
    }
3826
0
#endif
3827
0
    return_value = !result;
3828
0
#endif
3829
3830
0
    return return_value;
3831
0
}
3832
3833
#ifndef F_OK
3834
#define F_OK 0
3835
#endif
3836
#ifndef R_OK
3837
#define R_OK 4
3838
#endif
3839
#ifndef W_OK
3840
#define W_OK 2
3841
#endif
3842
#ifndef X_OK
3843
#define X_OK 1
3844
#endif
3845
3846
3847
#ifdef HAVE_TTYNAME_R
3848
/*[clinic input]
3849
os.ttyname
3850
3851
    fd: int
3852
        Integer file descriptor handle.
3853
3854
    /
3855
3856
Return the name of the terminal device connected to 'fd'.
3857
[clinic start generated code]*/
3858
3859
static PyObject *
3860
os_ttyname_impl(PyObject *module, int fd)
3861
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3862
0
{
3863
3864
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3865
0
    if (size == -1) {
3866
0
        return posix_error();
3867
0
    }
3868
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3869
0
    if (buffer == NULL) {
3870
0
        return PyErr_NoMemory();
3871
0
    }
3872
0
    int ret = ttyname_r(fd, buffer, size);
3873
0
    if (ret != 0) {
3874
0
        PyMem_RawFree(buffer);
3875
0
        errno = ret;
3876
0
        return posix_error();
3877
0
    }
3878
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3879
0
    PyMem_RawFree(buffer);
3880
0
    return res;
3881
0
}
3882
#endif
3883
3884
#ifdef HAVE_CTERMID
3885
/*[clinic input]
3886
os.ctermid
3887
3888
Return the name of the controlling terminal for this process.
3889
[clinic start generated code]*/
3890
3891
static PyObject *
3892
os_ctermid_impl(PyObject *module)
3893
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3894
0
{
3895
0
    char *ret;
3896
0
    char buffer[L_ctermid];
3897
3898
#ifdef USE_CTERMID_R
3899
    ret = ctermid_r(buffer);
3900
#else
3901
0
    ret = ctermid(buffer);
3902
0
#endif
3903
0
    if (ret == NULL)
3904
0
        return posix_error();
3905
0
    return PyUnicode_DecodeFSDefault(buffer);
3906
0
}
3907
#endif /* HAVE_CTERMID */
3908
3909
3910
/*[clinic input]
3911
os.chdir
3912
3913
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3914
3915
Change the current working directory to the specified path.
3916
3917
path may always be specified as a string.
3918
On some platforms, path may also be specified as an open file descriptor.
3919
If this functionality is unavailable, using it raises an exception.
3920
[clinic start generated code]*/
3921
3922
static PyObject *
3923
os_chdir_impl(PyObject *module, path_t *path)
3924
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3925
0
{
3926
0
    int result;
3927
3928
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3929
0
        return NULL;
3930
0
    }
3931
3932
0
    Py_BEGIN_ALLOW_THREADS
3933
#ifdef MS_WINDOWS
3934
    /* on unix, success = 0, on windows, success = !0 */
3935
    result = !win32_wchdir(path->wide);
3936
#else
3937
0
#ifdef HAVE_FCHDIR
3938
0
    if (path->is_fd)
3939
0
        result = fchdir(path->fd);
3940
0
    else
3941
0
#endif
3942
0
        result = chdir(path->narrow);
3943
0
#endif
3944
0
    Py_END_ALLOW_THREADS
3945
3946
0
    if (result) {
3947
0
        return path_error(path);
3948
0
    }
3949
3950
0
    Py_RETURN_NONE;
3951
0
}
3952
3953
3954
#ifdef HAVE_FCHDIR
3955
/*[clinic input]
3956
os.fchdir
3957
3958
    fd: fildes
3959
3960
Change to the directory of the given file descriptor.
3961
3962
fd must be opened on a directory, not a file.
3963
Equivalent to os.chdir(fd).
3964
3965
[clinic start generated code]*/
3966
3967
static PyObject *
3968
os_fchdir_impl(PyObject *module, int fd)
3969
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3970
0
{
3971
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3972
0
        return NULL;
3973
0
    }
3974
0
    return posix_fildes_fd(fd, fchdir);
3975
0
}
3976
#endif /* HAVE_FCHDIR */
3977
3978
#ifdef MS_WINDOWS
3979
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3980
#else
3981
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3982
#endif
3983
3984
#ifdef MS_WINDOWS
3985
static int
3986
win32_lchmod(LPCWSTR path, int mode)
3987
{
3988
    DWORD attr = GetFileAttributesW(path);
3989
    if (attr == INVALID_FILE_ATTRIBUTES) {
3990
        return 0;
3991
    }
3992
    if (mode & _S_IWRITE) {
3993
        attr &= ~FILE_ATTRIBUTE_READONLY;
3994
    }
3995
    else {
3996
        attr |= FILE_ATTRIBUTE_READONLY;
3997
    }
3998
    return SetFileAttributesW(path, attr);
3999
}
4000
4001
static int
4002
win32_hchmod(HANDLE hfile, int mode)
4003
{
4004
    FILE_BASIC_INFO info;
4005
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4006
                                      &info, sizeof(info)))
4007
    {
4008
        return 0;
4009
    }
4010
    if (mode & _S_IWRITE) {
4011
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4012
    }
4013
    else {
4014
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4015
    }
4016
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4017
                                      &info, sizeof(info));
4018
}
4019
4020
static int
4021
win32_fchmod(int fd, int mode)
4022
{
4023
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4024
    if (hfile == INVALID_HANDLE_VALUE) {
4025
        SetLastError(ERROR_INVALID_HANDLE);
4026
        return 0;
4027
    }
4028
    return win32_hchmod(hfile, mode);
4029
}
4030
4031
#endif /* MS_WINDOWS */
4032
4033
/*[clinic input]
4034
os.chmod
4035
4036
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4037
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
4038
        On some platforms, path may also be specified as an open file descriptor.
4039
        If this functionality is unavailable, using it raises an exception.
4040
4041
    mode: int
4042
        Operating-system mode bitfield.
4043
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4044
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4045
        Python.
4046
4047
    *
4048
4049
    dir_fd : dir_fd(requires='fchmodat') = None
4050
        If not None, it should be a file descriptor open to a directory,
4051
        and path should be relative; path will then be relative to that
4052
        directory.
4053
4054
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4055
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4056
        If False, and the last element of the path is a symbolic link,
4057
        chmod will modify the symbolic link itself instead of the file
4058
        the link points to.
4059
4060
Change the access permissions of a file.
4061
4062
It is an error to use dir_fd or follow_symlinks when specifying path as
4063
  an open file descriptor.
4064
dir_fd and follow_symlinks may not be implemented on your platform.
4065
  If they are unavailable, using them will raise a NotImplementedError.
4066
4067
[clinic start generated code]*/
4068
4069
static PyObject *
4070
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4071
              int follow_symlinks)
4072
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
4073
0
{
4074
0
    int result;
4075
4076
0
#ifdef HAVE_FCHMODAT
4077
0
    int fchmodat_nofollow_unsupported = 0;
4078
0
    int fchmodat_unsupported = 0;
4079
0
#endif
4080
4081
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4082
    if (follow_symlinks_specified("chmod", follow_symlinks))
4083
        return NULL;
4084
#endif
4085
4086
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4087
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4088
0
        return NULL;
4089
0
    }
4090
4091
#ifdef MS_WINDOWS
4092
    result = 0;
4093
    Py_BEGIN_ALLOW_THREADS
4094
    if (path->is_fd) {
4095
        result = win32_fchmod(path->fd, mode);
4096
    }
4097
    else if (follow_symlinks) {
4098
        HANDLE hfile = CreateFileW(path->wide,
4099
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4100
                                   0, NULL,
4101
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4102
        if (hfile != INVALID_HANDLE_VALUE) {
4103
            result = win32_hchmod(hfile, mode);
4104
            (void)CloseHandle(hfile);
4105
        }
4106
    }
4107
    else {
4108
        result = win32_lchmod(path->wide, mode);
4109
    }
4110
    Py_END_ALLOW_THREADS
4111
    if (!result) {
4112
        return path_error(path);
4113
    }
4114
#else /* MS_WINDOWS */
4115
0
    Py_BEGIN_ALLOW_THREADS
4116
0
#ifdef HAVE_FCHMOD
4117
0
    if (path->is_fd) {
4118
0
        result = fchmod(path->fd, mode);
4119
0
    }
4120
0
    else
4121
0
#endif /* HAVE_CHMOD */
4122
#ifdef HAVE_LCHMOD
4123
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4124
        result = lchmod(path->narrow, mode);
4125
    else
4126
#endif /* HAVE_LCHMOD */
4127
0
#ifdef HAVE_FCHMODAT
4128
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4129
0
        if (HAVE_FCHMODAT_RUNTIME) {
4130
            /*
4131
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4132
             * The documentation specifically shows how to use it,
4133
             * and then says it isn't implemented yet.
4134
             * (true on linux with glibc 2.15, and openindiana 3.x)
4135
             *
4136
             * Once it is supported, os.chmod will automatically
4137
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4138
             * Until then, we need to be careful what exception we raise.
4139
             */
4140
0
            result = fchmodat(dir_fd, path->narrow, mode,
4141
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4142
            /*
4143
             * But wait!  We can't throw the exception without allowing threads,
4144
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4145
             */
4146
0
            fchmodat_nofollow_unsupported =
4147
0
                             result &&
4148
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4149
0
                             !follow_symlinks;
4150
0
        } else {
4151
0
            fchmodat_unsupported = 1;
4152
0
            fchmodat_nofollow_unsupported = 1;
4153
4154
0
            result = -1;
4155
0
        }
4156
0
    }
4157
0
    else
4158
0
#endif /* HAVE_FHCMODAT */
4159
0
    {
4160
0
#ifdef HAVE_CHMOD
4161
0
        result = chmod(path->narrow, mode);
4162
#elif defined(__wasi__)
4163
        // WASI SDK 15.0 does not support chmod.
4164
        // Ignore missing syscall for now.
4165
        result = 0;
4166
#else
4167
        result = -1;
4168
        errno = ENOSYS;
4169
#endif
4170
0
    }
4171
0
    Py_END_ALLOW_THREADS
4172
4173
0
    if (result) {
4174
0
#ifdef HAVE_FCHMODAT
4175
0
        if (fchmodat_unsupported) {
4176
0
            if (dir_fd != DEFAULT_DIR_FD) {
4177
0
                argument_unavailable_error("chmod", "dir_fd");
4178
0
                return NULL;
4179
0
            }
4180
0
        }
4181
4182
0
        if (fchmodat_nofollow_unsupported) {
4183
0
            if (dir_fd != DEFAULT_DIR_FD)
4184
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4185
0
                                                   dir_fd, follow_symlinks);
4186
0
            else
4187
0
                follow_symlinks_specified("chmod", follow_symlinks);
4188
0
            return NULL;
4189
0
        }
4190
0
        else
4191
0
#endif /* HAVE_FCHMODAT */
4192
0
        return path_error(path);
4193
0
    }
4194
0
#endif /* MS_WINDOWS */
4195
4196
0
    Py_RETURN_NONE;
4197
0
}
4198
4199
4200
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4201
/*[clinic input]
4202
os.fchmod
4203
4204
    fd: int
4205
        The file descriptor of the file to be modified.
4206
    mode: int
4207
        Operating-system mode bitfield.
4208
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4209
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4210
        Python.
4211
4212
Change the access permissions of the file given by file descriptor fd.
4213
4214
Equivalent to os.chmod(fd, mode).
4215
[clinic start generated code]*/
4216
4217
static PyObject *
4218
os_fchmod_impl(PyObject *module, int fd, int mode)
4219
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
4220
0
{
4221
0
    int res;
4222
4223
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4224
0
        return NULL;
4225
0
    }
4226
4227
#ifdef MS_WINDOWS
4228
    res = 0;
4229
    Py_BEGIN_ALLOW_THREADS
4230
    res = win32_fchmod(fd, mode);
4231
    Py_END_ALLOW_THREADS
4232
    if (!res) {
4233
        return PyErr_SetFromWindowsErr(0);
4234
    }
4235
#else /* MS_WINDOWS */
4236
0
    int async_err = 0;
4237
0
    do {
4238
0
        Py_BEGIN_ALLOW_THREADS
4239
0
        res = fchmod(fd, mode);
4240
0
        Py_END_ALLOW_THREADS
4241
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4242
0
    if (res != 0)
4243
0
        return (!async_err) ? posix_error() : NULL;
4244
0
#endif /* MS_WINDOWS */
4245
4246
0
    Py_RETURN_NONE;
4247
0
}
4248
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4249
4250
4251
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4252
/*[clinic input]
4253
os.lchmod
4254
4255
    path: path_t
4256
    mode: int
4257
4258
Change the access permissions of a file, without following symbolic links.
4259
4260
If path is a symlink, this affects the link itself rather than the target.
4261
Equivalent to chmod(path, mode, follow_symlinks=False)."
4262
[clinic start generated code]*/
4263
4264
static PyObject *
4265
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4266
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
4267
{
4268
    int res;
4269
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4270
        return NULL;
4271
    }
4272
#ifdef MS_WINDOWS
4273
    Py_BEGIN_ALLOW_THREADS
4274
    res = win32_lchmod(path->wide, mode);
4275
    Py_END_ALLOW_THREADS
4276
    if (!res) {
4277
        path_error(path);
4278
        return NULL;
4279
    }
4280
#else /* MS_WINDOWS */
4281
    Py_BEGIN_ALLOW_THREADS
4282
    res = lchmod(path->narrow, mode);
4283
    Py_END_ALLOW_THREADS
4284
    if (res < 0) {
4285
        path_error(path);
4286
        return NULL;
4287
    }
4288
#endif /* MS_WINDOWS */
4289
    Py_RETURN_NONE;
4290
}
4291
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4292
4293
4294
#ifdef HAVE_CHFLAGS
4295
/*[clinic input]
4296
os.chflags
4297
4298
    path: path_t
4299
    flags: unsigned_long(bitwise=True)
4300
    follow_symlinks: bool=True
4301
4302
Set file flags.
4303
4304
If follow_symlinks is False, and the last element of the path is a symbolic
4305
  link, chflags will change flags on the symbolic link itself instead of the
4306
  file the link points to.
4307
follow_symlinks may not be implemented on your platform.  If it is
4308
unavailable, using it will raise a NotImplementedError.
4309
4310
[clinic start generated code]*/
4311
4312
static PyObject *
4313
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4314
                int follow_symlinks)
4315
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
4316
{
4317
    int result;
4318
4319
#ifndef HAVE_LCHFLAGS
4320
    if (follow_symlinks_specified("chflags", follow_symlinks))
4321
        return NULL;
4322
#endif
4323
4324
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4325
        return NULL;
4326
    }
4327
4328
    Py_BEGIN_ALLOW_THREADS
4329
#ifdef HAVE_LCHFLAGS
4330
    if (!follow_symlinks)
4331
        result = lchflags(path->narrow, flags);
4332
    else
4333
#endif
4334
        result = chflags(path->narrow, flags);
4335
    Py_END_ALLOW_THREADS
4336
4337
    if (result)
4338
        return path_error(path);
4339
4340
    Py_RETURN_NONE;
4341
}
4342
#endif /* HAVE_CHFLAGS */
4343
4344
4345
#ifdef HAVE_LCHFLAGS
4346
/*[clinic input]
4347
os.lchflags
4348
4349
    path: path_t
4350
    flags: unsigned_long(bitwise=True)
4351
4352
Set file flags.
4353
4354
This function will not follow symbolic links.
4355
Equivalent to chflags(path, flags, follow_symlinks=False).
4356
[clinic start generated code]*/
4357
4358
static PyObject *
4359
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4360
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4361
{
4362
    int res;
4363
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4364
        return NULL;
4365
    }
4366
    Py_BEGIN_ALLOW_THREADS
4367
    res = lchflags(path->narrow, flags);
4368
    Py_END_ALLOW_THREADS
4369
    if (res < 0) {
4370
        return path_error(path);
4371
    }
4372
    Py_RETURN_NONE;
4373
}
4374
#endif /* HAVE_LCHFLAGS */
4375
4376
4377
#ifdef HAVE_CHROOT
4378
/*[clinic input]
4379
os.chroot
4380
    path: path_t
4381
4382
Change root directory to path.
4383
4384
[clinic start generated code]*/
4385
4386
static PyObject *
4387
os_chroot_impl(PyObject *module, path_t *path)
4388
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4389
0
{
4390
0
    int res;
4391
0
    Py_BEGIN_ALLOW_THREADS
4392
0
    res = chroot(path->narrow);
4393
0
    Py_END_ALLOW_THREADS
4394
0
    if (res < 0)
4395
0
        return path_error(path);
4396
0
    Py_RETURN_NONE;
4397
0
}
4398
#endif /* HAVE_CHROOT */
4399
4400
4401
#ifdef HAVE_FSYNC
4402
/*[clinic input]
4403
os.fsync
4404
4405
    fd: fildes
4406
4407
Force write of fd to disk.
4408
[clinic start generated code]*/
4409
4410
static PyObject *
4411
os_fsync_impl(PyObject *module, int fd)
4412
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4413
0
{
4414
0
    return posix_fildes_fd(fd, fsync);
4415
0
}
4416
#endif /* HAVE_FSYNC */
4417
4418
4419
#ifdef HAVE_SYNC
4420
/*[clinic input]
4421
os.sync
4422
4423
Force write of everything to disk.
4424
[clinic start generated code]*/
4425
4426
static PyObject *
4427
os_sync_impl(PyObject *module)
4428
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4429
0
{
4430
0
    Py_BEGIN_ALLOW_THREADS
4431
0
    sync();
4432
0
    Py_END_ALLOW_THREADS
4433
0
    Py_RETURN_NONE;
4434
0
}
4435
#endif /* HAVE_SYNC */
4436
4437
4438
#ifdef HAVE_FDATASYNC
4439
#ifdef __hpux
4440
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4441
#endif
4442
4443
/*[clinic input]
4444
os.fdatasync
4445
4446
    fd: fildes
4447
4448
Force write of fd to disk without forcing update of metadata.
4449
[clinic start generated code]*/
4450
4451
static PyObject *
4452
os_fdatasync_impl(PyObject *module, int fd)
4453
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4454
0
{
4455
0
    return posix_fildes_fd(fd, fdatasync);
4456
0
}
4457
#endif /* HAVE_FDATASYNC */
4458
4459
4460
#ifdef HAVE_CHOWN
4461
/*[clinic input]
4462
os.chown
4463
4464
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4465
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4466
4467
    uid: uid_t
4468
4469
    gid: gid_t
4470
4471
    *
4472
4473
    dir_fd : dir_fd(requires='fchownat') = None
4474
        If not None, it should be a file descriptor open to a directory,
4475
        and path should be relative; path will then be relative to that
4476
        directory.
4477
4478
    follow_symlinks: bool = True
4479
        If False, and the last element of the path is a symbolic link,
4480
        stat will examine the symbolic link itself instead of the file
4481
        the link points to.
4482
4483
Change the owner and group id of path to the numeric uid and gid.\
4484
4485
path may always be specified as a string.
4486
On some platforms, path may also be specified as an open file descriptor.
4487
  If this functionality is unavailable, using it raises an exception.
4488
If dir_fd is not None, it should be a file descriptor open to a directory,
4489
  and path should be relative; path will then be relative to that directory.
4490
If follow_symlinks is False, and the last element of the path is a symbolic
4491
  link, chown will modify the symbolic link itself instead of the file the
4492
  link points to.
4493
It is an error to use dir_fd or follow_symlinks when specifying path as
4494
  an open file descriptor.
4495
dir_fd and follow_symlinks may not be implemented on your platform.
4496
  If they are unavailable, using them will raise a NotImplementedError.
4497
4498
[clinic start generated code]*/
4499
4500
static PyObject *
4501
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4502
              int dir_fd, int follow_symlinks)
4503
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4504
0
{
4505
0
    int result;
4506
4507
0
#if defined(HAVE_FCHOWNAT)
4508
0
    int fchownat_unsupported = 0;
4509
0
#endif
4510
4511
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4512
    if (follow_symlinks_specified("chown", follow_symlinks))
4513
        return NULL;
4514
#endif
4515
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4516
0
        fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
4517
0
        return NULL;
4518
4519
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4520
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4521
0
        return NULL;
4522
0
    }
4523
4524
0
    Py_BEGIN_ALLOW_THREADS
4525
0
#ifdef HAVE_FCHOWN
4526
0
    if (path->is_fd)
4527
0
        result = fchown(path->fd, uid, gid);
4528
0
    else
4529
0
#endif
4530
0
#ifdef HAVE_LCHOWN
4531
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4532
0
        result = lchown(path->narrow, uid, gid);
4533
0
    else
4534
0
#endif
4535
0
#ifdef HAVE_FCHOWNAT
4536
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4537
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4538
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4539
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4540
0
      } else {
4541
0
         fchownat_unsupported = 1;
4542
0
      }
4543
0
    } else
4544
0
#endif
4545
0
        result = chown(path->narrow, uid, gid);
4546
0
    Py_END_ALLOW_THREADS
4547
4548
0
#ifdef HAVE_FCHOWNAT
4549
0
    if (fchownat_unsupported) {
4550
        /* This would be incorrect if the current platform
4551
         * doesn't support lchown.
4552
         */
4553
0
        argument_unavailable_error(NULL, "dir_fd");
4554
0
        return NULL;
4555
0
    }
4556
0
#endif
4557
4558
0
    if (result)
4559
0
        return path_error(path);
4560
4561
0
    Py_RETURN_NONE;
4562
0
}
4563
#endif /* HAVE_CHOWN */
4564
4565
4566
#ifdef HAVE_FCHOWN
4567
/*[clinic input]
4568
os.fchown
4569
4570
    fd: int
4571
    uid: uid_t
4572
    gid: gid_t
4573
4574
Change the owner and group id of the file specified by file descriptor.
4575
4576
Equivalent to os.chown(fd, uid, gid).
4577
4578
[clinic start generated code]*/
4579
4580
static PyObject *
4581
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4582
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4583
0
{
4584
0
    int res;
4585
0
    int async_err = 0;
4586
4587
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4588
0
        return NULL;
4589
0
    }
4590
4591
0
    do {
4592
0
        Py_BEGIN_ALLOW_THREADS
4593
0
        res = fchown(fd, uid, gid);
4594
0
        Py_END_ALLOW_THREADS
4595
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4596
0
    if (res != 0)
4597
0
        return (!async_err) ? posix_error() : NULL;
4598
4599
0
    Py_RETURN_NONE;
4600
0
}
4601
#endif /* HAVE_FCHOWN */
4602
4603
4604
#ifdef HAVE_LCHOWN
4605
/*[clinic input]
4606
os.lchown
4607
4608
    path : path_t
4609
    uid: uid_t
4610
    gid: gid_t
4611
4612
Change the owner and group id of path to the numeric uid and gid.
4613
4614
This function will not follow symbolic links.
4615
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4616
[clinic start generated code]*/
4617
4618
static PyObject *
4619
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4620
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4621
0
{
4622
0
    int res;
4623
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4624
0
        return NULL;
4625
0
    }
4626
0
    Py_BEGIN_ALLOW_THREADS
4627
0
    res = lchown(path->narrow, uid, gid);
4628
0
    Py_END_ALLOW_THREADS
4629
0
    if (res < 0) {
4630
0
        return path_error(path);
4631
0
    }
4632
0
    Py_RETURN_NONE;
4633
0
}
4634
#endif /* HAVE_LCHOWN */
4635
4636
4637
static PyObject *
4638
posix_getcwd(int use_bytes)
4639
5
{
4640
#ifdef MS_WINDOWS
4641
    wchar_t wbuf[MAXPATHLEN];
4642
    wchar_t *wbuf2 = wbuf;
4643
    DWORD len;
4644
4645
    Py_BEGIN_ALLOW_THREADS
4646
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4647
    /* If the buffer is large enough, len does not include the
4648
       terminating \0. If the buffer is too small, len includes
4649
       the space needed for the terminator. */
4650
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4651
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4652
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4653
        }
4654
        else {
4655
            wbuf2 = NULL;
4656
        }
4657
        if (wbuf2) {
4658
            len = GetCurrentDirectoryW(len, wbuf2);
4659
        }
4660
    }
4661
    Py_END_ALLOW_THREADS
4662
4663
    if (!wbuf2) {
4664
        PyErr_NoMemory();
4665
        return NULL;
4666
    }
4667
    if (!len) {
4668
        PyErr_SetFromWindowsErr(0);
4669
        if (wbuf2 != wbuf)
4670
            PyMem_RawFree(wbuf2);
4671
        return NULL;
4672
    }
4673
4674
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4675
    if (wbuf2 != wbuf) {
4676
        PyMem_RawFree(wbuf2);
4677
    }
4678
4679
    if (use_bytes) {
4680
        if (resobj == NULL) {
4681
            return NULL;
4682
        }
4683
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4684
    }
4685
4686
    return resobj;
4687
#else
4688
5
    const size_t chunk = 1024;
4689
4690
5
    char *buf = NULL;
4691
5
    char *cwd = NULL;
4692
5
    size_t buflen = 0;
4693
4694
5
    Py_BEGIN_ALLOW_THREADS
4695
5
    do {
4696
5
        char *newbuf;
4697
5
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4698
5
            buflen += chunk;
4699
5
            newbuf = PyMem_RawRealloc(buf, buflen);
4700
5
        }
4701
0
        else {
4702
0
            newbuf = NULL;
4703
0
        }
4704
5
        if (newbuf == NULL) {
4705
0
            PyMem_RawFree(buf);
4706
0
            buf = NULL;
4707
0
            break;
4708
0
        }
4709
5
        buf = newbuf;
4710
4711
5
        cwd = getcwd(buf, buflen);
4712
5
    } while (cwd == NULL && errno == ERANGE);
4713
5
    Py_END_ALLOW_THREADS
4714
4715
5
    if (buf == NULL) {
4716
0
        return PyErr_NoMemory();
4717
0
    }
4718
5
    if (cwd == NULL) {
4719
0
        posix_error();
4720
0
        PyMem_RawFree(buf);
4721
0
        return NULL;
4722
0
    }
4723
4724
5
    PyObject *obj;
4725
5
    if (use_bytes) {
4726
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4727
0
    }
4728
5
    else {
4729
5
        obj = PyUnicode_DecodeFSDefault(buf);
4730
5
    }
4731
5
#ifdef __linux__
4732
5
    if (buf[0] != '/') {
4733
        /*
4734
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4735
         * relative pathname starting with '(unreachable)'. We detect this
4736
         * and fail with ENOENT, matching newer glibc behaviour.
4737
         */
4738
0
        errno = ENOENT;
4739
0
        path_object_error(obj);
4740
0
        PyMem_RawFree(buf);
4741
0
        return NULL;
4742
0
    }
4743
5
#endif
4744
5
    assert(buf[0] == '/');
4745
5
    PyMem_RawFree(buf);
4746
4747
5
    return obj;
4748
5
#endif   /* !MS_WINDOWS */
4749
5
}
4750
4751
4752
/*[clinic input]
4753
os.getcwd
4754
4755
Return a unicode string representing the current working directory.
4756
[clinic start generated code]*/
4757
4758
static PyObject *
4759
os_getcwd_impl(PyObject *module)
4760
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4761
5
{
4762
5
    return posix_getcwd(0);
4763
5
}
4764
4765
4766
/*[clinic input]
4767
os.getcwdb
4768
4769
Return a bytes string representing the current working directory.
4770
[clinic start generated code]*/
4771
4772
static PyObject *
4773
os_getcwdb_impl(PyObject *module)
4774
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4775
0
{
4776
0
    return posix_getcwd(1);
4777
0
}
4778
4779
4780
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4781
#define HAVE_LINK 1
4782
#endif
4783
4784
#ifdef HAVE_LINK
4785
/*[clinic input]
4786
4787
@permit_long_docstring_body
4788
os.link
4789
4790
    src : path_t
4791
    dst : path_t
4792
    *
4793
    src_dir_fd : dir_fd = None
4794
    dst_dir_fd : dir_fd = None
4795
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4796
4797
Create a hard link to a file.
4798
4799
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4800
  descriptor open to a directory, and the respective path string (src or dst)
4801
  should be relative; the path will then be relative to that directory.
4802
If follow_symlinks is False, and the last element of src is a symbolic
4803
  link, link will create a link to the symbolic link itself instead of the
4804
  file the link points to.
4805
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4806
  platform.  If they are unavailable, using them will raise a
4807
  NotImplementedError.
4808
[clinic start generated code]*/
4809
4810
static PyObject *
4811
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4812
             int dst_dir_fd, int follow_symlinks)
4813
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4814
0
{
4815
#ifdef MS_WINDOWS
4816
    BOOL result = FALSE;
4817
#else
4818
0
    int result;
4819
0
#endif
4820
4821
0
#ifdef HAVE_LINKAT
4822
0
    if (HAVE_LINKAT_RUNTIME) {
4823
0
        if (follow_symlinks < 0) {
4824
0
            follow_symlinks = 1;
4825
0
        }
4826
0
    }
4827
0
    else
4828
0
#endif
4829
0
    {
4830
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4831
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4832
0
            return NULL;
4833
0
        }
4834
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4835
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4836
0
#if defined(MS_WINDOWS) || defined(__linux__)
4837
0
        if (follow_symlinks == 1) {
4838
0
            argument_unavailable_error("link", "follow_symlinks=True");
4839
0
            return NULL;
4840
0
        }
4841
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4842
        if (follow_symlinks == 0) {
4843
            argument_unavailable_error("link", "follow_symlinks=False");
4844
            return NULL;
4845
        }
4846
#else
4847
        if (follow_symlinks >= 0) {
4848
            argument_unavailable_error("link", "follow_symlinks");
4849
            return NULL;
4850
        }
4851
#endif
4852
0
    }
4853
4854
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4855
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4856
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4857
0
        return NULL;
4858
0
    }
4859
4860
#ifdef MS_WINDOWS
4861
    Py_BEGIN_ALLOW_THREADS
4862
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4863
    Py_END_ALLOW_THREADS
4864
4865
    if (!result)
4866
        return path_error2(src, dst);
4867
#else
4868
0
    Py_BEGIN_ALLOW_THREADS
4869
0
#ifdef HAVE_LINKAT
4870
0
    if (HAVE_LINKAT_RUNTIME) {
4871
0
        result = linkat(src_dir_fd, src->narrow,
4872
0
            dst_dir_fd, dst->narrow,
4873
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4874
0
    }
4875
0
    else
4876
0
#endif
4877
0
    {
4878
        /* linkat not available */
4879
0
        result = link(src->narrow, dst->narrow);
4880
0
    }
4881
0
    Py_END_ALLOW_THREADS
4882
4883
0
    if (result)
4884
0
        return path_error2(src, dst);
4885
0
#endif /* MS_WINDOWS */
4886
4887
0
    Py_RETURN_NONE;
4888
0
}
4889
#endif
4890
4891
4892
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4893
static PyObject *
4894
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4895
{
4896
    PyObject *v;
4897
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4898
    BOOL result, return_bytes;
4899
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4900
    /* only claim to have space for MAX_PATH */
4901
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4902
    wchar_t *wnamebuf = NULL;
4903
4904
    WIN32_FIND_DATAW wFileData;
4905
    const wchar_t *po_wchars;
4906
4907
    if (!path->wide) { /* Default arg: "." */
4908
        po_wchars = L".";
4909
        len = 1;
4910
        return_bytes = 0;
4911
    } else {
4912
        po_wchars = path->wide;
4913
        len = wcslen(path->wide);
4914
        return_bytes = PyBytes_Check(path->object);
4915
    }
4916
    /* The +5 is so we can append "\\*.*\0" */
4917
    wnamebuf = PyMem_New(wchar_t, len + 5);
4918
    if (!wnamebuf) {
4919
        PyErr_NoMemory();
4920
        goto exit;
4921
    }
4922
    wcscpy(wnamebuf, po_wchars);
4923
    if (len > 0) {
4924
        wchar_t wch = wnamebuf[len-1];
4925
        if (wch != SEP && wch != ALTSEP && wch != L':')
4926
            wnamebuf[len++] = SEP;
4927
        wcscpy(wnamebuf + len, L"*.*");
4928
    }
4929
    if ((list = PyList_New(0)) == NULL) {
4930
        goto exit;
4931
    }
4932
    Py_BEGIN_ALLOW_THREADS
4933
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4934
    Py_END_ALLOW_THREADS
4935
    if (hFindFile == INVALID_HANDLE_VALUE) {
4936
        int error = GetLastError();
4937
        if (error == ERROR_FILE_NOT_FOUND)
4938
            goto exit;
4939
        path_error(path);
4940
        Py_CLEAR(list);
4941
        goto exit;
4942
    }
4943
    do {
4944
        /* Skip over . and .. */
4945
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4946
            wcscmp(wFileData.cFileName, L"..") != 0) {
4947
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4948
                                       wcslen(wFileData.cFileName));
4949
            if (return_bytes && v) {
4950
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4951
            }
4952
            if (v == NULL) {
4953
                Py_CLEAR(list);
4954
                break;
4955
            }
4956
            if (PyList_Append(list, v) != 0) {
4957
                Py_DECREF(v);
4958
                Py_CLEAR(list);
4959
                break;
4960
            }
4961
            Py_DECREF(v);
4962
        }
4963
        Py_BEGIN_ALLOW_THREADS
4964
        result = FindNextFileW(hFindFile, &wFileData);
4965
        Py_END_ALLOW_THREADS
4966
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4967
           it got to the end of the directory. */
4968
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4969
            path_error(path);
4970
            Py_CLEAR(list);
4971
            goto exit;
4972
        }
4973
    } while (result == TRUE);
4974
4975
exit:
4976
    if (hFindFile != INVALID_HANDLE_VALUE) {
4977
        if (FindClose(hFindFile) == FALSE) {
4978
            if (list != NULL) {
4979
                path_error(path);
4980
                Py_CLEAR(list);
4981
            }
4982
        }
4983
    }
4984
    PyMem_Free(wnamebuf);
4985
4986
    return list;
4987
}  /* end of _listdir_windows_no_opendir */
4988
4989
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4990
4991
static PyObject *
4992
_posix_listdir(path_t *path, PyObject *list)
4993
380
{
4994
380
    PyObject *v;
4995
380
    DIR *dirp = NULL;
4996
380
    struct dirent *ep;
4997
380
    int return_str; /* if false, return bytes */
4998
380
#ifdef HAVE_FDOPENDIR
4999
380
    int fd = -1;
5000
380
#endif
5001
5002
380
    errno = 0;
5003
380
#ifdef HAVE_FDOPENDIR
5004
380
    if (path->is_fd) {
5005
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5006
        /* closedir() closes the FD, so we duplicate it */
5007
0
        fd = _Py_dup(path->fd);
5008
0
        if (fd == -1)
5009
0
            return NULL;
5010
5011
0
        return_str = 1;
5012
5013
0
        Py_BEGIN_ALLOW_THREADS
5014
0
        dirp = fdopendir(fd);
5015
0
        Py_END_ALLOW_THREADS
5016
0
      } else {
5017
0
        PyErr_SetString(PyExc_TypeError,
5018
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5019
0
        return NULL;
5020
0
      }
5021
0
    }
5022
380
    else
5023
380
#endif
5024
380
    {
5025
380
        const char *name;
5026
380
        if (path->narrow) {
5027
380
            name = path->narrow;
5028
            /* only return bytes if they specified a bytes object */
5029
380
            return_str = !PyBytes_Check(path->object);
5030
380
        }
5031
0
        else {
5032
0
            name = ".";
5033
0
            return_str = 1;
5034
0
        }
5035
5036
380
        Py_BEGIN_ALLOW_THREADS
5037
380
        dirp = opendir(name);
5038
380
        Py_END_ALLOW_THREADS
5039
380
    }
5040
5041
380
    if (dirp == NULL) {
5042
8
        path_error(path);
5043
8
        list = NULL;
5044
8
#ifdef HAVE_FDOPENDIR
5045
8
        if (fd != -1) {
5046
0
            Py_BEGIN_ALLOW_THREADS
5047
0
            close(fd);
5048
0
            Py_END_ALLOW_THREADS
5049
0
        }
5050
8
#endif
5051
8
        goto exit;
5052
8
    }
5053
372
    if ((list = PyList_New(0)) == NULL) {
5054
0
        goto exit;
5055
0
    }
5056
18.1k
    for (;;) {
5057
18.1k
        errno = 0;
5058
18.1k
        Py_BEGIN_ALLOW_THREADS
5059
18.1k
        ep = readdir(dirp);
5060
18.1k
        Py_END_ALLOW_THREADS
5061
18.1k
        if (ep == NULL) {
5062
372
            if (errno == 0) {
5063
372
                break;
5064
372
            } else {
5065
0
                path_error(path);
5066
0
                Py_CLEAR(list);
5067
0
                goto exit;
5068
0
            }
5069
372
        }
5070
17.7k
        if (ep->d_name[0] == '.' &&
5071
744
            (NAMLEN(ep) == 1 ||
5072
372
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5073
744
            continue;
5074
16.9k
        if (return_str)
5075
16.9k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5076
0
        else
5077
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5078
16.9k
        if (v == NULL) {
5079
0
            Py_CLEAR(list);
5080
0
            break;
5081
0
        }
5082
16.9k
        if (PyList_Append(list, v) != 0) {
5083
0
            Py_DECREF(v);
5084
0
            Py_CLEAR(list);
5085
0
            break;
5086
0
        }
5087
16.9k
        Py_DECREF(v);
5088
16.9k
    }
5089
5090
380
exit:
5091
380
    if (dirp != NULL) {
5092
372
        Py_BEGIN_ALLOW_THREADS
5093
372
#ifdef HAVE_FDOPENDIR
5094
372
        if (fd > -1)
5095
0
            rewinddir(dirp);
5096
372
#endif
5097
372
        closedir(dirp);
5098
372
        Py_END_ALLOW_THREADS
5099
372
    }
5100
5101
380
    return list;
5102
372
}  /* end of _posix_listdir */
5103
#endif  /* which OS */
5104
5105
5106
/*[clinic input]
5107
@permit_long_docstring_body
5108
os.listdir
5109
5110
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5111
5112
Return a list containing the names of the files in the directory.
5113
5114
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
5115
  the filenames returned will also be bytes; in all other circumstances
5116
  the filenames returned will be str.
5117
If path is None, uses the path='.'.
5118
On some platforms, path may also be specified as an open file descriptor;\
5119
  the file descriptor must refer to a directory.
5120
  If this functionality is unavailable, using it raises NotImplementedError.
5121
5122
The list is in arbitrary order.  It does not include the special
5123
entries '.' and '..' even if they are present in the directory.
5124
5125
5126
[clinic start generated code]*/
5127
5128
static PyObject *
5129
os_listdir_impl(PyObject *module, path_t *path)
5130
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
5131
380
{
5132
380
    if (PySys_Audit("os.listdir", "O",
5133
380
                    path->object ? path->object : Py_None) < 0) {
5134
0
        return NULL;
5135
0
    }
5136
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5137
    return _listdir_windows_no_opendir(path, NULL);
5138
#else
5139
380
    return _posix_listdir(path, NULL);
5140
380
#endif
5141
380
}
5142
5143
5144
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5145
5146
/*[clinic input]
5147
os.listdrives
5148
5149
Return a list containing the names of drives in the system.
5150
5151
A drive name typically looks like 'C:\\'.
5152
5153
[clinic start generated code]*/
5154
5155
static PyObject *
5156
os_listdrives_impl(PyObject *module)
5157
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5158
{
5159
    /* Number of possible drives is limited, so 256 should always be enough.
5160
       On the day when it is not, listmounts() will have to be used. */
5161
    wchar_t buffer[256];
5162
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5163
    PyObject *result = NULL;
5164
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5165
        return NULL;
5166
    }
5167
5168
    Py_BEGIN_ALLOW_THREADS;
5169
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5170
    Py_END_ALLOW_THREADS;
5171
5172
    if (!buflen) {
5173
        PyErr_SetFromWindowsErr(0);
5174
        return NULL;
5175
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5176
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5177
        return NULL;
5178
    }
5179
5180
    /* buflen includes a null terminator, so remove it */
5181
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5182
    if (str) {
5183
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5184
        if (nullchar) {
5185
            result = PyUnicode_Split(str, nullchar, -1);
5186
            Py_DECREF(nullchar);
5187
        }
5188
        Py_DECREF(str);
5189
    }
5190
    return result;
5191
}
5192
5193
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5194
5195
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5196
5197
/*[clinic input]
5198
os.listvolumes
5199
5200
Return a list containing the volumes in the system.
5201
5202
Volumes are typically represented as a GUID path.
5203
5204
[clinic start generated code]*/
5205
5206
static PyObject *
5207
os_listvolumes_impl(PyObject *module)
5208
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5209
{
5210
    PyObject *result = PyList_New(0);
5211
    HANDLE find = INVALID_HANDLE_VALUE;
5212
    wchar_t buffer[MAX_PATH + 1];
5213
    if (!result) {
5214
        return NULL;
5215
    }
5216
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5217
        Py_DECREF(result);
5218
        return NULL;
5219
    }
5220
5221
    int err = 0;
5222
    Py_BEGIN_ALLOW_THREADS;
5223
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5224
    if (find == INVALID_HANDLE_VALUE) {
5225
        err = GetLastError();
5226
    }
5227
    Py_END_ALLOW_THREADS;
5228
5229
    while (!err) {
5230
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5231
        if (!s || PyList_Append(result, s) < 0) {
5232
            Py_XDECREF(s);
5233
            Py_CLEAR(result);
5234
            break;
5235
        }
5236
        Py_DECREF(s);
5237
5238
        Py_BEGIN_ALLOW_THREADS;
5239
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5240
            err = GetLastError();
5241
        }
5242
        Py_END_ALLOW_THREADS;
5243
    }
5244
5245
    if (find != INVALID_HANDLE_VALUE) {
5246
        Py_BEGIN_ALLOW_THREADS;
5247
        FindVolumeClose(find);
5248
        Py_END_ALLOW_THREADS;
5249
    }
5250
    if (err && err != ERROR_NO_MORE_FILES) {
5251
        PyErr_SetFromWindowsErr(err);
5252
        Py_XDECREF(result);
5253
        result = NULL;
5254
    }
5255
    return result;
5256
}
5257
5258
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5259
5260
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5261
5262
/*[clinic input]
5263
os.listmounts
5264
5265
    volume: path_t
5266
5267
Return a list containing mount points for a particular volume.
5268
5269
'volume' should be a GUID path as returned from os.listvolumes.
5270
5271
[clinic start generated code]*/
5272
5273
static PyObject *
5274
os_listmounts_impl(PyObject *module, path_t *volume)
5275
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5276
{
5277
    wchar_t default_buffer[MAX_PATH + 1];
5278
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5279
    LPWSTR buffer = default_buffer;
5280
    DWORD attributes;
5281
    PyObject *str = NULL;
5282
    PyObject *nullchar = NULL;
5283
    PyObject *result = NULL;
5284
5285
    /* Ensure we have a valid volume path before continuing */
5286
    Py_BEGIN_ALLOW_THREADS
5287
    attributes = GetFileAttributesW(volume->wide);
5288
    Py_END_ALLOW_THREADS
5289
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5290
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5291
    {
5292
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5293
    }
5294
5295
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5296
        return NULL;
5297
    }
5298
5299
    while (1) {
5300
        BOOL success;
5301
        Py_BEGIN_ALLOW_THREADS
5302
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5303
                                                   buflen, &buflen);
5304
        Py_END_ALLOW_THREADS
5305
        if (success) {
5306
            break;
5307
        }
5308
        if (GetLastError() != ERROR_MORE_DATA) {
5309
            PyErr_SetFromWindowsErr(0);
5310
            goto exit;
5311
        }
5312
        if (buffer != default_buffer) {
5313
            PyMem_Free((void *)buffer);
5314
        }
5315
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5316
        if (!buffer) {
5317
            PyErr_NoMemory();
5318
            goto exit;
5319
        }
5320
    }
5321
    if (buflen < 2) {
5322
        result = PyList_New(0);
5323
        goto exit;
5324
    }
5325
    // buflen includes two null terminators, one for the last string
5326
    // and one for the array of strings.
5327
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5328
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5329
    if (str && nullchar) {
5330
        result = PyUnicode_Split(str, nullchar, -1);
5331
    }
5332
exit:
5333
    if (buffer != default_buffer) {
5334
        PyMem_Free(buffer);
5335
    }
5336
    Py_XDECREF(nullchar);
5337
    Py_XDECREF(str);
5338
    return result;
5339
}
5340
5341
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5342
5343
#ifdef MS_WINDOWS
5344
5345
/*[clinic input]
5346
os._path_isdevdrive
5347
5348
    path: path_t
5349
5350
Determines whether the specified path is on a Windows Dev Drive.
5351
5352
[clinic start generated code]*/
5353
5354
static PyObject *
5355
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5356
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5357
{
5358
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5359
    /* This flag will be documented at
5360
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5361
       after release, and will be available in the latest WinSDK.
5362
       We include the flag to avoid a specific version dependency
5363
       on the latest WinSDK. */
5364
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5365
#endif
5366
    int err = 0;
5367
    PyObject *r = NULL;
5368
    wchar_t volume[MAX_PATH];
5369
5370
    Py_BEGIN_ALLOW_THREADS
5371
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5372
        /* invalid path of some kind */
5373
        /* Note that this also includes the case where a volume is mounted
5374
           in a path longer than 260 characters. This is likely to be rare
5375
           and problematic for other reasons, so a (soft) failure in this
5376
           check seems okay. */
5377
        err = GetLastError();
5378
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5379
        /* only care about local dev drives */
5380
        r = Py_False;
5381
    } else {
5382
        HANDLE hVolume = CreateFileW(
5383
            volume,
5384
            FILE_READ_ATTRIBUTES,
5385
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5386
            NULL,
5387
            OPEN_EXISTING,
5388
            FILE_FLAG_BACKUP_SEMANTICS,
5389
            NULL
5390
        );
5391
        if (hVolume == INVALID_HANDLE_VALUE) {
5392
            err = GetLastError();
5393
        } else {
5394
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5395
            volumeState.Version = 1;
5396
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5397
            if (!DeviceIoControl(
5398
                hVolume,
5399
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5400
                &volumeState,
5401
                sizeof(volumeState),
5402
                &volumeState,
5403
                sizeof(volumeState),
5404
                NULL,
5405
                NULL
5406
            )) {
5407
                err = GetLastError();
5408
            }
5409
            CloseHandle(hVolume);
5410
            if (err == ERROR_INVALID_PARAMETER) {
5411
                /* not supported on this platform */
5412
                r = Py_False;
5413
            } else if (!err) {
5414
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5415
                    ? Py_True : Py_False;
5416
            }
5417
        }
5418
    }
5419
    Py_END_ALLOW_THREADS
5420
5421
    if (err) {
5422
        PyErr_SetFromWindowsErr(err);
5423
        return NULL;
5424
    }
5425
5426
    if (r) {
5427
        return Py_NewRef(r);
5428
    }
5429
5430
    return NULL;
5431
}
5432
5433
5434
int
5435
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5436
{
5437
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5438
    DWORD result;
5439
5440
    result = GetFullPathNameW(path,
5441
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5442
                              NULL);
5443
    if (!result) {
5444
        return -1;
5445
    }
5446
5447
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5448
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5449
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5450
        }
5451
        else {
5452
            woutbufp = NULL;
5453
        }
5454
        if (!woutbufp) {
5455
            *abspath_p = NULL;
5456
            return 0;
5457
        }
5458
5459
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5460
        if (!result) {
5461
            PyMem_RawFree(woutbufp);
5462
            return -1;
5463
        }
5464
    }
5465
5466
    if (woutbufp != woutbuf) {
5467
        *abspath_p = woutbufp;
5468
        return 0;
5469
    }
5470
5471
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5472
    return 0;
5473
}
5474
5475
5476
/* A helper function for abspath on win32 */
5477
/*[clinic input]
5478
os._getfullpathname
5479
5480
    path: path_t
5481
    /
5482
5483
[clinic start generated code]*/
5484
5485
static PyObject *
5486
os__getfullpathname_impl(PyObject *module, path_t *path)
5487
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5488
{
5489
    wchar_t *abspath;
5490
5491
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5492
        return win32_error_object("GetFullPathNameW", path->object);
5493
    }
5494
    if (abspath == NULL) {
5495
        return PyErr_NoMemory();
5496
    }
5497
5498
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5499
    PyMem_RawFree(abspath);
5500
    if (str == NULL) {
5501
        return NULL;
5502
    }
5503
    if (PyBytes_Check(path->object)) {
5504
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5505
    }
5506
    return str;
5507
}
5508
5509
5510
/*[clinic input]
5511
os._getfinalpathname
5512
5513
    path: path_t
5514
    /
5515
5516
A helper function for samepath on windows.
5517
[clinic start generated code]*/
5518
5519
static PyObject *
5520
os__getfinalpathname_impl(PyObject *module, path_t *path)
5521
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5522
{
5523
    HANDLE hFile;
5524
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5525
    int buf_size = Py_ARRAY_LENGTH(buf);
5526
    int result_length;
5527
    PyObject *result;
5528
5529
    Py_BEGIN_ALLOW_THREADS
5530
    hFile = CreateFileW(
5531
        path->wide,
5532
        0, /* desired access */
5533
        0, /* share mode */
5534
        NULL, /* security attributes */
5535
        OPEN_EXISTING,
5536
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5537
        FILE_FLAG_BACKUP_SEMANTICS,
5538
        NULL);
5539
    Py_END_ALLOW_THREADS
5540
5541
    if (hFile == INVALID_HANDLE_VALUE) {
5542
        return win32_error_object("CreateFileW", path->object);
5543
    }
5544
5545
    /* We have a good handle to the target, use it to determine the
5546
       target path name. */
5547
    while (1) {
5548
        Py_BEGIN_ALLOW_THREADS
5549
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5550
                                                  buf_size, VOLUME_NAME_DOS);
5551
        Py_END_ALLOW_THREADS
5552
5553
        if (!result_length) {
5554
            result = win32_error_object("GetFinalPathNameByHandleW",
5555
                                         path->object);
5556
            goto cleanup;
5557
        }
5558
5559
        if (result_length < buf_size) {
5560
            break;
5561
        }
5562
5563
        wchar_t *tmp;
5564
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5565
                            result_length * sizeof(*tmp));
5566
        if (!tmp) {
5567
            result = PyErr_NoMemory();
5568
            goto cleanup;
5569
        }
5570
5571
        buf_size = result_length;
5572
        target_path = tmp;
5573
    }
5574
5575
    result = PyUnicode_FromWideChar(target_path, result_length);
5576
    if (result && PyBytes_Check(path->object)) {
5577
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5578
    }
5579
5580
cleanup:
5581
    if (target_path != buf) {
5582
        PyMem_Free(target_path);
5583
    }
5584
    CloseHandle(hFile);
5585
    return result;
5586
}
5587
5588
/*[clinic input]
5589
os._findfirstfile
5590
    path: path_t
5591
    /
5592
A function to get the real file name without accessing the file in Windows.
5593
[clinic start generated code]*/
5594
5595
static PyObject *
5596
os__findfirstfile_impl(PyObject *module, path_t *path)
5597
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5598
{
5599
    PyObject *result;
5600
    HANDLE hFindFile;
5601
    WIN32_FIND_DATAW wFileData;
5602
    WCHAR *wRealFileName;
5603
5604
    Py_BEGIN_ALLOW_THREADS
5605
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5606
    Py_END_ALLOW_THREADS
5607
5608
    if (hFindFile == INVALID_HANDLE_VALUE) {
5609
        path_error(path);
5610
        return NULL;
5611
    }
5612
5613
    wRealFileName = wFileData.cFileName;
5614
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5615
    FindClose(hFindFile);
5616
    return result;
5617
}
5618
5619
5620
/*[clinic input]
5621
os._getvolumepathname
5622
5623
    path: path_t
5624
5625
A helper function for ismount on Win32.
5626
[clinic start generated code]*/
5627
5628
static PyObject *
5629
os__getvolumepathname_impl(PyObject *module, path_t *path)
5630
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5631
{
5632
    PyObject *result;
5633
    wchar_t *mountpath=NULL;
5634
    size_t buflen;
5635
    BOOL ret;
5636
5637
    /* Volume path should be shorter than entire path */
5638
    buflen = Py_MAX(path->length, MAX_PATH);
5639
5640
    if (buflen > PY_DWORD_MAX) {
5641
        PyErr_SetString(PyExc_OverflowError, "path too long");
5642
        return NULL;
5643
    }
5644
5645
    mountpath = PyMem_New(wchar_t, buflen);
5646
    if (mountpath == NULL)
5647
        return PyErr_NoMemory();
5648
5649
    Py_BEGIN_ALLOW_THREADS
5650
    ret = GetVolumePathNameW(path->wide, mountpath,
5651
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5652
    Py_END_ALLOW_THREADS
5653
5654
    if (!ret) {
5655
        result = win32_error_object("_getvolumepathname", path->object);
5656
        goto exit;
5657
    }
5658
    result = PyUnicode_FromWideChar(mountpath, -1);
5659
    if (PyBytes_Check(path->object))
5660
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5661
5662
exit:
5663
    PyMem_Free(mountpath);
5664
    return result;
5665
}
5666
5667
5668
/*[clinic input]
5669
os._path_splitroot
5670
5671
    path: path_t,
5672
    /
5673
5674
Removes everything after the root on Win32.
5675
[clinic start generated code]*/
5676
5677
static PyObject *
5678
os__path_splitroot_impl(PyObject *module, path_t *path)
5679
/*[clinic end generated code: output=ab7f1a88b654581c input=42831e41f8458f6d]*/
5680
{
5681
    wchar_t *buffer;
5682
    wchar_t *end;
5683
    PyObject *result = NULL;
5684
    HRESULT ret;
5685
5686
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5687
    if (!buffer) {
5688
        return NULL;
5689
    }
5690
    wcscpy(buffer, path->wide);
5691
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5692
        *p = L'\\';
5693
    }
5694
5695
    Py_BEGIN_ALLOW_THREADS
5696
    ret = PathCchSkipRoot(buffer, &end);
5697
    Py_END_ALLOW_THREADS
5698
    if (FAILED(ret)) {
5699
        result = Py_BuildValue("sO", "", path->object);
5700
    } else if (end != buffer) {
5701
        size_t rootLen = (size_t)(end - buffer);
5702
        result = Py_BuildValue("NN",
5703
            PyUnicode_FromWideChar(path->wide, rootLen),
5704
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5705
        );
5706
    } else {
5707
        result = Py_BuildValue("Os", path->object, "");
5708
    }
5709
    PyMem_Free(buffer);
5710
5711
    return result;
5712
}
5713
5714
5715
#define PY_IFREG  1 // Regular file
5716
#define PY_IFDIR  2 // Directory
5717
#define PY_IFLNK  4 // Symlink
5718
#define PY_IFMNT  8 // Mount Point (junction)
5719
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5720
#define PY_IFRRP 32 // Regular Reparse Point
5721
5722
static inline BOOL
5723
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5724
{
5725
    switch (testedType) {
5726
    case PY_IFREG:
5727
        return diskDevice && attributes &&
5728
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5729
    case PY_IFDIR:
5730
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5731
    case PY_IFLNK:
5732
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5733
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5734
    case PY_IFMNT:
5735
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5736
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5737
    case PY_IFLRP:
5738
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5739
               IsReparseTagNameSurrogate(reparseTag);
5740
    case PY_IFRRP:
5741
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5742
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5743
    }
5744
5745
    return FALSE;
5746
}
5747
5748
static BOOL
5749
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5750
{
5751
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5752
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5753
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5754
5755
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5756
    if (diskOnly && !diskDevice) {
5757
        return FALSE;
5758
    }
5759
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5760
        FILE_ATTRIBUTE_TAG_INFO info;
5761
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5762
                                            sizeof(info)) &&
5763
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5764
                         testedType);
5765
    }
5766
    FILE_BASIC_INFO info;
5767
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5768
                                        sizeof(info)) &&
5769
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5770
}
5771
5772
static BOOL
5773
_testFileTypeByName(LPCWSTR path, int testedType)
5774
{
5775
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5776
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5777
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5778
5779
    FILE_STAT_BASIC_INFORMATION info;
5780
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5781
                                     sizeof(info)))
5782
    {
5783
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5784
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5785
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5786
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5787
                                diskDevice, testedType);
5788
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5789
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5790
        {
5791
            return result;
5792
        }
5793
    }
5794
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5795
                GetLastError()))
5796
    {
5797
        return FALSE;
5798
    }
5799
5800
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5801
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5802
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5803
    }
5804
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5805
                               OPEN_EXISTING, flags, NULL);
5806
    if (hfile != INVALID_HANDLE_VALUE) {
5807
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5808
        CloseHandle(hfile);
5809
        return result;
5810
    }
5811
5812
    switch (GetLastError()) {
5813
    case ERROR_ACCESS_DENIED:
5814
    case ERROR_SHARING_VIOLATION:
5815
    case ERROR_CANT_ACCESS_FILE:
5816
    case ERROR_INVALID_PARAMETER:
5817
        int rc;
5818
        STRUCT_STAT st;
5819
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5820
            rc = STAT(path, &st);
5821
        }
5822
        else {
5823
            // PY_IFRRP is not generally supported in this case, except for
5824
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5825
            rc = LSTAT(path, &st);
5826
        }
5827
        if (!rc) {
5828
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5829
                             st.st_mode & S_IFREG, testedType);
5830
        }
5831
    }
5832
5833
    return FALSE;
5834
}
5835
5836
5837
static BOOL
5838
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5839
{
5840
    FILE_STAT_BASIC_INFORMATION info;
5841
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5842
                                     sizeof(info)))
5843
    {
5844
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5845
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5846
        {
5847
            return TRUE;
5848
        }
5849
    }
5850
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5851
                    GetLastError()))
5852
    {
5853
        return FALSE;
5854
    }
5855
5856
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5857
    if (!followLinks) {
5858
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5859
    }
5860
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5861
                               OPEN_EXISTING, flags, NULL);
5862
    if (hfile != INVALID_HANDLE_VALUE) {
5863
        if (followLinks) {
5864
            CloseHandle(hfile);
5865
            return TRUE;
5866
        }
5867
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5868
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5869
        CloseHandle(hfile);
5870
        if (!result) {
5871
            return TRUE;
5872
        }
5873
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5874
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5875
        if (hfile != INVALID_HANDLE_VALUE) {
5876
            CloseHandle(hfile);
5877
            return TRUE;
5878
        }
5879
    }
5880
5881
    switch (GetLastError()) {
5882
    case ERROR_ACCESS_DENIED:
5883
    case ERROR_SHARING_VIOLATION:
5884
    case ERROR_CANT_ACCESS_FILE:
5885
    case ERROR_INVALID_PARAMETER:
5886
        STRUCT_STAT _st;
5887
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5888
    }
5889
5890
    return FALSE;
5891
}
5892
5893
5894
static BOOL
5895
_testFileExists(path_t *path, BOOL followLinks)
5896
{
5897
    BOOL result = FALSE;
5898
    if (path->value_error) {
5899
        return FALSE;
5900
    }
5901
5902
    Py_BEGIN_ALLOW_THREADS
5903
    if (path->is_fd) {
5904
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5905
        if (hfile != INVALID_HANDLE_VALUE) {
5906
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5907
                result = TRUE;
5908
            }
5909
        }
5910
    }
5911
    else if (path->wide) {
5912
        result = _testFileExistsByName(path->wide, followLinks);
5913
    }
5914
    Py_END_ALLOW_THREADS
5915
5916
    return result;
5917
}
5918
5919
5920
static BOOL
5921
_testFileType(path_t *path, int testedType)
5922
{
5923
    BOOL result = FALSE;
5924
    if (path->value_error) {
5925
        return FALSE;
5926
    }
5927
5928
    Py_BEGIN_ALLOW_THREADS
5929
    if (path->is_fd) {
5930
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5931
        if (hfile != INVALID_HANDLE_VALUE) {
5932
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5933
        }
5934
    }
5935
    else if (path->wide) {
5936
        result = _testFileTypeByName(path->wide, testedType);
5937
    }
5938
    Py_END_ALLOW_THREADS
5939
5940
    return result;
5941
}
5942
5943
5944
/*[clinic input]
5945
os._path_exists -> bool
5946
5947
    path: path_t(allow_fd=True, suppress_value_error=True)
5948
5949
Test whether a path exists.  Returns False for broken symbolic links.
5950
5951
[clinic start generated code]*/
5952
5953
static int
5954
os__path_exists_impl(PyObject *module, path_t *path)
5955
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5956
{
5957
    return _testFileExists(path, TRUE);
5958
}
5959
5960
5961
/*[clinic input]
5962
os._path_lexists -> bool
5963
5964
    path: path_t(allow_fd=True, suppress_value_error=True)
5965
5966
Test whether a path exists.  Returns True for broken symbolic links.
5967
5968
[clinic start generated code]*/
5969
5970
static int
5971
os__path_lexists_impl(PyObject *module, path_t *path)
5972
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5973
{
5974
    return _testFileExists(path, FALSE);
5975
}
5976
5977
5978
/*[clinic input]
5979
os._path_isdir -> bool
5980
5981
    path: path_t(allow_fd=True, suppress_value_error=True),
5982
    /
5983
5984
Return true if the pathname refers to an existing directory.
5985
5986
[clinic start generated code]*/
5987
5988
static int
5989
os__path_isdir_impl(PyObject *module, path_t *path)
5990
/*[clinic end generated code: output=d5786196f9e2fa7a input=0d3fd790564d244b]*/
5991
{
5992
    return _testFileType(path, PY_IFDIR);
5993
}
5994
5995
5996
/*[clinic input]
5997
os._path_isfile -> bool
5998
5999
    path: path_t(allow_fd=True, suppress_value_error=True)
6000
6001
Test whether a path is a regular file
6002
6003
[clinic start generated code]*/
6004
6005
static int
6006
os__path_isfile_impl(PyObject *module, path_t *path)
6007
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6008
{
6009
    return _testFileType(path, PY_IFREG);
6010
}
6011
6012
6013
/*[clinic input]
6014
os._path_islink -> bool
6015
6016
    path: path_t(allow_fd=True, suppress_value_error=True)
6017
6018
Test whether a path is a symbolic link
6019
6020
[clinic start generated code]*/
6021
6022
static int
6023
os__path_islink_impl(PyObject *module, path_t *path)
6024
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6025
{
6026
    return _testFileType(path, PY_IFLNK);
6027
}
6028
6029
6030
/*[clinic input]
6031
os._path_isjunction -> bool
6032
6033
    path: path_t(allow_fd=True, suppress_value_error=True)
6034
6035
Test whether a path is a junction
6036
6037
[clinic start generated code]*/
6038
6039
static int
6040
os__path_isjunction_impl(PyObject *module, path_t *path)
6041
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6042
{
6043
    return _testFileType(path, PY_IFMNT);
6044
}
6045
6046
#undef PY_IFREG
6047
#undef PY_IFDIR
6048
#undef PY_IFLNK
6049
#undef PY_IFMNT
6050
#undef PY_IFLRP
6051
#undef PY_IFRRP
6052
6053
#endif /* MS_WINDOWS */
6054
6055
6056
/*[clinic input]
6057
os._path_splitroot_ex
6058
6059
    path: path_t(make_wide=True, nonstrict=True),
6060
    /
6061
6062
Split a pathname into drive, root and tail.
6063
6064
The tail contains anything after the root.
6065
[clinic start generated code]*/
6066
6067
static PyObject *
6068
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6069
/*[clinic end generated code: output=4b0072b6cdf4b611 input=4ac47b394d68bd21]*/
6070
194k
{
6071
194k
    Py_ssize_t drvsize, rootsize;
6072
194k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6073
6074
194k
    const wchar_t *buffer = path->wide;
6075
194k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6076
194k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6077
194k
    if (drv == NULL) {
6078
0
        goto exit;
6079
0
    }
6080
194k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6081
194k
    if (root == NULL) {
6082
0
        goto exit;
6083
0
    }
6084
194k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6085
194k
                                  path->length - drvsize - rootsize);
6086
194k
    if (tail == NULL) {
6087
0
        goto exit;
6088
0
    }
6089
194k
    if (PyBytes_Check(path->object)) {
6090
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6091
0
        if (drv == NULL) {
6092
0
            goto exit;
6093
0
        }
6094
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6095
0
        if (root == NULL) {
6096
0
            goto exit;
6097
0
        }
6098
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6099
0
        if (tail == NULL) {
6100
0
            goto exit;
6101
0
        }
6102
0
    }
6103
194k
    result = PyTuple_Pack(3, drv, root, tail);
6104
194k
exit:
6105
194k
    Py_XDECREF(drv);
6106
194k
    Py_XDECREF(root);
6107
194k
    Py_XDECREF(tail);
6108
194k
    return result;
6109
194k
}
6110
6111
6112
/*[clinic input]
6113
os._path_normpath
6114
6115
    path: path_t(make_wide=True, nonstrict=True)
6116
6117
Normalize path, eliminating double slashes, etc.
6118
[clinic start generated code]*/
6119
6120
static PyObject *
6121
os__path_normpath_impl(PyObject *module, path_t *path)
6122
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6123
34.5k
{
6124
34.5k
    PyObject *result;
6125
34.5k
    Py_ssize_t norm_len;
6126
34.5k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6127
34.5k
                                               path->length, &norm_len);
6128
34.5k
    if (!norm_len) {
6129
0
        result = PyUnicode_FromOrdinal('.');
6130
0
    }
6131
34.5k
    else {
6132
34.5k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6133
34.5k
    }
6134
34.5k
    if (PyBytes_Check(path->object)) {
6135
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6136
0
    }
6137
34.5k
    return result;
6138
34.5k
}
6139
6140
/*[clinic input]
6141
os.mkdir
6142
6143
    path : path_t
6144
6145
    mode: int = 0o777
6146
6147
    *
6148
6149
    dir_fd : dir_fd(requires='mkdirat') = None
6150
6151
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
6152
6153
Create a directory.
6154
6155
If dir_fd is not None, it should be a file descriptor open to a directory,
6156
  and path should be relative; path will then be relative to that directory.
6157
dir_fd may not be implemented on your platform.
6158
  If it is unavailable, using it will raise a NotImplementedError.
6159
6160
The mode argument is ignored on Windows. Where it is used, the current umask
6161
value is first masked out.
6162
[clinic start generated code]*/
6163
6164
static PyObject *
6165
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6166
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
6167
167k
{
6168
167k
    int result;
6169
#ifdef MS_WINDOWS
6170
    int error = 0;
6171
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6172
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6173
#endif
6174
167k
#ifdef HAVE_MKDIRAT
6175
167k
    int mkdirat_unavailable = 0;
6176
167k
#endif
6177
6178
167k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6179
167k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6180
0
        return NULL;
6181
0
    }
6182
6183
#ifdef MS_WINDOWS
6184
    Py_BEGIN_ALLOW_THREADS
6185
    // For API sets that don't support these APIs, we have no choice
6186
    // but to silently create a directory with default ACL.
6187
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6188
    if (mode == 0700 /* 0o700 */) {
6189
        ULONG sdSize;
6190
        pSecAttr = &secAttr;
6191
        // Set a discretionary ACL (D) that is protected (P) and includes
6192
        // inheritable (OICI) entries that allow (A) full control (FA) to
6193
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6194
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6195
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6196
            SDDL_REVISION_1,
6197
            &secAttr.lpSecurityDescriptor,
6198
            &sdSize
6199
        )) {
6200
            error = GetLastError();
6201
        }
6202
    }
6203
#endif
6204
    if (!error) {
6205
        result = CreateDirectoryW(path->wide, pSecAttr);
6206
        if (secAttr.lpSecurityDescriptor &&
6207
            // uncommonly, LocalFree returns non-zero on error, but still uses
6208
            // GetLastError() to see what the error code is
6209
            LocalFree(secAttr.lpSecurityDescriptor)) {
6210
            error = GetLastError();
6211
        }
6212
    }
6213
    Py_END_ALLOW_THREADS
6214
6215
    if (error) {
6216
        return PyErr_SetFromWindowsErr(error);
6217
    }
6218
    if (!result) {
6219
        return path_error(path);
6220
    }
6221
#else
6222
167k
    Py_BEGIN_ALLOW_THREADS
6223
167k
#if HAVE_MKDIRAT
6224
167k
    if (dir_fd != DEFAULT_DIR_FD) {
6225
0
      if (HAVE_MKDIRAT_RUNTIME) {
6226
0
        result = mkdirat(dir_fd, path->narrow, mode);
6227
6228
0
      } else {
6229
0
        mkdirat_unavailable = 1;
6230
0
      }
6231
0
    } else
6232
167k
#endif
6233
#if defined(__WATCOMC__) && !defined(__QNX__)
6234
        result = mkdir(path->narrow);
6235
#else
6236
167k
        result = mkdir(path->narrow, mode);
6237
167k
#endif
6238
167k
    Py_END_ALLOW_THREADS
6239
6240
167k
#if HAVE_MKDIRAT
6241
167k
    if (mkdirat_unavailable) {
6242
0
        argument_unavailable_error(NULL, "dir_fd");
6243
0
        return NULL;
6244
0
    }
6245
167k
#endif
6246
6247
167k
    if (result < 0)
6248
394
        return path_error(path);
6249
167k
#endif /* MS_WINDOWS */
6250
167k
    Py_RETURN_NONE;
6251
167k
}
6252
6253
6254
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6255
#if defined(HAVE_SYS_RESOURCE_H)
6256
#include <sys/resource.h>
6257
#endif
6258
6259
6260
#ifdef HAVE_NICE
6261
/*[clinic input]
6262
os.nice
6263
6264
    increment: int
6265
    /
6266
6267
Add increment to the priority of process and return the new priority.
6268
[clinic start generated code]*/
6269
6270
static PyObject *
6271
os_nice_impl(PyObject *module, int increment)
6272
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6273
0
{
6274
0
    int value;
6275
6276
    /* There are two flavours of 'nice': one that returns the new
6277
       priority (as required by almost all standards out there) and the
6278
       Linux/FreeBSD one, which returns '0' on success and advices
6279
       the use of getpriority() to get the new priority.
6280
6281
       If we are of the nice family that returns the new priority, we
6282
       need to clear errno before the call, and check if errno is filled
6283
       before calling posix_error() on a returnvalue of -1, because the
6284
       -1 may be the actual new priority! */
6285
6286
0
    errno = 0;
6287
0
    value = nice(increment);
6288
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6289
    if (value == 0)
6290
        value = getpriority(PRIO_PROCESS, 0);
6291
#endif
6292
0
    if (value == -1 && errno != 0)
6293
        /* either nice() or getpriority() returned an error */
6294
0
        return posix_error();
6295
0
    return PyLong_FromLong((long) value);
6296
0
}
6297
#endif /* HAVE_NICE */
6298
6299
6300
#ifdef HAVE_GETPRIORITY
6301
/*[clinic input]
6302
os.getpriority
6303
6304
    which: int
6305
    who: int
6306
6307
Return program scheduling priority.
6308
[clinic start generated code]*/
6309
6310
static PyObject *
6311
os_getpriority_impl(PyObject *module, int which, int who)
6312
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6313
0
{
6314
0
    int retval;
6315
6316
0
    errno = 0;
6317
0
    retval = getpriority(which, who);
6318
0
    if (errno != 0)
6319
0
        return posix_error();
6320
0
    return PyLong_FromLong((long)retval);
6321
0
}
6322
#endif /* HAVE_GETPRIORITY */
6323
6324
6325
#ifdef HAVE_SETPRIORITY
6326
/*[clinic input]
6327
os.setpriority
6328
6329
    which: int
6330
    who: int
6331
    priority: int
6332
6333
Set program scheduling priority.
6334
[clinic start generated code]*/
6335
6336
static PyObject *
6337
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6338
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6339
0
{
6340
0
    int retval;
6341
6342
0
    retval = setpriority(which, who, priority);
6343
0
    if (retval == -1)
6344
0
        return posix_error();
6345
0
    Py_RETURN_NONE;
6346
0
}
6347
#endif /* HAVE_SETPRIORITY */
6348
6349
6350
static PyObject *
6351
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6352
169
{
6353
169
    const char *function_name = is_replace ? "replace" : "rename";
6354
169
    int dir_fd_specified;
6355
6356
169
#ifdef HAVE_RENAMEAT
6357
169
    int renameat_unavailable = 0;
6358
169
#endif
6359
6360
#ifdef MS_WINDOWS
6361
    BOOL result;
6362
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6363
#else
6364
169
    int result;
6365
169
#endif
6366
6367
169
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6368
169
                       (dst_dir_fd != DEFAULT_DIR_FD);
6369
#ifndef HAVE_RENAMEAT
6370
    if (dir_fd_specified) {
6371
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6372
        return NULL;
6373
    }
6374
#endif
6375
6376
169
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6377
169
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6378
169
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6379
0
        return NULL;
6380
0
    }
6381
6382
#ifdef MS_WINDOWS
6383
    Py_BEGIN_ALLOW_THREADS
6384
    result = MoveFileExW(src->wide, dst->wide, flags);
6385
    Py_END_ALLOW_THREADS
6386
6387
    if (!result)
6388
        return path_error2(src, dst);
6389
6390
#else
6391
169
    Py_BEGIN_ALLOW_THREADS
6392
169
#ifdef HAVE_RENAMEAT
6393
169
    if (dir_fd_specified) {
6394
0
        if (HAVE_RENAMEAT_RUNTIME) {
6395
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6396
0
        } else {
6397
0
            renameat_unavailable = 1;
6398
0
        }
6399
0
    } else
6400
169
#endif
6401
169
    result = rename(src->narrow, dst->narrow);
6402
169
    Py_END_ALLOW_THREADS
6403
6404
6405
169
#ifdef HAVE_RENAMEAT
6406
169
    if (renameat_unavailable) {
6407
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6408
0
        return NULL;
6409
0
    }
6410
169
#endif
6411
6412
169
    if (result)
6413
0
        return path_error2(src, dst);
6414
169
#endif
6415
169
    Py_RETURN_NONE;
6416
169
}
6417
6418
6419
/*[clinic input]
6420
@permit_long_docstring_body
6421
os.rename
6422
6423
    src : path_t
6424
    dst : path_t
6425
    *
6426
    src_dir_fd : dir_fd = None
6427
    dst_dir_fd : dir_fd = None
6428
6429
Rename a file or directory.
6430
6431
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6432
  descriptor open to a directory, and the respective path string (src or dst)
6433
  should be relative; the path will then be relative to that directory.
6434
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6435
  If they are unavailable, using them will raise a NotImplementedError.
6436
[clinic start generated code]*/
6437
6438
static PyObject *
6439
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6440
               int dst_dir_fd)
6441
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6442
5
{
6443
5
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6444
5
}
6445
6446
6447
/*[clinic input]
6448
@permit_long_docstring_body
6449
os.replace = os.rename
6450
6451
Rename a file or directory, overwriting the destination.
6452
6453
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6454
  descriptor open to a directory, and the respective path string (src or dst)
6455
  should be relative; the path will then be relative to that directory.
6456
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6457
  If they are unavailable, using them will raise a NotImplementedError.
6458
[clinic start generated code]*/
6459
6460
static PyObject *
6461
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6462
                int dst_dir_fd)
6463
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6464
164
{
6465
164
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6466
164
}
6467
6468
6469
/*[clinic input]
6470
os.rmdir
6471
6472
    path: path_t
6473
    *
6474
    dir_fd: dir_fd(requires='unlinkat') = None
6475
6476
Remove a directory.
6477
6478
If dir_fd is not None, it should be a file descriptor open to a directory,
6479
  and path should be relative; path will then be relative to that directory.
6480
dir_fd may not be implemented on your platform.
6481
  If it is unavailable, using it will raise a NotImplementedError.
6482
[clinic start generated code]*/
6483
6484
static PyObject *
6485
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6486
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6487
167k
{
6488
167k
    int result;
6489
167k
#ifdef HAVE_UNLINKAT
6490
167k
    int unlinkat_unavailable = 0;
6491
167k
#endif
6492
6493
167k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6494
167k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6495
0
        return NULL;
6496
0
    }
6497
6498
167k
    Py_BEGIN_ALLOW_THREADS
6499
#ifdef MS_WINDOWS
6500
    /* Windows, success=1, UNIX, success=0 */
6501
    result = !RemoveDirectoryW(path->wide);
6502
#else
6503
167k
#ifdef HAVE_UNLINKAT
6504
167k
    if (dir_fd != DEFAULT_DIR_FD) {
6505
163k
      if (HAVE_UNLINKAT_RUNTIME) {
6506
163k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6507
163k
      } else {
6508
0
        unlinkat_unavailable = 1;
6509
0
        result = -1;
6510
0
      }
6511
163k
    } else
6512
3.87k
#endif
6513
3.87k
        result = rmdir(path->narrow);
6514
167k
#endif
6515
167k
    Py_END_ALLOW_THREADS
6516
6517
167k
#ifdef HAVE_UNLINKAT
6518
167k
    if (unlinkat_unavailable) {
6519
0
        argument_unavailable_error("rmdir", "dir_fd");
6520
0
        return NULL;
6521
0
    }
6522
167k
#endif
6523
6524
167k
    if (result)
6525
5
        return path_error(path);
6526
6527
167k
    Py_RETURN_NONE;
6528
167k
}
6529
6530
6531
#ifdef HAVE_SYSTEM
6532
#ifdef MS_WINDOWS
6533
/*[clinic input]
6534
os.system -> long
6535
6536
    command: Py_UNICODE
6537
6538
Execute the command in a subshell.
6539
[clinic start generated code]*/
6540
6541
static long
6542
os_system_impl(PyObject *module, const wchar_t *command)
6543
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6544
{
6545
    long result;
6546
6547
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6548
        return -1;
6549
    }
6550
6551
    Py_BEGIN_ALLOW_THREADS
6552
    _Py_BEGIN_SUPPRESS_IPH
6553
    result = _wsystem(command);
6554
    _Py_END_SUPPRESS_IPH
6555
    Py_END_ALLOW_THREADS
6556
    return result;
6557
}
6558
#else /* MS_WINDOWS */
6559
/*[clinic input]
6560
os.system -> long
6561
6562
    command: unicode_fs_encoded
6563
6564
Execute the command in a subshell.
6565
[clinic start generated code]*/
6566
6567
static long
6568
os_system_impl(PyObject *module, PyObject *command)
6569
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6570
0
{
6571
0
    long result;
6572
0
    const char *bytes = PyBytes_AsString(command);
6573
6574
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6575
0
        return -1;
6576
0
    }
6577
6578
0
    Py_BEGIN_ALLOW_THREADS
6579
0
    result = system(bytes);
6580
0
    Py_END_ALLOW_THREADS
6581
0
    return result;
6582
0
}
6583
#endif
6584
#endif /* HAVE_SYSTEM */
6585
6586
6587
#ifdef HAVE_UMASK
6588
/*[clinic input]
6589
os.umask
6590
6591
    mask: int
6592
    /
6593
6594
Set the current numeric umask and return the previous umask.
6595
[clinic start generated code]*/
6596
6597
static PyObject *
6598
os_umask_impl(PyObject *module, int mask)
6599
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6600
0
{
6601
0
    int i = (int)umask(mask);
6602
0
    if (i < 0)
6603
0
        return posix_error();
6604
0
    return PyLong_FromLong((long)i);
6605
0
}
6606
#endif
6607
6608
#ifdef MS_WINDOWS
6609
6610
/* override the default DeleteFileW behavior so that directory
6611
symlinks can be removed with this function, the same as with
6612
Unix symlinks */
6613
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6614
{
6615
    WIN32_FILE_ATTRIBUTE_DATA info;
6616
    WIN32_FIND_DATAW find_data;
6617
    HANDLE find_data_handle;
6618
    int is_directory = 0;
6619
    int is_link = 0;
6620
6621
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6622
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6623
6624
        /* Get WIN32_FIND_DATA structure for the path to determine if
6625
           it is a symlink */
6626
        if(is_directory &&
6627
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6628
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6629
6630
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6631
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6632
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6633
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6634
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6635
                FindClose(find_data_handle);
6636
            }
6637
        }
6638
    }
6639
6640
    if (is_directory && is_link)
6641
        return RemoveDirectoryW(lpFileName);
6642
6643
    return DeleteFileW(lpFileName);
6644
}
6645
#endif /* MS_WINDOWS */
6646
6647
6648
/*[clinic input]
6649
os.unlink
6650
6651
    path: path_t
6652
    *
6653
    dir_fd: dir_fd(requires='unlinkat')=None
6654
6655
Remove a file (same as remove()).
6656
6657
If dir_fd is not None, it should be a file descriptor open to a directory,
6658
  and path should be relative; path will then be relative to that directory.
6659
dir_fd may not be implemented on your platform.
6660
  If it is unavailable, using it will raise a NotImplementedError.
6661
6662
[clinic start generated code]*/
6663
6664
static PyObject *
6665
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6666
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6667
26.5k
{
6668
26.5k
    int result;
6669
26.5k
#ifdef HAVE_UNLINKAT
6670
26.5k
    int unlinkat_unavailable = 0;
6671
26.5k
#endif
6672
6673
26.5k
    if (PySys_Audit("os.remove", "Oi", path->object,
6674
26.5k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6675
0
        return NULL;
6676
0
    }
6677
6678
26.5k
    Py_BEGIN_ALLOW_THREADS
6679
26.5k
    _Py_BEGIN_SUPPRESS_IPH
6680
#ifdef MS_WINDOWS
6681
    /* Windows, success=1, UNIX, success=0 */
6682
    result = !Py_DeleteFileW(path->wide);
6683
#else
6684
26.5k
#ifdef HAVE_UNLINKAT
6685
26.5k
    if (dir_fd != DEFAULT_DIR_FD) {
6686
26.5k
      if (HAVE_UNLINKAT_RUNTIME) {
6687
6688
26.5k
        result = unlinkat(dir_fd, path->narrow, 0);
6689
26.5k
      } else {
6690
0
        unlinkat_unavailable = 1;
6691
0
      }
6692
26.5k
    } else
6693
1
#endif /* HAVE_UNLINKAT */
6694
1
        result = unlink(path->narrow);
6695
26.5k
#endif
6696
26.5k
    _Py_END_SUPPRESS_IPH
6697
26.5k
    Py_END_ALLOW_THREADS
6698
6699
26.5k
#ifdef HAVE_UNLINKAT
6700
26.5k
    if (unlinkat_unavailable) {
6701
0
        argument_unavailable_error(NULL, "dir_fd");
6702
0
        return NULL;
6703
0
    }
6704
26.5k
#endif
6705
6706
26.5k
    if (result)
6707
0
        return path_error(path);
6708
6709
26.5k
    Py_RETURN_NONE;
6710
26.5k
}
6711
6712
6713
/*[clinic input]
6714
os.remove = os.unlink
6715
6716
Remove a file (same as unlink()).
6717
6718
If dir_fd is not None, it should be a file descriptor open to a directory,
6719
  and path should be relative; path will then be relative to that directory.
6720
dir_fd may not be implemented on your platform.
6721
  If it is unavailable, using it will raise a NotImplementedError.
6722
[clinic start generated code]*/
6723
6724
static PyObject *
6725
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6726
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6727
0
{
6728
0
    return os_unlink_impl(module, path, dir_fd);
6729
0
}
6730
6731
6732
static PyStructSequence_Field uname_result_fields[] = {
6733
    {"sysname",    "operating system name"},
6734
    {"nodename",   "name of machine on network (implementation-defined)"},
6735
    {"release",    "operating system release"},
6736
    {"version",    "operating system version"},
6737
    {"machine",    "hardware identifier"},
6738
    {NULL}
6739
};
6740
6741
PyDoc_STRVAR(uname_result__doc__,
6742
"uname_result: Result from os.uname().\n\n\
6743
This object may be accessed either as a tuple of\n\
6744
  (sysname, nodename, release, version, machine),\n\
6745
or via the attributes sysname, nodename, release, version, and machine.\n\
6746
\n\
6747
See os.uname for more information.");
6748
6749
static PyStructSequence_Desc uname_result_desc = {
6750
    MODNAME ".uname_result", /* name */
6751
    uname_result__doc__, /* doc */
6752
    uname_result_fields,
6753
    5
6754
};
6755
6756
#ifdef HAVE_UNAME
6757
/*[clinic input]
6758
os.uname
6759
6760
Return an object identifying the current operating system.
6761
6762
The object behaves like a named tuple with the following fields:
6763
  (sysname, nodename, release, version, machine)
6764
6765
[clinic start generated code]*/
6766
6767
static PyObject *
6768
os_uname_impl(PyObject *module)
6769
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6770
4
{
6771
4
    struct utsname u;
6772
4
    int res;
6773
4
    PyObject *value;
6774
6775
4
    Py_BEGIN_ALLOW_THREADS
6776
4
    res = uname(&u);
6777
4
    Py_END_ALLOW_THREADS
6778
4
    if (res < 0)
6779
0
        return posix_error();
6780
6781
4
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6782
4
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6783
4
    if (value == NULL)
6784
0
        return NULL;
6785
6786
4
#define SET(i, field) \
6787
20
    { \
6788
20
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6789
20
    if (!o) { \
6790
0
        Py_DECREF(value); \
6791
0
        return NULL; \
6792
0
    } \
6793
20
    PyStructSequence_SET_ITEM(value, i, o); \
6794
20
    } \
6795
4
6796
8
    SET(0, u.sysname);
6797
8
    SET(1, u.nodename);
6798
4
    SET(2, u.release);
6799
4
    SET(3, u.version);
6800
4
    SET(4, u.machine);
6801
6802
4
#undef SET
6803
6804
4
    return value;
6805
4
}
6806
#endif /* HAVE_UNAME */
6807
6808
6809
6810
typedef struct {
6811
    int    now;
6812
    time_t atime_s;
6813
    long   atime_ns;
6814
    time_t mtime_s;
6815
    long   mtime_ns;
6816
} utime_t;
6817
6818
/*
6819
 * these macros assume that "ut" is a pointer to a utime_t
6820
 * they also intentionally leak the declaration of a pointer named "time"
6821
 */
6822
#define UTIME_TO_TIMESPEC \
6823
0
    struct timespec ts[2]; \
6824
0
    struct timespec *time; \
6825
0
    if (ut->now) \
6826
0
        time = NULL; \
6827
0
    else { \
6828
0
        ts[0].tv_sec = ut->atime_s; \
6829
0
        ts[0].tv_nsec = ut->atime_ns; \
6830
0
        ts[1].tv_sec = ut->mtime_s; \
6831
0
        ts[1].tv_nsec = ut->mtime_ns; \
6832
0
        time = ts; \
6833
0
    } \
6834
6835
#define UTIME_TO_TIMEVAL \
6836
0
    struct timeval tv[2]; \
6837
0
    struct timeval *time; \
6838
0
    if (ut->now) \
6839
0
        time = NULL; \
6840
0
    else { \
6841
0
        tv[0].tv_sec = ut->atime_s; \
6842
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6843
0
        tv[1].tv_sec = ut->mtime_s; \
6844
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6845
0
        time = tv; \
6846
0
    } \
6847
6848
#define UTIME_TO_UTIMBUF \
6849
    struct utimbuf u; \
6850
    struct utimbuf *time; \
6851
    if (ut->now) \
6852
        time = NULL; \
6853
    else { \
6854
        u.actime = ut->atime_s; \
6855
        u.modtime = ut->mtime_s; \
6856
        time = &u; \
6857
    }
6858
6859
#define UTIME_TO_TIME_T \
6860
    time_t timet[2]; \
6861
    time_t *time; \
6862
    if (ut->now) \
6863
        time = NULL; \
6864
    else { \
6865
        timet[0] = ut->atime_s; \
6866
        timet[1] = ut->mtime_s; \
6867
        time = timet; \
6868
    } \
6869
6870
6871
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6872
6873
static int
6874
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6875
0
{
6876
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6877
    if (HAVE_UTIMENSAT_RUNTIME) {
6878
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6879
        UTIME_TO_TIMESPEC;
6880
        return utimensat(dir_fd, path, time, flags);
6881
    }  else {
6882
        errno = ENOSYS;
6883
        return -1;
6884
    }
6885
#elif defined(HAVE_UTIMENSAT)
6886
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6887
0
    UTIME_TO_TIMESPEC;
6888
0
    return utimensat(dir_fd, path, time, flags);
6889
#elif defined(HAVE_FUTIMESAT)
6890
    UTIME_TO_TIMEVAL;
6891
    /*
6892
     * follow_symlinks will never be false here;
6893
     * we only allow !follow_symlinks and dir_fd together
6894
     * if we have utimensat()
6895
     */
6896
    assert(follow_symlinks);
6897
    return futimesat(dir_fd, path, time);
6898
#endif
6899
0
}
6900
6901
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6902
#else
6903
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6904
#endif
6905
6906
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6907
6908
static int
6909
utime_fd(utime_t *ut, int fd)
6910
0
{
6911
0
#ifdef HAVE_FUTIMENS
6912
6913
0
    if (HAVE_FUTIMENS_RUNTIME) {
6914
6915
0
    UTIME_TO_TIMESPEC;
6916
0
    return futimens(fd, time);
6917
6918
0
    } else
6919
#ifndef HAVE_FUTIMES
6920
    {
6921
        /* Not sure if this can happen */
6922
        PyErr_SetString(
6923
            PyExc_RuntimeError,
6924
            "neither futimens nor futimes are supported"
6925
            " on this system");
6926
        return -1;
6927
    }
6928
#endif
6929
6930
0
#endif
6931
0
#ifdef HAVE_FUTIMES
6932
0
    {
6933
0
    UTIME_TO_TIMEVAL;
6934
0
    return futimes(fd, time);
6935
0
    }
6936
0
#endif
6937
0
}
6938
6939
    #define PATH_UTIME_HAVE_FD 1
6940
#else
6941
    #define PATH_UTIME_HAVE_FD 0
6942
#endif
6943
6944
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6945
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6946
#endif
6947
6948
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6949
6950
static int
6951
utime_nofollow_symlinks(utime_t *ut, const char *path)
6952
0
{
6953
0
#ifdef HAVE_UTIMENSAT
6954
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6955
0
        UTIME_TO_TIMESPEC;
6956
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6957
0
    } else
6958
#ifndef HAVE_LUTIMES
6959
    {
6960
        /* Not sure if this can happen */
6961
        PyErr_SetString(
6962
            PyExc_RuntimeError,
6963
            "neither utimensat nor lutimes are supported"
6964
            " on this system");
6965
        return -1;
6966
    }
6967
#endif
6968
0
#endif
6969
6970
0
#ifdef HAVE_LUTIMES
6971
0
    {
6972
0
    UTIME_TO_TIMEVAL;
6973
0
    return lutimes(path, time);
6974
0
    }
6975
0
#endif
6976
0
}
6977
6978
#endif
6979
6980
#ifndef MS_WINDOWS
6981
6982
static int
6983
utime_default(utime_t *ut, const char *path)
6984
0
{
6985
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6986
    if (HAVE_UTIMENSAT_RUNTIME) {
6987
        UTIME_TO_TIMESPEC;
6988
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6989
    } else {
6990
        UTIME_TO_TIMEVAL;
6991
        return utimes(path, time);
6992
    }
6993
#elif defined(HAVE_UTIMENSAT)
6994
0
    UTIME_TO_TIMESPEC;
6995
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6996
#elif defined(HAVE_UTIMES)
6997
    UTIME_TO_TIMEVAL;
6998
    return utimes(path, time);
6999
#elif defined(HAVE_UTIME_H)
7000
    UTIME_TO_UTIMBUF;
7001
    return utime(path, time);
7002
#else
7003
    UTIME_TO_TIME_T;
7004
    return utime(path, time);
7005
#endif
7006
0
}
7007
7008
#endif
7009
7010
static int
7011
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7012
0
{
7013
0
    int result = 0;
7014
0
    PyObject *divmod;
7015
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7016
0
    if (!divmod)
7017
0
        goto exit;
7018
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7019
0
        PyErr_Format(PyExc_TypeError,
7020
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7021
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7022
0
        goto exit;
7023
0
    }
7024
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7025
0
    if ((*s == -1) && PyErr_Occurred())
7026
0
        goto exit;
7027
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7028
0
    if ((*ns == -1) && PyErr_Occurred())
7029
0
        goto exit;
7030
7031
0
    result = 1;
7032
0
exit:
7033
0
    Py_XDECREF(divmod);
7034
0
    return result;
7035
0
}
7036
7037
7038
/*[clinic input]
7039
os.utime
7040
7041
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7042
    times: object = None
7043
    *
7044
    ns: object = NULL
7045
    dir_fd: dir_fd(requires='futimensat') = None
7046
    follow_symlinks: bool=True
7047
7048
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
7049
7050
Set the access and modified time of path.
7051
7052
path may always be specified as a string.
7053
On some platforms, path may also be specified as an open file descriptor.
7054
  If this functionality is unavailable, using it raises an exception.
7055
7056
If times is not None, it must be a tuple (atime, mtime);
7057
    atime and mtime should be expressed as float seconds since the epoch.
7058
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7059
    atime_ns and mtime_ns should be expressed as integer nanoseconds
7060
    since the epoch.
7061
If times is None and ns is unspecified, utime uses the current time.
7062
Specifying tuples for both times and ns is an error.
7063
7064
If dir_fd is not None, it should be a file descriptor open to a directory,
7065
  and path should be relative; path will then be relative to that directory.
7066
If follow_symlinks is False, and the last element of the path is a symbolic
7067
  link, utime will modify the symbolic link itself instead of the file the
7068
  link points to.
7069
It is an error to use dir_fd or follow_symlinks when specifying path
7070
  as an open file descriptor.
7071
dir_fd and follow_symlinks may not be available on your platform.
7072
  If they are unavailable, using them will raise a NotImplementedError.
7073
7074
[clinic start generated code]*/
7075
7076
static PyObject *
7077
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7078
              int dir_fd, int follow_symlinks)
7079
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
7080
0
{
7081
#ifdef MS_WINDOWS
7082
    HANDLE hFile;
7083
    FILETIME atime, mtime;
7084
#else
7085
0
    int result;
7086
0
#endif
7087
7088
0
    utime_t utime;
7089
7090
0
    memset(&utime, 0, sizeof(utime_t));
7091
7092
0
    if (times != Py_None && ns) {
7093
0
        PyErr_SetString(PyExc_ValueError,
7094
0
                     "utime: you may specify either 'times'"
7095
0
                     " or 'ns' but not both");
7096
0
        return NULL;
7097
0
    }
7098
7099
0
    if (times != Py_None) {
7100
0
        time_t a_sec, m_sec;
7101
0
        long a_nsec, m_nsec;
7102
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7103
0
            PyErr_SetString(PyExc_TypeError,
7104
0
                         "utime: 'times' must be either"
7105
0
                         " a tuple of two numbers or None");
7106
0
            return NULL;
7107
0
        }
7108
0
        utime.now = 0;
7109
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7110
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7111
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7112
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7113
0
            return NULL;
7114
0
        }
7115
0
        utime.atime_s = a_sec;
7116
0
        utime.atime_ns = a_nsec;
7117
0
        utime.mtime_s = m_sec;
7118
0
        utime.mtime_ns = m_nsec;
7119
0
    }
7120
0
    else if (ns) {
7121
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7122
0
            PyErr_SetString(PyExc_TypeError,
7123
0
                         "utime: 'ns' must be a tuple of two ints");
7124
0
            return NULL;
7125
0
        }
7126
0
        utime.now = 0;
7127
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7128
0
                                      &utime.atime_s, &utime.atime_ns) ||
7129
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7130
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7131
0
            return NULL;
7132
0
        }
7133
0
    }
7134
0
    else {
7135
        /* times and ns are both None/unspecified. use "now". */
7136
0
        utime.now = 1;
7137
0
    }
7138
7139
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7140
    if (follow_symlinks_specified("utime", follow_symlinks))
7141
        return NULL;
7142
#endif
7143
7144
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7145
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7146
0
        fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
7147
0
        return NULL;
7148
7149
#if !defined(HAVE_UTIMENSAT)
7150
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7151
        PyErr_SetString(PyExc_ValueError,
7152
                     "utime: cannot use dir_fd and follow_symlinks "
7153
                     "together on this platform");
7154
        return NULL;
7155
    }
7156
#endif
7157
7158
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7159
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7160
0
        return NULL;
7161
0
    }
7162
7163
#ifdef MS_WINDOWS
7164
    Py_BEGIN_ALLOW_THREADS
7165
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7166
                        NULL, OPEN_EXISTING,
7167
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7168
    Py_END_ALLOW_THREADS
7169
    if (hFile == INVALID_HANDLE_VALUE) {
7170
        path_error(path);
7171
        return NULL;
7172
    }
7173
7174
    if (utime.now) {
7175
        GetSystemTimeAsFileTime(&mtime);
7176
        atime = mtime;
7177
    }
7178
    else {
7179
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7180
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7181
    }
7182
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7183
        path_error(path);
7184
        CloseHandle(hFile);
7185
        return NULL;
7186
    }
7187
    CloseHandle(hFile);
7188
#else /* MS_WINDOWS */
7189
0
    Py_BEGIN_ALLOW_THREADS
7190
7191
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7192
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7193
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7194
0
    else
7195
0
#endif
7196
7197
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7198
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7199
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7200
7201
0
    } else
7202
0
#endif
7203
7204
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7205
0
    if (path->is_fd)
7206
0
        result = utime_fd(&utime, path->fd);
7207
0
    else
7208
0
#endif
7209
7210
0
    result = utime_default(&utime, path->narrow);
7211
7212
0
    Py_END_ALLOW_THREADS
7213
7214
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7215
    /* See utime_dir_fd implementation */
7216
    if (result == -1 && errno == ENOSYS) {
7217
        argument_unavailable_error(NULL, "dir_fd");
7218
        return NULL;
7219
    }
7220
#endif
7221
7222
0
    if (result < 0) {
7223
0
        path_error(path);
7224
0
        return NULL;
7225
0
    }
7226
7227
0
#endif /* MS_WINDOWS */
7228
7229
0
    Py_RETURN_NONE;
7230
0
}
7231
7232
/* Process operations */
7233
7234
7235
/*[clinic input]
7236
os._exit
7237
7238
    status: int
7239
7240
Exit to the system with specified status, without normal exit processing.
7241
[clinic start generated code]*/
7242
7243
static PyObject *
7244
os__exit_impl(PyObject *module, int status)
7245
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
7246
0
{
7247
0
    _exit(status);
7248
0
    return NULL; /* Make gcc -Wall happy */
7249
0
}
7250
7251
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7252
#define EXECV_CHAR wchar_t
7253
#else
7254
0
#define EXECV_CHAR char
7255
#endif
7256
7257
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7258
static void
7259
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7260
0
{
7261
0
    Py_ssize_t i;
7262
0
    for (i = 0; i < count; i++)
7263
0
        PyMem_Free(array[i]);
7264
0
    PyMem_Free(array);
7265
0
}
7266
7267
static int
7268
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7269
0
{
7270
0
    Py_ssize_t size;
7271
0
    PyObject *ub;
7272
0
    int result = 0;
7273
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7274
    if (!PyUnicode_FSDecoder(o, &ub))
7275
        return 0;
7276
    *out = PyUnicode_AsWideCharString(ub, &size);
7277
    if (*out)
7278
        result = 1;
7279
#else
7280
0
    if (!PyUnicode_FSConverter(o, &ub))
7281
0
        return 0;
7282
0
    size = PyBytes_GET_SIZE(ub);
7283
0
    *out = PyMem_Malloc(size + 1);
7284
0
    if (*out) {
7285
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7286
0
        result = 1;
7287
0
    } else
7288
0
        PyErr_NoMemory();
7289
0
#endif
7290
0
    Py_DECREF(ub);
7291
0
    return result;
7292
0
}
7293
#endif
7294
7295
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7296
static EXECV_CHAR**
7297
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7298
0
{
7299
0
    Py_ssize_t i, pos, envc;
7300
0
    PyObject *keys = NULL, *vals = NULL;
7301
0
    PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
7302
0
    EXECV_CHAR **envlist;
7303
7304
0
    i = PyMapping_Size(env);
7305
0
    if (i < 0)
7306
0
        return NULL;
7307
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7308
0
    if (envlist == NULL) {
7309
0
        PyErr_NoMemory();
7310
0
        return NULL;
7311
0
    }
7312
0
    envc = 0;
7313
0
    keys = PyMapping_Keys(env);
7314
0
    if (!keys)
7315
0
        goto error;
7316
0
    vals = PyMapping_Values(env);
7317
0
    if (!vals)
7318
0
        goto error;
7319
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7320
0
        PyErr_Format(PyExc_TypeError,
7321
0
                     "env.keys() or env.values() is not a list");
7322
0
        goto error;
7323
0
    }
7324
7325
0
    for (pos = 0; pos < i; pos++) {
7326
        // The 'key' and 'val' must be strong references because of
7327
        // possible side-effects by PyUnicode_FS{Converter,Decoder}().
7328
0
        key = PyList_GetItemRef(keys, pos);
7329
0
        if (key == NULL) {
7330
0
            goto error;
7331
0
        }
7332
0
        val = PyList_GetItemRef(vals, pos);
7333
0
        if (val == NULL) {
7334
0
            goto error;
7335
0
        }
7336
7337
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7338
        if (!PyUnicode_FSDecoder(key, &key2)) {
7339
            goto error;
7340
        }
7341
        if (!PyUnicode_FSDecoder(val, &val2)) {
7342
            goto error;
7343
        }
7344
        /* Search from index 1 because on Windows starting '=' is allowed for
7345
           defining hidden environment variables. */
7346
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7347
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7348
        {
7349
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7350
            goto error;
7351
        }
7352
        PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7353
#else
7354
0
        if (!PyUnicode_FSConverter(key, &key2)) {
7355
0
            goto error;
7356
0
        }
7357
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7358
0
            goto error;
7359
0
        }
7360
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7361
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7362
0
        {
7363
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7364
0
            goto error;
7365
0
        }
7366
0
        PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7367
0
                                              PyBytes_AS_STRING(val2));
7368
0
#endif
7369
0
        if (!keyval) {
7370
0
            goto error;
7371
0
        }
7372
7373
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7374
0
            Py_DECREF(keyval);
7375
0
            goto error;
7376
0
        }
7377
7378
0
        Py_CLEAR(key);
7379
0
        Py_CLEAR(val);
7380
0
        Py_CLEAR(key2);
7381
0
        Py_CLEAR(val2);
7382
0
        Py_DECREF(keyval);
7383
0
    }
7384
0
    Py_DECREF(vals);
7385
0
    Py_DECREF(keys);
7386
7387
0
    envlist[envc] = 0;
7388
0
    *envc_ptr = envc;
7389
0
    return envlist;
7390
7391
0
error:
7392
0
    Py_XDECREF(key);
7393
0
    Py_XDECREF(val);
7394
0
    Py_XDECREF(key2);
7395
0
    Py_XDECREF(val2);
7396
0
    Py_XDECREF(keys);
7397
0
    Py_XDECREF(vals);
7398
0
    free_string_array(envlist, envc);
7399
0
    return NULL;
7400
0
}
7401
7402
static EXECV_CHAR**
7403
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7404
0
{
7405
0
    int i;
7406
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7407
0
    if (argvlist == NULL) {
7408
0
        PyErr_NoMemory();
7409
0
        return NULL;
7410
0
    }
7411
0
    for (i = 0; i < *argc; i++) {
7412
0
        PyObject* item = PySequence_ITEM(argv, i);
7413
0
        if (item == NULL)
7414
0
            goto fail;
7415
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7416
0
            Py_DECREF(item);
7417
0
            goto fail;
7418
0
        }
7419
0
        Py_DECREF(item);
7420
0
    }
7421
0
    argvlist[*argc] = NULL;
7422
0
    return argvlist;
7423
0
fail:
7424
0
    *argc = i;
7425
0
    free_string_array(argvlist, *argc);
7426
0
    return NULL;
7427
0
}
7428
7429
#endif
7430
7431
7432
#ifdef HAVE_EXECV
7433
/*[clinic input]
7434
os.execv
7435
7436
    path: path_t
7437
        Path of executable file.
7438
    argv: object
7439
        Tuple or list of strings.
7440
    /
7441
7442
Execute an executable path with arguments, replacing current process.
7443
[clinic start generated code]*/
7444
7445
static PyObject *
7446
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7447
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7448
0
{
7449
0
    EXECV_CHAR **argvlist;
7450
0
    Py_ssize_t argc;
7451
7452
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7453
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7454
0
        PyErr_SetString(PyExc_RuntimeError,
7455
0
                        "exec not supported for isolated subinterpreters");
7456
0
        return NULL;
7457
0
    }
7458
7459
    /* execv has two arguments: (path, argv), where
7460
       argv is a list or tuple of strings. */
7461
7462
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7463
0
        PyErr_SetString(PyExc_TypeError,
7464
0
                        "execv() arg 2 must be a tuple or list");
7465
0
        return NULL;
7466
0
    }
7467
0
    argc = PySequence_Size(argv);
7468
0
    if (argc < 1) {
7469
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7470
0
        return NULL;
7471
0
    }
7472
7473
0
    argvlist = parse_arglist(argv, &argc);
7474
0
    if (argvlist == NULL) {
7475
0
        return NULL;
7476
0
    }
7477
0
    if (!argvlist[0][0]) {
7478
0
        PyErr_SetString(PyExc_ValueError,
7479
0
            "execv() arg 2 first element cannot be empty");
7480
0
        free_string_array(argvlist, argc);
7481
0
        return NULL;
7482
0
    }
7483
7484
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7485
0
        free_string_array(argvlist, argc);
7486
0
        return NULL;
7487
0
    }
7488
7489
0
    _Py_BEGIN_SUPPRESS_IPH
7490
#ifdef HAVE_WEXECV
7491
    _wexecv(path->wide, argvlist);
7492
#else
7493
0
    execv(path->narrow, argvlist);
7494
0
#endif
7495
0
    _Py_END_SUPPRESS_IPH
7496
7497
    /* If we get here it's definitely an error */
7498
7499
0
    posix_error();
7500
0
    free_string_array(argvlist, argc);
7501
0
    return NULL;
7502
0
}
7503
7504
7505
/*[clinic input]
7506
os.execve
7507
7508
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7509
        Path of executable file.
7510
    argv: object
7511
        Tuple or list of strings.
7512
    env: object
7513
        Dictionary of strings mapping to strings.
7514
7515
Execute an executable path with arguments, replacing current process.
7516
[clinic start generated code]*/
7517
7518
static PyObject *
7519
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7520
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7521
0
{
7522
0
    EXECV_CHAR **argvlist = NULL;
7523
0
    EXECV_CHAR **envlist;
7524
0
    Py_ssize_t argc, envc;
7525
7526
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7527
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7528
0
        PyErr_SetString(PyExc_RuntimeError,
7529
0
                        "exec not supported for isolated subinterpreters");
7530
0
        return NULL;
7531
0
    }
7532
7533
    /* execve has three arguments: (path, argv, env), where
7534
       argv is a list or tuple of strings and env is a dictionary
7535
       like posix.environ. */
7536
7537
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7538
0
        PyErr_SetString(PyExc_TypeError,
7539
0
                        "execve: argv must be a tuple or list");
7540
0
        goto fail_0;
7541
0
    }
7542
0
    argc = PySequence_Size(argv);
7543
0
    if (argc < 1) {
7544
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7545
0
        return NULL;
7546
0
    }
7547
7548
0
    if (!PyMapping_Check(env)) {
7549
0
        PyErr_SetString(PyExc_TypeError,
7550
0
                        "execve: environment must be a mapping object");
7551
0
        goto fail_0;
7552
0
    }
7553
7554
0
    argvlist = parse_arglist(argv, &argc);
7555
0
    if (argvlist == NULL) {
7556
0
        goto fail_0;
7557
0
    }
7558
0
    if (!argvlist[0][0]) {
7559
0
        PyErr_SetString(PyExc_ValueError,
7560
0
            "execve: argv first element cannot be empty");
7561
0
        goto fail_0;
7562
0
    }
7563
7564
0
    envlist = parse_envlist(env, &envc);
7565
0
    if (envlist == NULL)
7566
0
        goto fail_0;
7567
7568
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7569
0
        goto fail_1;
7570
0
    }
7571
7572
0
    _Py_BEGIN_SUPPRESS_IPH
7573
0
#ifdef HAVE_FEXECVE
7574
0
    if (path->is_fd)
7575
0
        fexecve(path->fd, argvlist, envlist);
7576
0
    else
7577
0
#endif
7578
#ifdef HAVE_WEXECV
7579
        _wexecve(path->wide, argvlist, envlist);
7580
#else
7581
0
        execve(path->narrow, argvlist, envlist);
7582
0
#endif
7583
0
    _Py_END_SUPPRESS_IPH
7584
7585
    /* If we get here it's definitely an error */
7586
7587
0
    posix_path_error(path);
7588
0
  fail_1:
7589
0
    free_string_array(envlist, envc);
7590
0
  fail_0:
7591
0
    if (argvlist)
7592
0
        free_string_array(argvlist, argc);
7593
0
    return NULL;
7594
0
}
7595
7596
#endif /* HAVE_EXECV */
7597
7598
#ifdef HAVE_POSIX_SPAWN
7599
7600
enum posix_spawn_file_actions_identifier {
7601
    POSIX_SPAWN_OPEN,
7602
    POSIX_SPAWN_CLOSE,
7603
    POSIX_SPAWN_DUP2
7604
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7605
    ,POSIX_SPAWN_CLOSEFROM
7606
#endif
7607
};
7608
7609
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7610
static int
7611
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7612
#endif
7613
7614
static int
7615
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7616
                        int resetids, int setsid, PyObject *setsigmask,
7617
                        PyObject *setsigdef, PyObject *scheduler,
7618
                        posix_spawnattr_t *attrp)
7619
0
{
7620
0
    assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
7621
0
    long all_flags = 0;
7622
7623
0
    errno = posix_spawnattr_init(attrp);
7624
0
    if (errno) {
7625
0
        posix_error();
7626
0
        return -1;
7627
0
    }
7628
7629
0
    if (setpgroup && setpgroup != Py_None) {
7630
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7631
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7632
0
            goto fail;
7633
0
        }
7634
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7635
0
        if (errno) {
7636
0
            posix_error();
7637
0
            goto fail;
7638
0
        }
7639
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7640
0
    }
7641
7642
0
    if (resetids) {
7643
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7644
0
    }
7645
7646
0
    if (setsid) {
7647
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7648
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7649
#endif
7650
0
#ifdef POSIX_SPAWN_SETSID
7651
0
        all_flags |= POSIX_SPAWN_SETSID;
7652
#elif defined(POSIX_SPAWN_SETSID_NP)
7653
        all_flags |= POSIX_SPAWN_SETSID_NP;
7654
#else
7655
        argument_unavailable_error(func_name, "setsid");
7656
        return -1;
7657
#endif
7658
7659
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7660
        } else {
7661
            argument_unavailable_error(func_name, "setsid");
7662
            return -1;
7663
        }
7664
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7665
7666
0
    }
7667
7668
0
#ifdef HAVE_SIGSET_T
7669
0
   if (setsigmask) {
7670
0
        sigset_t set;
7671
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7672
0
            goto fail;
7673
0
        }
7674
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7675
0
        if (errno) {
7676
0
            posix_error();
7677
0
            goto fail;
7678
0
        }
7679
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7680
0
    }
7681
7682
0
    if (setsigdef) {
7683
0
        sigset_t set;
7684
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7685
0
            goto fail;
7686
0
        }
7687
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7688
0
        if (errno) {
7689
0
            posix_error();
7690
0
            goto fail;
7691
0
        }
7692
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7693
0
    }
7694
#else
7695
    if (setsigmask || setsigdef) {
7696
        PyErr_SetString(PyExc_NotImplementedError,
7697
                        "sigset is not supported on this platform");
7698
        goto fail;
7699
    }
7700
#endif
7701
7702
0
    if (scheduler && scheduler != Py_None) {
7703
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7704
0
        PyObject *py_schedpolicy;
7705
0
        PyObject *schedparam_obj;
7706
0
        struct sched_param schedparam;
7707
7708
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7709
0
                        ";A scheduler tuple must have two elements",
7710
0
                        &py_schedpolicy, &schedparam_obj)) {
7711
0
            goto fail;
7712
0
        }
7713
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7714
0
            goto fail;
7715
0
        }
7716
0
        if (py_schedpolicy != Py_None) {
7717
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7718
7719
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7720
0
                goto fail;
7721
0
            }
7722
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7723
0
            if (errno) {
7724
0
                posix_error();
7725
0
                goto fail;
7726
0
            }
7727
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7728
0
        }
7729
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7730
0
        if (errno) {
7731
0
            posix_error();
7732
0
            goto fail;
7733
0
        }
7734
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7735
#else
7736
        PyErr_SetString(PyExc_NotImplementedError,
7737
                "The scheduler option is not supported in this system.");
7738
        goto fail;
7739
#endif
7740
0
    }
7741
7742
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7743
0
    if (errno) {
7744
0
        posix_error();
7745
0
        goto fail;
7746
0
    }
7747
7748
0
    return 0;
7749
7750
0
fail:
7751
0
    (void)posix_spawnattr_destroy(attrp);
7752
0
    return -1;
7753
0
}
7754
7755
static int
7756
parse_file_actions(PyObject *file_actions,
7757
                   posix_spawn_file_actions_t *file_actionsp,
7758
                   PyObject *temp_buffer)
7759
0
{
7760
0
    PyObject *seq;
7761
0
    PyObject *file_action = NULL;
7762
0
    PyObject *tag_obj;
7763
7764
0
    seq = PySequence_Fast(file_actions,
7765
0
                          "file_actions must be a sequence or None");
7766
0
    if (seq == NULL) {
7767
0
        return -1;
7768
0
    }
7769
7770
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7771
0
    if (errno) {
7772
0
        posix_error();
7773
0
        Py_DECREF(seq);
7774
0
        return -1;
7775
0
    }
7776
7777
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7778
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7779
0
        Py_INCREF(file_action);
7780
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7781
0
            PyErr_SetString(PyExc_TypeError,
7782
0
                "Each file_actions element must be a non-empty tuple");
7783
0
            goto fail;
7784
0
        }
7785
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7786
0
        if (tag == -1 && PyErr_Occurred()) {
7787
0
            goto fail;
7788
0
        }
7789
7790
        /* Populate the file_actions object */
7791
0
        switch (tag) {
7792
0
            case POSIX_SPAWN_OPEN: {
7793
0
                int fd, oflag;
7794
0
                PyObject *path;
7795
0
                unsigned long mode;
7796
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7797
0
                        ";A open file_action tuple must have 5 elements",
7798
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7799
0
                        &oflag, &mode))
7800
0
                {
7801
0
                    goto fail;
7802
0
                }
7803
0
                if (PyList_Append(temp_buffer, path)) {
7804
0
                    Py_DECREF(path);
7805
0
                    goto fail;
7806
0
                }
7807
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7808
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7809
0
                if (errno) {
7810
0
                    posix_error();
7811
0
                    Py_DECREF(path);
7812
0
                    goto fail;
7813
0
                }
7814
0
                Py_DECREF(path);
7815
0
                break;
7816
0
            }
7817
0
            case POSIX_SPAWN_CLOSE: {
7818
0
                int fd;
7819
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7820
0
                        ";A close file_action tuple must have 2 elements",
7821
0
                        &tag_obj, &fd))
7822
0
                {
7823
0
                    goto fail;
7824
0
                }
7825
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7826
0
                if (errno) {
7827
0
                    posix_error();
7828
0
                    goto fail;
7829
0
                }
7830
0
                break;
7831
0
            }
7832
0
            case POSIX_SPAWN_DUP2: {
7833
0
                int fd1, fd2;
7834
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7835
0
                        ";A dup2 file_action tuple must have 3 elements",
7836
0
                        &tag_obj, &fd1, &fd2))
7837
0
                {
7838
0
                    goto fail;
7839
0
                }
7840
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7841
0
                                                         fd1, fd2);
7842
0
                if (errno) {
7843
0
                    posix_error();
7844
0
                    goto fail;
7845
0
                }
7846
0
                break;
7847
0
            }
7848
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7849
            case POSIX_SPAWN_CLOSEFROM: {
7850
                int fd;
7851
                if (!PyArg_ParseTuple(file_action, "Oi"
7852
                        ";A closefrom file_action tuple must have 2 elements",
7853
                        &tag_obj, &fd))
7854
                {
7855
                    goto fail;
7856
                }
7857
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7858
                                                                 fd);
7859
                if (errno) {
7860
                    posix_error();
7861
                    goto fail;
7862
                }
7863
                break;
7864
            }
7865
#endif
7866
0
            default: {
7867
0
                PyErr_SetString(PyExc_TypeError,
7868
0
                                "Unknown file_actions identifier");
7869
0
                goto fail;
7870
0
            }
7871
0
        }
7872
0
        Py_DECREF(file_action);
7873
0
    }
7874
7875
0
    Py_DECREF(seq);
7876
0
    return 0;
7877
7878
0
fail:
7879
0
    Py_DECREF(seq);
7880
0
    Py_DECREF(file_action);
7881
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7882
0
    return -1;
7883
0
}
7884
7885
7886
static PyObject *
7887
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7888
               PyObject *env, PyObject *file_actions,
7889
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7890
               PyObject *setsigdef, PyObject *scheduler)
7891
0
{
7892
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7893
0
    EXECV_CHAR **argvlist = NULL;
7894
0
    EXECV_CHAR **envlist = NULL;
7895
0
    posix_spawn_file_actions_t file_actions_buf;
7896
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7897
0
    posix_spawnattr_t attr;
7898
0
    posix_spawnattr_t *attrp = NULL;
7899
0
    Py_ssize_t argc, envc;
7900
0
    PyObject *result = NULL;
7901
0
    PyObject *temp_buffer = NULL;
7902
0
    pid_t pid;
7903
0
    int err_code;
7904
7905
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7906
       argv is a list or tuple of strings and env is a dictionary
7907
       like posix.environ. */
7908
7909
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7910
0
        PyErr_Format(PyExc_TypeError,
7911
0
                     "%s: argv must be a tuple or list", func_name);
7912
0
        goto exit;
7913
0
    }
7914
0
    argc = PySequence_Size(argv);
7915
0
    if (argc < 1) {
7916
0
        PyErr_Format(PyExc_ValueError,
7917
0
                     "%s: argv must not be empty", func_name);
7918
0
        goto exit;
7919
0
    }
7920
7921
0
    if (!PyMapping_Check(env) && env != Py_None) {
7922
0
        PyErr_Format(PyExc_TypeError,
7923
0
                     "%s: environment must be a mapping object or None", func_name);
7924
0
        goto exit;
7925
0
    }
7926
7927
0
    if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7928
0
        PyErr_Format(PyExc_TypeError,
7929
0
                     "%s: scheduler must be a tuple or None", func_name);
7930
0
        goto exit;
7931
0
    }
7932
7933
0
    argvlist = parse_arglist(argv, &argc);
7934
0
    if (argvlist == NULL) {
7935
0
        goto exit;
7936
0
    }
7937
0
    if (!argvlist[0][0]) {
7938
0
        PyErr_Format(PyExc_ValueError,
7939
0
                     "%s: argv first element cannot be empty", func_name);
7940
0
        goto exit;
7941
0
    }
7942
7943
#ifdef USE_DARWIN_NS_GET_ENVIRON
7944
    // There is no environ global in this situation.
7945
    char **environ = NULL;
7946
#endif
7947
7948
0
    if (env == Py_None) {
7949
#ifdef USE_DARWIN_NS_GET_ENVIRON
7950
        environ = *_NSGetEnviron();
7951
#endif
7952
0
        envlist = environ;
7953
0
    } else {
7954
0
        envlist = parse_envlist(env, &envc);
7955
0
        if (envlist == NULL) {
7956
0
            goto exit;
7957
0
        }
7958
0
    }
7959
7960
0
    if (file_actions != NULL && file_actions != Py_None) {
7961
        /* There is a bug in old versions of glibc that makes some of the
7962
         * helper functions for manipulating file actions not copy the provided
7963
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7964
         * copy the value of path for some old versions of glibc (<2.20).
7965
         * The use of temp_buffer here is a workaround that keeps the
7966
         * python objects that own the buffers alive until posix_spawn gets called.
7967
         * Check https://bugs.python.org/issue33630 and
7968
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7969
0
        temp_buffer = PyList_New(0);
7970
0
        if (!temp_buffer) {
7971
0
            goto exit;
7972
0
        }
7973
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7974
0
            goto exit;
7975
0
        }
7976
0
        file_actionsp = &file_actions_buf;
7977
0
    }
7978
7979
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7980
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7981
0
        goto exit;
7982
0
    }
7983
0
    attrp = &attr;
7984
7985
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7986
0
        goto exit;
7987
0
    }
7988
7989
0
    _Py_BEGIN_SUPPRESS_IPH
7990
0
#ifdef HAVE_POSIX_SPAWNP
7991
0
    if (use_posix_spawnp) {
7992
0
        err_code = posix_spawnp(&pid, path->narrow,
7993
0
                                file_actionsp, attrp, argvlist, envlist);
7994
0
    }
7995
0
    else
7996
0
#endif /* HAVE_POSIX_SPAWNP */
7997
0
    {
7998
0
        err_code = posix_spawn(&pid, path->narrow,
7999
0
                               file_actionsp, attrp, argvlist, envlist);
8000
0
    }
8001
0
    _Py_END_SUPPRESS_IPH
8002
8003
0
    if (err_code) {
8004
0
        errno = err_code;
8005
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8006
0
        goto exit;
8007
0
    }
8008
#ifdef _Py_MEMORY_SANITIZER
8009
    __msan_unpoison(&pid, sizeof(pid));
8010
#endif
8011
0
    result = PyLong_FromPid(pid);
8012
8013
0
exit:
8014
0
    if (file_actionsp) {
8015
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
8016
0
    }
8017
0
    if (attrp) {
8018
0
        (void)posix_spawnattr_destroy(attrp);
8019
0
    }
8020
0
    if (envlist && envlist != environ) {
8021
0
        free_string_array(envlist, envc);
8022
0
    }
8023
0
    if (argvlist) {
8024
0
        free_string_array(argvlist, argc);
8025
0
    }
8026
0
    Py_XDECREF(temp_buffer);
8027
0
    return result;
8028
0
}
8029
8030
8031
/*[clinic input]
8032
8033
os.posix_spawn
8034
    path: path_t
8035
        Path of executable file.
8036
    argv: object
8037
        Tuple or list of strings.
8038
    env: object
8039
        Dictionary of strings mapping to strings.
8040
    /
8041
    *
8042
    file_actions: object(c_default='NULL') = ()
8043
        A sequence of file action tuples.
8044
    setpgroup: object(c_default='NULL') = None
8045
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8046
    resetids: bool = False
8047
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8048
    setsid: bool = False
8049
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8050
    setsigmask: object(c_default='NULL') = ()
8051
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8052
    setsigdef: object(c_default='NULL') = ()
8053
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8054
    scheduler: object(c_default='NULL') = None
8055
        A tuple with the scheduler policy (optional) and parameters.
8056
8057
Execute the program specified by path in a new process.
8058
[clinic start generated code]*/
8059
8060
static PyObject *
8061
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8062
                    PyObject *env, PyObject *file_actions,
8063
                    PyObject *setpgroup, int resetids, int setsid,
8064
                    PyObject *setsigmask, PyObject *setsigdef,
8065
                    PyObject *scheduler)
8066
/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/
8067
0
{
8068
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8069
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8070
0
                          scheduler);
8071
0
}
8072
 #endif /* HAVE_POSIX_SPAWN */
8073
8074
8075
8076
#ifdef HAVE_POSIX_SPAWNP
8077
/*[clinic input]
8078
8079
os.posix_spawnp
8080
    path: path_t
8081
        Path of executable file.
8082
    argv: object
8083
        Tuple or list of strings.
8084
    env: object
8085
        Dictionary of strings mapping to strings.
8086
    /
8087
    *
8088
    file_actions: object(c_default='NULL') = ()
8089
        A sequence of file action tuples.
8090
    setpgroup: object(c_default='NULL') = None
8091
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8092
    resetids: bool = False
8093
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8094
    setsid: bool = False
8095
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8096
    setsigmask: object(c_default='NULL') = ()
8097
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8098
    setsigdef: object(c_default='NULL') = ()
8099
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8100
    scheduler: object(c_default='NULL') = None
8101
        A tuple with the scheduler policy (optional) and parameters.
8102
8103
Execute the program specified by path in a new process.
8104
[clinic start generated code]*/
8105
8106
static PyObject *
8107
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8108
                     PyObject *env, PyObject *file_actions,
8109
                     PyObject *setpgroup, int resetids, int setsid,
8110
                     PyObject *setsigmask, PyObject *setsigdef,
8111
                     PyObject *scheduler)
8112
/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/
8113
0
{
8114
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8115
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8116
0
                          scheduler);
8117
0
}
8118
#endif /* HAVE_POSIX_SPAWNP */
8119
8120
#ifdef HAVE_RTPSPAWN
8121
static intptr_t
8122
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8123
               const char  *envp[])
8124
{
8125
     RTP_ID rtpid;
8126
     int status;
8127
     pid_t res;
8128
     int async_err = 0;
8129
8130
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8131
        uStackSize=0 cannot be used, the default stack size is too small for
8132
        Python. */
8133
     if (envp) {
8134
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8135
                          100, 0x1000000, 0, VX_FP_TASK);
8136
     }
8137
     else {
8138
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8139
                          100, 0x1000000, 0, VX_FP_TASK);
8140
     }
8141
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8142
         do {
8143
             res = waitpid((pid_t)rtpid, &status, 0);
8144
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8145
8146
         if (res < 0)
8147
             return RTP_ID_ERROR;
8148
         return ((intptr_t)status);
8149
     }
8150
     return ((intptr_t)rtpid);
8151
}
8152
#endif
8153
8154
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8155
/*[clinic input]
8156
os.spawnv
8157
8158
    mode: int
8159
        Mode of process creation.
8160
    path: path_t
8161
        Path of executable file.
8162
    argv: object
8163
        Tuple or list of strings.
8164
    /
8165
8166
Execute the program specified by path in a new process.
8167
[clinic start generated code]*/
8168
8169
static PyObject *
8170
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8171
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8172
{
8173
    EXECV_CHAR **argvlist;
8174
    int i;
8175
    Py_ssize_t argc;
8176
    intptr_t spawnval;
8177
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8178
8179
    /* spawnv has three arguments: (mode, path, argv), where
8180
       argv is a list or tuple of strings. */
8181
8182
    if (PyList_Check(argv)) {
8183
        argc = PyList_Size(argv);
8184
        getitem = PyList_GetItem;
8185
    }
8186
    else if (PyTuple_Check(argv)) {
8187
        argc = PyTuple_Size(argv);
8188
        getitem = PyTuple_GetItem;
8189
    }
8190
    else {
8191
        PyErr_SetString(PyExc_TypeError,
8192
                        "spawnv() arg 2 must be a tuple or list");
8193
        return NULL;
8194
    }
8195
    if (argc == 0) {
8196
        PyErr_SetString(PyExc_ValueError,
8197
            "spawnv() arg 2 cannot be empty");
8198
        return NULL;
8199
    }
8200
8201
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8202
    if (argvlist == NULL) {
8203
        return PyErr_NoMemory();
8204
    }
8205
    for (i = 0; i < argc; i++) {
8206
        if (!fsconvert_strdup((*getitem)(argv, i),
8207
                              &argvlist[i])) {
8208
            free_string_array(argvlist, i);
8209
            PyErr_SetString(
8210
                PyExc_TypeError,
8211
                "spawnv() arg 2 must contain only strings");
8212
            return NULL;
8213
        }
8214
        if (i == 0 && !argvlist[0][0]) {
8215
            free_string_array(argvlist, i + 1);
8216
            PyErr_SetString(
8217
                PyExc_ValueError,
8218
                "spawnv() arg 2 first element cannot be empty");
8219
            return NULL;
8220
        }
8221
    }
8222
    argvlist[argc] = NULL;
8223
8224
#if !defined(HAVE_RTPSPAWN)
8225
    if (mode == _OLD_P_OVERLAY)
8226
        mode = _P_OVERLAY;
8227
#endif
8228
8229
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8230
                    Py_None) < 0) {
8231
        free_string_array(argvlist, argc);
8232
        return NULL;
8233
    }
8234
8235
    Py_BEGIN_ALLOW_THREADS
8236
    _Py_BEGIN_SUPPRESS_IPH
8237
#ifdef HAVE_WSPAWNV
8238
    spawnval = _wspawnv(mode, path->wide, argvlist);
8239
#elif defined(HAVE_RTPSPAWN)
8240
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8241
#else
8242
    spawnval = _spawnv(mode, path->narrow, argvlist);
8243
#endif
8244
    _Py_END_SUPPRESS_IPH
8245
    Py_END_ALLOW_THREADS
8246
8247
    int saved_errno = errno;
8248
    free_string_array(argvlist, argc);
8249
8250
    if (spawnval == -1) {
8251
        errno = saved_errno;
8252
        posix_error();
8253
        return NULL;
8254
    }
8255
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8256
}
8257
8258
/*[clinic input]
8259
os.spawnve
8260
8261
    mode: int
8262
        Mode of process creation.
8263
    path: path_t
8264
        Path of executable file.
8265
    argv: object
8266
        Tuple or list of strings.
8267
    env: object
8268
        Dictionary of strings mapping to strings.
8269
    /
8270
8271
Execute the program specified by path in a new process.
8272
[clinic start generated code]*/
8273
8274
static PyObject *
8275
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8276
                PyObject *env)
8277
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8278
{
8279
    EXECV_CHAR **argvlist;
8280
    EXECV_CHAR **envlist;
8281
    PyObject *res = NULL;
8282
    Py_ssize_t argc, i, envc;
8283
    intptr_t spawnval;
8284
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8285
    Py_ssize_t lastarg = 0;
8286
8287
    /* spawnve has four arguments: (mode, path, argv, env), where
8288
       argv is a list or tuple of strings and env is a dictionary
8289
       like posix.environ. */
8290
8291
    if (PyList_Check(argv)) {
8292
        argc = PyList_Size(argv);
8293
        getitem = PyList_GetItem;
8294
    }
8295
    else if (PyTuple_Check(argv)) {
8296
        argc = PyTuple_Size(argv);
8297
        getitem = PyTuple_GetItem;
8298
    }
8299
    else {
8300
        PyErr_SetString(PyExc_TypeError,
8301
                        "spawnve() arg 2 must be a tuple or list");
8302
        goto fail_0;
8303
    }
8304
    if (argc == 0) {
8305
        PyErr_SetString(PyExc_ValueError,
8306
            "spawnve() arg 2 cannot be empty");
8307
        goto fail_0;
8308
    }
8309
    if (!PyMapping_Check(env)) {
8310
        PyErr_SetString(PyExc_TypeError,
8311
                        "spawnve() arg 3 must be a mapping object");
8312
        goto fail_0;
8313
    }
8314
8315
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8316
    if (argvlist == NULL) {
8317
        PyErr_NoMemory();
8318
        goto fail_0;
8319
    }
8320
    for (i = 0; i < argc; i++) {
8321
        if (!fsconvert_strdup((*getitem)(argv, i),
8322
                              &argvlist[i]))
8323
        {
8324
            lastarg = i;
8325
            goto fail_1;
8326
        }
8327
        if (i == 0 && !argvlist[0][0]) {
8328
            lastarg = i + 1;
8329
            PyErr_SetString(
8330
                PyExc_ValueError,
8331
                "spawnv() arg 2 first element cannot be empty");
8332
            goto fail_1;
8333
        }
8334
    }
8335
    lastarg = argc;
8336
    argvlist[argc] = NULL;
8337
8338
    envlist = parse_envlist(env, &envc);
8339
    if (envlist == NULL)
8340
        goto fail_1;
8341
8342
#if !defined(HAVE_RTPSPAWN)
8343
    if (mode == _OLD_P_OVERLAY)
8344
        mode = _P_OVERLAY;
8345
#endif
8346
8347
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8348
        goto fail_2;
8349
    }
8350
8351
    Py_BEGIN_ALLOW_THREADS
8352
    _Py_BEGIN_SUPPRESS_IPH
8353
#ifdef HAVE_WSPAWNV
8354
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8355
#elif defined(HAVE_RTPSPAWN)
8356
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8357
                           (const char **)envlist);
8358
#else
8359
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8360
#endif
8361
    _Py_END_SUPPRESS_IPH
8362
    Py_END_ALLOW_THREADS
8363
8364
    if (spawnval == -1)
8365
        (void) posix_error();
8366
    else
8367
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8368
8369
  fail_2:
8370
    while (--envc >= 0) {
8371
        PyMem_Free(envlist[envc]);
8372
    }
8373
    PyMem_Free(envlist);
8374
  fail_1:
8375
    free_string_array(argvlist, lastarg);
8376
  fail_0:
8377
    return res;
8378
}
8379
8380
#endif /* HAVE_SPAWNV */
8381
8382
#ifdef HAVE_FORK
8383
8384
/* Helper function to validate arguments.
8385
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8386
   If obj is non-NULL it must be callable.  */
8387
static int
8388
check_null_or_callable(PyObject *obj, const char* obj_name)
8389
72
{
8390
72
    if (obj && !PyCallable_Check(obj)) {
8391
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8392
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8393
0
        return -1;
8394
0
    }
8395
72
    return 0;
8396
72
}
8397
8398
/*[clinic input]
8399
os.register_at_fork
8400
8401
    *
8402
    before: object=NULL
8403
        A callable to be called in the parent before the fork() syscall.
8404
    after_in_child: object=NULL
8405
        A callable to be called in the child after fork().
8406
    after_in_parent: object=NULL
8407
        A callable to be called in the parent after fork().
8408
8409
Register callables to be called when forking a new process.
8410
8411
'before' callbacks are called in reverse order.
8412
'after_in_child' and 'after_in_parent' callbacks are called in order.
8413
8414
[clinic start generated code]*/
8415
8416
static PyObject *
8417
os_register_at_fork_impl(PyObject *module, PyObject *before,
8418
                         PyObject *after_in_child, PyObject *after_in_parent)
8419
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8420
24
{
8421
24
    PyInterpreterState *interp;
8422
8423
24
    if (!before && !after_in_child && !after_in_parent) {
8424
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8425
0
        return NULL;
8426
0
    }
8427
24
    if (check_null_or_callable(before, "before") ||
8428
24
        check_null_or_callable(after_in_child, "after_in_child") ||
8429
24
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8430
0
        return NULL;
8431
0
    }
8432
24
    interp = _PyInterpreterState_GET();
8433
8434
24
    if (register_at_forker(&interp->before_forkers, before)) {
8435
0
        return NULL;
8436
0
    }
8437
24
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8438
0
        return NULL;
8439
0
    }
8440
24
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8441
0
        return NULL;
8442
0
    }
8443
24
    Py_RETURN_NONE;
8444
24
}
8445
#endif /* HAVE_FORK */
8446
8447
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8448
// Common code to raise a warning if we detect there is more than one thread
8449
// running in the process. Best effort, silent if unable to count threads.
8450
// Constraint: Quick. Never overcounts. Never leaves an error set.
8451
//
8452
// This MUST only be called from the parent process after
8453
// PyOS_AfterFork_Parent().
8454
static int
8455
warn_about_fork_with_threads(
8456
    const char* name,  // Name of the API to use in the warning message.
8457
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8458
)
8459
0
{
8460
    // It's not safe to issue the warning while the world is stopped, because
8461
    // other threads might be holding locks that we need, which would deadlock.
8462
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8463
8464
0
    Py_ssize_t num_python_threads = num_os_threads;
8465
0
    if (num_python_threads <= 0) {
8466
        // Fall back to just the number our threading module knows about.
8467
        // An incomplete view of the world, but better than nothing.
8468
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8469
0
        if (!threading) {
8470
0
            PyErr_Clear();
8471
0
            return 0;
8472
0
        }
8473
0
        PyObject *threading_active =
8474
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8475
0
        if (!threading_active) {
8476
0
            PyErr_Clear();
8477
0
            Py_DECREF(threading);
8478
0
            return 0;
8479
0
        }
8480
0
        PyObject *threading_limbo =
8481
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8482
0
        if (!threading_limbo) {
8483
0
            PyErr_Clear();
8484
0
            Py_DECREF(threading);
8485
0
            Py_DECREF(threading_active);
8486
0
            return 0;
8487
0
        }
8488
0
        Py_DECREF(threading);
8489
        // Duplicating what threading.active_count() does but without holding
8490
        // threading._active_limbo_lock so our count could be inaccurate if
8491
        // these dicts are mid-update from another thread.  Not a big deal.
8492
        // Worst case if someone replaced threading._active or threading._limbo
8493
        // with non-dicts, we get -1 from *Length() below and undercount.
8494
        // Nobody should, but we're best effort so we clear errors and move on.
8495
0
        num_python_threads = (PyMapping_Length(threading_active)
8496
0
                              + PyMapping_Length(threading_limbo));
8497
0
        PyErr_Clear();
8498
0
        Py_DECREF(threading_active);
8499
0
        Py_DECREF(threading_limbo);
8500
0
    }
8501
0
    if (num_python_threads > 1) {
8502
0
        return PyErr_WarnFormat(
8503
0
                PyExc_DeprecationWarning, 1,
8504
0
#ifdef HAVE_GETPID
8505
0
                "This process (pid=%d) is multi-threaded, "
8506
#else
8507
                "This process is multi-threaded, "
8508
#endif
8509
0
                "use of %s() may lead to deadlocks in the child.",
8510
0
#ifdef HAVE_GETPID
8511
0
                getpid(),
8512
0
#endif
8513
0
                name);
8514
0
    }
8515
0
    return 0;
8516
0
}
8517
8518
// If this returns <= 0, we were unable to successfully use any OS APIs.
8519
// Returns a positive number of threads otherwise.
8520
static Py_ssize_t get_number_of_os_threads(void)
8521
0
{
8522
    // TODO: Consider making an `os` module API to return the current number
8523
    // of threads in the process. That'd presumably use this platform code but
8524
    // raise an error rather than using the inaccurate fallback.
8525
0
    Py_ssize_t num_python_threads = 0;
8526
#if defined(__APPLE__) && defined(HAVE_GETPID)
8527
    mach_port_t macos_self = mach_task_self();
8528
    mach_port_t macos_task;
8529
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8530
        thread_array_t macos_threads;
8531
        mach_msg_type_number_t macos_n_threads;
8532
        if (task_threads(macos_task, &macos_threads,
8533
                         &macos_n_threads) == KERN_SUCCESS) {
8534
            num_python_threads = macos_n_threads;
8535
        }
8536
    }
8537
#elif defined(__linux__)
8538
    // Linux /proc/self/stat 20th field is the number of threads.
8539
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8540
0
    if (proc_stat) {
8541
0
        size_t n;
8542
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8543
        // observed on the author's workstation.
8544
0
        char stat_line[160];
8545
0
        n = fread(&stat_line, 1, 159, proc_stat);
8546
0
        stat_line[n] = '\0';
8547
0
        fclose(proc_stat);
8548
8549
0
        char *saveptr = NULL;
8550
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8551
0
        unsigned int idx;
8552
0
        for (idx = 19; idx && field; --idx) {
8553
0
            field = strtok_r(NULL, " ", &saveptr);
8554
0
        }
8555
0
        if (idx == 0 && field) {  // found the 20th field
8556
0
            num_python_threads = atoi(field);  // 0 on error
8557
0
        }
8558
0
    }
8559
0
#endif
8560
0
    return num_python_threads;
8561
0
}
8562
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8563
8564
#ifdef HAVE_FORK1
8565
/*[clinic input]
8566
os.fork1
8567
8568
Fork a child process with a single multiplexed (i.e., not bound) thread.
8569
8570
Return 0 to child process and PID of child to parent process.
8571
[clinic start generated code]*/
8572
8573
static PyObject *
8574
os_fork1_impl(PyObject *module)
8575
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8576
{
8577
    pid_t pid;
8578
8579
    PyInterpreterState *interp = _PyInterpreterState_GET();
8580
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8581
        PyErr_SetString(PyExc_PythonFinalizationError,
8582
                        "can't fork at interpreter shutdown");
8583
        return NULL;
8584
    }
8585
    if (!_Py_IsMainInterpreter(interp)) {
8586
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8587
        return NULL;
8588
    }
8589
    PyOS_BeforeFork();
8590
    pid = fork1();
8591
    int saved_errno = errno;
8592
    if (pid == 0) {
8593
        /* child: this clobbers and resets the import lock. */
8594
        PyOS_AfterFork_Child();
8595
    } else {
8596
        // Called before AfterFork_Parent in case those hooks start threads.
8597
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8598
        /* parent: release the import lock. */
8599
        PyOS_AfterFork_Parent();
8600
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8601
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8602
            return NULL;
8603
        }
8604
    }
8605
    if (pid == -1) {
8606
        errno = saved_errno;
8607
        return posix_error();
8608
    }
8609
    return PyLong_FromPid(pid);
8610
}
8611
#endif /* HAVE_FORK1 */
8612
8613
8614
#ifdef HAVE_FORK
8615
/*[clinic input]
8616
os.fork
8617
8618
Fork a child process.
8619
8620
Return 0 to child process and PID of child to parent process.
8621
[clinic start generated code]*/
8622
8623
static PyObject *
8624
os_fork_impl(PyObject *module)
8625
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8626
0
{
8627
0
    pid_t pid;
8628
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8629
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8630
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8631
0
                        "can't fork at interpreter shutdown");
8632
0
        return NULL;
8633
0
    }
8634
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8635
0
        PyErr_SetString(PyExc_RuntimeError,
8636
0
                        "fork not supported for isolated subinterpreters");
8637
0
        return NULL;
8638
0
    }
8639
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8640
0
        return NULL;
8641
0
    }
8642
0
    PyOS_BeforeFork();
8643
0
    pid = fork();
8644
0
    int saved_errno = errno;
8645
0
    if (pid == 0) {
8646
        /* child: this clobbers and resets the import lock. */
8647
0
        PyOS_AfterFork_Child();
8648
0
    } else {
8649
        // Called before AfterFork_Parent in case those hooks start threads.
8650
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8651
        /* parent: release the import lock. */
8652
0
        PyOS_AfterFork_Parent();
8653
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8654
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8655
0
            return NULL;
8656
0
    }
8657
0
    if (pid == -1) {
8658
0
        errno = saved_errno;
8659
0
        return posix_error();
8660
0
    }
8661
0
    return PyLong_FromPid(pid);
8662
0
}
8663
#endif /* HAVE_FORK */
8664
8665
8666
#ifdef HAVE_SCHED_H
8667
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8668
/*[clinic input]
8669
os.sched_get_priority_max
8670
8671
    policy: int
8672
8673
Get the maximum scheduling priority for policy.
8674
[clinic start generated code]*/
8675
8676
static PyObject *
8677
os_sched_get_priority_max_impl(PyObject *module, int policy)
8678
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8679
0
{
8680
    /* make sure that errno is cleared before the call */
8681
0
    errno = 0;
8682
0
    int max = sched_get_priority_max(policy);
8683
0
    if (max == -1 && errno)
8684
0
        return posix_error();
8685
0
    return PyLong_FromLong(max);
8686
0
}
8687
8688
8689
/*[clinic input]
8690
os.sched_get_priority_min
8691
8692
    policy: int
8693
8694
Get the minimum scheduling priority for policy.
8695
[clinic start generated code]*/
8696
8697
static PyObject *
8698
os_sched_get_priority_min_impl(PyObject *module, int policy)
8699
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8700
0
{
8701
    /* make sure that errno is cleared before the call */
8702
0
    errno = 0;
8703
0
    int min = sched_get_priority_min(policy);
8704
0
    if (min == -1 && errno)
8705
0
        return posix_error();
8706
0
    return PyLong_FromLong(min);
8707
0
}
8708
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8709
8710
8711
#ifdef HAVE_SCHED_SETSCHEDULER
8712
/*[clinic input]
8713
os.sched_getscheduler
8714
    pid: pid_t
8715
    /
8716
8717
Get the scheduling policy for the process identified by pid.
8718
8719
Passing 0 for pid returns the scheduling policy for the calling process.
8720
[clinic start generated code]*/
8721
8722
static PyObject *
8723
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8724
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8725
0
{
8726
0
    int policy;
8727
8728
0
    policy = sched_getscheduler(pid);
8729
0
    if (policy < 0)
8730
0
        return posix_error();
8731
0
    return PyLong_FromLong(policy);
8732
0
}
8733
#endif /* HAVE_SCHED_SETSCHEDULER */
8734
8735
8736
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8737
/*[clinic input]
8738
class os.sched_param "PyObject *" "SchedParamType"
8739
8740
@classmethod
8741
os.sched_param.__new__
8742
8743
    sched_priority: object
8744
        A scheduling parameter.
8745
8746
Currently has only one field: sched_priority
8747
[clinic start generated code]*/
8748
8749
static PyObject *
8750
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8751
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8752
0
{
8753
0
    PyObject *res;
8754
8755
0
    res = PyStructSequence_New(type);
8756
0
    if (!res)
8757
0
        return NULL;
8758
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8759
0
    return res;
8760
0
}
8761
8762
static PyObject *
8763
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8764
0
{
8765
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8766
0
}
8767
8768
static PyMethodDef os_sched_param_reduce_method = {
8769
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8770
};
8771
8772
PyDoc_VAR(os_sched_param__doc__);
8773
8774
static PyStructSequence_Field sched_param_fields[] = {
8775
    {"sched_priority", "the scheduling priority"},
8776
    {0}
8777
};
8778
8779
static PyStructSequence_Desc sched_param_desc = {
8780
    MODNAME ".sched_param", /* name */
8781
    os_sched_param__doc__, /* doc */
8782
    sched_param_fields,
8783
    1
8784
};
8785
8786
static int
8787
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8788
0
{
8789
0
    long priority;
8790
8791
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8792
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8793
0
        return 0;
8794
0
    }
8795
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8796
0
    if (priority == -1 && PyErr_Occurred())
8797
0
        return 0;
8798
0
    if (priority > INT_MAX || priority < INT_MIN) {
8799
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8800
0
        return 0;
8801
0
    }
8802
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8803
0
    return 1;
8804
0
}
8805
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8806
8807
8808
#ifdef HAVE_SCHED_SETSCHEDULER
8809
/*[clinic input]
8810
os.sched_setscheduler
8811
8812
    pid: pid_t
8813
    policy: int
8814
    param as param_obj: object
8815
    /
8816
8817
Set the scheduling policy for the process identified by pid.
8818
8819
If pid is 0, the calling process is changed.
8820
param is an instance of sched_param.
8821
[clinic start generated code]*/
8822
8823
static PyObject *
8824
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8825
                           PyObject *param_obj)
8826
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8827
0
{
8828
0
    struct sched_param param;
8829
0
    if (!convert_sched_param(module, param_obj, &param)) {
8830
0
        return NULL;
8831
0
    }
8832
8833
    /*
8834
    ** sched_setscheduler() returns 0 in Linux, but the previous
8835
    ** scheduling policy under Solaris/Illumos, and others.
8836
    ** On error, -1 is returned in all Operating Systems.
8837
    */
8838
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8839
0
        return posix_error();
8840
0
    Py_RETURN_NONE;
8841
0
}
8842
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8843
8844
8845
#ifdef HAVE_SCHED_SETPARAM
8846
/*[clinic input]
8847
os.sched_getparam
8848
    pid: pid_t
8849
    /
8850
8851
Returns scheduling parameters for the process identified by pid.
8852
8853
If pid is 0, returns parameters for the calling process.
8854
Return value is an instance of sched_param.
8855
[clinic start generated code]*/
8856
8857
static PyObject *
8858
os_sched_getparam_impl(PyObject *module, pid_t pid)
8859
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8860
0
{
8861
0
    struct sched_param param;
8862
0
    PyObject *result;
8863
0
    PyObject *priority;
8864
8865
0
    if (sched_getparam(pid, &param))
8866
0
        return posix_error();
8867
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8868
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8869
0
    if (!result)
8870
0
        return NULL;
8871
0
    priority = PyLong_FromLong(param.sched_priority);
8872
0
    if (!priority) {
8873
0
        Py_DECREF(result);
8874
0
        return NULL;
8875
0
    }
8876
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8877
0
    return result;
8878
0
}
8879
8880
8881
/*[clinic input]
8882
os.sched_setparam
8883
    pid: pid_t
8884
    param as param_obj: object
8885
    /
8886
8887
Set scheduling parameters for the process identified by pid.
8888
8889
If pid is 0, sets parameters for the calling process.
8890
param should be an instance of sched_param.
8891
[clinic start generated code]*/
8892
8893
static PyObject *
8894
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8895
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8896
0
{
8897
0
    struct sched_param param;
8898
0
    if (!convert_sched_param(module, param_obj, &param)) {
8899
0
        return NULL;
8900
0
    }
8901
8902
0
    if (sched_setparam(pid, &param))
8903
0
        return posix_error();
8904
0
    Py_RETURN_NONE;
8905
0
}
8906
#endif /* HAVE_SCHED_SETPARAM */
8907
8908
8909
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8910
/*[clinic input]
8911
@permit_long_summary
8912
os.sched_rr_get_interval -> double
8913
    pid: pid_t
8914
    /
8915
8916
Return the round-robin quantum for the process identified by pid, in seconds.
8917
8918
Value returned is a float.
8919
[clinic start generated code]*/
8920
8921
static double
8922
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8923
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8924
0
{
8925
0
    struct timespec interval;
8926
0
    if (sched_rr_get_interval(pid, &interval)) {
8927
0
        posix_error();
8928
0
        return -1.0;
8929
0
    }
8930
#ifdef _Py_MEMORY_SANITIZER
8931
    __msan_unpoison(&interval, sizeof(interval));
8932
#endif
8933
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8934
0
}
8935
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8936
8937
8938
/*[clinic input]
8939
os.sched_yield
8940
8941
Voluntarily relinquish the CPU.
8942
[clinic start generated code]*/
8943
8944
static PyObject *
8945
os_sched_yield_impl(PyObject *module)
8946
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8947
0
{
8948
0
    int result;
8949
0
    Py_BEGIN_ALLOW_THREADS
8950
0
    result = sched_yield();
8951
0
    Py_END_ALLOW_THREADS
8952
0
    if (result < 0) {
8953
0
        return posix_error();
8954
0
    }
8955
0
    Py_RETURN_NONE;
8956
0
}
8957
8958
#ifdef HAVE_SCHED_SETAFFINITY
8959
/* The minimum number of CPUs allocated in a cpu_set_t */
8960
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8961
8962
/*[clinic input]
8963
os.sched_setaffinity
8964
    pid: pid_t
8965
    mask : object
8966
    /
8967
8968
Set the CPU affinity of the process identified by pid to mask.
8969
8970
mask should be an iterable of integers identifying CPUs.
8971
[clinic start generated code]*/
8972
8973
static PyObject *
8974
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8975
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8976
0
{
8977
0
    int ncpus;
8978
0
    size_t setsize;
8979
0
    cpu_set_t *cpu_set = NULL;
8980
0
    PyObject *iterator = NULL, *item;
8981
8982
0
    iterator = PyObject_GetIter(mask);
8983
0
    if (iterator == NULL)
8984
0
        return NULL;
8985
8986
0
    ncpus = NCPUS_START;
8987
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8988
0
    cpu_set = CPU_ALLOC(ncpus);
8989
0
    if (cpu_set == NULL) {
8990
0
        PyErr_NoMemory();
8991
0
        goto error;
8992
0
    }
8993
0
    CPU_ZERO_S(setsize, cpu_set);
8994
8995
0
    while ((item = PyIter_Next(iterator))) {
8996
0
        long cpu;
8997
0
        if (!PyIndex_Check(item)) {
8998
0
            PyErr_Format(PyExc_TypeError,
8999
0
                        "expected an iterator of ints, "
9000
0
                        "but iterator yielded %R",
9001
0
                        Py_TYPE(item));
9002
0
            Py_DECREF(item);
9003
0
            goto error;
9004
0
        }
9005
0
        cpu = PyLong_AsLong(item);
9006
0
        Py_DECREF(item);
9007
0
        if (cpu < 0) {
9008
0
            if (!PyErr_Occurred())
9009
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9010
0
            goto error;
9011
0
        }
9012
0
        if (cpu > INT_MAX - 1) {
9013
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9014
0
            goto error;
9015
0
        }
9016
0
        if (cpu >= ncpus) {
9017
            /* Grow CPU mask to fit the CPU number */
9018
0
            int newncpus = ncpus;
9019
0
            cpu_set_t *newmask;
9020
0
            size_t newsetsize;
9021
0
            while (newncpus <= cpu) {
9022
0
                if (newncpus > INT_MAX / 2)
9023
0
                    newncpus = cpu + 1;
9024
0
                else
9025
0
                    newncpus = newncpus * 2;
9026
0
            }
9027
0
            newmask = CPU_ALLOC(newncpus);
9028
0
            if (newmask == NULL) {
9029
0
                PyErr_NoMemory();
9030
0
                goto error;
9031
0
            }
9032
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9033
0
            CPU_ZERO_S(newsetsize, newmask);
9034
0
            memcpy(newmask, cpu_set, setsize);
9035
0
            CPU_FREE(cpu_set);
9036
0
            setsize = newsetsize;
9037
0
            cpu_set = newmask;
9038
0
            ncpus = newncpus;
9039
0
        }
9040
0
        CPU_SET_S(cpu, setsize, cpu_set);
9041
0
    }
9042
0
    if (PyErr_Occurred()) {
9043
0
        goto error;
9044
0
    }
9045
0
    Py_CLEAR(iterator);
9046
9047
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9048
0
        posix_error();
9049
0
        goto error;
9050
0
    }
9051
0
    CPU_FREE(cpu_set);
9052
0
    Py_RETURN_NONE;
9053
9054
0
error:
9055
0
    if (cpu_set)
9056
0
        CPU_FREE(cpu_set);
9057
0
    Py_XDECREF(iterator);
9058
0
    return NULL;
9059
0
}
9060
9061
9062
/*[clinic input]
9063
@permit_long_summary
9064
os.sched_getaffinity
9065
    pid: pid_t
9066
    /
9067
9068
Return the affinity of the process identified by pid (or the current process if zero).
9069
9070
The affinity is returned as a set of CPU identifiers.
9071
[clinic start generated code]*/
9072
9073
static PyObject *
9074
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9075
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9076
0
{
9077
0
    int ncpus = NCPUS_START;
9078
0
    size_t setsize;
9079
0
    cpu_set_t *mask;
9080
9081
0
    while (1) {
9082
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9083
0
        mask = CPU_ALLOC(ncpus);
9084
0
        if (mask == NULL) {
9085
0
            return PyErr_NoMemory();
9086
0
        }
9087
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9088
0
            break;
9089
0
        }
9090
0
        CPU_FREE(mask);
9091
0
        if (errno != EINVAL) {
9092
0
            return posix_error();
9093
0
        }
9094
0
        if (ncpus > INT_MAX / 2) {
9095
0
            PyErr_SetString(PyExc_OverflowError,
9096
0
                            "could not allocate a large enough CPU set");
9097
0
            return NULL;
9098
0
        }
9099
0
        ncpus *= 2;
9100
0
    }
9101
9102
0
    PyObject *res = PySet_New(NULL);
9103
0
    if (res == NULL) {
9104
0
        goto error;
9105
0
    }
9106
9107
0
    int cpu = 0;
9108
0
    int count = CPU_COUNT_S(setsize, mask);
9109
0
    for (; count; cpu++) {
9110
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9111
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9112
0
            --count;
9113
0
            if (cpu_num == NULL) {
9114
0
                goto error;
9115
0
            }
9116
0
            if (PySet_Add(res, cpu_num)) {
9117
0
                Py_DECREF(cpu_num);
9118
0
                goto error;
9119
0
            }
9120
0
            Py_DECREF(cpu_num);
9121
0
        }
9122
0
    }
9123
0
    CPU_FREE(mask);
9124
0
    return res;
9125
9126
0
error:
9127
0
    if (mask) {
9128
0
        CPU_FREE(mask);
9129
0
    }
9130
0
    Py_XDECREF(res);
9131
0
    return NULL;
9132
0
}
9133
#endif /* HAVE_SCHED_SETAFFINITY */
9134
9135
#endif /* HAVE_SCHED_H */
9136
9137
9138
#ifdef HAVE_POSIX_OPENPT
9139
/*[clinic input]
9140
os.posix_openpt -> int
9141
9142
    oflag: int
9143
    /
9144
9145
Open and return a file descriptor for a master pseudo-terminal device.
9146
9147
Performs a posix_openpt() C function call. The oflag argument is used to
9148
set file status flags and file access modes as specified in the manual page
9149
of posix_openpt() of your system.
9150
[clinic start generated code]*/
9151
9152
static int
9153
os_posix_openpt_impl(PyObject *module, int oflag)
9154
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
9155
0
{
9156
0
    int fd;
9157
9158
0
#if defined(O_CLOEXEC)
9159
0
    oflag |= O_CLOEXEC;
9160
0
#endif
9161
9162
0
    fd = posix_openpt(oflag);
9163
0
    if (fd == -1) {
9164
0
        posix_error();
9165
0
        return -1;
9166
0
    }
9167
9168
    // Just in case, likely a no-op given O_CLOEXEC above.
9169
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9170
0
        close(fd);
9171
0
        return -1;
9172
0
    }
9173
9174
0
    return fd;
9175
0
}
9176
#endif /* HAVE_POSIX_OPENPT */
9177
9178
#ifdef HAVE_GRANTPT
9179
/*[clinic input]
9180
os.grantpt
9181
9182
    fd: fildes
9183
        File descriptor of a master pseudo-terminal device.
9184
    /
9185
9186
Grant access to the slave pseudo-terminal device.
9187
9188
Performs a grantpt() C function call.
9189
[clinic start generated code]*/
9190
9191
static PyObject *
9192
os_grantpt_impl(PyObject *module, int fd)
9193
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9194
0
{
9195
0
    int ret;
9196
0
    int saved_errno;
9197
0
    PyOS_sighandler_t sig_saved;
9198
9199
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9200
9201
0
    ret = grantpt(fd);
9202
0
    if (ret == -1)
9203
0
        saved_errno = errno;
9204
9205
0
    PyOS_setsig(SIGCHLD, sig_saved);
9206
9207
0
    if (ret == -1) {
9208
0
        errno = saved_errno;
9209
0
        return posix_error();
9210
0
    }
9211
9212
0
    Py_RETURN_NONE;
9213
0
}
9214
#endif /* HAVE_GRANTPT */
9215
9216
#ifdef HAVE_UNLOCKPT
9217
/*[clinic input]
9218
os.unlockpt
9219
9220
    fd: fildes
9221
        File descriptor of a master pseudo-terminal device.
9222
    /
9223
9224
Unlock a pseudo-terminal master/slave pair.
9225
9226
Performs an unlockpt() C function call.
9227
[clinic start generated code]*/
9228
9229
static PyObject *
9230
os_unlockpt_impl(PyObject *module, int fd)
9231
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9232
0
{
9233
0
    if (unlockpt(fd) == -1)
9234
0
        return posix_error();
9235
9236
0
    Py_RETURN_NONE;
9237
0
}
9238
#endif /* HAVE_UNLOCKPT */
9239
9240
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9241
static PyObject *
9242
py_ptsname(int fd)
9243
0
{
9244
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9245
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9246
0
    errno = 0;
9247
0
    char *name = ptsname(fd);
9248
0
    if (name == NULL) {
9249
0
        return posix_error();
9250
0
    }
9251
0
    return PyUnicode_DecodeFSDefault(name);
9252
0
}
9253
9254
/*[clinic input]
9255
os.ptsname
9256
9257
    fd: fildes
9258
        File descriptor of a master pseudo-terminal device.
9259
    /
9260
9261
Return the name of the slave pseudo-terminal device.
9262
9263
If the ptsname_r() C function is available, it is called;
9264
otherwise, performs a ptsname() C function call.
9265
[clinic start generated code]*/
9266
9267
static PyObject *
9268
os_ptsname_impl(PyObject *module, int fd)
9269
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9270
0
{
9271
0
#ifdef HAVE_PTSNAME_R
9272
0
    int ret;
9273
0
    char name[MAXPATHLEN+1];
9274
9275
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9276
0
        ret = ptsname_r(fd, name, sizeof(name));
9277
0
    }
9278
0
    else {
9279
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9280
0
        return py_ptsname(fd);
9281
0
    }
9282
0
    if (ret != 0) {
9283
0
        errno = ret;
9284
0
        return posix_error();
9285
0
    }
9286
9287
0
    return PyUnicode_DecodeFSDefault(name);
9288
#else
9289
    return py_ptsname(fd);
9290
#endif /* HAVE_PTSNAME_R */
9291
0
}
9292
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9293
9294
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9295
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9296
#  define DEV_PTY_FILE "/dev/ptc"
9297
#  define HAVE_DEV_PTMX
9298
#else
9299
#  define DEV_PTY_FILE "/dev/ptmx"
9300
#endif
9301
9302
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9303
#ifdef HAVE_PTY_H
9304
#include <pty.h>
9305
#elif defined(HAVE_LIBUTIL_H)
9306
#include <libutil.h>
9307
#elif defined(HAVE_UTIL_H)
9308
#include <util.h>
9309
#endif /* HAVE_PTY_H */
9310
#ifdef HAVE_UTMP_H
9311
#include <utmp.h>
9312
#endif /* HAVE_UTMP_H */
9313
#ifdef HAVE_STROPTS_H
9314
#include <stropts.h>
9315
#endif
9316
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9317
9318
9319
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9320
/*[clinic input]
9321
os.openpty
9322
9323
Open a pseudo-terminal.
9324
9325
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9326
for both the master and slave ends.
9327
[clinic start generated code]*/
9328
9329
static PyObject *
9330
os_openpty_impl(PyObject *module)
9331
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9332
0
{
9333
0
    int master_fd = -1, slave_fd = -1;
9334
#ifndef HAVE_OPENPTY
9335
    char * slave_name;
9336
#endif
9337
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9338
    PyOS_sighandler_t sig_saved;
9339
#if defined(__sun) && defined(__SVR4)
9340
    extern char *ptsname(int fildes);
9341
#endif
9342
#endif
9343
9344
0
#ifdef HAVE_OPENPTY
9345
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9346
0
        goto posix_error;
9347
9348
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9349
0
        goto error;
9350
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9351
0
        goto error;
9352
9353
#elif defined(HAVE__GETPTY)
9354
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9355
    if (slave_name == NULL)
9356
        goto posix_error;
9357
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9358
        goto error;
9359
9360
    slave_fd = _Py_open(slave_name, O_RDWR);
9361
    if (slave_fd < 0)
9362
        goto error;
9363
9364
#else
9365
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9366
    if (master_fd < 0)
9367
        goto posix_error;
9368
9369
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9370
9371
    /* change permission of slave */
9372
    if (grantpt(master_fd) < 0) {
9373
        int saved_errno = errno;
9374
        PyOS_setsig(SIGCHLD, sig_saved);
9375
        errno = saved_errno;
9376
        goto posix_error;
9377
    }
9378
9379
    /* unlock slave */
9380
    if (unlockpt(master_fd) < 0) {
9381
        int saved_errno = errno;
9382
        PyOS_setsig(SIGCHLD, sig_saved);
9383
        errno = saved_errno;
9384
        goto posix_error;
9385
    }
9386
9387
    PyOS_setsig(SIGCHLD, sig_saved);
9388
9389
    slave_name = ptsname(master_fd); /* get name of slave */
9390
    if (slave_name == NULL)
9391
        goto posix_error;
9392
9393
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9394
    if (slave_fd == -1)
9395
        goto error;
9396
9397
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9398
        goto posix_error;
9399
9400
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
9401
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9402
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9403
#ifndef __hpux
9404
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9405
#endif /* __hpux */
9406
#endif /* HAVE_CYGWIN */
9407
#endif /* HAVE_OPENPTY */
9408
9409
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9410
9411
0
posix_error:
9412
0
    posix_error();
9413
0
error:
9414
0
    if (master_fd != -1)
9415
0
        close(master_fd);
9416
0
    if (slave_fd != -1)
9417
0
        close(slave_fd);
9418
0
    return NULL;
9419
0
}
9420
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9421
9422
9423
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9424
#define HAVE_FALLBACK_LOGIN_TTY 1
9425
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9426
9427
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9428
/*[clinic input]
9429
os.login_tty
9430
9431
    fd: fildes
9432
    /
9433
9434
Prepare the tty of which fd is a file descriptor for a new login session.
9435
9436
Make the calling process a session leader; make the tty the
9437
controlling tty, the stdin, the stdout, and the stderr of the
9438
calling process; close fd.
9439
[clinic start generated code]*/
9440
9441
static PyObject *
9442
os_login_tty_impl(PyObject *module, int fd)
9443
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
9444
0
{
9445
0
#ifdef HAVE_LOGIN_TTY
9446
0
    if (login_tty(fd) == -1) {
9447
0
        return posix_error();
9448
0
    }
9449
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9450
    /* Establish a new session. */
9451
    if (setsid() == -1) {
9452
        return posix_error();
9453
    }
9454
9455
    /* The tty becomes the controlling terminal. */
9456
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9457
        return posix_error();
9458
    }
9459
9460
    /* The tty becomes stdin/stdout/stderr */
9461
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9462
        return posix_error();
9463
    }
9464
    if (fd > 2) {
9465
        close(fd);
9466
    }
9467
#endif /* HAVE_LOGIN_TTY */
9468
0
    Py_RETURN_NONE;
9469
0
}
9470
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9471
9472
9473
#ifdef HAVE_FORKPTY
9474
/*[clinic input]
9475
os.forkpty
9476
9477
Fork a new process with a new pseudo-terminal as controlling tty.
9478
9479
Returns a tuple of (pid, master_fd).
9480
Like fork(), return pid of 0 to the child process,
9481
and pid of child to the parent process.
9482
To both, return fd of newly opened pseudo-terminal.
9483
The master_fd is non-inheritable.
9484
[clinic start generated code]*/
9485
9486
static PyObject *
9487
os_forkpty_impl(PyObject *module)
9488
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9489
0
{
9490
0
    int master_fd = -1;
9491
0
    pid_t pid;
9492
9493
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9494
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9495
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9496
0
                        "can't fork at interpreter shutdown");
9497
0
        return NULL;
9498
0
    }
9499
0
    if (!_Py_IsMainInterpreter(interp)) {
9500
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9501
0
        return NULL;
9502
0
    }
9503
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9504
0
        return NULL;
9505
0
    }
9506
0
    PyOS_BeforeFork();
9507
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9508
0
    if (pid == 0) {
9509
        /* child: this clobbers and resets the import lock. */
9510
0
        PyOS_AfterFork_Child();
9511
0
    } else {
9512
        // Called before AfterFork_Parent in case those hooks start threads.
9513
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9514
        /* parent: release the import lock. */
9515
0
        PyOS_AfterFork_Parent();
9516
        /* set O_CLOEXEC on master_fd */
9517
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9518
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9519
0
                                   "non-inheritable in forkpty()");
9520
0
        }
9521
9522
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9523
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9524
0
            return NULL;
9525
0
    }
9526
0
    if (pid == -1) {
9527
0
        return posix_error();
9528
0
    }
9529
9530
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9531
0
}
9532
#endif /* HAVE_FORKPTY */
9533
9534
9535
#ifdef HAVE_GETEGID
9536
/*[clinic input]
9537
os.getegid
9538
9539
Return the current process's effective group id.
9540
[clinic start generated code]*/
9541
9542
static PyObject *
9543
os_getegid_impl(PyObject *module)
9544
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9545
34
{
9546
34
    return _PyLong_FromGid(getegid());
9547
34
}
9548
#endif /* HAVE_GETEGID */
9549
9550
9551
#ifdef HAVE_GETEUID
9552
/*[clinic input]
9553
os.geteuid
9554
9555
Return the current process's effective user id.
9556
[clinic start generated code]*/
9557
9558
static PyObject *
9559
os_geteuid_impl(PyObject *module)
9560
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9561
34
{
9562
34
    return _PyLong_FromUid(geteuid());
9563
34
}
9564
#endif /* HAVE_GETEUID */
9565
9566
9567
#ifdef HAVE_GETGID
9568
/*[clinic input]
9569
os.getgid
9570
9571
Return the current process's group id.
9572
[clinic start generated code]*/
9573
9574
static PyObject *
9575
os_getgid_impl(PyObject *module)
9576
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9577
34
{
9578
34
    return _PyLong_FromGid(getgid());
9579
34
}
9580
#endif /* HAVE_GETGID */
9581
9582
9583
#if defined(HAVE_GETPID)
9584
/*[clinic input]
9585
os.getpid
9586
9587
Return the current process id.
9588
[clinic start generated code]*/
9589
9590
static PyObject *
9591
os_getpid_impl(PyObject *module)
9592
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9593
3.87k
{
9594
3.87k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9595
3.87k
    return PyLong_FromPid(getpid());
9596
#else
9597
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9598
#endif
9599
3.87k
}
9600
#endif /* defined(HAVE_GETPID) */
9601
9602
#ifdef NGROUPS_MAX
9603
0
#define MAX_GROUPS NGROUPS_MAX
9604
#else
9605
    /* defined to be 16 on Solaris7, so this should be a small number */
9606
#define MAX_GROUPS 64
9607
#endif
9608
9609
#ifdef HAVE_GETGROUPLIST
9610
9611
#ifdef __APPLE__
9612
/*[clinic input]
9613
os.getgrouplist
9614
9615
    user: str
9616
        username to lookup
9617
    group as basegid: int
9618
        base group id of the user
9619
    /
9620
9621
Returns a list of groups to which a user belongs.
9622
[clinic start generated code]*/
9623
9624
static PyObject *
9625
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9626
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9627
#else
9628
/*[clinic input]
9629
os.getgrouplist
9630
9631
    user: str
9632
        username to lookup
9633
    group as basegid: gid_t
9634
        base group id of the user
9635
    /
9636
9637
Returns a list of groups to which a user belongs.
9638
[clinic start generated code]*/
9639
9640
static PyObject *
9641
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9642
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9643
#endif
9644
0
{
9645
0
    int i, ngroups;
9646
0
    PyObject *list;
9647
#ifdef __APPLE__
9648
    int *groups;
9649
#else
9650
0
    gid_t *groups;
9651
0
#endif
9652
9653
    /*
9654
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9655
     * number of supplemental groups a users can belong to.
9656
     * We have to increment it by one because
9657
     * getgrouplist() returns both the supplemental groups
9658
     * and the primary group, i.e. all of the groups the
9659
     * user belongs to.
9660
     */
9661
0
    ngroups = 1 + MAX_GROUPS;
9662
9663
0
    while (1) {
9664
#ifdef __APPLE__
9665
        groups = PyMem_New(int, ngroups);
9666
#else
9667
0
        groups = PyMem_New(gid_t, ngroups);
9668
0
#endif
9669
0
        if (groups == NULL) {
9670
0
            return PyErr_NoMemory();
9671
0
        }
9672
9673
0
        int old_ngroups = ngroups;
9674
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9675
            /* Success */
9676
0
            break;
9677
0
        }
9678
9679
        /* getgrouplist() fails if the group list is too small */
9680
0
        PyMem_Free(groups);
9681
9682
0
        if (ngroups > old_ngroups) {
9683
            /* If the group list is too small, the glibc implementation of
9684
               getgrouplist() sets ngroups to the total number of groups and
9685
               returns -1. */
9686
0
        }
9687
0
        else {
9688
            /* Double the group list size */
9689
0
            if (ngroups > INT_MAX / 2) {
9690
0
                return PyErr_NoMemory();
9691
0
            }
9692
0
            ngroups *= 2;
9693
0
        }
9694
9695
        /* Retry getgrouplist() with a larger group list */
9696
0
    }
9697
9698
#ifdef _Py_MEMORY_SANITIZER
9699
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9700
    __msan_unpoison(&ngroups, sizeof(ngroups));
9701
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9702
#endif
9703
9704
0
    list = PyList_New(ngroups);
9705
0
    if (list == NULL) {
9706
0
        PyMem_Free(groups);
9707
0
        return NULL;
9708
0
    }
9709
9710
0
    for (i = 0; i < ngroups; i++) {
9711
#ifdef __APPLE__
9712
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9713
#else
9714
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9715
0
#endif
9716
0
        if (o == NULL) {
9717
0
            Py_DECREF(list);
9718
0
            PyMem_Free(groups);
9719
0
            return NULL;
9720
0
        }
9721
0
        PyList_SET_ITEM(list, i, o);
9722
0
    }
9723
9724
0
    PyMem_Free(groups);
9725
9726
0
    return list;
9727
0
}
9728
#endif /* HAVE_GETGROUPLIST */
9729
9730
9731
#ifdef HAVE_GETGROUPS
9732
/*[clinic input]
9733
os.getgroups
9734
9735
Return list of supplemental group IDs for the process.
9736
[clinic start generated code]*/
9737
9738
static PyObject *
9739
os_getgroups_impl(PyObject *module)
9740
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9741
0
{
9742
    // Call getgroups with length 0 to get the actual number of groups
9743
0
    int n = getgroups(0, NULL);
9744
0
    if (n < 0) {
9745
0
        return posix_error();
9746
0
    }
9747
9748
0
    if (n == 0) {
9749
0
        return PyList_New(0);
9750
0
    }
9751
9752
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9753
0
    if (grouplist == NULL) {
9754
0
        return PyErr_NoMemory();
9755
0
    }
9756
9757
0
    n = getgroups(n, grouplist);
9758
0
    if (n == -1) {
9759
0
        posix_error();
9760
0
        PyMem_Free(grouplist);
9761
0
        return NULL;
9762
0
    }
9763
9764
0
    PyObject *result = PyList_New(n);
9765
0
    if (result == NULL) {
9766
0
        goto error;
9767
0
    }
9768
9769
0
    for (int i = 0; i < n; ++i) {
9770
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9771
0
        if (group == NULL) {
9772
0
            goto error;
9773
0
        }
9774
0
        PyList_SET_ITEM(result, i, group);
9775
0
    }
9776
0
    PyMem_Free(grouplist);
9777
9778
0
    return result;
9779
9780
0
error:
9781
0
    PyMem_Free(grouplist);
9782
0
    Py_XDECREF(result);
9783
0
    return NULL;
9784
0
}
9785
#endif /* HAVE_GETGROUPS */
9786
9787
#ifdef HAVE_INITGROUPS
9788
#ifdef __APPLE__
9789
/*[clinic input]
9790
os.initgroups
9791
9792
    username as oname: unicode_fs_encoded
9793
    gid: int
9794
    /
9795
9796
Initialize the group access list.
9797
9798
Call the system initgroups() to initialize the group access list with all of
9799
the groups of which the specified username is a member, plus the specified
9800
group id.
9801
[clinic start generated code]*/
9802
9803
static PyObject *
9804
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9805
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9806
#else
9807
/*[clinic input]
9808
os.initgroups
9809
9810
    username as oname: unicode_fs_encoded
9811
    gid: gid_t
9812
    /
9813
9814
Initialize the group access list.
9815
9816
Call the system initgroups() to initialize the group access list with all of
9817
the groups of which the specified username is a member, plus the specified
9818
group id.
9819
[clinic start generated code]*/
9820
9821
static PyObject *
9822
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9823
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9824
#endif
9825
0
{
9826
0
    const char *username = PyBytes_AS_STRING(oname);
9827
9828
0
    if (initgroups(username, gid) == -1)
9829
0
        return PyErr_SetFromErrno(PyExc_OSError);
9830
9831
0
    Py_RETURN_NONE;
9832
0
}
9833
#endif /* HAVE_INITGROUPS */
9834
9835
9836
#ifdef HAVE_GETPGID
9837
/*[clinic input]
9838
os.getpgid
9839
9840
    pid: pid_t
9841
9842
Call the system call getpgid(), and return the result.
9843
[clinic start generated code]*/
9844
9845
static PyObject *
9846
os_getpgid_impl(PyObject *module, pid_t pid)
9847
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9848
0
{
9849
0
    pid_t pgid = getpgid(pid);
9850
0
    if (pgid < 0)
9851
0
        return posix_error();
9852
0
    return PyLong_FromPid(pgid);
9853
0
}
9854
#endif /* HAVE_GETPGID */
9855
9856
9857
#ifdef HAVE_GETPGRP
9858
/*[clinic input]
9859
os.getpgrp
9860
9861
Return the current process group id.
9862
[clinic start generated code]*/
9863
9864
static PyObject *
9865
os_getpgrp_impl(PyObject *module)
9866
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9867
0
{
9868
#ifdef GETPGRP_HAVE_ARG
9869
    return PyLong_FromPid(getpgrp(0));
9870
#else /* GETPGRP_HAVE_ARG */
9871
0
    return PyLong_FromPid(getpgrp());
9872
0
#endif /* GETPGRP_HAVE_ARG */
9873
0
}
9874
#endif /* HAVE_GETPGRP */
9875
9876
9877
#ifdef HAVE_SETPGRP
9878
/*[clinic input]
9879
os.setpgrp
9880
9881
Make the current process the leader of its process group.
9882
[clinic start generated code]*/
9883
9884
static PyObject *
9885
os_setpgrp_impl(PyObject *module)
9886
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9887
0
{
9888
#ifdef SETPGRP_HAVE_ARG
9889
    if (setpgrp(0, 0) < 0)
9890
#else /* SETPGRP_HAVE_ARG */
9891
0
    if (setpgrp() < 0)
9892
0
#endif /* SETPGRP_HAVE_ARG */
9893
0
        return posix_error();
9894
0
    Py_RETURN_NONE;
9895
0
}
9896
#endif /* HAVE_SETPGRP */
9897
9898
#ifdef HAVE_GETPPID
9899
9900
#ifdef MS_WINDOWS
9901
#include <winternl.h>
9902
#include <ProcessSnapshot.h>
9903
9904
// The structure definition in winternl.h may be incomplete.
9905
// This structure is the full version from the MSDN documentation.
9906
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9907
    NTSTATUS ExitStatus;
9908
    PVOID PebBaseAddress;
9909
    ULONG_PTR AffinityMask;
9910
    LONG BasePriority;
9911
    ULONG_PTR UniqueProcessId;
9912
    ULONG_PTR InheritedFromUniqueProcessId;
9913
} PROCESS_BASIC_INFORMATION_FULL;
9914
9915
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9916
    IN    HANDLE           ProcessHandle,
9917
    IN    PROCESSINFOCLASS ProcessInformationClass,
9918
    OUT   PVOID            ProcessInformation,
9919
    IN    ULONG            ProcessInformationLength,
9920
    OUT   PULONG           ReturnLength OPTIONAL);
9921
9922
// This function returns the process ID of the parent process.
9923
// Returns 0 on failure.
9924
static ULONG
9925
win32_getppid_fast(void)
9926
{
9927
    NTSTATUS status;
9928
    HMODULE ntdll;
9929
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9930
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9931
    static ULONG cached_ppid = 0;
9932
9933
    if (cached_ppid) {
9934
        // No need to query the kernel again.
9935
        return cached_ppid;
9936
    }
9937
9938
    ntdll = GetModuleHandleW(L"ntdll.dll");
9939
    if (!ntdll) {
9940
        return 0;
9941
    }
9942
9943
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9944
    if (!pNtQueryInformationProcess) {
9945
        return 0;
9946
    }
9947
9948
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9949
                                        ProcessBasicInformation,
9950
                                        &basic_information,
9951
                                        sizeof(basic_information),
9952
                                        NULL);
9953
9954
    if (!NT_SUCCESS(status)) {
9955
        return 0;
9956
    }
9957
9958
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9959
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9960
    // zero and (ULONG) -1.
9961
9962
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9963
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9964
    {
9965
        return 0;
9966
    }
9967
9968
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9969
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9970
    // process. This process ID will be correctly returned even if the parent process has
9971
    // exited or been terminated.
9972
9973
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9974
    return cached_ppid;
9975
}
9976
9977
static PyObject*
9978
win32_getppid(void)
9979
{
9980
    DWORD error;
9981
    PyObject* result = NULL;
9982
    HANDLE process = GetCurrentProcess();
9983
    HPSS snapshot = NULL;
9984
    ULONG pid;
9985
9986
    pid = win32_getppid_fast();
9987
    if (pid != 0) {
9988
        return PyLong_FromUnsignedLong(pid);
9989
    }
9990
9991
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9992
9993
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9994
    if (error != ERROR_SUCCESS) {
9995
        return PyErr_SetFromWindowsErr(error);
9996
    }
9997
9998
    PSS_PROCESS_INFORMATION info;
9999
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
10000
                             sizeof(info));
10001
    if (error == ERROR_SUCCESS) {
10002
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
10003
    }
10004
    else {
10005
        result = PyErr_SetFromWindowsErr(error);
10006
    }
10007
10008
    PssFreeSnapshot(process, snapshot);
10009
    return result;
10010
}
10011
#endif /*MS_WINDOWS*/
10012
10013
10014
/*[clinic input]
10015
os.getppid
10016
10017
Return the parent's process id.
10018
10019
If the parent process has already exited, Windows machines will still
10020
return its id; others systems will return the id of the 'init' process (1).
10021
[clinic start generated code]*/
10022
10023
static PyObject *
10024
os_getppid_impl(PyObject *module)
10025
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
10026
0
{
10027
#ifdef MS_WINDOWS
10028
    return win32_getppid();
10029
#else
10030
0
    return PyLong_FromPid(getppid());
10031
0
#endif
10032
0
}
10033
#endif /* HAVE_GETPPID */
10034
10035
10036
#ifdef HAVE_GETLOGIN
10037
/*[clinic input]
10038
os.getlogin
10039
10040
Return the actual login name.
10041
[clinic start generated code]*/
10042
10043
static PyObject *
10044
os_getlogin_impl(PyObject *module)
10045
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10046
0
{
10047
0
    PyObject *result = NULL;
10048
#ifdef MS_WINDOWS
10049
    wchar_t user_name[UNLEN + 1];
10050
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10051
10052
    if (GetUserNameW(user_name, &num_chars)) {
10053
        /* num_chars is the number of unicode chars plus null terminator */
10054
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10055
    }
10056
    else
10057
        result = PyErr_SetFromWindowsErr(GetLastError());
10058
#elif defined (HAVE_GETLOGIN_R)
10059
# if defined (HAVE_MAXLOGNAME)
10060
    char name[MAXLOGNAME + 1];
10061
# elif defined (HAVE_UT_NAMESIZE)
10062
    char name[UT_NAMESIZE + 1];
10063
# else
10064
    char name[256];
10065
# endif
10066
0
    int err = getlogin_r(name, sizeof(name));
10067
0
    if (err) {
10068
0
        int old_errno = errno;
10069
0
        errno = err;
10070
0
        posix_error();
10071
0
        errno = old_errno;
10072
0
    }
10073
0
    else {
10074
0
        result = PyUnicode_DecodeFSDefault(name);
10075
0
    }
10076
#else
10077
    char *name;
10078
    int old_errno = errno;
10079
10080
    errno = 0;
10081
    name = getlogin();
10082
    if (name == NULL) {
10083
        if (errno)
10084
            posix_error();
10085
        else
10086
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10087
    }
10088
    else
10089
        result = PyUnicode_DecodeFSDefault(name);
10090
    errno = old_errno;
10091
#endif
10092
0
    return result;
10093
0
}
10094
#endif /* HAVE_GETLOGIN */
10095
10096
10097
#ifdef HAVE_GETUID
10098
/*[clinic input]
10099
os.getuid
10100
10101
Return the current process's user id.
10102
[clinic start generated code]*/
10103
10104
static PyObject *
10105
os_getuid_impl(PyObject *module)
10106
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10107
34
{
10108
34
    return _PyLong_FromUid(getuid());
10109
34
}
10110
#endif /* HAVE_GETUID */
10111
10112
10113
#ifdef MS_WINDOWS
10114
#define HAVE_KILL
10115
#endif /* MS_WINDOWS */
10116
10117
#ifdef HAVE_KILL
10118
/*[clinic input]
10119
os.kill
10120
10121
    pid: pid_t
10122
    signal: Py_ssize_t
10123
    /
10124
10125
Kill a process with a signal.
10126
[clinic start generated code]*/
10127
10128
static PyObject *
10129
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10130
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10131
0
{
10132
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10133
0
        return NULL;
10134
0
    }
10135
0
#ifndef MS_WINDOWS
10136
0
    if (kill(pid, (int)signal) == -1) {
10137
0
        return posix_error();
10138
0
    }
10139
10140
    // Check immediately if the signal was sent to the current process.
10141
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10142
    // is cheap.
10143
0
    if (PyErr_CheckSignals()) {
10144
0
        return NULL;
10145
0
    }
10146
10147
0
    Py_RETURN_NONE;
10148
#else /* !MS_WINDOWS */
10149
    DWORD sig = (DWORD)signal;
10150
10151
#ifdef HAVE_WINDOWS_CONSOLE_IO
10152
    /* Console processes which share a common console can be sent CTRL+C or
10153
       CTRL+BREAK events, provided they handle said events. */
10154
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10155
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10156
            return PyErr_SetFromWindowsErr(0);
10157
        }
10158
        Py_RETURN_NONE;
10159
    }
10160
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10161
10162
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10163
       attempt to open and terminate the process. */
10164
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10165
    if (handle == NULL) {
10166
        return PyErr_SetFromWindowsErr(0);
10167
    }
10168
10169
    BOOL res = TerminateProcess(handle, sig);
10170
    CloseHandle(handle);
10171
    if (res == 0) {
10172
        return PyErr_SetFromWindowsErr(0);
10173
    }
10174
10175
    Py_RETURN_NONE;
10176
#endif /* !MS_WINDOWS */
10177
0
}
10178
#endif /* HAVE_KILL */
10179
10180
10181
#ifdef HAVE_KILLPG
10182
/*[clinic input]
10183
os.killpg
10184
10185
    pgid: pid_t
10186
    signal: int
10187
    /
10188
10189
Kill a process group with a signal.
10190
[clinic start generated code]*/
10191
10192
static PyObject *
10193
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10194
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10195
0
{
10196
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10197
0
        return NULL;
10198
0
    }
10199
    /* XXX some man pages make the `pgid` parameter an int, others
10200
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10201
       take the same type. Moreover, pid_t is always at least as wide as
10202
       int (else compilation of this module fails), which is safe. */
10203
0
    if (killpg(pgid, signal) == -1)
10204
0
        return posix_error();
10205
0
    Py_RETURN_NONE;
10206
0
}
10207
#endif /* HAVE_KILLPG */
10208
10209
10210
#ifdef HAVE_PLOCK
10211
#ifdef HAVE_SYS_LOCK_H
10212
#include <sys/lock.h>
10213
#endif
10214
10215
/*[clinic input]
10216
os.plock
10217
    op: int
10218
    /
10219
10220
Lock program segments into memory.");
10221
[clinic start generated code]*/
10222
10223
static PyObject *
10224
os_plock_impl(PyObject *module, int op)
10225
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10226
{
10227
    if (plock(op) == -1)
10228
        return posix_error();
10229
    Py_RETURN_NONE;
10230
}
10231
#endif /* HAVE_PLOCK */
10232
10233
10234
#ifdef HAVE_SETUID
10235
/*[clinic input]
10236
os.setuid
10237
10238
    uid: uid_t
10239
    /
10240
10241
Set the current process's user id.
10242
[clinic start generated code]*/
10243
10244
static PyObject *
10245
os_setuid_impl(PyObject *module, uid_t uid)
10246
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10247
0
{
10248
0
    if (setuid(uid) < 0)
10249
0
        return posix_error();
10250
0
    Py_RETURN_NONE;
10251
0
}
10252
#endif /* HAVE_SETUID */
10253
10254
10255
#ifdef HAVE_SETEUID
10256
/*[clinic input]
10257
os.seteuid
10258
10259
    euid: uid_t
10260
    /
10261
10262
Set the current process's effective user id.
10263
[clinic start generated code]*/
10264
10265
static PyObject *
10266
os_seteuid_impl(PyObject *module, uid_t euid)
10267
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10268
0
{
10269
0
    if (seteuid(euid) < 0)
10270
0
        return posix_error();
10271
0
    Py_RETURN_NONE;
10272
0
}
10273
#endif /* HAVE_SETEUID */
10274
10275
10276
#ifdef HAVE_SETEGID
10277
/*[clinic input]
10278
os.setegid
10279
10280
    egid: gid_t
10281
    /
10282
10283
Set the current process's effective group id.
10284
[clinic start generated code]*/
10285
10286
static PyObject *
10287
os_setegid_impl(PyObject *module, gid_t egid)
10288
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10289
0
{
10290
0
    if (setegid(egid) < 0)
10291
0
        return posix_error();
10292
0
    Py_RETURN_NONE;
10293
0
}
10294
#endif /* HAVE_SETEGID */
10295
10296
10297
#ifdef HAVE_SETREUID
10298
/*[clinic input]
10299
os.setreuid
10300
10301
    ruid: uid_t
10302
    euid: uid_t
10303
    /
10304
10305
Set the current process's real and effective user ids.
10306
[clinic start generated code]*/
10307
10308
static PyObject *
10309
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10310
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10311
0
{
10312
0
    if (setreuid(ruid, euid) < 0) {
10313
0
        return posix_error();
10314
0
    } else {
10315
0
        Py_RETURN_NONE;
10316
0
    }
10317
0
}
10318
#endif /* HAVE_SETREUID */
10319
10320
10321
#ifdef HAVE_SETREGID
10322
/*[clinic input]
10323
os.setregid
10324
10325
    rgid: gid_t
10326
    egid: gid_t
10327
    /
10328
10329
Set the current process's real and effective group ids.
10330
[clinic start generated code]*/
10331
10332
static PyObject *
10333
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10334
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10335
0
{
10336
0
    if (setregid(rgid, egid) < 0)
10337
0
        return posix_error();
10338
0
    Py_RETURN_NONE;
10339
0
}
10340
#endif /* HAVE_SETREGID */
10341
10342
10343
#ifdef HAVE_SETGID
10344
/*[clinic input]
10345
os.setgid
10346
    gid: gid_t
10347
    /
10348
10349
Set the current process's group id.
10350
[clinic start generated code]*/
10351
10352
static PyObject *
10353
os_setgid_impl(PyObject *module, gid_t gid)
10354
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10355
0
{
10356
0
    if (setgid(gid) < 0)
10357
0
        return posix_error();
10358
0
    Py_RETURN_NONE;
10359
0
}
10360
#endif /* HAVE_SETGID */
10361
10362
10363
#ifdef HAVE_SETGROUPS
10364
/*[clinic input]
10365
os.setgroups
10366
10367
    groups: object
10368
    /
10369
10370
Set the groups of the current process to list.
10371
[clinic start generated code]*/
10372
10373
static PyObject *
10374
os_setgroups(PyObject *module, PyObject *groups)
10375
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10376
0
{
10377
0
    if (!PySequence_Check(groups)) {
10378
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10379
0
        return NULL;
10380
0
    }
10381
0
    Py_ssize_t len = PySequence_Size(groups);
10382
0
    if (len < 0) {
10383
0
        return NULL;
10384
0
    }
10385
0
    if (len > MAX_GROUPS) {
10386
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10387
0
        return NULL;
10388
0
    }
10389
10390
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10391
0
    if (grouplist == NULL) {
10392
0
        PyErr_NoMemory();
10393
0
        return NULL;
10394
0
    }
10395
0
    for (Py_ssize_t i = 0; i < len; i++) {
10396
0
        PyObject *elem;
10397
0
        elem = PySequence_GetItem(groups, i);
10398
0
        if (!elem) {
10399
0
            PyMem_Free(grouplist);
10400
0
            return NULL;
10401
0
        }
10402
0
        if (!PyIndex_Check(elem)) {
10403
0
            PyErr_SetString(PyExc_TypeError,
10404
0
                            "groups must be integers");
10405
0
            Py_DECREF(elem);
10406
0
            PyMem_Free(grouplist);
10407
0
            return NULL;
10408
0
        } else {
10409
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10410
0
                Py_DECREF(elem);
10411
0
                PyMem_Free(grouplist);
10412
0
                return NULL;
10413
0
            }
10414
0
        }
10415
0
        Py_DECREF(elem);
10416
0
    }
10417
10418
0
    if (setgroups(len, grouplist) < 0) {
10419
0
        posix_error();
10420
0
        PyMem_Free(grouplist);
10421
0
        return NULL;
10422
0
    }
10423
0
    PyMem_Free(grouplist);
10424
0
    Py_RETURN_NONE;
10425
0
}
10426
#endif /* HAVE_SETGROUPS */
10427
10428
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10429
static PyObject *
10430
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10431
0
{
10432
0
    PyObject *result;
10433
0
    PyObject *struct_rusage;
10434
10435
0
    if (pid == -1)
10436
0
        return posix_error();
10437
10438
    // If wait succeeded but no child was ready to report status, ru will not
10439
    // have been populated.
10440
0
    if (pid == 0) {
10441
0
        memset(ru, 0, sizeof(*ru));
10442
0
    }
10443
10444
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10445
0
    if (struct_rusage == NULL)
10446
0
        return NULL;
10447
10448
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10449
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10450
0
    Py_DECREF(struct_rusage);
10451
0
    if (!result)
10452
0
        return NULL;
10453
10454
0
    int pos = 0;
10455
10456
0
#ifndef doubletime
10457
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10458
0
#endif
10459
10460
0
#define SET_RESULT(CALL)                                     \
10461
0
    do {                                                     \
10462
0
        PyObject *item = (CALL);                             \
10463
0
        if (item == NULL) {                                  \
10464
0
            Py_DECREF(result);                               \
10465
0
            return NULL;                                     \
10466
0
        }                                                    \
10467
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10468
0
    } while(0)
10469
10470
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10471
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10472
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10473
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10474
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10475
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10476
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10477
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10478
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10479
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10480
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10481
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10482
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10483
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10484
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10485
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10486
0
#undef SET_RESULT
10487
10488
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10489
0
}
10490
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10491
10492
10493
#ifdef HAVE_WAIT3
10494
/*[clinic input]
10495
os.wait3
10496
10497
    options: int
10498
Wait for completion of a child process.
10499
10500
Returns a tuple of information about the child process:
10501
  (pid, status, rusage)
10502
[clinic start generated code]*/
10503
10504
static PyObject *
10505
os_wait3_impl(PyObject *module, int options)
10506
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10507
0
{
10508
0
    pid_t pid;
10509
0
    struct rusage ru;
10510
0
    int async_err = 0;
10511
0
    WAIT_TYPE status;
10512
0
    WAIT_STATUS_INT(status) = 0;
10513
10514
0
    do {
10515
0
        Py_BEGIN_ALLOW_THREADS
10516
0
        pid = wait3(&status, options, &ru);
10517
0
        Py_END_ALLOW_THREADS
10518
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10519
0
    if (pid < 0)
10520
0
        return (!async_err) ? posix_error() : NULL;
10521
10522
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10523
0
}
10524
#endif /* HAVE_WAIT3 */
10525
10526
10527
#ifdef HAVE_WAIT4
10528
/*[clinic input]
10529
10530
os.wait4
10531
10532
    pid: pid_t
10533
    options: int
10534
10535
Wait for completion of a specific child process.
10536
10537
Returns a tuple of information about the child process:
10538
  (pid, status, rusage)
10539
[clinic start generated code]*/
10540
10541
static PyObject *
10542
os_wait4_impl(PyObject *module, pid_t pid, int options)
10543
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10544
0
{
10545
0
    pid_t res;
10546
0
    struct rusage ru;
10547
0
    int async_err = 0;
10548
0
    WAIT_TYPE status;
10549
0
    WAIT_STATUS_INT(status) = 0;
10550
10551
0
    do {
10552
0
        Py_BEGIN_ALLOW_THREADS
10553
0
        res = wait4(pid, &status, options, &ru);
10554
0
        Py_END_ALLOW_THREADS
10555
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10556
0
    if (res < 0)
10557
0
        return (!async_err) ? posix_error() : NULL;
10558
10559
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10560
0
}
10561
#endif /* HAVE_WAIT4 */
10562
10563
10564
#if defined(HAVE_WAITID)
10565
/*[clinic input]
10566
os.waitid
10567
10568
    idtype: idtype_t
10569
        Must be one of be P_PID, P_PGID or P_ALL.
10570
    id: id_t
10571
        The id to wait on.
10572
    options: int
10573
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10574
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10575
    /
10576
10577
Returns the result of waiting for a process or processes.
10578
10579
Returns either waitid_result or None if WNOHANG is specified and there are
10580
no children in a waitable state.
10581
[clinic start generated code]*/
10582
10583
static PyObject *
10584
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10585
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10586
0
{
10587
0
    PyObject *result;
10588
0
    int res;
10589
0
    int async_err = 0;
10590
0
    siginfo_t si;
10591
0
    si.si_pid = 0;
10592
10593
0
    do {
10594
0
        Py_BEGIN_ALLOW_THREADS
10595
0
        res = waitid(idtype, id, &si, options);
10596
0
        Py_END_ALLOW_THREADS
10597
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10598
0
    if (res < 0)
10599
0
        return (!async_err) ? posix_error() : NULL;
10600
10601
0
    if (si.si_pid == 0)
10602
0
        Py_RETURN_NONE;
10603
10604
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10605
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10606
0
    if (!result)
10607
0
        return NULL;
10608
10609
0
    int pos = 0;
10610
10611
0
#define SET_RESULT(CALL)                                     \
10612
0
    do {                                                     \
10613
0
        PyObject *item = (CALL);                             \
10614
0
        if (item == NULL) {                                  \
10615
0
            Py_DECREF(result);                               \
10616
0
            return NULL;                                     \
10617
0
        }                                                    \
10618
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10619
0
    } while(0)
10620
10621
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10622
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10623
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10624
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10625
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10626
10627
0
#undef SET_RESULT
10628
10629
0
    return result;
10630
0
}
10631
#endif /* defined(HAVE_WAITID) */
10632
10633
10634
#if defined(HAVE_WAITPID)
10635
/*[clinic input]
10636
os.waitpid
10637
    pid: pid_t
10638
    options: int
10639
    /
10640
10641
Wait for completion of a given child process.
10642
10643
Returns a tuple of information regarding the child process:
10644
    (pid, status)
10645
10646
The options argument is ignored on Windows.
10647
[clinic start generated code]*/
10648
10649
static PyObject *
10650
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10651
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10652
0
{
10653
0
    pid_t res;
10654
0
    int async_err = 0;
10655
0
    WAIT_TYPE status;
10656
0
    WAIT_STATUS_INT(status) = 0;
10657
10658
0
    do {
10659
0
        Py_BEGIN_ALLOW_THREADS
10660
0
        res = waitpid(pid, &status, options);
10661
0
        Py_END_ALLOW_THREADS
10662
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10663
0
    if (res < 0)
10664
0
        return (!async_err) ? posix_error() : NULL;
10665
10666
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10667
0
}
10668
#elif defined(HAVE_CWAIT)
10669
/* MS C has a variant of waitpid() that's usable for most purposes. */
10670
/*[clinic input]
10671
os.waitpid
10672
    pid: intptr_t
10673
    options: int
10674
    /
10675
10676
Wait for completion of a given process.
10677
10678
Returns a tuple of information regarding the process:
10679
    (pid, status << 8)
10680
10681
The options argument is ignored on Windows.
10682
[clinic start generated code]*/
10683
10684
static PyObject *
10685
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10686
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10687
{
10688
    int status;
10689
    intptr_t res;
10690
    int async_err = 0;
10691
10692
    do {
10693
        Py_BEGIN_ALLOW_THREADS
10694
        _Py_BEGIN_SUPPRESS_IPH
10695
        res = _cwait(&status, pid, options);
10696
        _Py_END_SUPPRESS_IPH
10697
        Py_END_ALLOW_THREADS
10698
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10699
    if (res < 0)
10700
        return (!async_err) ? posix_error() : NULL;
10701
10702
    unsigned long long ustatus = (unsigned int)status;
10703
10704
    /* shift the status left a byte so this is more like the POSIX waitpid */
10705
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10706
}
10707
#endif
10708
10709
10710
#ifdef HAVE_WAIT
10711
/*[clinic input]
10712
os.wait
10713
10714
Wait for completion of a child process.
10715
10716
Returns a tuple of information about the child process:
10717
    (pid, status)
10718
[clinic start generated code]*/
10719
10720
static PyObject *
10721
os_wait_impl(PyObject *module)
10722
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10723
0
{
10724
0
    pid_t pid;
10725
0
    int async_err = 0;
10726
0
    WAIT_TYPE status;
10727
0
    WAIT_STATUS_INT(status) = 0;
10728
10729
0
    do {
10730
0
        Py_BEGIN_ALLOW_THREADS
10731
0
        pid = wait(&status);
10732
0
        Py_END_ALLOW_THREADS
10733
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10734
0
    if (pid < 0)
10735
0
        return (!async_err) ? posix_error() : NULL;
10736
10737
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10738
0
}
10739
#endif /* HAVE_WAIT */
10740
10741
10742
// This system call always crashes on older Android versions.
10743
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10744
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10745
/*[clinic input]
10746
os.pidfd_open
10747
  pid: pid_t
10748
  flags: unsigned_int = 0
10749
10750
Return a file descriptor referring to the process *pid*.
10751
10752
The descriptor can be used to perform process management without races and
10753
signals.
10754
[clinic start generated code]*/
10755
10756
static PyObject *
10757
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10758
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10759
4
{
10760
4
    int fd = syscall(__NR_pidfd_open, pid, flags);
10761
4
    if (fd < 0) {
10762
0
        return posix_error();
10763
0
    }
10764
4
    return PyLong_FromLong(fd);
10765
4
}
10766
#endif
10767
10768
10769
#ifdef HAVE_SETNS
10770
/*[clinic input]
10771
os.setns
10772
  fd: fildes
10773
    A file descriptor to a namespace.
10774
  nstype: int = 0
10775
    Type of namespace.
10776
10777
Move the calling thread into different namespaces.
10778
[clinic start generated code]*/
10779
10780
static PyObject *
10781
os_setns_impl(PyObject *module, int fd, int nstype)
10782
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10783
0
{
10784
0
    int res;
10785
10786
0
    Py_BEGIN_ALLOW_THREADS
10787
0
    res = setns(fd, nstype);
10788
0
    Py_END_ALLOW_THREADS
10789
10790
0
    if (res != 0) {
10791
0
        return posix_error();
10792
0
    }
10793
10794
0
    Py_RETURN_NONE;
10795
0
}
10796
#endif
10797
10798
10799
#ifdef HAVE_UNSHARE
10800
/*[clinic input]
10801
os.unshare
10802
  flags: int
10803
    Namespaces to be unshared.
10804
10805
Disassociate parts of a process (or thread) execution context.
10806
[clinic start generated code]*/
10807
10808
static PyObject *
10809
os_unshare_impl(PyObject *module, int flags)
10810
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10811
0
{
10812
0
    int res;
10813
10814
0
    Py_BEGIN_ALLOW_THREADS
10815
0
    res = unshare(flags);
10816
0
    Py_END_ALLOW_THREADS
10817
10818
0
    if (res != 0) {
10819
0
        return posix_error();
10820
0
    }
10821
10822
0
    Py_RETURN_NONE;
10823
0
}
10824
#endif
10825
10826
10827
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10828
/*[clinic input]
10829
os.readlink
10830
10831
    path: path_t
10832
    *
10833
    dir_fd: dir_fd(requires='readlinkat') = None
10834
10835
Return a string representing the path to which the symbolic link points.
10836
10837
If dir_fd is not None, it should be a file descriptor open to a directory,
10838
and path should be relative; path will then be relative to that directory.
10839
10840
dir_fd may not be implemented on your platform.  If it is unavailable,
10841
using it will raise a NotImplementedError.
10842
[clinic start generated code]*/
10843
10844
static PyObject *
10845
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10846
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10847
4
{
10848
4
#if defined(HAVE_READLINK)
10849
4
    char buffer[MAXPATHLEN+1];
10850
4
    ssize_t length;
10851
4
#ifdef HAVE_READLINKAT
10852
4
    int readlinkat_unavailable = 0;
10853
4
#endif
10854
10855
4
    Py_BEGIN_ALLOW_THREADS
10856
4
#ifdef HAVE_READLINKAT
10857
4
    if (dir_fd != DEFAULT_DIR_FD) {
10858
0
        if (HAVE_READLINKAT_RUNTIME) {
10859
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10860
0
        } else {
10861
0
            readlinkat_unavailable = 1;
10862
0
        }
10863
0
    } else
10864
4
#endif
10865
4
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10866
4
    Py_END_ALLOW_THREADS
10867
10868
4
#ifdef HAVE_READLINKAT
10869
4
    if (readlinkat_unavailable) {
10870
0
        argument_unavailable_error(NULL, "dir_fd");
10871
0
        return NULL;
10872
0
    }
10873
4
#endif
10874
10875
4
    if (length < 0) {
10876
0
        return path_error(path);
10877
0
    }
10878
4
    buffer[length] = '\0';
10879
10880
4
    if (PyUnicode_Check(path->object))
10881
4
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10882
0
    else
10883
0
        return PyBytes_FromStringAndSize(buffer, length);
10884
#elif defined(MS_WINDOWS)
10885
    DWORD n_bytes_returned;
10886
    DWORD io_result = 0;
10887
    HANDLE reparse_point_handle;
10888
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10889
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10890
    PyObject *result = NULL;
10891
10892
    /* First get a handle to the reparse point */
10893
    Py_BEGIN_ALLOW_THREADS
10894
    reparse_point_handle = CreateFileW(
10895
        path->wide,
10896
        0,
10897
        0,
10898
        0,
10899
        OPEN_EXISTING,
10900
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10901
        0);
10902
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10903
        /* New call DeviceIoControl to read the reparse point */
10904
        io_result = DeviceIoControl(
10905
            reparse_point_handle,
10906
            FSCTL_GET_REPARSE_POINT,
10907
            0, 0, /* in buffer */
10908
            target_buffer, sizeof(target_buffer),
10909
            &n_bytes_returned,
10910
            0 /* we're not using OVERLAPPED_IO */
10911
            );
10912
        CloseHandle(reparse_point_handle);
10913
    }
10914
    Py_END_ALLOW_THREADS
10915
10916
    if (io_result == 0) {
10917
        return path_error(path);
10918
    }
10919
10920
    wchar_t *name = NULL;
10921
    Py_ssize_t nameLen = 0;
10922
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10923
    {
10924
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10925
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10926
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10927
    }
10928
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10929
    {
10930
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10931
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10932
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10933
    }
10934
    else
10935
    {
10936
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10937
    }
10938
    if (name) {
10939
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10940
            /* Our buffer is mutable, so this is okay */
10941
            name[1] = L'\\';
10942
        }
10943
        result = PyUnicode_FromWideChar(name, nameLen);
10944
        if (result && PyBytes_Check(path->object)) {
10945
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10946
        }
10947
    }
10948
    return result;
10949
#endif
10950
4
}
10951
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10952
10953
#if defined(MS_WINDOWS)
10954
10955
/* Remove the last portion of the path - return 0 on success */
10956
static int
10957
_dirnameW(WCHAR *path)
10958
{
10959
    WCHAR *ptr;
10960
    size_t length = wcsnlen_s(path, MAX_PATH);
10961
    if (length == MAX_PATH) {
10962
        return -1;
10963
    }
10964
10965
    /* walk the path from the end until a backslash is encountered */
10966
    for(ptr = path + length; ptr != path; ptr--) {
10967
        if (*ptr == L'\\' || *ptr == L'/') {
10968
            break;
10969
        }
10970
    }
10971
    *ptr = 0;
10972
    return 0;
10973
}
10974
10975
#endif
10976
10977
#ifdef HAVE_SYMLINK
10978
10979
#if defined(MS_WINDOWS)
10980
10981
/* Is this path absolute? */
10982
static int
10983
_is_absW(const WCHAR *path)
10984
{
10985
    return path[0] == L'\\' || path[0] == L'/' ||
10986
        (path[0] && path[1] == L':');
10987
}
10988
10989
/* join root and rest with a backslash - return 0 on success */
10990
static int
10991
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10992
{
10993
    if (_is_absW(rest)) {
10994
        return wcscpy_s(dest_path, MAX_PATH, rest);
10995
    }
10996
10997
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
10998
        return -1;
10999
    }
11000
11001
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
11002
        return -1;
11003
    }
11004
11005
    return wcscat_s(dest_path, MAX_PATH, rest);
11006
}
11007
11008
/* Return True if the path at src relative to dest is a directory */
11009
static int
11010
_check_dirW(LPCWSTR src, LPCWSTR dest)
11011
{
11012
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11013
    WCHAR dest_parent[MAX_PATH];
11014
    WCHAR src_resolved[MAX_PATH] = L"";
11015
11016
    /* dest_parent = os.path.dirname(dest) */
11017
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11018
        _dirnameW(dest_parent)) {
11019
        return 0;
11020
    }
11021
    /* src_resolved = os.path.join(dest_parent, src) */
11022
    if (_joinW(src_resolved, dest_parent, src)) {
11023
        return 0;
11024
    }
11025
    return (
11026
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11027
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11028
    );
11029
}
11030
#endif
11031
11032
11033
/*[clinic input]
11034
os.symlink
11035
    src: path_t
11036
    dst: path_t
11037
    target_is_directory: bool = False
11038
    *
11039
    dir_fd: dir_fd(requires='symlinkat')=None
11040
11041
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
11042
11043
Create a symbolic link pointing to src named dst.
11044
11045
target_is_directory is required on Windows if the target is to be
11046
  interpreted as a directory.  (On Windows, symlink requires
11047
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
11048
  target_is_directory is ignored on non-Windows platforms.
11049
11050
If dir_fd is not None, it should be a file descriptor open to a directory,
11051
  and path should be relative; path will then be relative to that directory.
11052
dir_fd may not be implemented on your platform.
11053
  If it is unavailable, using it will raise a NotImplementedError.
11054
11055
[clinic start generated code]*/
11056
11057
static PyObject *
11058
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11059
                int target_is_directory, int dir_fd)
11060
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
11061
0
{
11062
#ifdef MS_WINDOWS
11063
    DWORD result;
11064
    DWORD flags = 0;
11065
11066
    /* Assumed true, set to false if detected to not be available. */
11067
    static int windows_has_symlink_unprivileged_flag = TRUE;
11068
#else
11069
0
    int result;
11070
0
#ifdef HAVE_SYMLINKAT
11071
0
    int symlinkat_unavailable = 0;
11072
0
#endif
11073
0
#endif
11074
11075
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11076
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11077
0
        return NULL;
11078
0
    }
11079
11080
#ifdef MS_WINDOWS
11081
11082
    if (windows_has_symlink_unprivileged_flag) {
11083
        /* Allow non-admin symlinks if system allows it. */
11084
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11085
    }
11086
11087
    Py_BEGIN_ALLOW_THREADS
11088
    _Py_BEGIN_SUPPRESS_IPH
11089
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11090
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11091
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11092
    }
11093
11094
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11095
    _Py_END_SUPPRESS_IPH
11096
    Py_END_ALLOW_THREADS
11097
11098
    if (windows_has_symlink_unprivileged_flag && !result &&
11099
        ERROR_INVALID_PARAMETER == GetLastError()) {
11100
11101
        Py_BEGIN_ALLOW_THREADS
11102
        _Py_BEGIN_SUPPRESS_IPH
11103
        /* This error might be caused by
11104
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11105
        Try again, and update windows_has_symlink_unprivileged_flag if we
11106
        are successful this time.
11107
11108
        NOTE: There is a risk of a race condition here if there are other
11109
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11110
        another process (or thread) changes that condition in between our
11111
        calls to CreateSymbolicLink.
11112
        */
11113
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11114
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11115
        _Py_END_SUPPRESS_IPH
11116
        Py_END_ALLOW_THREADS
11117
11118
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11119
            windows_has_symlink_unprivileged_flag = FALSE;
11120
        }
11121
    }
11122
11123
    if (!result)
11124
        return path_error2(src, dst);
11125
11126
#else
11127
11128
0
    Py_BEGIN_ALLOW_THREADS
11129
0
#ifdef HAVE_SYMLINKAT
11130
0
    if (dir_fd != DEFAULT_DIR_FD) {
11131
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11132
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11133
0
        } else {
11134
0
            symlinkat_unavailable = 1;
11135
0
        }
11136
0
    } else
11137
0
#endif
11138
0
        result = symlink(src->narrow, dst->narrow);
11139
0
    Py_END_ALLOW_THREADS
11140
11141
0
#ifdef HAVE_SYMLINKAT
11142
0
    if (symlinkat_unavailable) {
11143
0
          argument_unavailable_error(NULL, "dir_fd");
11144
0
          return NULL;
11145
0
    }
11146
0
#endif
11147
11148
0
    if (result)
11149
0
        return path_error2(src, dst);
11150
0
#endif
11151
11152
0
    Py_RETURN_NONE;
11153
0
}
11154
#endif /* HAVE_SYMLINK */
11155
11156
11157
static PyStructSequence_Field times_result_fields[] = {
11158
    {"user",    "user time"},
11159
    {"system",   "system time"},
11160
    {"children_user",    "user time of children"},
11161
    {"children_system",    "system time of children"},
11162
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11163
    {NULL}
11164
};
11165
11166
PyDoc_STRVAR(times_result__doc__,
11167
"times_result: Result from os.times().\n\n\
11168
This object may be accessed either as a tuple of\n\
11169
  (user, system, children_user, children_system, elapsed),\n\
11170
or via the attributes user, system, children_user, children_system,\n\
11171
and elapsed.\n\
11172
\n\
11173
See os.times for more information.");
11174
11175
static PyStructSequence_Desc times_result_desc = {
11176
    MODNAME ".times_result", /* name */
11177
    times_result__doc__, /* doc */
11178
    times_result_fields,
11179
    5
11180
};
11181
11182
static PyObject *
11183
build_times_result(PyObject *module, double user, double system,
11184
    double children_user, double children_system,
11185
    double elapsed)
11186
0
{
11187
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11188
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11189
0
    if (value == NULL)
11190
0
        return NULL;
11191
11192
0
#define SET(i, field) \
11193
0
    { \
11194
0
    PyObject *o = PyFloat_FromDouble(field); \
11195
0
    if (!o) { \
11196
0
        Py_DECREF(value); \
11197
0
        return NULL; \
11198
0
    } \
11199
0
    PyStructSequence_SET_ITEM(value, i, o); \
11200
0
    } \
11201
0
11202
0
    SET(0, user);
11203
0
    SET(1, system);
11204
0
    SET(2, children_user);
11205
0
    SET(3, children_system);
11206
0
    SET(4, elapsed);
11207
11208
0
#undef SET
11209
11210
0
    return value;
11211
0
}
11212
11213
11214
/*[clinic input]
11215
os.times
11216
11217
Return a collection containing process timing information.
11218
11219
The object returned behaves like a named tuple with these fields:
11220
  (utime, stime, cutime, cstime, elapsed_time)
11221
All fields are floating-point numbers.
11222
[clinic start generated code]*/
11223
11224
static PyObject *
11225
os_times_impl(PyObject *module)
11226
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11227
0
{
11228
#ifdef MS_WINDOWS
11229
    FILETIME create, exit, kernel, user;
11230
    HANDLE hProc;
11231
    hProc = GetCurrentProcess();
11232
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11233
    /* The fields of a FILETIME structure are the hi and lo part
11234
       of a 64-bit value expressed in 100 nanosecond units.
11235
       1e7 is one second in such units; 1e-7 the inverse.
11236
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11237
    */
11238
    return build_times_result(module,
11239
        (double)(user.dwHighDateTime*429.4967296 +
11240
                 user.dwLowDateTime*1e-7),
11241
        (double)(kernel.dwHighDateTime*429.4967296 +
11242
                 kernel.dwLowDateTime*1e-7),
11243
        (double)0,
11244
        (double)0,
11245
        (double)0);
11246
#else /* MS_WINDOWS */
11247
0
    _posixstate *state = get_posix_state(module);
11248
0
    long ticks_per_second = state->ticks_per_second;
11249
11250
0
    struct tms process;
11251
0
    clock_t elapsed;
11252
0
    errno = 0;
11253
0
    elapsed = times(&process);
11254
0
    if (elapsed == (clock_t) -1) {
11255
0
        return posix_error();
11256
0
    }
11257
11258
0
    return build_times_result(module,
11259
0
        (double)process.tms_utime / ticks_per_second,
11260
0
        (double)process.tms_stime / ticks_per_second,
11261
0
        (double)process.tms_cutime / ticks_per_second,
11262
0
        (double)process.tms_cstime / ticks_per_second,
11263
0
        (double)elapsed / ticks_per_second);
11264
0
#endif /* MS_WINDOWS */
11265
0
}
11266
11267
11268
#if defined(HAVE_TIMERFD_CREATE)
11269
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11270
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11271
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11272
11273
static PyObject *
11274
build_itimerspec(const struct itimerspec* curr_value)
11275
0
{
11276
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11277
0
                                                          curr_value->it_value.tv_nsec);
11278
0
    PyObject *value = PyFloat_FromDouble(_value);
11279
0
    if (value == NULL) {
11280
0
        return NULL;
11281
0
    }
11282
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11283
0
                                                   curr_value->it_interval.tv_nsec);
11284
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11285
0
    if (interval == NULL) {
11286
0
        Py_DECREF(value);
11287
0
        return NULL;
11288
0
    }
11289
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
11290
0
    Py_DECREF(interval);
11291
0
    Py_DECREF(value);
11292
0
    return tuple;
11293
0
}
11294
11295
static PyObject *
11296
build_itimerspec_ns(const struct itimerspec* curr_value)
11297
0
{
11298
0
    PyTime_t value, interval;
11299
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11300
0
        return NULL;
11301
0
    }
11302
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11303
0
        return NULL;
11304
0
    }
11305
0
    return Py_BuildValue("LL", value, interval);
11306
0
}
11307
11308
/*[clinic input]
11309
os.timerfd_create
11310
11311
    clockid: int
11312
        A valid clock ID constant as timer file descriptor.
11313
11314
        time.CLOCK_REALTIME
11315
        time.CLOCK_MONOTONIC
11316
        time.CLOCK_BOOTTIME
11317
    /
11318
    *
11319
    flags: int = 0
11320
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11321
11322
        os.TFD_NONBLOCK
11323
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11324
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11325
11326
        os.TFD_CLOEXEC
11327
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11328
11329
Create and return a timer file descriptor.
11330
[clinic start generated code]*/
11331
11332
static PyObject *
11333
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11334
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11335
11336
0
{
11337
0
    int fd;
11338
0
    Py_BEGIN_ALLOW_THREADS
11339
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11340
0
    fd = timerfd_create(clockid, flags);
11341
0
    Py_END_ALLOW_THREADS
11342
0
    if (fd == -1) {
11343
0
        return PyErr_SetFromErrno(PyExc_OSError);
11344
0
    }
11345
0
    return PyLong_FromLong(fd);
11346
0
}
11347
11348
/*[clinic input]
11349
os.timerfd_settime
11350
11351
    fd: fildes
11352
        A timer file descriptor.
11353
    /
11354
    *
11355
    flags: int = 0
11356
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11357
    initial as initial_double: double = 0.0
11358
        The initial expiration time, in seconds.
11359
    interval as interval_double: double = 0.0
11360
        The timer's interval, in seconds.
11361
11362
Alter a timer file descriptor's internal timer in seconds.
11363
[clinic start generated code]*/
11364
11365
static PyObject *
11366
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11367
                        double initial_double, double interval_double)
11368
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11369
0
{
11370
0
    PyTime_t initial, interval;
11371
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11372
0
                                  &initial) < 0) {
11373
0
        return NULL;
11374
0
    }
11375
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11376
0
                                  &interval) < 0) {
11377
0
        return NULL;
11378
0
    }
11379
11380
0
    struct itimerspec new_value, old_value;
11381
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11382
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11383
0
        return NULL;
11384
0
    }
11385
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11386
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11387
0
        return NULL;
11388
0
    }
11389
11390
0
    int result;
11391
0
    Py_BEGIN_ALLOW_THREADS
11392
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11393
0
    Py_END_ALLOW_THREADS
11394
0
    if (result == -1) {
11395
0
        return PyErr_SetFromErrno(PyExc_OSError);
11396
0
    }
11397
0
    return build_itimerspec(&old_value);
11398
0
}
11399
11400
11401
/*[clinic input]
11402
os.timerfd_settime_ns
11403
11404
    fd: fildes
11405
        A timer file descriptor.
11406
    /
11407
    *
11408
    flags: int = 0
11409
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11410
    initial: long_long = 0
11411
        initial expiration timing in seconds.
11412
    interval: long_long = 0
11413
        interval for the timer in seconds.
11414
11415
Alter a timer file descriptor's internal timer in nanoseconds.
11416
[clinic start generated code]*/
11417
11418
static PyObject *
11419
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11420
                           long long initial, long long interval)
11421
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11422
0
{
11423
0
    struct itimerspec new_value;
11424
0
    struct itimerspec old_value;
11425
0
    int result;
11426
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11427
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11428
0
        return NULL;
11429
0
    }
11430
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11431
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11432
0
        return NULL;
11433
0
    }
11434
0
    Py_BEGIN_ALLOW_THREADS
11435
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11436
0
    Py_END_ALLOW_THREADS
11437
0
    if (result == -1) {
11438
0
        return PyErr_SetFromErrno(PyExc_OSError);
11439
0
    }
11440
0
    return build_itimerspec_ns(&old_value);
11441
0
}
11442
11443
/*[clinic input]
11444
@permit_long_summary
11445
os.timerfd_gettime
11446
11447
    fd: fildes
11448
        A timer file descriptor.
11449
    /
11450
11451
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11452
[clinic start generated code]*/
11453
11454
static PyObject *
11455
os_timerfd_gettime_impl(PyObject *module, int fd)
11456
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11457
0
{
11458
0
    struct itimerspec curr_value;
11459
0
    int result;
11460
0
    Py_BEGIN_ALLOW_THREADS
11461
0
    result = timerfd_gettime(fd, &curr_value);
11462
0
    Py_END_ALLOW_THREADS
11463
0
    if (result == -1) {
11464
0
        return PyErr_SetFromErrno(PyExc_OSError);
11465
0
    }
11466
0
    return build_itimerspec(&curr_value);
11467
0
}
11468
11469
11470
/*[clinic input]
11471
@permit_long_summary
11472
os.timerfd_gettime_ns
11473
11474
    fd: fildes
11475
        A timer file descriptor.
11476
    /
11477
11478
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11479
[clinic start generated code]*/
11480
11481
static PyObject *
11482
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11483
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11484
0
{
11485
0
    struct itimerspec curr_value;
11486
0
    int result;
11487
0
    Py_BEGIN_ALLOW_THREADS
11488
0
    result = timerfd_gettime(fd, &curr_value);
11489
0
    Py_END_ALLOW_THREADS
11490
0
    if (result == -1) {
11491
0
        return PyErr_SetFromErrno(PyExc_OSError);
11492
0
    }
11493
0
    return build_itimerspec_ns(&curr_value);
11494
0
}
11495
11496
#undef ONE_SECOND_IN_NS
11497
#undef EXTRACT_NSEC
11498
11499
#endif  /* HAVE_TIMERFD_CREATE */
11500
11501
#ifdef HAVE_GETSID
11502
/*[clinic input]
11503
os.getsid
11504
11505
    pid: pid_t
11506
    /
11507
11508
Call the system call getsid(pid) and return the result.
11509
[clinic start generated code]*/
11510
11511
static PyObject *
11512
os_getsid_impl(PyObject *module, pid_t pid)
11513
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11514
0
{
11515
0
    int sid;
11516
0
    sid = getsid(pid);
11517
0
    if (sid < 0)
11518
0
        return posix_error();
11519
0
    return PyLong_FromLong((long)sid);
11520
0
}
11521
#endif /* HAVE_GETSID */
11522
11523
11524
#ifdef HAVE_SETSID
11525
/*[clinic input]
11526
os.setsid
11527
11528
Call the system call setsid().
11529
[clinic start generated code]*/
11530
11531
static PyObject *
11532
os_setsid_impl(PyObject *module)
11533
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11534
0
{
11535
0
    if (setsid() < 0)
11536
0
        return posix_error();
11537
0
    Py_RETURN_NONE;
11538
0
}
11539
#endif /* HAVE_SETSID */
11540
11541
11542
#ifdef HAVE_SETPGID
11543
/*[clinic input]
11544
os.setpgid
11545
11546
    pid: pid_t
11547
    pgrp: pid_t
11548
    /
11549
11550
Call the system call setpgid(pid, pgrp).
11551
[clinic start generated code]*/
11552
11553
static PyObject *
11554
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11555
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11556
0
{
11557
0
    if (setpgid(pid, pgrp) < 0)
11558
0
        return posix_error();
11559
0
    Py_RETURN_NONE;
11560
0
}
11561
#endif /* HAVE_SETPGID */
11562
11563
11564
#ifdef HAVE_TCGETPGRP
11565
/*[clinic input]
11566
os.tcgetpgrp
11567
11568
    fd: int
11569
    /
11570
11571
Return the process group associated with the terminal specified by fd.
11572
[clinic start generated code]*/
11573
11574
static PyObject *
11575
os_tcgetpgrp_impl(PyObject *module, int fd)
11576
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11577
0
{
11578
0
    pid_t pgid = tcgetpgrp(fd);
11579
0
    if (pgid < 0)
11580
0
        return posix_error();
11581
0
    return PyLong_FromPid(pgid);
11582
0
}
11583
#endif /* HAVE_TCGETPGRP */
11584
11585
11586
#ifdef HAVE_TCSETPGRP
11587
/*[clinic input]
11588
os.tcsetpgrp
11589
11590
    fd: int
11591
    pgid: pid_t
11592
    /
11593
11594
Set the process group associated with the terminal specified by fd.
11595
[clinic start generated code]*/
11596
11597
static PyObject *
11598
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11599
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11600
0
{
11601
0
    if (tcsetpgrp(fd, pgid) < 0)
11602
0
        return posix_error();
11603
0
    Py_RETURN_NONE;
11604
0
}
11605
#endif /* HAVE_TCSETPGRP */
11606
11607
/* Functions acting on file descriptors */
11608
11609
#ifdef O_CLOEXEC
11610
extern int _Py_open_cloexec_works;
11611
#endif
11612
11613
11614
/*[clinic input]
11615
os.open -> int
11616
    path: path_t
11617
    flags: int
11618
    mode: int = 0o777
11619
    *
11620
    dir_fd: dir_fd(requires='openat') = None
11621
11622
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11623
11624
Open a file for low level IO.  Returns a file descriptor (integer).
11625
11626
If dir_fd is not None, it should be a file descriptor open to a directory,
11627
  and path should be relative; path will then be relative to that directory.
11628
dir_fd may not be implemented on your platform.
11629
  If it is unavailable, using it will raise a NotImplementedError.
11630
[clinic start generated code]*/
11631
11632
static int
11633
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11634
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11635
167k
{
11636
167k
    int fd;
11637
167k
    int async_err = 0;
11638
167k
#ifdef HAVE_OPENAT
11639
167k
    int openat_unavailable = 0;
11640
167k
#endif
11641
11642
167k
#ifdef O_CLOEXEC
11643
167k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11644
#elif !defined(MS_WINDOWS)
11645
    int *atomic_flag_works = NULL;
11646
#endif
11647
11648
#ifdef MS_WINDOWS
11649
    flags |= O_NOINHERIT;
11650
#elif defined(O_CLOEXEC)
11651
167k
    flags |= O_CLOEXEC;
11652
167k
#endif
11653
11654
167k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11655
0
        return -1;
11656
0
    }
11657
11658
167k
    _Py_BEGIN_SUPPRESS_IPH
11659
167k
    do {
11660
167k
        Py_BEGIN_ALLOW_THREADS
11661
#ifdef MS_WINDOWS
11662
        fd = _wopen(path->wide, flags, mode);
11663
#else
11664
167k
#ifdef HAVE_OPENAT
11665
167k
        if (dir_fd != DEFAULT_DIR_FD) {
11666
163k
            if (HAVE_OPENAT_RUNTIME) {
11667
163k
                fd = openat(dir_fd, path->narrow, flags, mode);
11668
11669
163k
            } else {
11670
0
                openat_unavailable = 1;
11671
0
                fd = -1;
11672
0
            }
11673
163k
        } else
11674
4.03k
#endif /* HAVE_OPENAT */
11675
4.03k
            fd = open(path->narrow, flags, mode);
11676
167k
#endif /* !MS_WINDOWS */
11677
167k
        Py_END_ALLOW_THREADS
11678
167k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11679
167k
    _Py_END_SUPPRESS_IPH
11680
11681
167k
#ifdef HAVE_OPENAT
11682
167k
    if (openat_unavailable) {
11683
0
        argument_unavailable_error(NULL, "dir_fd");
11684
0
        return -1;
11685
0
    }
11686
167k
#endif
11687
11688
167k
    if (fd < 0) {
11689
0
        if (!async_err)
11690
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11691
0
        return -1;
11692
0
    }
11693
11694
167k
#ifndef MS_WINDOWS
11695
167k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11696
0
        close(fd);
11697
0
        return -1;
11698
0
    }
11699
167k
#endif
11700
11701
167k
    return fd;
11702
167k
}
11703
11704
11705
/*[clinic input]
11706
os.close
11707
11708
    fd: int
11709
11710
Close a file descriptor.
11711
[clinic start generated code]*/
11712
11713
static PyObject *
11714
os_close_impl(PyObject *module, int fd)
11715
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11716
167k
{
11717
167k
    int res;
11718
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11719
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11720
     * for more details.
11721
     */
11722
167k
    Py_BEGIN_ALLOW_THREADS
11723
167k
    _Py_BEGIN_SUPPRESS_IPH
11724
167k
    res = close(fd);
11725
167k
    _Py_END_SUPPRESS_IPH
11726
167k
    Py_END_ALLOW_THREADS
11727
167k
    if (res < 0)
11728
0
        return posix_error();
11729
167k
    Py_RETURN_NONE;
11730
167k
}
11731
11732
/*[clinic input]
11733
os.closerange
11734
11735
    fd_low: int
11736
    fd_high: int
11737
    /
11738
11739
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11740
[clinic start generated code]*/
11741
11742
static PyObject *
11743
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11744
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11745
0
{
11746
0
    Py_BEGIN_ALLOW_THREADS
11747
0
    _Py_closerange(fd_low, fd_high - 1);
11748
0
    Py_END_ALLOW_THREADS
11749
0
    Py_RETURN_NONE;
11750
0
}
11751
11752
11753
/*[clinic input]
11754
os.dup -> int
11755
11756
    fd: int
11757
    /
11758
11759
Return a duplicate of a file descriptor.
11760
[clinic start generated code]*/
11761
11762
static int
11763
os_dup_impl(PyObject *module, int fd)
11764
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11765
0
{
11766
0
    return _Py_dup(fd);
11767
0
}
11768
11769
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11770
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11771
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11772
/*[clinic input]
11773
os.dup2 -> int
11774
    fd: int
11775
    fd2: int
11776
    inheritable: bool=True
11777
11778
Duplicate file descriptor.
11779
[clinic start generated code]*/
11780
11781
static int
11782
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11783
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11784
0
{
11785
0
    int res = 0;
11786
0
#if defined(HAVE_DUP3) && \
11787
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11788
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11789
0
    static int dup3_works = -1;
11790
0
#endif
11791
11792
    /* dup2() can fail with EINTR if the target FD is already open, because it
11793
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11794
     * upon close(), and therefore below.
11795
     */
11796
#ifdef MS_WINDOWS
11797
    Py_BEGIN_ALLOW_THREADS
11798
    _Py_BEGIN_SUPPRESS_IPH
11799
    res = dup2(fd, fd2);
11800
    _Py_END_SUPPRESS_IPH
11801
    Py_END_ALLOW_THREADS
11802
    if (res < 0) {
11803
        posix_error();
11804
        return -1;
11805
    }
11806
    res = fd2; // msvcrt dup2 returns 0 on success.
11807
11808
    /* Character files like console cannot be make non-inheritable */
11809
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11810
        close(fd2);
11811
        return -1;
11812
    }
11813
11814
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11815
    Py_BEGIN_ALLOW_THREADS
11816
    if (!inheritable)
11817
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11818
    else
11819
        res = dup2(fd, fd2);
11820
    Py_END_ALLOW_THREADS
11821
    if (res < 0) {
11822
        posix_error();
11823
        return -1;
11824
    }
11825
11826
#else
11827
11828
0
#ifdef HAVE_DUP3
11829
0
    if (!inheritable && dup3_works != 0) {
11830
0
        Py_BEGIN_ALLOW_THREADS
11831
0
        res = dup3(fd, fd2, O_CLOEXEC);
11832
0
        Py_END_ALLOW_THREADS
11833
0
        if (res < 0) {
11834
0
            if (dup3_works == -1)
11835
0
                dup3_works = (errno != ENOSYS);
11836
0
            if (dup3_works) {
11837
0
                posix_error();
11838
0
                return -1;
11839
0
            }
11840
0
        }
11841
0
    }
11842
11843
0
    if (inheritable || dup3_works == 0)
11844
0
    {
11845
0
#endif
11846
0
        Py_BEGIN_ALLOW_THREADS
11847
0
        res = dup2(fd, fd2);
11848
0
        Py_END_ALLOW_THREADS
11849
0
        if (res < 0) {
11850
0
            posix_error();
11851
0
            return -1;
11852
0
        }
11853
11854
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11855
0
            close(fd2);
11856
0
            return -1;
11857
0
        }
11858
0
#ifdef HAVE_DUP3
11859
0
    }
11860
0
#endif
11861
11862
0
#endif
11863
11864
0
    return res;
11865
0
}
11866
#endif
11867
11868
11869
#ifdef HAVE_LOCKF
11870
/*[clinic input]
11871
os.lockf
11872
11873
    fd: int
11874
        An open file descriptor.
11875
    command: int
11876
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11877
    length: Py_off_t
11878
        The number of bytes to lock, starting at the current position.
11879
    /
11880
11881
Apply, test or remove a POSIX lock on an open file descriptor.
11882
11883
[clinic start generated code]*/
11884
11885
static PyObject *
11886
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11887
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11888
0
{
11889
0
    int res;
11890
11891
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11892
0
        return NULL;
11893
0
    }
11894
11895
0
    Py_BEGIN_ALLOW_THREADS
11896
0
    res = lockf(fd, command, length);
11897
0
    Py_END_ALLOW_THREADS
11898
11899
0
    if (res < 0)
11900
0
        return posix_error();
11901
11902
0
    Py_RETURN_NONE;
11903
0
}
11904
#endif /* HAVE_LOCKF */
11905
11906
11907
/*[clinic input]
11908
@permit_long_docstring_body
11909
os.lseek -> Py_off_t
11910
11911
    fd: int
11912
        An open file descriptor, as returned by os.open().
11913
    position: Py_off_t
11914
        Position, interpreted relative to 'whence'.
11915
    whence as how: int
11916
        The relative position to seek from. Valid values are:
11917
        - SEEK_SET: seek from the start of the file.
11918
        - SEEK_CUR: seek from the current file position.
11919
        - SEEK_END: seek from the end of the file.
11920
    /
11921
11922
Set the position of a file descriptor.  Return the new position.
11923
11924
The return value is the number of bytes relative to the beginning of the file.
11925
[clinic start generated code]*/
11926
11927
static Py_off_t
11928
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11929
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11930
0
{
11931
0
    Py_off_t result;
11932
11933
0
#ifdef SEEK_SET
11934
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11935
0
    switch (how) {
11936
0
        case 0: how = SEEK_SET; break;
11937
0
        case 1: how = SEEK_CUR; break;
11938
0
        case 2: how = SEEK_END; break;
11939
0
    }
11940
0
#endif /* SEEK_END */
11941
11942
0
    Py_BEGIN_ALLOW_THREADS
11943
0
    _Py_BEGIN_SUPPRESS_IPH
11944
#ifdef MS_WINDOWS
11945
    result = _lseeki64(fd, position, how);
11946
#else
11947
0
    result = lseek(fd, position, how);
11948
0
#endif
11949
0
    _Py_END_SUPPRESS_IPH
11950
0
    Py_END_ALLOW_THREADS
11951
0
    if (result < 0)
11952
0
        posix_error();
11953
11954
0
    return result;
11955
0
}
11956
11957
11958
/*[clinic input]
11959
os.read
11960
    fd: int
11961
    length: Py_ssize_t
11962
    /
11963
11964
Read from a file descriptor.  Returns a bytes object.
11965
[clinic start generated code]*/
11966
11967
static PyObject *
11968
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11969
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11970
0
{
11971
0
    if (length < 0) {
11972
0
        errno = EINVAL;
11973
0
        return posix_error();
11974
0
    }
11975
11976
0
    length = Py_MIN(length, _PY_READ_MAX);
11977
11978
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11979
0
    if (writer == NULL) {
11980
0
        return NULL;
11981
0
    }
11982
11983
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11984
0
    if (n == -1) {
11985
0
        PyBytesWriter_Discard(writer);
11986
0
        return NULL;
11987
0
    }
11988
11989
0
    return PyBytesWriter_FinishWithSize(writer, n);
11990
0
}
11991
11992
/*[clinic input]
11993
@permit_long_docstring_body
11994
os.readinto -> Py_ssize_t
11995
    fd: int
11996
    buffer: Py_buffer(accept={rwbuffer})
11997
    /
11998
11999
Read into a buffer object from a file descriptor.
12000
12001
The buffer should be mutable and bytes-like. On success, returns the number of
12002
bytes read. Less bytes may be read than the size of the buffer. The underlying
12003
system call will be retried when interrupted by a signal, unless the signal
12004
handler raises an exception. Other errors will not be retried and an error will
12005
be raised.
12006
12007
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
12008
(which can be used to check for errors without reading data). Never returns
12009
negative.
12010
[clinic start generated code]*/
12011
12012
static Py_ssize_t
12013
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12014
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
12015
0
{
12016
0
    assert(buffer->len >= 0);
12017
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12018
    /* Ensure negative is never returned without an error. Simplifies calling
12019
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12020
        error. */
12021
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12022
0
    return result;
12023
0
}
12024
12025
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12026
                                || defined(__APPLE__))) \
12027
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12028
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12029
static int
12030
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12031
0
{
12032
0
    Py_ssize_t i, j;
12033
12034
0
    *iov = PyMem_New(struct iovec, cnt);
12035
0
    if (*iov == NULL) {
12036
0
        PyErr_NoMemory();
12037
0
        return -1;
12038
0
    }
12039
12040
0
    *buf = PyMem_New(Py_buffer, cnt);
12041
0
    if (*buf == NULL) {
12042
0
        PyMem_Free(*iov);
12043
0
        PyErr_NoMemory();
12044
0
        return -1;
12045
0
    }
12046
12047
0
    for (i = 0; i < cnt; i++) {
12048
0
        PyObject *item = PySequence_GetItem(seq, i);
12049
0
        if (item == NULL)
12050
0
            goto fail;
12051
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12052
0
            Py_DECREF(item);
12053
0
            goto fail;
12054
0
        }
12055
0
        Py_DECREF(item);
12056
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12057
0
        (*iov)[i].iov_len = (*buf)[i].len;
12058
0
    }
12059
0
    return 0;
12060
12061
0
fail:
12062
0
    PyMem_Free(*iov);
12063
0
    for (j = 0; j < i; j++) {
12064
0
        PyBuffer_Release(&(*buf)[j]);
12065
0
    }
12066
0
    PyMem_Free(*buf);
12067
0
    return -1;
12068
0
}
12069
12070
static void
12071
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12072
0
{
12073
0
    int i;
12074
0
    PyMem_Free(iov);
12075
0
    for (i = 0; i < cnt; i++) {
12076
0
        PyBuffer_Release(&buf[i]);
12077
0
    }
12078
0
    PyMem_Free(buf);
12079
0
}
12080
#endif
12081
12082
12083
#ifdef HAVE_READV
12084
/*[clinic input]
12085
os.readv -> Py_ssize_t
12086
12087
    fd: int
12088
    buffers: object
12089
    /
12090
12091
Read from a file descriptor fd into an iterable of buffers.
12092
12093
The buffers should be mutable buffers accepting bytes.
12094
readv will transfer data into each buffer until it is full
12095
and then move on to the next buffer in the sequence to hold
12096
the rest of the data.
12097
12098
readv returns the total number of bytes read,
12099
which may be less than the total capacity of all the buffers.
12100
[clinic start generated code]*/
12101
12102
static Py_ssize_t
12103
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12104
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12105
0
{
12106
0
    Py_ssize_t cnt, n;
12107
0
    int async_err = 0;
12108
0
    struct iovec *iov;
12109
0
    Py_buffer *buf;
12110
12111
0
    if (!PySequence_Check(buffers)) {
12112
0
        PyErr_SetString(PyExc_TypeError,
12113
0
            "readv() arg 2 must be a sequence");
12114
0
        return -1;
12115
0
    }
12116
12117
0
    cnt = PySequence_Size(buffers);
12118
0
    if (cnt < 0)
12119
0
        return -1;
12120
12121
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12122
0
        return -1;
12123
12124
0
    do {
12125
0
        Py_BEGIN_ALLOW_THREADS
12126
0
        n = readv(fd, iov, cnt);
12127
0
        Py_END_ALLOW_THREADS
12128
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12129
12130
0
    int saved_errno = errno;
12131
0
    iov_cleanup(iov, buf, cnt);
12132
0
    if (n < 0) {
12133
0
        if (!async_err) {
12134
0
            errno = saved_errno;
12135
0
            posix_error();
12136
0
        }
12137
0
        return -1;
12138
0
    }
12139
12140
0
    return n;
12141
0
}
12142
#endif /* HAVE_READV */
12143
12144
12145
#ifdef HAVE_PREAD
12146
/*[clinic input]
12147
@permit_long_summary
12148
os.pread
12149
12150
    fd: int
12151
    length: Py_ssize_t
12152
    offset: Py_off_t
12153
    /
12154
12155
Read a number of bytes from a file descriptor starting at a particular offset.
12156
12157
Read length bytes from file descriptor fd, starting at offset bytes from
12158
the beginning of the file.  The file offset remains unchanged.
12159
[clinic start generated code]*/
12160
12161
static PyObject *
12162
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12163
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12164
0
{
12165
0
    Py_ssize_t n;
12166
0
    int async_err = 0;
12167
12168
0
    if (length < 0) {
12169
0
        errno = EINVAL;
12170
0
        return posix_error();
12171
0
    }
12172
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12173
0
    if (writer == NULL) {
12174
0
        return NULL;
12175
0
    }
12176
12177
0
    do {
12178
0
        Py_BEGIN_ALLOW_THREADS
12179
0
        _Py_BEGIN_SUPPRESS_IPH
12180
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12181
0
        _Py_END_SUPPRESS_IPH
12182
0
        Py_END_ALLOW_THREADS
12183
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12184
12185
0
    if (n < 0) {
12186
0
        if (!async_err) {
12187
0
            posix_error();
12188
0
        }
12189
0
        PyBytesWriter_Discard(writer);
12190
0
        return NULL;
12191
0
    }
12192
0
    return PyBytesWriter_FinishWithSize(writer, n);
12193
0
}
12194
#endif /* HAVE_PREAD */
12195
12196
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12197
/*[clinic input]
12198
@permit_long_docstring_body
12199
os.preadv -> Py_ssize_t
12200
12201
    fd: int
12202
    buffers: object
12203
    offset: Py_off_t
12204
    flags: int = 0
12205
    /
12206
12207
Reads from a file descriptor into a number of mutable bytes-like objects.
12208
12209
Combines the functionality of readv() and pread(). As readv(), it will
12210
transfer data into each buffer until it is full and then move on to the next
12211
buffer in the sequence to hold the rest of the data. Its fourth argument,
12212
specifies the file offset at which the input operation is to be performed. It
12213
will return the total number of bytes read (which can be less than the total
12214
capacity of all the objects).
12215
12216
The flags argument contains a bitwise OR of zero or more of the following flags:
12217
12218
- RWF_HIPRI
12219
- RWF_NOWAIT
12220
- RWF_DONTCACHE
12221
12222
Using non-zero flags requires Linux 4.6 or newer.
12223
[clinic start generated code]*/
12224
12225
static Py_ssize_t
12226
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12227
               int flags)
12228
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
12229
0
{
12230
0
    Py_ssize_t cnt, n;
12231
0
    int async_err = 0;
12232
0
    struct iovec *iov;
12233
0
    Py_buffer *buf;
12234
12235
0
    if (!PySequence_Check(buffers)) {
12236
0
        PyErr_SetString(PyExc_TypeError,
12237
0
            "preadv2() arg 2 must be a sequence");
12238
0
        return -1;
12239
0
    }
12240
12241
0
    cnt = PySequence_Size(buffers);
12242
0
    if (cnt < 0) {
12243
0
        return -1;
12244
0
    }
12245
12246
#ifndef HAVE_PREADV2
12247
    if(flags != 0) {
12248
        argument_unavailable_error("preadv2", "flags");
12249
        return -1;
12250
    }
12251
#endif
12252
12253
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12254
0
        return -1;
12255
0
    }
12256
0
#ifdef HAVE_PREADV2
12257
0
    do {
12258
0
        Py_BEGIN_ALLOW_THREADS
12259
0
        _Py_BEGIN_SUPPRESS_IPH
12260
0
        n = preadv2(fd, iov, cnt, offset, flags);
12261
0
        _Py_END_SUPPRESS_IPH
12262
0
        Py_END_ALLOW_THREADS
12263
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12264
#else
12265
    do {
12266
#if defined(__APPLE__) && defined(__clang__)
12267
/* This entire function will be removed from the module dict when the API
12268
 * is not available.
12269
 */
12270
#pragma clang diagnostic push
12271
#pragma clang diagnostic ignored "-Wunguarded-availability"
12272
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12273
#endif
12274
        Py_BEGIN_ALLOW_THREADS
12275
        _Py_BEGIN_SUPPRESS_IPH
12276
        n = preadv(fd, iov, cnt, offset);
12277
        _Py_END_SUPPRESS_IPH
12278
        Py_END_ALLOW_THREADS
12279
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12280
12281
#if defined(__APPLE__) && defined(__clang__)
12282
#pragma clang diagnostic pop
12283
#endif
12284
12285
#endif
12286
12287
0
    int saved_errno = errno;
12288
0
    iov_cleanup(iov, buf, cnt);
12289
0
    if (n < 0) {
12290
0
        if (!async_err) {
12291
0
            errno = saved_errno;
12292
0
            posix_error();
12293
0
        }
12294
0
        return -1;
12295
0
    }
12296
12297
0
    return n;
12298
0
}
12299
#endif /* HAVE_PREADV */
12300
12301
12302
/*[clinic input]
12303
os.write -> Py_ssize_t
12304
12305
    fd: int
12306
    data: Py_buffer
12307
    /
12308
12309
Write a bytes object to a file descriptor.
12310
[clinic start generated code]*/
12311
12312
static Py_ssize_t
12313
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12314
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12315
1
{
12316
1
    return _Py_write(fd, data->buf, data->len);
12317
1
}
12318
12319
#ifdef HAVE_SENDFILE
12320
#ifdef __APPLE__
12321
/*[clinic input]
12322
os.sendfile
12323
12324
    out_fd: int
12325
    in_fd: int
12326
    offset: Py_off_t
12327
    count as sbytes: Py_off_t
12328
    headers: object(c_default="NULL") = ()
12329
    trailers: object(c_default="NULL") = ()
12330
    flags: int = 0
12331
12332
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12333
[clinic start generated code]*/
12334
12335
static PyObject *
12336
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12337
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12338
                 int flags)
12339
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12340
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12341
/*[clinic input]
12342
os.sendfile
12343
12344
    out_fd: int
12345
    in_fd: int
12346
    offset: Py_off_t
12347
    count: Py_ssize_t(allow_negative=False)
12348
    headers: object(c_default="NULL") = ()
12349
    trailers: object(c_default="NULL") = ()
12350
    flags: int = 0
12351
12352
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12353
[clinic start generated code]*/
12354
12355
static PyObject *
12356
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12357
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12358
                 int flags)
12359
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12360
#else
12361
/*[clinic input]
12362
os.sendfile
12363
12364
    out_fd: int
12365
    in_fd: int
12366
    offset as offobj: object
12367
    count: Py_ssize_t(allow_negative=False)
12368
12369
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12370
[clinic start generated code]*/
12371
12372
static PyObject *
12373
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12374
                 Py_ssize_t count)
12375
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12376
#endif
12377
0
{
12378
0
    Py_ssize_t ret;
12379
0
    int async_err = 0;
12380
12381
#ifdef __APPLE__
12382
    if(sbytes < 0) {
12383
        PyErr_SetString(PyExc_ValueError,
12384
                        "count cannot be negative");
12385
        return NULL;
12386
    }
12387
#else
12388
0
    assert(count >= 0);
12389
0
#endif
12390
12391
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12392
#ifndef __APPLE__
12393
    off_t sbytes;
12394
#endif
12395
    Py_buffer *hbuf, *tbuf;
12396
    struct sf_hdtr sf;
12397
12398
    sf.headers = NULL;
12399
    sf.trailers = NULL;
12400
12401
    if (headers != NULL) {
12402
        if (!PySequence_Check(headers)) {
12403
            PyErr_SetString(PyExc_TypeError,
12404
                "sendfile() headers must be a sequence");
12405
            return NULL;
12406
        } else {
12407
            Py_ssize_t i = PySequence_Size(headers);
12408
            if (i < 0)
12409
                return NULL;
12410
            if (i > INT_MAX) {
12411
                PyErr_SetString(PyExc_OverflowError,
12412
                    "sendfile() header is too large");
12413
                return NULL;
12414
            }
12415
            if (i > 0) {
12416
                sf.hdr_cnt = (int)i;
12417
                if (iov_setup(&(sf.headers), &hbuf,
12418
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12419
                    return NULL;
12420
#ifdef __APPLE__
12421
                for (i = 0; i < sf.hdr_cnt; i++) {
12422
                    Py_ssize_t blen = sf.headers[i].iov_len;
12423
# define OFF_T_MAX 0x7fffffffffffffff
12424
                    if (sbytes >= OFF_T_MAX - blen) {
12425
                        PyErr_SetString(PyExc_OverflowError,
12426
                            "sendfile() header is too large");
12427
                        return NULL;
12428
                    }
12429
                    sbytes += blen;
12430
                }
12431
#endif
12432
            }
12433
        }
12434
    }
12435
    if (trailers != NULL) {
12436
        if (!PySequence_Check(trailers)) {
12437
            PyErr_SetString(PyExc_TypeError,
12438
                "sendfile() trailers must be a sequence");
12439
            return NULL;
12440
        } else {
12441
            Py_ssize_t i = PySequence_Size(trailers);
12442
            if (i < 0)
12443
                return NULL;
12444
            if (i > INT_MAX) {
12445
                PyErr_SetString(PyExc_OverflowError,
12446
                    "sendfile() trailer is too large");
12447
                return NULL;
12448
            }
12449
            if (i > 0) {
12450
                sf.trl_cnt = (int)i;
12451
                if (iov_setup(&(sf.trailers), &tbuf,
12452
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12453
                    return NULL;
12454
            }
12455
        }
12456
    }
12457
12458
    _Py_BEGIN_SUPPRESS_IPH
12459
    do {
12460
        Py_BEGIN_ALLOW_THREADS
12461
#ifdef __APPLE__
12462
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12463
#else
12464
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12465
#endif
12466
        Py_END_ALLOW_THREADS
12467
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12468
    _Py_END_SUPPRESS_IPH
12469
12470
    int saved_errno = errno;
12471
    if (sf.headers != NULL)
12472
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12473
    if (sf.trailers != NULL)
12474
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12475
12476
    if (ret < 0) {
12477
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12478
            if (sbytes != 0) {
12479
                // some data has been sent
12480
                goto done;
12481
            }
12482
            // no data has been sent; upper application is supposed
12483
            // to retry on EAGAIN or EBUSY
12484
        }
12485
        if (!async_err) {
12486
            errno = saved_errno;
12487
            posix_error();
12488
        }
12489
        return NULL;
12490
    }
12491
    goto done;
12492
12493
done:
12494
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12495
        return PyLong_FromLong(sbytes);
12496
    #else
12497
        return PyLong_FromLongLong(sbytes);
12498
    #endif
12499
12500
#else
12501
0
#ifdef __linux__
12502
0
    if (offobj == Py_None) {
12503
0
        do {
12504
0
            Py_BEGIN_ALLOW_THREADS
12505
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12506
0
            Py_END_ALLOW_THREADS
12507
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12508
0
        if (ret < 0)
12509
0
            return (!async_err) ? posix_error() : NULL;
12510
0
        return PyLong_FromSsize_t(ret);
12511
0
    }
12512
0
#endif
12513
0
    off_t offset;
12514
0
    if (!Py_off_t_converter(offobj, &offset))
12515
0
        return NULL;
12516
12517
#if defined(__sun) && defined(__SVR4)
12518
    // On Solaris, sendfile raises EINVAL rather than returning 0
12519
    // when the offset is equal or bigger than the in_fd size.
12520
    struct stat st;
12521
12522
    do {
12523
        Py_BEGIN_ALLOW_THREADS
12524
        ret = fstat(in_fd, &st);
12525
        Py_END_ALLOW_THREADS
12526
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12527
    if (ret < 0)
12528
        return (!async_err) ? posix_error() : NULL;
12529
12530
    if (offset >= st.st_size) {
12531
        return PyLong_FromLong(0);
12532
    }
12533
12534
    // On illumos specifically sendfile() may perform a partial write but
12535
    // return -1/an error (in one confirmed case the destination socket
12536
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12537
    // code to check if the offset parameter was modified by sendfile().
12538
    //
12539
    // We need this variable to track said change.
12540
    off_t original_offset = offset;
12541
#endif
12542
12543
0
    do {
12544
0
        Py_BEGIN_ALLOW_THREADS
12545
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12546
#if defined(__sun) && defined(__SVR4)
12547
        // This handles illumos-specific sendfile() partial write behavior,
12548
        // see a comment above for more details.
12549
        if (ret < 0 && offset != original_offset) {
12550
            ret = offset - original_offset;
12551
        }
12552
#endif
12553
0
        Py_END_ALLOW_THREADS
12554
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12555
0
    if (ret < 0)
12556
0
        return (!async_err) ? posix_error() : NULL;
12557
0
    return PyLong_FromSsize_t(ret);
12558
0
#endif
12559
0
}
12560
#endif /* HAVE_SENDFILE */
12561
12562
12563
#if defined(__APPLE__)
12564
/*[clinic input]
12565
os._fcopyfile
12566
12567
    in_fd: int
12568
    out_fd: int
12569
    flags: int
12570
    /
12571
12572
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12573
[clinic start generated code]*/
12574
12575
static PyObject *
12576
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12577
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12578
{
12579
    int ret;
12580
12581
    Py_BEGIN_ALLOW_THREADS
12582
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12583
    Py_END_ALLOW_THREADS
12584
    if (ret < 0)
12585
        return posix_error();
12586
    Py_RETURN_NONE;
12587
}
12588
#endif
12589
12590
12591
/*[clinic input]
12592
os.fstat
12593
12594
    fd : int
12595
12596
Perform a stat system call on the given file descriptor.
12597
12598
Like stat(), but for an open file descriptor.
12599
Equivalent to os.stat(fd).
12600
[clinic start generated code]*/
12601
12602
static PyObject *
12603
os_fstat_impl(PyObject *module, int fd)
12604
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12605
167k
{
12606
167k
    STRUCT_STAT st;
12607
167k
    int res;
12608
167k
    int async_err = 0;
12609
12610
167k
    do {
12611
167k
        Py_BEGIN_ALLOW_THREADS
12612
167k
        res = FSTAT(fd, &st);
12613
167k
        Py_END_ALLOW_THREADS
12614
167k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12615
167k
    if (res != 0) {
12616
#ifdef MS_WINDOWS
12617
        return PyErr_SetFromWindowsErr(0);
12618
#else
12619
0
        return (!async_err) ? posix_error() : NULL;
12620
0
#endif
12621
0
    }
12622
12623
167k
    return _pystat_fromstructstat(module, &st);
12624
167k
}
12625
12626
12627
/*[clinic input]
12628
os.isatty -> bool
12629
    fd: int
12630
    /
12631
12632
Return True if the fd is connected to a terminal.
12633
12634
Return True if the file descriptor is an open file descriptor
12635
connected to the slave end of a terminal.
12636
[clinic start generated code]*/
12637
12638
static int
12639
os_isatty_impl(PyObject *module, int fd)
12640
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12641
0
{
12642
0
    int return_value;
12643
0
    Py_BEGIN_ALLOW_THREADS
12644
0
    _Py_BEGIN_SUPPRESS_IPH
12645
0
    return_value = isatty(fd);
12646
0
    _Py_END_SUPPRESS_IPH
12647
0
    Py_END_ALLOW_THREADS
12648
0
    return return_value;
12649
0
}
12650
12651
12652
#ifdef HAVE_PIPE
12653
/*[clinic input]
12654
os.pipe
12655
12656
Create a pipe.
12657
12658
Returns a tuple of two file descriptors:
12659
  (read_fd, write_fd)
12660
[clinic start generated code]*/
12661
12662
static PyObject *
12663
os_pipe_impl(PyObject *module)
12664
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12665
0
{
12666
0
    int fds[2];
12667
#ifdef MS_WINDOWS
12668
    HANDLE read, write;
12669
    SECURITY_ATTRIBUTES attr;
12670
    BOOL ok;
12671
#else
12672
0
    int res;
12673
0
#endif
12674
12675
#ifdef MS_WINDOWS
12676
    attr.nLength = sizeof(attr);
12677
    attr.lpSecurityDescriptor = NULL;
12678
    attr.bInheritHandle = FALSE;
12679
12680
    Py_BEGIN_ALLOW_THREADS
12681
    ok = CreatePipe(&read, &write, &attr, 0);
12682
    if (ok) {
12683
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12684
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12685
        if (fds[0] == -1 || fds[1] == -1) {
12686
            CloseHandle(read);
12687
            CloseHandle(write);
12688
            ok = 0;
12689
        }
12690
    }
12691
    Py_END_ALLOW_THREADS
12692
12693
    if (!ok)
12694
        return PyErr_SetFromWindowsErr(0);
12695
#else
12696
12697
0
#ifdef HAVE_PIPE2
12698
0
    Py_BEGIN_ALLOW_THREADS
12699
0
    res = pipe2(fds, O_CLOEXEC);
12700
0
    Py_END_ALLOW_THREADS
12701
12702
0
    if (res != 0 && errno == ENOSYS)
12703
0
    {
12704
0
#endif
12705
0
        Py_BEGIN_ALLOW_THREADS
12706
0
        res = pipe(fds);
12707
0
        Py_END_ALLOW_THREADS
12708
12709
0
        if (res == 0) {
12710
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12711
0
                close(fds[0]);
12712
0
                close(fds[1]);
12713
0
                return NULL;
12714
0
            }
12715
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12716
0
                close(fds[0]);
12717
0
                close(fds[1]);
12718
0
                return NULL;
12719
0
            }
12720
0
        }
12721
0
#ifdef HAVE_PIPE2
12722
0
    }
12723
0
#endif
12724
12725
0
    if (res != 0)
12726
0
        return PyErr_SetFromErrno(PyExc_OSError);
12727
0
#endif /* !MS_WINDOWS */
12728
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12729
0
}
12730
#endif  /* HAVE_PIPE */
12731
12732
12733
#ifdef HAVE_PIPE2
12734
/*[clinic input]
12735
os.pipe2
12736
12737
    flags: int
12738
    /
12739
12740
Create a pipe with flags set atomically.
12741
12742
Returns a tuple of two file descriptors:
12743
  (read_fd, write_fd)
12744
12745
flags can be constructed by ORing together one or more of these values:
12746
O_NONBLOCK, O_CLOEXEC.
12747
[clinic start generated code]*/
12748
12749
static PyObject *
12750
os_pipe2_impl(PyObject *module, int flags)
12751
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12752
0
{
12753
0
    int fds[2];
12754
0
    int res;
12755
12756
0
    res = pipe2(fds, flags);
12757
0
    if (res != 0)
12758
0
        return posix_error();
12759
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12760
0
}
12761
#endif /* HAVE_PIPE2 */
12762
12763
12764
#ifdef HAVE_WRITEV
12765
/*[clinic input]
12766
os.writev -> Py_ssize_t
12767
    fd: int
12768
    buffers: object
12769
    /
12770
12771
Iterate over buffers, and write the contents of each to a file descriptor.
12772
12773
Returns the total number of bytes written.
12774
buffers must be a sequence of bytes-like objects.
12775
[clinic start generated code]*/
12776
12777
static Py_ssize_t
12778
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12779
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12780
0
{
12781
0
    Py_ssize_t cnt;
12782
0
    Py_ssize_t result;
12783
0
    int async_err = 0;
12784
0
    struct iovec *iov;
12785
0
    Py_buffer *buf;
12786
12787
0
    if (!PySequence_Check(buffers)) {
12788
0
        PyErr_SetString(PyExc_TypeError,
12789
0
            "writev() arg 2 must be a sequence");
12790
0
        return -1;
12791
0
    }
12792
0
    cnt = PySequence_Size(buffers);
12793
0
    if (cnt < 0)
12794
0
        return -1;
12795
12796
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12797
0
        return -1;
12798
0
    }
12799
12800
0
    do {
12801
0
        Py_BEGIN_ALLOW_THREADS
12802
0
        result = writev(fd, iov, cnt);
12803
0
        Py_END_ALLOW_THREADS
12804
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12805
12806
0
    if (result < 0 && !async_err)
12807
0
        posix_error();
12808
12809
0
    iov_cleanup(iov, buf, cnt);
12810
0
    return result;
12811
0
}
12812
#endif /* HAVE_WRITEV */
12813
12814
12815
#ifdef HAVE_PWRITE
12816
/*[clinic input]
12817
os.pwrite -> Py_ssize_t
12818
12819
    fd: int
12820
    buffer: Py_buffer
12821
    offset: Py_off_t
12822
    /
12823
12824
Write bytes to a file descriptor starting at a particular offset.
12825
12826
Write buffer to fd, starting at offset bytes from the beginning of
12827
the file.  Returns the number of bytes written.  Does not change the
12828
current file offset.
12829
[clinic start generated code]*/
12830
12831
static Py_ssize_t
12832
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12833
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12834
0
{
12835
0
    Py_ssize_t size;
12836
0
    int async_err = 0;
12837
12838
0
    do {
12839
0
        Py_BEGIN_ALLOW_THREADS
12840
0
        _Py_BEGIN_SUPPRESS_IPH
12841
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12842
0
        _Py_END_SUPPRESS_IPH
12843
0
        Py_END_ALLOW_THREADS
12844
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12845
12846
0
    if (size < 0 && !async_err)
12847
0
        posix_error();
12848
0
    return size;
12849
0
}
12850
#endif /* HAVE_PWRITE */
12851
12852
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12853
/*[clinic input]
12854
@permit_long_summary
12855
@permit_long_docstring_body
12856
os.pwritev -> Py_ssize_t
12857
12858
    fd: int
12859
    buffers: object
12860
    offset: Py_off_t
12861
    flags: int = 0
12862
    /
12863
12864
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12865
12866
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12867
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12868
buffer is written before proceeding to second, and so on. The operating system may
12869
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12870
This function writes the contents of each object to the file descriptor and returns
12871
the total number of bytes written.
12872
12873
The flags argument contains a bitwise OR of zero or more of the following flags:
12874
12875
- RWF_DSYNC
12876
- RWF_SYNC
12877
- RWF_APPEND
12878
- RWF_DONTCACHE
12879
- RWF_ATOMIC
12880
12881
Using non-zero flags requires Linux 4.7 or newer.
12882
[clinic start generated code]*/
12883
12884
static Py_ssize_t
12885
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12886
                int flags)
12887
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=7de72245873f56bf]*/
12888
0
{
12889
0
    Py_ssize_t cnt;
12890
0
    Py_ssize_t result;
12891
0
    int async_err = 0;
12892
0
    struct iovec *iov;
12893
0
    Py_buffer *buf;
12894
12895
0
    if (!PySequence_Check(buffers)) {
12896
0
        PyErr_SetString(PyExc_TypeError,
12897
0
            "pwritev() arg 2 must be a sequence");
12898
0
        return -1;
12899
0
    }
12900
12901
0
    cnt = PySequence_Size(buffers);
12902
0
    if (cnt < 0) {
12903
0
        return -1;
12904
0
    }
12905
12906
#ifndef HAVE_PWRITEV2
12907
    if(flags != 0) {
12908
        argument_unavailable_error("pwritev2", "flags");
12909
        return -1;
12910
    }
12911
#endif
12912
12913
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12914
0
        return -1;
12915
0
    }
12916
0
#ifdef HAVE_PWRITEV2
12917
0
    do {
12918
0
        Py_BEGIN_ALLOW_THREADS
12919
0
        _Py_BEGIN_SUPPRESS_IPH
12920
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12921
0
        _Py_END_SUPPRESS_IPH
12922
0
        Py_END_ALLOW_THREADS
12923
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12924
#else
12925
12926
#if defined(__APPLE__) && defined(__clang__)
12927
/* This entire function will be removed from the module dict when the API
12928
 * is not available.
12929
 */
12930
#pragma clang diagnostic push
12931
#pragma clang diagnostic ignored "-Wunguarded-availability"
12932
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12933
#endif
12934
    do {
12935
        Py_BEGIN_ALLOW_THREADS
12936
        _Py_BEGIN_SUPPRESS_IPH
12937
        result = pwritev(fd, iov, cnt, offset);
12938
        _Py_END_SUPPRESS_IPH
12939
        Py_END_ALLOW_THREADS
12940
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12941
12942
#if defined(__APPLE__) && defined(__clang__)
12943
#pragma clang diagnostic pop
12944
#endif
12945
12946
#endif
12947
12948
0
    if (result < 0) {
12949
0
        if (!async_err) {
12950
0
            posix_error();
12951
0
        }
12952
0
        result = -1;
12953
0
    }
12954
0
    iov_cleanup(iov, buf, cnt);
12955
12956
0
    return result;
12957
0
}
12958
#endif /* HAVE_PWRITEV */
12959
12960
#ifdef HAVE_COPY_FILE_RANGE
12961
/*[clinic input]
12962
12963
os.copy_file_range
12964
    src: int
12965
        Source file descriptor.
12966
    dst: int
12967
        Destination file descriptor.
12968
    count: Py_ssize_t(allow_negative=False)
12969
        Number of bytes to copy.
12970
    offset_src: object = None
12971
        Starting offset in src.
12972
    offset_dst: object = None
12973
        Starting offset in dst.
12974
12975
Copy count bytes from one file descriptor to another.
12976
12977
If offset_src is None, then src is read from the current position;
12978
respectively for offset_dst.
12979
[clinic start generated code]*/
12980
12981
static PyObject *
12982
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12983
                        PyObject *offset_src, PyObject *offset_dst)
12984
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12985
0
{
12986
0
    off_t offset_src_val, offset_dst_val;
12987
0
    off_t *p_offset_src = NULL;
12988
0
    off_t *p_offset_dst = NULL;
12989
0
    Py_ssize_t ret;
12990
0
    int async_err = 0;
12991
    /* The flags argument is provided to allow
12992
     * for future extensions and currently must be to 0. */
12993
0
    int flags = 0;
12994
12995
12996
0
    if (offset_src != Py_None) {
12997
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12998
0
            return NULL;
12999
0
        }
13000
0
        p_offset_src = &offset_src_val;
13001
0
    }
13002
13003
0
    if (offset_dst != Py_None) {
13004
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13005
0
            return NULL;
13006
0
        }
13007
0
        p_offset_dst = &offset_dst_val;
13008
0
    }
13009
13010
0
    do {
13011
0
        Py_BEGIN_ALLOW_THREADS
13012
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13013
0
        Py_END_ALLOW_THREADS
13014
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13015
13016
0
    if (ret < 0) {
13017
0
        return (!async_err) ? posix_error() : NULL;
13018
0
    }
13019
13020
0
    return PyLong_FromSsize_t(ret);
13021
0
}
13022
#endif /* HAVE_COPY_FILE_RANGE*/
13023
13024
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13025
/*[clinic input]
13026
13027
os.splice
13028
    src: int
13029
        Source file descriptor.
13030
    dst: int
13031
        Destination file descriptor.
13032
    count: Py_ssize_t(allow_negative=False)
13033
        Number of bytes to copy.
13034
    offset_src: object = None
13035
        Starting offset in src.
13036
    offset_dst: object = None
13037
        Starting offset in dst.
13038
    flags: unsigned_int = 0
13039
        Flags to modify the semantics of the call.
13040
13041
Transfer count bytes from one pipe to a descriptor or vice versa.
13042
13043
If offset_src is None, then src is read from the current position;
13044
respectively for offset_dst. The offset associated to the file
13045
descriptor that refers to a pipe must be None.
13046
[clinic start generated code]*/
13047
13048
static PyObject *
13049
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13050
               PyObject *offset_src, PyObject *offset_dst,
13051
               unsigned int flags)
13052
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13053
0
{
13054
0
    off_t offset_src_val, offset_dst_val;
13055
0
    off_t *p_offset_src = NULL;
13056
0
    off_t *p_offset_dst = NULL;
13057
0
    Py_ssize_t ret;
13058
0
    int async_err = 0;
13059
13060
13061
0
    if (offset_src != Py_None) {
13062
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13063
0
            return NULL;
13064
0
        }
13065
0
        p_offset_src = &offset_src_val;
13066
0
    }
13067
13068
0
    if (offset_dst != Py_None) {
13069
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13070
0
            return NULL;
13071
0
        }
13072
0
        p_offset_dst = &offset_dst_val;
13073
0
    }
13074
13075
0
    do {
13076
0
        Py_BEGIN_ALLOW_THREADS
13077
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13078
0
        Py_END_ALLOW_THREADS
13079
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13080
13081
0
    if (ret < 0) {
13082
0
        return (!async_err) ? posix_error() : NULL;
13083
0
    }
13084
13085
0
    return PyLong_FromSsize_t(ret);
13086
0
}
13087
#endif /* HAVE_SPLICE*/
13088
13089
#ifdef HAVE_MKFIFO
13090
/*[clinic input]
13091
os.mkfifo
13092
13093
    path: path_t
13094
    mode: int=0o666
13095
    *
13096
    dir_fd: dir_fd(requires='mkfifoat')=None
13097
13098
Create a "fifo" (a POSIX named pipe).
13099
13100
If dir_fd is not None, it should be a file descriptor open to a directory,
13101
  and path should be relative; path will then be relative to that directory.
13102
dir_fd may not be implemented on your platform.
13103
  If it is unavailable, using it will raise a NotImplementedError.
13104
[clinic start generated code]*/
13105
13106
static PyObject *
13107
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13108
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
13109
0
{
13110
0
    int result;
13111
0
    int async_err = 0;
13112
0
#ifdef HAVE_MKFIFOAT
13113
0
    int mkfifoat_unavailable = 0;
13114
0
#endif
13115
13116
0
    do {
13117
0
        Py_BEGIN_ALLOW_THREADS
13118
0
#ifdef HAVE_MKFIFOAT
13119
0
        if (dir_fd != DEFAULT_DIR_FD) {
13120
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13121
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13122
13123
0
            } else {
13124
0
                mkfifoat_unavailable = 1;
13125
0
                result = 0;
13126
0
            }
13127
0
        } else
13128
0
#endif
13129
0
            result = mkfifo(path->narrow, mode);
13130
0
        Py_END_ALLOW_THREADS
13131
0
    } while (result != 0 && errno == EINTR &&
13132
0
             !(async_err = PyErr_CheckSignals()));
13133
13134
0
#ifdef HAVE_MKFIFOAT
13135
0
    if (mkfifoat_unavailable) {
13136
0
        argument_unavailable_error(NULL, "dir_fd");
13137
0
        return NULL;
13138
0
    }
13139
0
#endif
13140
13141
0
    if (result != 0)
13142
0
        return (!async_err) ? posix_error() : NULL;
13143
13144
0
    Py_RETURN_NONE;
13145
0
}
13146
#endif /* HAVE_MKFIFO */
13147
13148
13149
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13150
/*[clinic input]
13151
@permit_long_docstring_body
13152
os.mknod
13153
13154
    path: path_t
13155
    mode: int=0o600
13156
    device: dev_t=0
13157
    *
13158
    dir_fd: dir_fd(requires='mknodat')=None
13159
13160
Create a node in the file system.
13161
13162
Create a node in the file system (file, device special file or named pipe)
13163
at path.  mode specifies both the permissions to use and the
13164
type of node to be created, being combined (bitwise OR) with one of
13165
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
13166
device defines the newly created device special file (probably using
13167
os.makedev()).  Otherwise device is ignored.
13168
13169
If dir_fd is not None, it should be a file descriptor open to a directory,
13170
  and path should be relative; path will then be relative to that directory.
13171
dir_fd may not be implemented on your platform.
13172
  If it is unavailable, using it will raise a NotImplementedError.
13173
[clinic start generated code]*/
13174
13175
static PyObject *
13176
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13177
              int dir_fd)
13178
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
13179
0
{
13180
0
    int result;
13181
0
    int async_err = 0;
13182
0
#ifdef HAVE_MKNODAT
13183
0
    int mknodat_unavailable = 0;
13184
0
#endif
13185
13186
0
    do {
13187
0
        Py_BEGIN_ALLOW_THREADS
13188
0
#ifdef HAVE_MKNODAT
13189
0
        if (dir_fd != DEFAULT_DIR_FD) {
13190
0
            if (HAVE_MKNODAT_RUNTIME) {
13191
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13192
13193
0
            } else {
13194
0
                mknodat_unavailable = 1;
13195
0
                result = 0;
13196
0
            }
13197
0
        } else
13198
0
#endif
13199
0
            result = mknod(path->narrow, mode, device);
13200
0
        Py_END_ALLOW_THREADS
13201
0
    } while (result != 0 && errno == EINTR &&
13202
0
             !(async_err = PyErr_CheckSignals()));
13203
0
#ifdef HAVE_MKNODAT
13204
0
    if (mknodat_unavailable) {
13205
0
        argument_unavailable_error(NULL, "dir_fd");
13206
0
        return NULL;
13207
0
    }
13208
0
#endif
13209
0
    if (result != 0)
13210
0
        return (!async_err) ? posix_error() : NULL;
13211
13212
0
    Py_RETURN_NONE;
13213
0
}
13214
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13215
13216
13217
#ifdef HAVE_DEVICE_MACROS
13218
static PyObject *
13219
major_minor_conv(unsigned int value)
13220
0
{
13221
0
#ifdef NODEV
13222
0
    if (value == (unsigned int)NODEV) {
13223
0
        return PyLong_FromLong((int)NODEV);
13224
0
    }
13225
0
#endif
13226
0
    return PyLong_FromUnsignedLong(value);
13227
0
}
13228
13229
static int
13230
major_minor_check(dev_t value)
13231
0
{
13232
0
#ifdef NODEV
13233
0
    if (value == NODEV) {
13234
0
        return 1;
13235
0
    }
13236
0
#endif
13237
0
    return (dev_t)(unsigned int)value == value;
13238
0
}
13239
13240
/*[clinic input]
13241
os.major
13242
13243
    device: dev_t
13244
    /
13245
13246
Extracts a device major number from a raw device number.
13247
[clinic start generated code]*/
13248
13249
static PyObject *
13250
os_major_impl(PyObject *module, dev_t device)
13251
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13252
0
{
13253
0
    return major_minor_conv(major(device));
13254
0
}
13255
13256
13257
/*[clinic input]
13258
os.minor
13259
13260
    device: dev_t
13261
    /
13262
13263
Extracts a device minor number from a raw device number.
13264
[clinic start generated code]*/
13265
13266
static PyObject *
13267
os_minor_impl(PyObject *module, dev_t device)
13268
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13269
0
{
13270
0
    return major_minor_conv(minor(device));
13271
0
}
13272
13273
13274
/*[clinic input]
13275
os.makedev -> dev_t
13276
13277
    major: dev_t
13278
    minor: dev_t
13279
    /
13280
13281
Composes a raw device number from the major and minor device numbers.
13282
[clinic start generated code]*/
13283
13284
static dev_t
13285
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13286
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13287
0
{
13288
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13289
0
        PyErr_SetString(PyExc_OverflowError,
13290
0
                        "Python int too large to convert to C unsigned int");
13291
0
        return (dev_t)-1;
13292
0
    }
13293
0
    return makedev(major, minor);
13294
0
}
13295
#endif /* HAVE_DEVICE_MACROS */
13296
13297
13298
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13299
/*[clinic input]
13300
os.ftruncate
13301
13302
    fd: int
13303
    length: Py_off_t
13304
    /
13305
13306
Truncate a file, specified by file descriptor, to a specific length.
13307
[clinic start generated code]*/
13308
13309
static PyObject *
13310
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13311
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13312
0
{
13313
0
    int result;
13314
0
    int async_err = 0;
13315
13316
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13317
0
        return NULL;
13318
0
    }
13319
13320
0
    do {
13321
0
        Py_BEGIN_ALLOW_THREADS
13322
0
        _Py_BEGIN_SUPPRESS_IPH
13323
#ifdef MS_WINDOWS
13324
        result = _chsize_s(fd, length);
13325
#else
13326
0
        result = ftruncate(fd, length);
13327
0
#endif
13328
0
        _Py_END_SUPPRESS_IPH
13329
0
        Py_END_ALLOW_THREADS
13330
0
    } while (result != 0 && errno == EINTR &&
13331
0
             !(async_err = PyErr_CheckSignals()));
13332
0
    if (result != 0)
13333
0
        return (!async_err) ? posix_error() : NULL;
13334
0
    Py_RETURN_NONE;
13335
0
}
13336
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13337
13338
13339
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13340
/*[clinic input]
13341
os.truncate
13342
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13343
    length: Py_off_t
13344
13345
Truncate a file, specified by path, to a specific length.
13346
13347
On some platforms, path may also be specified as an open file descriptor.
13348
  If this functionality is unavailable, using it raises an exception.
13349
[clinic start generated code]*/
13350
13351
static PyObject *
13352
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13353
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
13354
0
{
13355
0
    int result;
13356
#ifdef MS_WINDOWS
13357
    int fd;
13358
#endif
13359
13360
0
    if (path->is_fd)
13361
0
        return os_ftruncate_impl(module, path->fd, length);
13362
13363
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13364
0
        return NULL;
13365
0
    }
13366
13367
0
    Py_BEGIN_ALLOW_THREADS
13368
0
    _Py_BEGIN_SUPPRESS_IPH
13369
#ifdef MS_WINDOWS
13370
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13371
    if (fd < 0)
13372
        result = -1;
13373
    else {
13374
        result = _chsize_s(fd, length);
13375
        close(fd);
13376
        if (result < 0)
13377
            errno = result;
13378
    }
13379
#else
13380
0
    result = truncate(path->narrow, length);
13381
0
#endif
13382
0
    _Py_END_SUPPRESS_IPH
13383
0
    Py_END_ALLOW_THREADS
13384
0
    if (result < 0)
13385
0
        return posix_path_error(path);
13386
13387
0
    Py_RETURN_NONE;
13388
0
}
13389
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13390
13391
13392
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13393
   OSs, support was dropped in WASI preview2. */
13394
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13395
/*[clinic input]
13396
os.posix_fallocate
13397
13398
    fd: int
13399
    offset: Py_off_t
13400
    length: Py_off_t
13401
    /
13402
13403
Ensure a file has allocated at least a particular number of bytes on disk.
13404
13405
Ensure that the file specified by fd encompasses a range of bytes
13406
starting at offset bytes from the beginning and continuing for length bytes.
13407
[clinic start generated code]*/
13408
13409
static PyObject *
13410
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13411
                        Py_off_t length)
13412
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
13413
0
{
13414
0
    int result;
13415
0
    int async_err = 0;
13416
13417
0
    do {
13418
0
        Py_BEGIN_ALLOW_THREADS
13419
0
        result = posix_fallocate(fd, offset, length);
13420
0
        Py_END_ALLOW_THREADS
13421
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13422
13423
0
    if (result == 0)
13424
0
        Py_RETURN_NONE;
13425
13426
0
    if (async_err)
13427
0
        return NULL;
13428
13429
0
    errno = result;
13430
0
    return posix_error();
13431
0
}
13432
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13433
13434
13435
#if defined(HAVE_POSIX_FADVISE)
13436
/*[clinic input]
13437
os.posix_fadvise
13438
13439
    fd: int
13440
    offset: Py_off_t
13441
    length: Py_off_t
13442
    advice: int
13443
    /
13444
13445
Announce an intention to access data in a specific pattern.
13446
13447
Announce an intention to access data in a specific pattern, thus allowing
13448
the kernel to make optimizations.
13449
The advice applies to the region of the file specified by fd starting at
13450
offset and continuing for length bytes.
13451
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13452
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13453
POSIX_FADV_DONTNEED.
13454
[clinic start generated code]*/
13455
13456
static PyObject *
13457
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13458
                      Py_off_t length, int advice)
13459
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13460
0
{
13461
0
    int result;
13462
0
    int async_err = 0;
13463
13464
0
    do {
13465
0
        Py_BEGIN_ALLOW_THREADS
13466
0
        result = posix_fadvise(fd, offset, length, advice);
13467
0
        Py_END_ALLOW_THREADS
13468
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13469
13470
0
    if (result == 0)
13471
0
        Py_RETURN_NONE;
13472
13473
0
    if (async_err)
13474
0
        return NULL;
13475
13476
0
    errno = result;
13477
0
    return posix_error();
13478
0
}
13479
#endif /* HAVE_POSIX_FADVISE */
13480
13481
13482
#ifdef MS_WINDOWS
13483
static PyObject*
13484
win32_putenv(PyObject *name, PyObject *value)
13485
{
13486
    /* Search from index 1 because on Windows starting '=' is allowed for
13487
       defining hidden environment variables. */
13488
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13489
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13490
    {
13491
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13492
        return NULL;
13493
    }
13494
    PyObject *unicode;
13495
    if (value != NULL) {
13496
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13497
    }
13498
    else {
13499
        unicode = PyUnicode_FromFormat("%U=", name);
13500
    }
13501
    if (unicode == NULL) {
13502
        return NULL;
13503
    }
13504
13505
    Py_ssize_t size;
13506
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13507
    Py_DECREF(unicode);
13508
13509
    if (env == NULL) {
13510
        return NULL;
13511
    }
13512
    if (size > _MAX_ENV) {
13513
        PyErr_Format(PyExc_ValueError,
13514
                     "the environment variable is longer than %u characters",
13515
                     _MAX_ENV);
13516
        PyMem_Free(env);
13517
        return NULL;
13518
    }
13519
    if (wcslen(env) != (size_t)size) {
13520
        PyErr_SetString(PyExc_ValueError,
13521
                        "embedded null character");
13522
        PyMem_Free(env);
13523
        return NULL;
13524
    }
13525
13526
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13527
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13528
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13529
13530
       Prefer _wputenv() to be compatible with C libraries using CRT
13531
       variables and CRT functions using these variables (ex: getenv()). */
13532
    int err = _wputenv(env);
13533
13534
    if (err) {
13535
        posix_error();
13536
        PyMem_Free(env);
13537
        return NULL;
13538
    }
13539
    PyMem_Free(env);
13540
13541
    Py_RETURN_NONE;
13542
}
13543
#endif
13544
13545
13546
#ifdef MS_WINDOWS
13547
/*[clinic input]
13548
os.putenv
13549
13550
    name: unicode
13551
    value: unicode
13552
    /
13553
13554
Change or add an environment variable.
13555
[clinic start generated code]*/
13556
13557
static PyObject *
13558
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13559
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13560
{
13561
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13562
        return NULL;
13563
    }
13564
    return win32_putenv(name, value);
13565
}
13566
#else
13567
/*[clinic input]
13568
os.putenv
13569
13570
    name: unicode_fs_encoded
13571
    value: unicode_fs_encoded
13572
    /
13573
13574
Change or add an environment variable.
13575
[clinic start generated code]*/
13576
13577
static PyObject *
13578
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13579
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13580
0
{
13581
0
    const char *name_string = PyBytes_AS_STRING(name);
13582
0
    const char *value_string = PyBytes_AS_STRING(value);
13583
13584
0
    if (strchr(name_string, '=') != NULL) {
13585
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13586
0
        return NULL;
13587
0
    }
13588
13589
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13590
0
        return NULL;
13591
0
    }
13592
13593
0
    if (setenv(name_string, value_string, 1)) {
13594
0
        return posix_error();
13595
0
    }
13596
0
    Py_RETURN_NONE;
13597
0
}
13598
#endif  /* !defined(MS_WINDOWS) */
13599
13600
13601
#ifdef MS_WINDOWS
13602
/*[clinic input]
13603
os.unsetenv
13604
    name: unicode
13605
    /
13606
13607
Delete an environment variable.
13608
[clinic start generated code]*/
13609
13610
static PyObject *
13611
os_unsetenv_impl(PyObject *module, PyObject *name)
13612
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13613
{
13614
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13615
        return NULL;
13616
    }
13617
    return win32_putenv(name, NULL);
13618
}
13619
#else
13620
/*[clinic input]
13621
os.unsetenv
13622
    name: unicode_fs_encoded
13623
    /
13624
13625
Delete an environment variable.
13626
[clinic start generated code]*/
13627
13628
static PyObject *
13629
os_unsetenv_impl(PyObject *module, PyObject *name)
13630
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13631
0
{
13632
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13633
0
        return NULL;
13634
0
    }
13635
#ifdef HAVE_BROKEN_UNSETENV
13636
    unsetenv(PyBytes_AS_STRING(name));
13637
#else
13638
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13639
0
    if (err) {
13640
0
        return posix_error();
13641
0
    }
13642
0
#endif
13643
13644
0
    Py_RETURN_NONE;
13645
0
}
13646
#endif /* !MS_WINDOWS */
13647
13648
13649
#ifdef HAVE_CLEARENV
13650
/*[clinic input]
13651
os._clearenv
13652
[clinic start generated code]*/
13653
13654
static PyObject *
13655
os__clearenv_impl(PyObject *module)
13656
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13657
0
{
13658
0
    errno = 0;
13659
0
    int err = clearenv();
13660
0
    if (err) {
13661
0
        return posix_error();
13662
0
    }
13663
0
    Py_RETURN_NONE;
13664
0
}
13665
#endif
13666
13667
13668
/*[clinic input]
13669
os.strerror
13670
13671
    code: int
13672
    /
13673
13674
Translate an error code to a message string.
13675
[clinic start generated code]*/
13676
13677
static PyObject *
13678
os_strerror_impl(PyObject *module, int code)
13679
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13680
0
{
13681
0
    char *message = strerror(code);
13682
0
    if (message == NULL) {
13683
0
        PyErr_SetString(PyExc_ValueError,
13684
0
                        "strerror() argument out of range");
13685
0
        return NULL;
13686
0
    }
13687
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13688
0
}
13689
13690
13691
#ifdef HAVE_SYS_WAIT_H
13692
#ifdef WCOREDUMP
13693
/*[clinic input]
13694
os.WCOREDUMP -> bool
13695
13696
    status: int
13697
    /
13698
13699
Return True if the process returning status was dumped to a core file.
13700
[clinic start generated code]*/
13701
13702
static int
13703
os_WCOREDUMP_impl(PyObject *module, int status)
13704
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13705
0
{
13706
0
    WAIT_TYPE wait_status;
13707
0
    WAIT_STATUS_INT(wait_status) = status;
13708
0
    return WCOREDUMP(wait_status);
13709
0
}
13710
#endif /* WCOREDUMP */
13711
13712
13713
#ifdef WIFCONTINUED
13714
/*[clinic input]
13715
os.WIFCONTINUED -> bool
13716
13717
    status: int
13718
13719
Return True if a particular process was continued from a job control stop.
13720
13721
Return True if the process returning status was continued from a
13722
job control stop.
13723
[clinic start generated code]*/
13724
13725
static int
13726
os_WIFCONTINUED_impl(PyObject *module, int status)
13727
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13728
0
{
13729
0
    WAIT_TYPE wait_status;
13730
0
    WAIT_STATUS_INT(wait_status) = status;
13731
0
    return WIFCONTINUED(wait_status);
13732
0
}
13733
#endif /* WIFCONTINUED */
13734
13735
13736
#ifdef WIFSTOPPED
13737
/*[clinic input]
13738
os.WIFSTOPPED -> bool
13739
13740
    status: int
13741
13742
Return True if the process returning status was stopped.
13743
[clinic start generated code]*/
13744
13745
static int
13746
os_WIFSTOPPED_impl(PyObject *module, int status)
13747
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13748
0
{
13749
0
    WAIT_TYPE wait_status;
13750
0
    WAIT_STATUS_INT(wait_status) = status;
13751
0
    return WIFSTOPPED(wait_status);
13752
0
}
13753
#endif /* WIFSTOPPED */
13754
13755
13756
#ifdef WIFSIGNALED
13757
/*[clinic input]
13758
os.WIFSIGNALED -> bool
13759
13760
    status: int
13761
13762
Return True if the process returning status was terminated by a signal.
13763
[clinic start generated code]*/
13764
13765
static int
13766
os_WIFSIGNALED_impl(PyObject *module, int status)
13767
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13768
0
{
13769
0
    WAIT_TYPE wait_status;
13770
0
    WAIT_STATUS_INT(wait_status) = status;
13771
0
    return WIFSIGNALED(wait_status);
13772
0
}
13773
#endif /* WIFSIGNALED */
13774
13775
13776
#ifdef WIFEXITED
13777
/*[clinic input]
13778
@permit_long_summary
13779
os.WIFEXITED -> bool
13780
13781
    status: int
13782
13783
Return True if the process returning status exited via the exit() system call.
13784
[clinic start generated code]*/
13785
13786
static int
13787
os_WIFEXITED_impl(PyObject *module, int status)
13788
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13789
0
{
13790
0
    WAIT_TYPE wait_status;
13791
0
    WAIT_STATUS_INT(wait_status) = status;
13792
0
    return WIFEXITED(wait_status);
13793
0
}
13794
#endif /* WIFEXITED */
13795
13796
13797
#ifdef WEXITSTATUS
13798
/*[clinic input]
13799
os.WEXITSTATUS -> int
13800
13801
    status: int
13802
13803
Return the process return code from status.
13804
[clinic start generated code]*/
13805
13806
static int
13807
os_WEXITSTATUS_impl(PyObject *module, int status)
13808
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13809
0
{
13810
0
    WAIT_TYPE wait_status;
13811
0
    WAIT_STATUS_INT(wait_status) = status;
13812
0
    return WEXITSTATUS(wait_status);
13813
0
}
13814
#endif /* WEXITSTATUS */
13815
13816
13817
#ifdef WTERMSIG
13818
/*[clinic input]
13819
@permit_long_summary
13820
os.WTERMSIG -> int
13821
13822
    status: int
13823
13824
Return the signal that terminated the process that provided the status value.
13825
[clinic start generated code]*/
13826
13827
static int
13828
os_WTERMSIG_impl(PyObject *module, int status)
13829
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13830
0
{
13831
0
    WAIT_TYPE wait_status;
13832
0
    WAIT_STATUS_INT(wait_status) = status;
13833
0
    return WTERMSIG(wait_status);
13834
0
}
13835
#endif /* WTERMSIG */
13836
13837
13838
#ifdef WSTOPSIG
13839
/*[clinic input]
13840
os.WSTOPSIG -> int
13841
13842
    status: int
13843
13844
Return the signal that stopped the process that provided the status value.
13845
[clinic start generated code]*/
13846
13847
static int
13848
os_WSTOPSIG_impl(PyObject *module, int status)
13849
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13850
0
{
13851
0
    WAIT_TYPE wait_status;
13852
0
    WAIT_STATUS_INT(wait_status) = status;
13853
0
    return WSTOPSIG(wait_status);
13854
0
}
13855
#endif /* WSTOPSIG */
13856
#endif /* HAVE_SYS_WAIT_H */
13857
13858
13859
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13860
#ifdef _SCO_DS
13861
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13862
   needed definitions in sys/statvfs.h */
13863
#define _SVID3
13864
#endif
13865
#include <sys/statvfs.h>
13866
13867
#ifdef __APPLE__
13868
/* On macOS struct statvfs uses 32-bit integers for block counts,
13869
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13870
 * os.statvfs is implemented in terms of statfs(2).
13871
 */
13872
13873
static PyObject*
13874
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13875
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13876
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13877
    if (v == NULL) {
13878
        return NULL;
13879
    }
13880
13881
    long flags = 0;
13882
    if (st.f_flags & MNT_RDONLY) {
13883
        flags |= ST_RDONLY;
13884
    }
13885
    if (st.f_flags & MNT_NOSUID) {
13886
        flags |= ST_NOSUID;
13887
    }
13888
13889
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13890
13891
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13892
    do {                                                 \
13893
        PyObject *obj = (EXPR);                          \
13894
        if (obj == NULL) {                               \
13895
            Py_DECREF((SEQ));                            \
13896
            return NULL;                                 \
13897
        }                                                \
13898
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13899
    } while (0)
13900
13901
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13902
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13903
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13904
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13905
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13906
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13907
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13908
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13909
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13910
13911
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13912
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13913
13914
#undef SET_ITEM
13915
13916
    return v;
13917
}
13918
13919
#else
13920
13921
13922
13923
static PyObject*
13924
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13925
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13926
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13927
0
    if (v == NULL)
13928
0
        return NULL;
13929
13930
0
    int pos = 0;
13931
13932
0
#define SET_RESULT(CALL)                                     \
13933
0
    do {                                                     \
13934
0
        PyObject *item = (CALL);                             \
13935
0
        if (item == NULL) {                                  \
13936
0
            Py_DECREF(v);                                    \
13937
0
            return NULL;                                     \
13938
0
        }                                                    \
13939
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13940
0
    } while(0)
13941
13942
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13943
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13944
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13945
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13946
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13947
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13948
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13949
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13950
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13951
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13952
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13953
#else
13954
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13955
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13956
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13957
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13958
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13959
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13960
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13961
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13962
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13963
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13964
#endif
13965
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13966
 * (issue #32390). */
13967
#if defined(_AIX) && defined(_ALL_SOURCE)
13968
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13969
#else
13970
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13971
0
#endif
13972
13973
0
#undef SET_RESULT
13974
13975
0
    return v;
13976
0
}
13977
13978
#endif
13979
13980
13981
/*[clinic input]
13982
os.fstatvfs
13983
    fd: int
13984
    /
13985
13986
Perform an fstatvfs system call on the given fd.
13987
13988
Equivalent to statvfs(fd).
13989
[clinic start generated code]*/
13990
13991
static PyObject *
13992
os_fstatvfs_impl(PyObject *module, int fd)
13993
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13994
0
{
13995
0
    int result;
13996
0
    int async_err = 0;
13997
#ifdef __APPLE__
13998
    struct statfs st;
13999
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
14000
     * the former uses 32-bit values for block counts.
14001
     */
14002
    do {
14003
        Py_BEGIN_ALLOW_THREADS
14004
        result = fstatfs(fd, &st);
14005
        Py_END_ALLOW_THREADS
14006
    } while (result != 0 && errno == EINTR &&
14007
             !(async_err = PyErr_CheckSignals()));
14008
    if (result != 0)
14009
        return (!async_err) ? posix_error() : NULL;
14010
14011
    return _pystatvfs_fromstructstatfs(module, st);
14012
#else
14013
0
    struct statvfs st;
14014
14015
0
    do {
14016
0
        Py_BEGIN_ALLOW_THREADS
14017
0
        result = fstatvfs(fd, &st);
14018
0
        Py_END_ALLOW_THREADS
14019
0
    } while (result != 0 && errno == EINTR &&
14020
0
             !(async_err = PyErr_CheckSignals()));
14021
0
    if (result != 0)
14022
0
        return (!async_err) ? posix_error() : NULL;
14023
14024
0
    return _pystatvfs_fromstructstatvfs(module, st);
14025
0
#endif
14026
0
}
14027
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14028
14029
14030
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14031
#include <sys/statvfs.h>
14032
/*[clinic input]
14033
os.statvfs
14034
14035
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14036
14037
Perform a statvfs system call on the given path.
14038
14039
path may always be specified as a string.
14040
On some platforms, path may also be specified as an open file descriptor.
14041
  If this functionality is unavailable, using it raises an exception.
14042
[clinic start generated code]*/
14043
14044
static PyObject *
14045
os_statvfs_impl(PyObject *module, path_t *path)
14046
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
14047
0
{
14048
0
    int result;
14049
14050
#ifdef __APPLE__
14051
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14052
     * the former uses 32-bit values for block counts.
14053
     */
14054
    struct statfs st;
14055
14056
    Py_BEGIN_ALLOW_THREADS
14057
    if (path->is_fd) {
14058
        result = fstatfs(path->fd, &st);
14059
    }
14060
    else
14061
        result = statfs(path->narrow, &st);
14062
    Py_END_ALLOW_THREADS
14063
14064
    if (result) {
14065
        return path_error(path);
14066
    }
14067
14068
    return _pystatvfs_fromstructstatfs(module, st);
14069
14070
#else
14071
0
    struct statvfs st;
14072
14073
0
    Py_BEGIN_ALLOW_THREADS
14074
0
#ifdef HAVE_FSTATVFS
14075
0
    if (path->is_fd) {
14076
0
        result = fstatvfs(path->fd, &st);
14077
0
    }
14078
0
    else
14079
0
#endif
14080
0
        result = statvfs(path->narrow, &st);
14081
0
    Py_END_ALLOW_THREADS
14082
14083
0
    if (result) {
14084
0
        return path_error(path);
14085
0
    }
14086
14087
0
    return _pystatvfs_fromstructstatvfs(module, st);
14088
0
#endif
14089
0
}
14090
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14091
14092
14093
#ifdef MS_WINDOWS
14094
/*[clinic input]
14095
os._getdiskusage
14096
14097
    path: path_t
14098
14099
Return disk usage statistics about the given path as a (total, free) tuple.
14100
[clinic start generated code]*/
14101
14102
static PyObject *
14103
os__getdiskusage_impl(PyObject *module, path_t *path)
14104
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
14105
{
14106
    BOOL retval;
14107
    ULARGE_INTEGER _, total, free;
14108
    DWORD err = 0;
14109
14110
    Py_BEGIN_ALLOW_THREADS
14111
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14112
    Py_END_ALLOW_THREADS
14113
    if (retval == 0) {
14114
        if (GetLastError() == ERROR_DIRECTORY) {
14115
            wchar_t *dir_path = NULL;
14116
14117
            dir_path = PyMem_New(wchar_t, path->length + 1);
14118
            if (dir_path == NULL) {
14119
                return PyErr_NoMemory();
14120
            }
14121
14122
            wcscpy_s(dir_path, path->length + 1, path->wide);
14123
14124
            if (_dirnameW(dir_path) != -1) {
14125
                Py_BEGIN_ALLOW_THREADS
14126
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14127
                Py_END_ALLOW_THREADS
14128
            }
14129
            /* Record the last error in case it's modified by PyMem_Free. */
14130
            err = GetLastError();
14131
            PyMem_Free(dir_path);
14132
            if (retval) {
14133
                goto success;
14134
            }
14135
        }
14136
        return PyErr_SetFromWindowsErr(err);
14137
    }
14138
14139
success:
14140
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14141
}
14142
#endif /* MS_WINDOWS */
14143
14144
14145
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14146
 * It maps strings representing configuration variable names to
14147
 * integer values, allowing those functions to be called with the
14148
 * magic names instead of polluting the module's namespace with tons of
14149
 * rarely-used constants.  There are three separate tables that use
14150
 * these definitions.
14151
 *
14152
 * This code is always included, even if none of the interfaces that
14153
 * need it are included.  The #if hackery needed to avoid it would be
14154
 * sufficiently pervasive that it's not worth the loss of readability.
14155
 */
14156
struct constdef {
14157
    const char *name;
14158
    int value;
14159
};
14160
14161
static int
14162
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14163
8
{
14164
8
    if (PyUnicode_Check(arg)) {
14165
8
        PyObject *table = PyObject_GetAttrString(module, tablename);
14166
8
        if (table == NULL) {
14167
0
            return 0;
14168
0
        }
14169
14170
8
        arg = PyObject_GetItem(table, arg);
14171
8
        Py_DECREF(table);
14172
8
        if (arg == NULL) {
14173
0
            PyErr_SetString(
14174
0
                PyExc_ValueError, "unrecognized configuration name");
14175
0
            return 0;
14176
0
        }
14177
8
    } else {
14178
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14179
0
    }
14180
14181
8
    int success = 0;
14182
8
    if (!PyIndex_Check(arg)) {
14183
0
        PyErr_SetString(PyExc_TypeError,
14184
0
            "configuration names must be strings or integers");
14185
8
    } else {
14186
8
        int value = PyLong_AsInt(arg);
14187
8
        if (!(value == -1 && PyErr_Occurred())) {
14188
8
            *valuep = value;
14189
8
            success = 1;
14190
8
        }
14191
8
    }
14192
8
    Py_DECREF(arg);
14193
8
    return success;
14194
8
}
14195
14196
14197
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14198
static struct constdef  posix_constants_pathconf[] = {
14199
#ifdef _PC_ABI_AIO_XFER_MAX
14200
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14201
#endif
14202
#ifdef _PC_ABI_ASYNC_IO
14203
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14204
#endif
14205
#ifdef _PC_ASYNC_IO
14206
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14207
#endif
14208
#ifdef _PC_CHOWN_RESTRICTED
14209
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14210
#endif
14211
#ifdef _PC_FILESIZEBITS
14212
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14213
#endif
14214
#ifdef _PC_LAST
14215
    {"PC_LAST", _PC_LAST},
14216
#endif
14217
#ifdef _PC_LINK_MAX
14218
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14219
#endif
14220
#ifdef _PC_MAX_CANON
14221
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14222
#endif
14223
#ifdef _PC_MAX_INPUT
14224
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14225
#endif
14226
#ifdef _PC_NAME_MAX
14227
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14228
#endif
14229
#ifdef _PC_NO_TRUNC
14230
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14231
#endif
14232
#ifdef _PC_PATH_MAX
14233
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14234
#endif
14235
#ifdef _PC_PIPE_BUF
14236
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14237
#endif
14238
#ifdef _PC_PRIO_IO
14239
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14240
#endif
14241
#ifdef _PC_SOCK_MAXBUF
14242
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14243
#endif
14244
#ifdef _PC_SYNC_IO
14245
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14246
#endif
14247
#ifdef _PC_VDISABLE
14248
    {"PC_VDISABLE",     _PC_VDISABLE},
14249
#endif
14250
#ifdef _PC_ACL_ENABLED
14251
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14252
#endif
14253
#ifdef _PC_MIN_HOLE_SIZE
14254
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14255
#endif
14256
#ifdef _PC_ALLOC_SIZE_MIN
14257
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14258
#endif
14259
#ifdef _PC_REC_INCR_XFER_SIZE
14260
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14261
#endif
14262
#ifdef _PC_REC_MAX_XFER_SIZE
14263
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14264
#endif
14265
#ifdef _PC_REC_MIN_XFER_SIZE
14266
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14267
#endif
14268
#ifdef _PC_REC_XFER_ALIGN
14269
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14270
#endif
14271
#ifdef _PC_SYMLINK_MAX
14272
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14273
#endif
14274
#ifdef _PC_XATTR_ENABLED
14275
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14276
#endif
14277
#ifdef _PC_XATTR_EXISTS
14278
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14279
#endif
14280
#ifdef _PC_TIMESTAMP_RESOLUTION
14281
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14282
#endif
14283
};
14284
#endif
14285
14286
14287
#ifdef HAVE_FPATHCONF
14288
/*[clinic input]
14289
os.fpathconf -> long
14290
14291
    fd: fildes
14292
    name: confname(table="pathconf_names")
14293
    /
14294
14295
Return the configuration limit name for the file descriptor fd.
14296
14297
If there is no limit, return -1.
14298
[clinic start generated code]*/
14299
14300
static long
14301
os_fpathconf_impl(PyObject *module, int fd, int name)
14302
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14303
0
{
14304
0
    long limit;
14305
14306
0
    errno = 0;
14307
0
    limit = fpathconf(fd, name);
14308
0
    if (limit == -1 && errno != 0)
14309
0
        posix_error();
14310
14311
0
    return limit;
14312
0
}
14313
#endif /* HAVE_FPATHCONF */
14314
14315
14316
#ifdef HAVE_PATHCONF
14317
/*[clinic input]
14318
os.pathconf -> long
14319
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14320
    name: confname(table="pathconf_names")
14321
14322
Return the configuration limit name for the file or directory path.
14323
14324
If there is no limit, return -1.
14325
On some platforms, path may also be specified as an open file descriptor.
14326
  If this functionality is unavailable, using it raises an exception.
14327
[clinic start generated code]*/
14328
14329
static long
14330
os_pathconf_impl(PyObject *module, path_t *path, int name)
14331
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
14332
0
{
14333
0
    long limit;
14334
14335
0
    errno = 0;
14336
0
#ifdef HAVE_FPATHCONF
14337
0
    if (path->is_fd) {
14338
0
        limit = fpathconf(path->fd, name);
14339
0
    }
14340
0
    else
14341
0
#endif
14342
0
        limit = pathconf(path->narrow, name);
14343
0
    if (limit == -1 && errno != 0) {
14344
0
        if (errno == EINVAL)
14345
            /* could be a path or name problem */
14346
0
            posix_error();
14347
0
        else
14348
0
            path_error(path);
14349
0
    }
14350
14351
0
    return limit;
14352
0
}
14353
#endif /* HAVE_PATHCONF */
14354
14355
#ifdef HAVE_CONFSTR
14356
static struct constdef posix_constants_confstr[] = {
14357
#ifdef _CS_ARCHITECTURE
14358
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14359
#endif
14360
#ifdef _CS_GNU_LIBC_VERSION
14361
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14362
#endif
14363
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14364
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14365
#endif
14366
#ifdef _CS_HOSTNAME
14367
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14368
#endif
14369
#ifdef _CS_HW_PROVIDER
14370
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14371
#endif
14372
#ifdef _CS_HW_SERIAL
14373
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14374
#endif
14375
#ifdef _CS_INITTAB_NAME
14376
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14377
#endif
14378
#ifdef _CS_LFS64_CFLAGS
14379
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14380
#endif
14381
#ifdef _CS_LFS64_LDFLAGS
14382
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14383
#endif
14384
#ifdef _CS_LFS64_LIBS
14385
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14386
#endif
14387
#ifdef _CS_LFS64_LINTFLAGS
14388
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14389
#endif
14390
#ifdef _CS_LFS_CFLAGS
14391
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14392
#endif
14393
#ifdef _CS_LFS_LDFLAGS
14394
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14395
#endif
14396
#ifdef _CS_LFS_LIBS
14397
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14398
#endif
14399
#ifdef _CS_LFS_LINTFLAGS
14400
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14401
#endif
14402
#ifdef _CS_MACHINE
14403
    {"CS_MACHINE",      _CS_MACHINE},
14404
#endif
14405
#ifdef _CS_PATH
14406
    {"CS_PATH", _CS_PATH},
14407
#endif
14408
#ifdef _CS_RELEASE
14409
    {"CS_RELEASE",      _CS_RELEASE},
14410
#endif
14411
#ifdef _CS_SRPC_DOMAIN
14412
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14413
#endif
14414
#ifdef _CS_SYSNAME
14415
    {"CS_SYSNAME",      _CS_SYSNAME},
14416
#endif
14417
#ifdef _CS_VERSION
14418
    {"CS_VERSION",      _CS_VERSION},
14419
#endif
14420
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14421
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14422
#endif
14423
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14424
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14425
#endif
14426
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14427
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14428
#endif
14429
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14430
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14431
#endif
14432
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14433
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14434
#endif
14435
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14436
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14437
#endif
14438
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14439
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14440
#endif
14441
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14442
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14443
#endif
14444
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14445
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14446
#endif
14447
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14448
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14449
#endif
14450
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14451
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14452
#endif
14453
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14454
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14455
#endif
14456
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14457
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14458
#endif
14459
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14460
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14461
#endif
14462
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14463
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14464
#endif
14465
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14466
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14467
#endif
14468
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14469
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14470
#endif
14471
#ifdef _MIPS_CS_BASE
14472
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14473
#endif
14474
#ifdef _MIPS_CS_HOSTID
14475
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14476
#endif
14477
#ifdef _MIPS_CS_HW_NAME
14478
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14479
#endif
14480
#ifdef _MIPS_CS_NUM_PROCESSORS
14481
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14482
#endif
14483
#ifdef _MIPS_CS_OSREL_MAJ
14484
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14485
#endif
14486
#ifdef _MIPS_CS_OSREL_MIN
14487
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14488
#endif
14489
#ifdef _MIPS_CS_OSREL_PATCH
14490
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14491
#endif
14492
#ifdef _MIPS_CS_OS_NAME
14493
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14494
#endif
14495
#ifdef _MIPS_CS_OS_PROVIDER
14496
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14497
#endif
14498
#ifdef _MIPS_CS_PROCESSORS
14499
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14500
#endif
14501
#ifdef _MIPS_CS_SERIAL
14502
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14503
#endif
14504
#ifdef _MIPS_CS_VENDOR
14505
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14506
#endif
14507
};
14508
14509
14510
/*[clinic input]
14511
os.confstr
14512
14513
    name: confname(table="confstr_names")
14514
    /
14515
14516
Return a string-valued system configuration variable.
14517
[clinic start generated code]*/
14518
14519
static PyObject *
14520
os_confstr_impl(PyObject *module, int name)
14521
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14522
4
{
14523
4
    PyObject *result = NULL;
14524
4
    char buffer[255];
14525
4
    size_t len;
14526
14527
4
    errno = 0;
14528
4
    len = confstr(name, buffer, sizeof(buffer));
14529
4
    if (len == 0) {
14530
0
        if (errno) {
14531
0
            posix_error();
14532
0
            return NULL;
14533
0
        }
14534
0
        else {
14535
0
            Py_RETURN_NONE;
14536
0
        }
14537
0
    }
14538
14539
4
    if (len >= sizeof(buffer)) {
14540
0
        size_t len2;
14541
0
        char *buf = PyMem_Malloc(len);
14542
0
        if (buf == NULL)
14543
0
            return PyErr_NoMemory();
14544
0
        len2 = confstr(name, buf, len);
14545
0
        assert(len == len2);
14546
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14547
0
        PyMem_Free(buf);
14548
0
    }
14549
4
    else
14550
4
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14551
4
    return result;
14552
4
}
14553
#endif /* HAVE_CONFSTR */
14554
14555
14556
#ifdef HAVE_SYSCONF
14557
static struct constdef posix_constants_sysconf[] = {
14558
#ifdef _SC_2_CHAR_TERM
14559
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14560
#endif
14561
#ifdef _SC_2_C_BIND
14562
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14563
#endif
14564
#ifdef _SC_2_C_DEV
14565
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14566
#endif
14567
#ifdef _SC_2_C_VERSION
14568
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14569
#endif
14570
#ifdef _SC_2_FORT_DEV
14571
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14572
#endif
14573
#ifdef _SC_2_FORT_RUN
14574
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14575
#endif
14576
#ifdef _SC_2_LOCALEDEF
14577
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14578
#endif
14579
#ifdef _SC_2_SW_DEV
14580
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14581
#endif
14582
#ifdef _SC_2_UPE
14583
    {"SC_2_UPE",        _SC_2_UPE},
14584
#endif
14585
#ifdef _SC_2_VERSION
14586
    {"SC_2_VERSION",    _SC_2_VERSION},
14587
#endif
14588
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14589
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14590
#endif
14591
#ifdef _SC_ACL
14592
    {"SC_ACL",  _SC_ACL},
14593
#endif
14594
#ifdef _SC_AIO_LISTIO_MAX
14595
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14596
#endif
14597
#ifdef _SC_AIO_MAX
14598
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14599
#endif
14600
#ifdef _SC_AIO_PRIO_DELTA_MAX
14601
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14602
#endif
14603
#ifdef _SC_ARG_MAX
14604
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14605
#endif
14606
#ifdef _SC_ASYNCHRONOUS_IO
14607
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14608
#endif
14609
#ifdef _SC_ATEXIT_MAX
14610
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14611
#endif
14612
#ifdef _SC_AUDIT
14613
    {"SC_AUDIT",        _SC_AUDIT},
14614
#endif
14615
#ifdef _SC_AVPHYS_PAGES
14616
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14617
#endif
14618
#ifdef _SC_BC_BASE_MAX
14619
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14620
#endif
14621
#ifdef _SC_BC_DIM_MAX
14622
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14623
#endif
14624
#ifdef _SC_BC_SCALE_MAX
14625
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14626
#endif
14627
#ifdef _SC_BC_STRING_MAX
14628
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14629
#endif
14630
#ifdef _SC_CAP
14631
    {"SC_CAP",  _SC_CAP},
14632
#endif
14633
#ifdef _SC_CHARCLASS_NAME_MAX
14634
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14635
#endif
14636
#ifdef _SC_CHAR_BIT
14637
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14638
#endif
14639
#ifdef _SC_CHAR_MAX
14640
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14641
#endif
14642
#ifdef _SC_CHAR_MIN
14643
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14644
#endif
14645
#ifdef _SC_CHILD_MAX
14646
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14647
#endif
14648
#ifdef _SC_CLK_TCK
14649
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14650
#endif
14651
#ifdef _SC_COHER_BLKSZ
14652
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14653
#endif
14654
#ifdef _SC_COLL_WEIGHTS_MAX
14655
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14656
#endif
14657
#ifdef _SC_DCACHE_ASSOC
14658
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14659
#endif
14660
#ifdef _SC_DCACHE_BLKSZ
14661
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14662
#endif
14663
#ifdef _SC_DCACHE_LINESZ
14664
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14665
#endif
14666
#ifdef _SC_DCACHE_SZ
14667
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14668
#endif
14669
#ifdef _SC_DCACHE_TBLKSZ
14670
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14671
#endif
14672
#ifdef _SC_DELAYTIMER_MAX
14673
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14674
#endif
14675
#ifdef _SC_EQUIV_CLASS_MAX
14676
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14677
#endif
14678
#ifdef _SC_EXPR_NEST_MAX
14679
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14680
#endif
14681
#ifdef _SC_FSYNC
14682
    {"SC_FSYNC",        _SC_FSYNC},
14683
#endif
14684
#ifdef _SC_GETGR_R_SIZE_MAX
14685
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14686
#endif
14687
#ifdef _SC_GETPW_R_SIZE_MAX
14688
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14689
#endif
14690
#ifdef _SC_ICACHE_ASSOC
14691
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14692
#endif
14693
#ifdef _SC_ICACHE_BLKSZ
14694
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14695
#endif
14696
#ifdef _SC_ICACHE_LINESZ
14697
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14698
#endif
14699
#ifdef _SC_ICACHE_SZ
14700
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14701
#endif
14702
#ifdef _SC_INF
14703
    {"SC_INF",  _SC_INF},
14704
#endif
14705
#ifdef _SC_INT_MAX
14706
    {"SC_INT_MAX",      _SC_INT_MAX},
14707
#endif
14708
#ifdef _SC_INT_MIN
14709
    {"SC_INT_MIN",      _SC_INT_MIN},
14710
#endif
14711
#ifdef _SC_IOV_MAX
14712
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14713
#endif
14714
#ifdef _SC_IP_SECOPTS
14715
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14716
#endif
14717
#ifdef _SC_JOB_CONTROL
14718
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14719
#endif
14720
#ifdef _SC_KERN_POINTERS
14721
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14722
#endif
14723
#ifdef _SC_KERN_SIM
14724
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14725
#endif
14726
#ifdef _SC_LINE_MAX
14727
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14728
#endif
14729
#ifdef _SC_LOGIN_NAME_MAX
14730
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14731
#endif
14732
#ifdef _SC_LOGNAME_MAX
14733
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14734
#endif
14735
#ifdef _SC_LONG_BIT
14736
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14737
#endif
14738
#ifdef _SC_MAC
14739
    {"SC_MAC",  _SC_MAC},
14740
#endif
14741
#ifdef _SC_MAPPED_FILES
14742
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14743
#endif
14744
#ifdef _SC_MAXPID
14745
    {"SC_MAXPID",       _SC_MAXPID},
14746
#endif
14747
#ifdef _SC_MB_LEN_MAX
14748
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14749
#endif
14750
#ifdef _SC_MEMLOCK
14751
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14752
#endif
14753
#ifdef _SC_MEMLOCK_RANGE
14754
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14755
#endif
14756
#ifdef _SC_MEMORY_PROTECTION
14757
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14758
#endif
14759
#ifdef _SC_MESSAGE_PASSING
14760
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14761
#endif
14762
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14763
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14764
#endif
14765
#ifdef _SC_MQ_OPEN_MAX
14766
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14767
#endif
14768
#ifdef _SC_MQ_PRIO_MAX
14769
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14770
#endif
14771
#ifdef _SC_NACLS_MAX
14772
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14773
#endif
14774
#ifdef _SC_NGROUPS_MAX
14775
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14776
#endif
14777
#ifdef _SC_NL_ARGMAX
14778
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14779
#endif
14780
#ifdef _SC_NL_LANGMAX
14781
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14782
#endif
14783
#ifdef _SC_NL_MSGMAX
14784
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14785
#endif
14786
#ifdef _SC_NL_NMAX
14787
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14788
#endif
14789
#ifdef _SC_NL_SETMAX
14790
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14791
#endif
14792
#ifdef _SC_NL_TEXTMAX
14793
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14794
#endif
14795
#ifdef _SC_NPROCESSORS_CONF
14796
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14797
#endif
14798
#ifdef _SC_NPROCESSORS_ONLN
14799
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14800
#endif
14801
#ifdef _SC_NPROC_CONF
14802
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14803
#endif
14804
#ifdef _SC_NPROC_ONLN
14805
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14806
#endif
14807
#ifdef _SC_NZERO
14808
    {"SC_NZERO",        _SC_NZERO},
14809
#endif
14810
#ifdef _SC_OPEN_MAX
14811
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14812
#endif
14813
#ifdef _SC_PAGESIZE
14814
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14815
#endif
14816
#ifdef _SC_PAGE_SIZE
14817
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14818
#endif
14819
#ifdef _SC_AIX_REALMEM
14820
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14821
#endif
14822
#ifdef _SC_PASS_MAX
14823
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14824
#endif
14825
#ifdef _SC_PHYS_PAGES
14826
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14827
#endif
14828
#ifdef _SC_PII
14829
    {"SC_PII",  _SC_PII},
14830
#endif
14831
#ifdef _SC_PII_INTERNET
14832
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14833
#endif
14834
#ifdef _SC_PII_INTERNET_DGRAM
14835
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14836
#endif
14837
#ifdef _SC_PII_INTERNET_STREAM
14838
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14839
#endif
14840
#ifdef _SC_PII_OSI
14841
    {"SC_PII_OSI",      _SC_PII_OSI},
14842
#endif
14843
#ifdef _SC_PII_OSI_CLTS
14844
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14845
#endif
14846
#ifdef _SC_PII_OSI_COTS
14847
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14848
#endif
14849
#ifdef _SC_PII_OSI_M
14850
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14851
#endif
14852
#ifdef _SC_PII_SOCKET
14853
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14854
#endif
14855
#ifdef _SC_PII_XTI
14856
    {"SC_PII_XTI",      _SC_PII_XTI},
14857
#endif
14858
#ifdef _SC_POLL
14859
    {"SC_POLL", _SC_POLL},
14860
#endif
14861
#ifdef _SC_PRIORITIZED_IO
14862
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14863
#endif
14864
#ifdef _SC_PRIORITY_SCHEDULING
14865
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14866
#endif
14867
#ifdef _SC_REALTIME_SIGNALS
14868
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14869
#endif
14870
#ifdef _SC_RE_DUP_MAX
14871
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14872
#endif
14873
#ifdef _SC_RTSIG_MAX
14874
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14875
#endif
14876
#ifdef _SC_SAVED_IDS
14877
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14878
#endif
14879
#ifdef _SC_SCHAR_MAX
14880
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14881
#endif
14882
#ifdef _SC_SCHAR_MIN
14883
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14884
#endif
14885
#ifdef _SC_SELECT
14886
    {"SC_SELECT",       _SC_SELECT},
14887
#endif
14888
#ifdef _SC_SEMAPHORES
14889
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14890
#endif
14891
#ifdef _SC_SEM_NSEMS_MAX
14892
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14893
#endif
14894
#ifdef _SC_SEM_VALUE_MAX
14895
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14896
#endif
14897
#ifdef _SC_SHARED_MEMORY_OBJECTS
14898
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14899
#endif
14900
#ifdef _SC_SHRT_MAX
14901
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14902
#endif
14903
#ifdef _SC_SHRT_MIN
14904
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14905
#endif
14906
#ifdef _SC_SIGQUEUE_MAX
14907
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14908
#endif
14909
#ifdef _SC_SIGRT_MAX
14910
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14911
#endif
14912
#ifdef _SC_SIGRT_MIN
14913
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14914
#endif
14915
#ifdef _SC_SOFTPOWER
14916
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14917
#endif
14918
#ifdef _SC_SPLIT_CACHE
14919
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14920
#endif
14921
#ifdef _SC_SSIZE_MAX
14922
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14923
#endif
14924
#ifdef _SC_STACK_PROT
14925
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14926
#endif
14927
#ifdef _SC_STREAM_MAX
14928
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14929
#endif
14930
#ifdef _SC_SYNCHRONIZED_IO
14931
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14932
#endif
14933
#ifdef _SC_THREADS
14934
    {"SC_THREADS",      _SC_THREADS},
14935
#endif
14936
#ifdef _SC_THREAD_ATTR_STACKADDR
14937
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14938
#endif
14939
#ifdef _SC_THREAD_ATTR_STACKSIZE
14940
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14941
#endif
14942
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14943
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14944
#endif
14945
#ifdef _SC_THREAD_KEYS_MAX
14946
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14947
#endif
14948
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14949
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14950
#endif
14951
#ifdef _SC_THREAD_PRIO_INHERIT
14952
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14953
#endif
14954
#ifdef _SC_THREAD_PRIO_PROTECT
14955
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14956
#endif
14957
#ifdef _SC_THREAD_PROCESS_SHARED
14958
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14959
#endif
14960
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14961
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14962
#endif
14963
#ifdef _SC_THREAD_STACK_MIN
14964
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14965
#endif
14966
#ifdef _SC_THREAD_THREADS_MAX
14967
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14968
#endif
14969
#ifdef _SC_TIMERS
14970
    {"SC_TIMERS",       _SC_TIMERS},
14971
#endif
14972
#ifdef _SC_TIMER_MAX
14973
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14974
#endif
14975
#ifdef _SC_TTY_NAME_MAX
14976
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14977
#endif
14978
#ifdef _SC_TZNAME_MAX
14979
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14980
#endif
14981
#ifdef _SC_T_IOV_MAX
14982
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14983
#endif
14984
#ifdef _SC_UCHAR_MAX
14985
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14986
#endif
14987
#ifdef _SC_UINT_MAX
14988
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14989
#endif
14990
#ifdef _SC_UIO_MAXIOV
14991
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14992
#endif
14993
#ifdef _SC_ULONG_MAX
14994
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14995
#endif
14996
#ifdef _SC_USHRT_MAX
14997
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14998
#endif
14999
#ifdef _SC_VERSION
15000
    {"SC_VERSION",      _SC_VERSION},
15001
#endif
15002
#ifdef _SC_WORD_BIT
15003
    {"SC_WORD_BIT",     _SC_WORD_BIT},
15004
#endif
15005
#ifdef _SC_XBS5_ILP32_OFF32
15006
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15007
#endif
15008
#ifdef _SC_XBS5_ILP32_OFFBIG
15009
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15010
#endif
15011
#ifdef _SC_XBS5_LP64_OFF64
15012
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15013
#endif
15014
#ifdef _SC_XBS5_LPBIG_OFFBIG
15015
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15016
#endif
15017
#ifdef _SC_XOPEN_CRYPT
15018
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15019
#endif
15020
#ifdef _SC_XOPEN_ENH_I18N
15021
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15022
#endif
15023
#ifdef _SC_XOPEN_LEGACY
15024
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15025
#endif
15026
#ifdef _SC_XOPEN_REALTIME
15027
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15028
#endif
15029
#ifdef _SC_XOPEN_REALTIME_THREADS
15030
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15031
#endif
15032
#ifdef _SC_XOPEN_SHM
15033
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15034
#endif
15035
#ifdef _SC_XOPEN_UNIX
15036
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15037
#endif
15038
#ifdef _SC_XOPEN_VERSION
15039
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15040
#endif
15041
#ifdef _SC_XOPEN_XCU_VERSION
15042
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15043
#endif
15044
#ifdef _SC_XOPEN_XPG2
15045
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15046
#endif
15047
#ifdef _SC_XOPEN_XPG3
15048
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15049
#endif
15050
#ifdef _SC_XOPEN_XPG4
15051
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15052
#endif
15053
#ifdef _SC_MINSIGSTKSZ
15054
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15055
#endif
15056
};
15057
15058
15059
/*[clinic input]
15060
os.sysconf -> long
15061
    name: confname(table="sysconf_names")
15062
    /
15063
15064
Return an integer-valued system configuration variable.
15065
[clinic start generated code]*/
15066
15067
static long
15068
os_sysconf_impl(PyObject *module, int name)
15069
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15070
4
{
15071
4
    long value;
15072
15073
4
    errno = 0;
15074
4
    value = sysconf(name);
15075
4
    if (value == -1 && errno != 0)
15076
0
        posix_error();
15077
4
    return value;
15078
4
}
15079
#endif /* HAVE_SYSCONF */
15080
15081
15082
static int
15083
setup_confname_table(struct constdef *table, size_t tablesize,
15084
                     const char *tablename, PyObject *module)
15085
102
{
15086
102
    PyObject *d = PyDict_New();
15087
102
    if (d == NULL)
15088
0
        return -1;
15089
15090
6.25k
    for (size_t i=0; i < tablesize; ++i) {
15091
6.15k
        PyObject *o = PyLong_FromLong(table[i].value);
15092
6.15k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15093
0
            Py_XDECREF(o);
15094
0
            Py_DECREF(d);
15095
0
            return -1;
15096
0
        }
15097
6.15k
        Py_DECREF(o);
15098
6.15k
    }
15099
102
    return PyModule_Add(module, tablename, d);
15100
102
}
15101
15102
/* Return -1 on failure, 0 on success. */
15103
static int
15104
setup_confname_tables(PyObject *module)
15105
34
{
15106
34
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15107
34
    if (setup_confname_table(posix_constants_pathconf,
15108
34
                             sizeof(posix_constants_pathconf)
15109
34
                               / sizeof(struct constdef),
15110
34
                             "pathconf_names", module))
15111
0
        return -1;
15112
34
#endif
15113
34
#ifdef HAVE_CONFSTR
15114
34
    if (setup_confname_table(posix_constants_confstr,
15115
34
                             sizeof(posix_constants_confstr)
15116
34
                               / sizeof(struct constdef),
15117
34
                             "confstr_names", module))
15118
0
        return -1;
15119
34
#endif
15120
34
#ifdef HAVE_SYSCONF
15121
34
    if (setup_confname_table(posix_constants_sysconf,
15122
34
                             sizeof(posix_constants_sysconf)
15123
34
                               / sizeof(struct constdef),
15124
34
                             "sysconf_names", module))
15125
0
        return -1;
15126
34
#endif
15127
34
    return 0;
15128
34
}
15129
15130
15131
/*[clinic input]
15132
os.abort
15133
15134
Abort the interpreter immediately.
15135
15136
This function 'dumps core' or otherwise fails in the hardest way possible
15137
on the hosting operating system.  This function never returns.
15138
[clinic start generated code]*/
15139
15140
static PyObject *
15141
os_abort_impl(PyObject *module)
15142
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
15143
0
{
15144
0
    abort();
15145
    /*NOTREACHED*/
15146
#ifndef __clang__
15147
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15148
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15149
       is smarter and emits a warning on the return. */
15150
    Py_FatalError("abort() called from Python code didn't abort!");
15151
    return NULL;
15152
#endif
15153
0
}
15154
15155
#ifdef MS_WINDOWS
15156
/* Grab ShellExecute dynamically from shell32 */
15157
static int has_ShellExecute = -1;
15158
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15159
                                              LPCWSTR, INT);
15160
static int
15161
check_ShellExecute(void)
15162
{
15163
    HINSTANCE hShell32;
15164
15165
    /* only recheck */
15166
    if (-1 == has_ShellExecute) {
15167
        Py_BEGIN_ALLOW_THREADS
15168
        /* Security note: this call is not vulnerable to "DLL hijacking".
15169
           SHELL32 is part of "KnownDLLs" and so Windows always load
15170
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15171
           in the DLL search path. */
15172
        hShell32 = LoadLibraryW(L"SHELL32");
15173
        if (hShell32) {
15174
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15175
                                            "ShellExecuteW");
15176
            has_ShellExecute = Py_ShellExecuteW != NULL;
15177
        } else {
15178
            has_ShellExecute = 0;
15179
        }
15180
        Py_END_ALLOW_THREADS
15181
    }
15182
    return has_ShellExecute;
15183
}
15184
15185
15186
/*[clinic input]
15187
os.startfile
15188
    filepath: path_t
15189
    operation: Py_UNICODE = NULL
15190
    arguments: Py_UNICODE = NULL
15191
    cwd: path_t(nullable=True) = None
15192
    show_cmd: int = 1
15193
15194
Start a file with its associated application.
15195
15196
When "operation" is not specified or "open", this acts like
15197
double-clicking the file in Explorer, or giving the file name as an
15198
argument to the DOS "start" command: the file is opened with whatever
15199
application (if any) its extension is associated.
15200
When another "operation" is given, it specifies what should be done with
15201
the file.  A typical operation is "print".
15202
15203
"arguments" is passed to the application, but should be omitted if the
15204
file is a document.
15205
15206
"cwd" is the working directory for the operation. If "filepath" is
15207
relative, it will be resolved against this directory. This argument
15208
should usually be an absolute path.
15209
15210
"show_cmd" can be used to override the recommended visibility option.
15211
See the Windows ShellExecute documentation for values.
15212
15213
startfile returns as soon as the associated application is launched.
15214
There is no option to wait for the application to close, and no way
15215
to retrieve the application's exit status.
15216
15217
The filepath is relative to the current directory.  If you want to use
15218
an absolute path, make sure the first character is not a slash ("/");
15219
the underlying Win32 ShellExecute function doesn't work if it is.
15220
[clinic start generated code]*/
15221
15222
static PyObject *
15223
os_startfile_impl(PyObject *module, path_t *filepath,
15224
                  const wchar_t *operation, const wchar_t *arguments,
15225
                  path_t *cwd, int show_cmd)
15226
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15227
{
15228
    HINSTANCE rc;
15229
15230
    if(!check_ShellExecute()) {
15231
        /* If the OS doesn't have ShellExecute, return a
15232
           NotImplementedError. */
15233
        return PyErr_Format(PyExc_NotImplementedError,
15234
            "startfile not available on this platform");
15235
    }
15236
15237
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15238
        return NULL;
15239
    }
15240
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15241
                    arguments, cwd->object ? cwd->object : Py_None,
15242
                    show_cmd) < 0) {
15243
        return NULL;
15244
    }
15245
15246
    Py_BEGIN_ALLOW_THREADS
15247
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15248
                          arguments, cwd->wide, show_cmd);
15249
    Py_END_ALLOW_THREADS
15250
15251
    if (rc <= (HINSTANCE)32) {
15252
        win32_error_object("startfile", filepath->object);
15253
        return NULL;
15254
    }
15255
    Py_RETURN_NONE;
15256
}
15257
#endif /* MS_WINDOWS */
15258
15259
15260
#ifdef HAVE_GETLOADAVG
15261
/*[clinic input]
15262
os.getloadavg
15263
15264
Return average recent system load information.
15265
15266
Return the number of processes in the system run queue averaged over
15267
the last 1, 5, and 15 minutes as a tuple of three floats.
15268
Raises OSError if the load average was unobtainable.
15269
[clinic start generated code]*/
15270
15271
static PyObject *
15272
os_getloadavg_impl(PyObject *module)
15273
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15274
0
{
15275
0
    double loadavg[3];
15276
0
    if (getloadavg(loadavg, 3)!=3) {
15277
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15278
0
        return NULL;
15279
0
    } else
15280
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15281
0
}
15282
#endif /* HAVE_GETLOADAVG */
15283
15284
15285
/*[clinic input]
15286
os.device_encoding
15287
    fd: int
15288
15289
Return a string describing the encoding of a terminal's file descriptor.
15290
15291
The file descriptor must be attached to a terminal.
15292
If the device is not a terminal, return None.
15293
[clinic start generated code]*/
15294
15295
static PyObject *
15296
os_device_encoding_impl(PyObject *module, int fd)
15297
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15298
0
{
15299
0
    return _Py_device_encoding(fd);
15300
0
}
15301
15302
15303
#ifdef HAVE_SETRESUID
15304
/*[clinic input]
15305
os.setresuid
15306
15307
    ruid: uid_t
15308
    euid: uid_t
15309
    suid: uid_t
15310
    /
15311
15312
Set the current process's real, effective, and saved user ids.
15313
[clinic start generated code]*/
15314
15315
static PyObject *
15316
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15317
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15318
0
{
15319
0
    if (setresuid(ruid, euid, suid) < 0)
15320
0
        return posix_error();
15321
0
    Py_RETURN_NONE;
15322
0
}
15323
#endif /* HAVE_SETRESUID */
15324
15325
15326
#ifdef HAVE_SETRESGID
15327
/*[clinic input]
15328
os.setresgid
15329
15330
    rgid: gid_t
15331
    egid: gid_t
15332
    sgid: gid_t
15333
    /
15334
15335
Set the current process's real, effective, and saved group ids.
15336
[clinic start generated code]*/
15337
15338
static PyObject *
15339
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15340
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15341
0
{
15342
0
    if (setresgid(rgid, egid, sgid) < 0)
15343
0
        return posix_error();
15344
0
    Py_RETURN_NONE;
15345
0
}
15346
#endif /* HAVE_SETRESGID */
15347
15348
15349
#ifdef HAVE_GETRESUID
15350
/*[clinic input]
15351
os.getresuid
15352
15353
Return a tuple of the current process's real, effective, and saved user ids.
15354
[clinic start generated code]*/
15355
15356
static PyObject *
15357
os_getresuid_impl(PyObject *module)
15358
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
15359
0
{
15360
0
    uid_t ruid, euid, suid;
15361
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15362
0
        return posix_error();
15363
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15364
0
                                  _PyLong_FromUid(euid),
15365
0
                                  _PyLong_FromUid(suid));
15366
0
}
15367
#endif /* HAVE_GETRESUID */
15368
15369
15370
#ifdef HAVE_GETRESGID
15371
/*[clinic input]
15372
@permit_long_summary
15373
os.getresgid
15374
15375
Return a tuple of the current process's real, effective, and saved group ids.
15376
[clinic start generated code]*/
15377
15378
static PyObject *
15379
os_getresgid_impl(PyObject *module)
15380
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15381
0
{
15382
0
    gid_t rgid, egid, sgid;
15383
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15384
0
        return posix_error();
15385
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15386
0
                                  _PyLong_FromGid(egid),
15387
0
                                  _PyLong_FromGid(sgid));
15388
0
}
15389
#endif /* HAVE_GETRESGID */
15390
15391
15392
#ifdef USE_XATTRS
15393
/*[clinic input]
15394
os.getxattr
15395
15396
    path: path_t(allow_fd=True)
15397
    attribute: path_t
15398
    *
15399
    follow_symlinks: bool = True
15400
15401
Return the value of extended attribute attribute on path.
15402
15403
path may be either a string, a path-like object, or an open file descriptor.
15404
If follow_symlinks is False, and the last element of the path is a symbolic
15405
  link, getxattr will examine the symbolic link itself instead of the file
15406
  the link points to.
15407
15408
[clinic start generated code]*/
15409
15410
static PyObject *
15411
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15412
                 int follow_symlinks)
15413
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
15414
0
{
15415
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
15416
0
        return NULL;
15417
15418
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15419
0
        return NULL;
15420
0
    }
15421
15422
0
    for (Py_ssize_t i = 0; ; i++) {
15423
0
        ssize_t result;
15424
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15425
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15426
0
        if (!buffer_size) {
15427
0
            path_error(path);
15428
0
            return NULL;
15429
0
        }
15430
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15431
0
        if (writer == NULL) {
15432
0
            return NULL;
15433
0
        }
15434
0
        void *ptr = PyBytesWriter_GetData(writer);
15435
15436
0
        Py_BEGIN_ALLOW_THREADS;
15437
0
        if (path->is_fd)
15438
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15439
0
        else if (follow_symlinks)
15440
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15441
0
        else
15442
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15443
0
        Py_END_ALLOW_THREADS;
15444
15445
0
        if (result < 0) {
15446
0
            PyBytesWriter_Discard(writer);
15447
0
            if (errno == ERANGE) {
15448
0
                continue;
15449
0
            }
15450
0
            path_error(path);
15451
0
            return NULL;
15452
0
        }
15453
15454
0
        return PyBytesWriter_FinishWithSize(writer, result);
15455
0
    }
15456
0
}
15457
15458
15459
/*[clinic input]
15460
@permit_long_docstring_body
15461
os.setxattr
15462
15463
    path: path_t(allow_fd=True)
15464
    attribute: path_t
15465
    value: Py_buffer
15466
    flags: int = 0
15467
    *
15468
    follow_symlinks: bool = True
15469
15470
Set extended attribute attribute on path to value.
15471
15472
path may be either a string, a path-like object,  or an open file descriptor.
15473
If follow_symlinks is False, and the last element of the path is a symbolic
15474
  link, setxattr will modify the symbolic link itself instead of the file
15475
  the link points to.
15476
15477
[clinic start generated code]*/
15478
15479
static PyObject *
15480
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15481
                 Py_buffer *value, int flags, int follow_symlinks)
15482
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15483
0
{
15484
0
    ssize_t result;
15485
15486
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
15487
0
        return NULL;
15488
15489
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15490
0
                    value->buf, value->len, flags) < 0) {
15491
0
        return NULL;
15492
0
    }
15493
15494
0
    Py_BEGIN_ALLOW_THREADS;
15495
0
    if (path->is_fd)
15496
0
        result = fsetxattr(path->fd, attribute->narrow,
15497
0
                           value->buf, value->len, flags);
15498
0
    else if (follow_symlinks)
15499
0
        result = setxattr(path->narrow, attribute->narrow,
15500
0
                           value->buf, value->len, flags);
15501
0
    else
15502
0
        result = lsetxattr(path->narrow, attribute->narrow,
15503
0
                           value->buf, value->len, flags);
15504
0
    Py_END_ALLOW_THREADS;
15505
15506
0
    if (result) {
15507
0
        path_error(path);
15508
0
        return NULL;
15509
0
    }
15510
15511
0
    Py_RETURN_NONE;
15512
0
}
15513
15514
15515
/*[clinic input]
15516
os.removexattr
15517
15518
    path: path_t(allow_fd=True)
15519
    attribute: path_t
15520
    *
15521
    follow_symlinks: bool = True
15522
15523
Remove extended attribute attribute on path.
15524
15525
path may be either a string, a path-like object, or an open file descriptor.
15526
If follow_symlinks is False, and the last element of the path is a symbolic
15527
  link, removexattr will modify the symbolic link itself instead of the file
15528
  the link points to.
15529
15530
[clinic start generated code]*/
15531
15532
static PyObject *
15533
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15534
                    int follow_symlinks)
15535
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15536
0
{
15537
0
    ssize_t result;
15538
15539
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
15540
0
        return NULL;
15541
15542
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15543
0
        return NULL;
15544
0
    }
15545
15546
0
    Py_BEGIN_ALLOW_THREADS;
15547
0
    if (path->is_fd)
15548
0
        result = fremovexattr(path->fd, attribute->narrow);
15549
0
    else if (follow_symlinks)
15550
0
        result = removexattr(path->narrow, attribute->narrow);
15551
0
    else
15552
0
        result = lremovexattr(path->narrow, attribute->narrow);
15553
0
    Py_END_ALLOW_THREADS;
15554
15555
0
    if (result) {
15556
0
        return path_error(path);
15557
0
    }
15558
15559
0
    Py_RETURN_NONE;
15560
0
}
15561
15562
15563
/*[clinic input]
15564
@permit_long_docstring_body
15565
os.listxattr
15566
15567
    path: path_t(allow_fd=True, nullable=True) = None
15568
    *
15569
    follow_symlinks: bool = True
15570
15571
Return a list of extended attributes on path.
15572
15573
path may be either None, a string, a path-like object, or an open file descriptor.
15574
if path is None, listxattr will examine the current directory.
15575
If follow_symlinks is False, and the last element of the path is a symbolic
15576
  link, listxattr will examine the symbolic link itself instead of the file
15577
  the link points to.
15578
[clinic start generated code]*/
15579
15580
static PyObject *
15581
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15582
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15583
0
{
15584
0
    Py_ssize_t i;
15585
0
    PyObject *result = NULL;
15586
0
    const char *name;
15587
0
    char *buffer = NULL;
15588
15589
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
15590
0
        goto exit;
15591
15592
0
    if (PySys_Audit("os.listxattr", "(O)",
15593
0
                    path->object ? path->object : Py_None) < 0) {
15594
0
        return NULL;
15595
0
    }
15596
15597
0
    name = path->narrow ? path->narrow : ".";
15598
15599
0
    for (i = 0; ; i++) {
15600
0
        const char *start, *trace, *end;
15601
0
        ssize_t length;
15602
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15603
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15604
0
        if (!buffer_size) {
15605
            /* ERANGE */
15606
0
            path_error(path);
15607
0
            break;
15608
0
        }
15609
0
        buffer = PyMem_Malloc(buffer_size);
15610
0
        if (!buffer) {
15611
0
            PyErr_NoMemory();
15612
0
            break;
15613
0
        }
15614
15615
0
        Py_BEGIN_ALLOW_THREADS;
15616
0
        if (path->is_fd)
15617
0
            length = flistxattr(path->fd, buffer, buffer_size);
15618
0
        else if (follow_symlinks)
15619
0
            length = listxattr(name, buffer, buffer_size);
15620
0
        else
15621
0
            length = llistxattr(name, buffer, buffer_size);
15622
0
        Py_END_ALLOW_THREADS;
15623
15624
0
        if (length < 0) {
15625
0
            if (errno == ERANGE) {
15626
0
                PyMem_Free(buffer);
15627
0
                buffer = NULL;
15628
0
                continue;
15629
0
            }
15630
0
            path_error(path);
15631
0
            break;
15632
0
        }
15633
15634
0
        result = PyList_New(0);
15635
0
        if (!result) {
15636
0
            goto exit;
15637
0
        }
15638
15639
0
        end = buffer + length;
15640
0
        for (trace = start = buffer; trace != end; trace++) {
15641
0
            if (!*trace) {
15642
0
                int error;
15643
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15644
0
                                                                 trace - start);
15645
0
                if (!attribute) {
15646
0
                    Py_SETREF(result, NULL);
15647
0
                    goto exit;
15648
0
                }
15649
0
                error = PyList_Append(result, attribute);
15650
0
                Py_DECREF(attribute);
15651
0
                if (error) {
15652
0
                    Py_SETREF(result, NULL);
15653
0
                    goto exit;
15654
0
                }
15655
0
                start = trace + 1;
15656
0
            }
15657
0
        }
15658
0
    break;
15659
0
    }
15660
0
exit:
15661
0
    if (buffer)
15662
0
        PyMem_Free(buffer);
15663
0
    return result;
15664
0
}
15665
#endif /* USE_XATTRS */
15666
15667
15668
/*[clinic input]
15669
@permit_long_summary
15670
os.urandom
15671
15672
    size: Py_ssize_t(allow_negative=False)
15673
    /
15674
15675
Return a bytes object containing random bytes suitable for cryptographic use.
15676
[clinic start generated code]*/
15677
15678
static PyObject *
15679
os_urandom_impl(PyObject *module, Py_ssize_t size)
15680
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15681
0
{
15682
0
    if (size < 0) {
15683
0
        return PyErr_Format(PyExc_ValueError,
15684
0
                            "negative argument not allowed");
15685
0
    }
15686
15687
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15688
0
    if (writer == NULL) {
15689
0
        return NULL;
15690
0
    }
15691
15692
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15693
0
    if (result == -1) {
15694
0
        PyBytesWriter_Discard(writer);
15695
0
        return NULL;
15696
0
    }
15697
0
    return PyBytesWriter_Finish(writer);
15698
0
}
15699
15700
#ifdef HAVE_MEMFD_CREATE
15701
/*[clinic input]
15702
os.memfd_create
15703
15704
    name: unicode_fs_encoded
15705
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15706
15707
[clinic start generated code]*/
15708
15709
static PyObject *
15710
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15711
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15712
0
{
15713
0
    int fd;
15714
0
    const char *bytes = PyBytes_AS_STRING(name);
15715
0
    Py_BEGIN_ALLOW_THREADS
15716
0
    fd = memfd_create(bytes, flags);
15717
0
    Py_END_ALLOW_THREADS
15718
0
    if (fd == -1) {
15719
0
        return PyErr_SetFromErrno(PyExc_OSError);
15720
0
    }
15721
0
    return PyLong_FromLong(fd);
15722
0
}
15723
#endif
15724
15725
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15726
/*[clinic input]
15727
os.eventfd
15728
15729
    initval: unsigned_int
15730
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15731
15732
Creates and returns an event notification file descriptor.
15733
[clinic start generated code]*/
15734
15735
static PyObject *
15736
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15737
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15738
15739
0
{
15740
    /* initval is limited to uint32_t, internal counter is uint64_t */
15741
0
    int fd;
15742
0
    Py_BEGIN_ALLOW_THREADS
15743
0
    fd = eventfd(initval, flags);
15744
0
    Py_END_ALLOW_THREADS
15745
0
    if (fd == -1) {
15746
0
        return PyErr_SetFromErrno(PyExc_OSError);
15747
0
    }
15748
0
    return PyLong_FromLong(fd);
15749
0
}
15750
15751
/*[clinic input]
15752
os.eventfd_read
15753
15754
    fd: fildes
15755
15756
Read eventfd value
15757
[clinic start generated code]*/
15758
15759
static PyObject *
15760
os_eventfd_read_impl(PyObject *module, int fd)
15761
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15762
0
{
15763
0
    eventfd_t value;
15764
0
    int result;
15765
0
    Py_BEGIN_ALLOW_THREADS
15766
0
    result = eventfd_read(fd, &value);
15767
0
    Py_END_ALLOW_THREADS
15768
0
    if (result == -1) {
15769
0
        return PyErr_SetFromErrno(PyExc_OSError);
15770
0
    }
15771
0
    return PyLong_FromUnsignedLongLong(value);
15772
0
}
15773
15774
/*[clinic input]
15775
os.eventfd_write
15776
15777
    fd: fildes
15778
    value: unsigned_long_long
15779
15780
Write eventfd value.
15781
[clinic start generated code]*/
15782
15783
static PyObject *
15784
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15785
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15786
0
{
15787
0
    int result;
15788
0
    Py_BEGIN_ALLOW_THREADS
15789
0
    result = eventfd_write(fd, value);
15790
0
    Py_END_ALLOW_THREADS
15791
0
    if (result == -1) {
15792
0
        return PyErr_SetFromErrno(PyExc_OSError);
15793
0
    }
15794
0
    Py_RETURN_NONE;
15795
0
}
15796
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15797
15798
/* Terminal size querying */
15799
15800
PyDoc_STRVAR(TerminalSize_docstring,
15801
    "A tuple of (columns, lines) for holding terminal window size");
15802
15803
static PyStructSequence_Field TerminalSize_fields[] = {
15804
    {"columns", "width of the terminal window in characters"},
15805
    {"lines", "height of the terminal window in characters"},
15806
    {NULL, NULL}
15807
};
15808
15809
static PyStructSequence_Desc TerminalSize_desc = {
15810
    "os.terminal_size",
15811
    TerminalSize_docstring,
15812
    TerminalSize_fields,
15813
    2,
15814
};
15815
15816
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15817
/*[clinic input]
15818
os.get_terminal_size
15819
15820
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15821
    /
15822
15823
Return the size of the terminal window as (columns, lines).
15824
15825
The optional argument fd (default standard output) specifies
15826
which file descriptor should be queried.
15827
15828
If the file descriptor is not connected to a terminal, an OSError
15829
is thrown.
15830
15831
This function will only be defined if an implementation is
15832
available for this system.
15833
15834
shutil.get_terminal_size is the high-level function which should
15835
normally be used, os.get_terminal_size is the low-level implementation.
15836
[clinic start generated code]*/
15837
15838
static PyObject *
15839
os_get_terminal_size_impl(PyObject *module, int fd)
15840
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15841
0
{
15842
0
    int columns, lines;
15843
0
    PyObject *termsize;
15844
15845
    /* Under some conditions stdout may not be connected and
15846
     * fileno(stdout) may point to an invalid file descriptor. For example
15847
     * GUI apps don't have valid standard streams by default.
15848
     *
15849
     * If this happens, and the optional fd argument is not present,
15850
     * the ioctl below will fail returning EBADF. This is what we want.
15851
     */
15852
15853
0
#ifdef TERMSIZE_USE_IOCTL
15854
0
    {
15855
0
        struct winsize w;
15856
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15857
0
            return PyErr_SetFromErrno(PyExc_OSError);
15858
0
        columns = w.ws_col;
15859
0
        lines = w.ws_row;
15860
0
    }
15861
0
#endif /* TERMSIZE_USE_IOCTL */
15862
15863
#ifdef TERMSIZE_USE_CONIO
15864
    {
15865
        HANDLE handle;
15866
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15867
        handle = _Py_get_osfhandle(fd);
15868
        if (handle == INVALID_HANDLE_VALUE)
15869
            return NULL;
15870
15871
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15872
            return PyErr_SetFromWindowsErr(0);
15873
15874
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15875
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15876
    }
15877
#endif /* TERMSIZE_USE_CONIO */
15878
15879
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15880
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15881
0
    if (termsize == NULL)
15882
0
        return NULL;
15883
15884
0
    int pos = 0;
15885
15886
0
#define SET_TERMSIZE(CALL)                                   \
15887
0
    do {                                                     \
15888
0
        PyObject *item = (CALL);                             \
15889
0
        if (item == NULL) {                                  \
15890
0
            Py_DECREF(termsize);                             \
15891
0
            return NULL;                                     \
15892
0
        }                                                    \
15893
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15894
0
    } while(0)
15895
15896
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15897
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15898
0
#undef SET_TERMSIZE
15899
15900
0
    return termsize;
15901
0
}
15902
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15903
15904
/*[clinic input]
15905
os.cpu_count
15906
15907
Return the number of logical CPUs in the system.
15908
15909
Return None if indeterminable.
15910
[clinic start generated code]*/
15911
15912
static PyObject *
15913
os_cpu_count_impl(PyObject *module)
15914
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15915
0
{
15916
0
    const PyConfig *config = _Py_GetConfig();
15917
0
    if (config->cpu_count > 0) {
15918
0
        return PyLong_FromLong(config->cpu_count);
15919
0
    }
15920
15921
0
    int ncpu = 0;
15922
#ifdef MS_WINDOWS
15923
# ifdef MS_WINDOWS_DESKTOP
15924
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15925
# else
15926
    ncpu = 0;
15927
# endif
15928
15929
#elif defined(__hpux)
15930
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15931
15932
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15933
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15934
15935
#elif defined(__VXWORKS__)
15936
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15937
15938
#elif defined(__DragonFly__) || \
15939
      defined(__OpenBSD__)   || \
15940
      defined(__FreeBSD__)   || \
15941
      defined(__NetBSD__)    || \
15942
      defined(__APPLE__)
15943
    ncpu = 0;
15944
    size_t len = sizeof(ncpu);
15945
    int mib[2] = {CTL_HW, HW_NCPU};
15946
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15947
        ncpu = 0;
15948
    }
15949
#endif
15950
15951
0
    if (ncpu < 1) {
15952
0
        Py_RETURN_NONE;
15953
0
    }
15954
0
    return PyLong_FromLong(ncpu);
15955
0
}
15956
15957
15958
/*[clinic input]
15959
os.get_inheritable -> bool
15960
15961
    fd: int
15962
    /
15963
15964
Get the close-on-exe flag of the specified file descriptor.
15965
[clinic start generated code]*/
15966
15967
static int
15968
os_get_inheritable_impl(PyObject *module, int fd)
15969
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15970
0
{
15971
0
    int return_value;
15972
0
    _Py_BEGIN_SUPPRESS_IPH
15973
0
    return_value = _Py_get_inheritable(fd);
15974
0
    _Py_END_SUPPRESS_IPH
15975
0
    return return_value;
15976
0
}
15977
15978
15979
/*[clinic input]
15980
os.set_inheritable
15981
    fd: int
15982
    inheritable: int
15983
    /
15984
15985
Set the inheritable flag of the specified file descriptor.
15986
[clinic start generated code]*/
15987
15988
static PyObject *
15989
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15990
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15991
0
{
15992
0
    int result;
15993
15994
0
    _Py_BEGIN_SUPPRESS_IPH
15995
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15996
0
    _Py_END_SUPPRESS_IPH
15997
0
    if (result < 0)
15998
0
        return NULL;
15999
0
    Py_RETURN_NONE;
16000
0
}
16001
16002
16003
#ifdef MS_WINDOWS
16004
#ifndef HANDLE_FLAG_INHERIT
16005
#define HANDLE_FLAG_INHERIT 0x00000001
16006
#endif
16007
16008
/*[clinic input]
16009
os.get_handle_inheritable -> bool
16010
    handle: intptr_t
16011
    /
16012
16013
Get the close-on-exe flag of the specified file descriptor.
16014
[clinic start generated code]*/
16015
16016
static int
16017
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16018
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16019
{
16020
    DWORD flags;
16021
16022
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16023
        PyErr_SetFromWindowsErr(0);
16024
        return -1;
16025
    }
16026
16027
    return flags & HANDLE_FLAG_INHERIT;
16028
}
16029
16030
16031
/*[clinic input]
16032
os.set_handle_inheritable
16033
    handle: intptr_t
16034
    inheritable: bool
16035
    /
16036
16037
Set the inheritable flag of the specified handle.
16038
[clinic start generated code]*/
16039
16040
static PyObject *
16041
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16042
                               int inheritable)
16043
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16044
{
16045
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16046
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16047
        PyErr_SetFromWindowsErr(0);
16048
        return NULL;
16049
    }
16050
    Py_RETURN_NONE;
16051
}
16052
#endif /* MS_WINDOWS */
16053
16054
/*[clinic input]
16055
os.get_blocking -> bool
16056
    fd: int
16057
    /
16058
16059
Get the blocking mode of the file descriptor.
16060
16061
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16062
[clinic start generated code]*/
16063
16064
static int
16065
os_get_blocking_impl(PyObject *module, int fd)
16066
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16067
0
{
16068
0
    int blocking;
16069
16070
0
    _Py_BEGIN_SUPPRESS_IPH
16071
0
    blocking = _Py_get_blocking(fd);
16072
0
    _Py_END_SUPPRESS_IPH
16073
0
    return blocking;
16074
0
}
16075
16076
/*[clinic input]
16077
os.set_blocking
16078
    fd: int
16079
    blocking: bool
16080
    /
16081
16082
Set the blocking mode of the specified file descriptor.
16083
16084
Set the O_NONBLOCK flag if blocking is False,
16085
clear the O_NONBLOCK flag otherwise.
16086
[clinic start generated code]*/
16087
16088
static PyObject *
16089
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16090
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16091
0
{
16092
0
    int result;
16093
16094
0
    _Py_BEGIN_SUPPRESS_IPH
16095
0
    result = _Py_set_blocking(fd, blocking);
16096
0
    _Py_END_SUPPRESS_IPH
16097
0
    if (result < 0)
16098
0
        return NULL;
16099
0
    Py_RETURN_NONE;
16100
0
}
16101
16102
16103
/*[clinic input]
16104
class os.DirEntry "DirEntry *" "DirEntryType"
16105
[clinic start generated code]*/
16106
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16107
16108
typedef struct {
16109
    PyObject_HEAD
16110
    PyObject *name;
16111
    PyObject *path;
16112
    PyObject *stat;
16113
    PyObject *lstat;
16114
#ifdef MS_WINDOWS
16115
    struct _Py_stat_struct win32_lstat;
16116
    uint64_t win32_file_index;
16117
    uint64_t win32_file_index_high;
16118
    int got_file_index;
16119
#else /* POSIX */
16120
#ifdef HAVE_DIRENT_D_TYPE
16121
    unsigned char d_type;
16122
#endif
16123
    ino_t d_ino;
16124
    int dir_fd;
16125
#endif
16126
} DirEntry;
16127
16128
189k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16129
16130
static void
16131
DirEntry_dealloc(PyObject *op)
16132
189k
{
16133
189k
    DirEntry *entry = DirEntry_CAST(op);
16134
189k
    PyTypeObject *tp = Py_TYPE(entry);
16135
189k
    Py_XDECREF(entry->name);
16136
189k
    Py_XDECREF(entry->path);
16137
189k
    Py_XDECREF(entry->stat);
16138
189k
    Py_XDECREF(entry->lstat);
16139
189k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16140
189k
    free_func(entry);
16141
189k
    Py_DECREF(tp);
16142
189k
}
16143
16144
/* Forward reference */
16145
static int
16146
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16147
                   int follow_symlinks, unsigned short mode_bits);
16148
16149
/*[clinic input]
16150
os.DirEntry.is_symlink -> bool
16151
    defining_class: defining_class
16152
    /
16153
16154
Return True if the entry is a symbolic link; cached per entry.
16155
[clinic start generated code]*/
16156
16157
static int
16158
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16159
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16160
0
{
16161
#ifdef MS_WINDOWS
16162
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16163
#elif defined(HAVE_DIRENT_D_TYPE)
16164
    /* POSIX */
16165
0
    if (self->d_type != DT_UNKNOWN)
16166
0
        return self->d_type == DT_LNK;
16167
0
    else
16168
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16169
#else
16170
    /* POSIX without d_type */
16171
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16172
#endif
16173
0
}
16174
16175
/*[clinic input]
16176
os.DirEntry.is_junction -> bool
16177
16178
Return True if the entry is a junction; cached per entry.
16179
[clinic start generated code]*/
16180
16181
static int
16182
os_DirEntry_is_junction_impl(DirEntry *self)
16183
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16184
0
{
16185
#ifdef MS_WINDOWS
16186
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16187
#else
16188
0
    return 0;
16189
0
#endif
16190
0
}
16191
16192
static PyObject *
16193
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16194
163k
{
16195
163k
    int result;
16196
163k
    STRUCT_STAT st;
16197
163k
    PyObject *ub;
16198
16199
#ifdef MS_WINDOWS
16200
    if (!PyUnicode_FSDecoder(self->path, &ub))
16201
        return NULL;
16202
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16203
    Py_DECREF(ub);
16204
#else /* POSIX */
16205
163k
    if (!PyUnicode_FSConverter(self->path, &ub))
16206
0
        return NULL;
16207
163k
    const char *path = PyBytes_AS_STRING(ub);
16208
163k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16209
163k
#ifdef HAVE_FSTATAT
16210
163k
      if (HAVE_FSTATAT_RUNTIME) {
16211
163k
        Py_BEGIN_ALLOW_THREADS
16212
163k
        result = fstatat(self->dir_fd, path, &st,
16213
163k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16214
163k
        Py_END_ALLOW_THREADS
16215
163k
      } else
16216
16217
0
#endif /* HAVE_FSTATAT */
16218
0
      {
16219
0
        Py_DECREF(ub);
16220
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16221
0
        return NULL;
16222
0
      }
16223
163k
    }
16224
0
    else
16225
0
#endif
16226
0
    {
16227
0
        Py_BEGIN_ALLOW_THREADS
16228
0
        if (follow_symlinks) {
16229
0
            result = STAT(path, &st);
16230
0
        }
16231
0
        else {
16232
0
            result = LSTAT(path, &st);
16233
0
        }
16234
0
        Py_END_ALLOW_THREADS
16235
0
    }
16236
16237
163k
    int saved_errno = errno;
16238
#if defined(MS_WINDOWS)
16239
    PyMem_Free(path);
16240
#else
16241
163k
    Py_DECREF(ub);
16242
163k
#endif
16243
16244
163k
    if (result != 0) {
16245
0
        errno = saved_errno;
16246
0
        path_object_error(self->path);
16247
0
        return NULL;
16248
0
    }
16249
16250
163k
    return _pystat_fromstructstat(module, &st);
16251
163k
}
16252
16253
static PyObject *
16254
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16255
163k
{
16256
163k
    if (!self->lstat) {
16257
163k
        PyObject *module = PyType_GetModule(defining_class);
16258
#ifdef MS_WINDOWS
16259
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16260
#else /* POSIX */
16261
163k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16262
163k
#endif
16263
163k
    }
16264
163k
    return Py_XNewRef(self->lstat);
16265
163k
}
16266
16267
/*[clinic input]
16268
os.DirEntry.stat
16269
    defining_class: defining_class
16270
    /
16271
    *
16272
    follow_symlinks: bool = True
16273
16274
Return stat_result object for the entry; cached per entry.
16275
[clinic start generated code]*/
16276
16277
static PyObject *
16278
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16279
                      int follow_symlinks)
16280
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16281
163k
{
16282
163k
    if (!follow_symlinks) {
16283
163k
        return DirEntry_get_lstat(defining_class, self);
16284
163k
    }
16285
16286
0
    if (!self->stat) {
16287
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16288
0
        if (result == -1) {
16289
0
            return NULL;
16290
0
        }
16291
0
        if (result) {
16292
0
            PyObject *module = PyType_GetModule(defining_class);
16293
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16294
0
        }
16295
0
        else {
16296
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16297
0
        }
16298
0
    }
16299
16300
0
    return Py_XNewRef(self->stat);
16301
0
}
16302
16303
/* Set exception and return -1 on error, 0 for False, 1 for True */
16304
static int
16305
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16306
                   int follow_symlinks, unsigned short mode_bits)
16307
189k
{
16308
189k
    PyObject *stat = NULL;
16309
189k
    PyObject *st_mode = NULL;
16310
189k
    long mode;
16311
189k
    int result;
16312
189k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16313
189k
    int is_symlink;
16314
189k
    int need_stat;
16315
189k
#endif
16316
#ifdef MS_WINDOWS
16317
    unsigned long dir_bits;
16318
#endif
16319
16320
#ifdef MS_WINDOWS
16321
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16322
    need_stat = follow_symlinks && is_symlink;
16323
#elif defined(HAVE_DIRENT_D_TYPE)
16324
189k
    is_symlink = self->d_type == DT_LNK;
16325
189k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16326
189k
#endif
16327
16328
189k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16329
189k
    if (need_stat) {
16330
0
#endif
16331
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16332
0
        if (!stat) {
16333
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16334
                /* If file doesn't exist (anymore), then return False
16335
                   (i.e., say it's not a file/directory) */
16336
0
                PyErr_Clear();
16337
0
                return 0;
16338
0
            }
16339
0
            goto error;
16340
0
        }
16341
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16342
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16343
0
        if (!st_mode)
16344
0
            goto error;
16345
16346
0
        mode = PyLong_AsLong(st_mode);
16347
0
        if (mode == -1 && PyErr_Occurred())
16348
0
            goto error;
16349
0
        Py_CLEAR(st_mode);
16350
0
        Py_CLEAR(stat);
16351
0
        result = (mode & S_IFMT) == mode_bits;
16352
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16353
0
    }
16354
189k
    else if (is_symlink) {
16355
0
        assert(mode_bits != S_IFLNK);
16356
0
        result = 0;
16357
0
    }
16358
189k
    else {
16359
189k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16360
#ifdef MS_WINDOWS
16361
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16362
        if (mode_bits == S_IFDIR)
16363
            result = dir_bits != 0;
16364
        else
16365
            result = dir_bits == 0;
16366
#else /* POSIX */
16367
189k
        if (mode_bits == S_IFDIR)
16368
189k
            result = self->d_type == DT_DIR;
16369
0
        else
16370
0
            result = self->d_type == DT_REG;
16371
189k
#endif
16372
189k
    }
16373
189k
#endif
16374
16375
189k
    return result;
16376
16377
0
error:
16378
0
    Py_XDECREF(st_mode);
16379
0
    Py_XDECREF(stat);
16380
0
    return -1;
16381
189k
}
16382
16383
/*[clinic input]
16384
os.DirEntry.is_dir -> bool
16385
    defining_class: defining_class
16386
    /
16387
    *
16388
    follow_symlinks: bool = True
16389
16390
Return True if the entry is a directory; cached per entry.
16391
[clinic start generated code]*/
16392
16393
static int
16394
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16395
                        int follow_symlinks)
16396
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16397
189k
{
16398
189k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16399
189k
}
16400
16401
/*[clinic input]
16402
os.DirEntry.is_file -> bool
16403
    defining_class: defining_class
16404
    /
16405
    *
16406
    follow_symlinks: bool = True
16407
16408
Return True if the entry is a file; cached per entry.
16409
[clinic start generated code]*/
16410
16411
static int
16412
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16413
                         int follow_symlinks)
16414
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16415
0
{
16416
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16417
0
}
16418
16419
/*[clinic input]
16420
os.DirEntry.inode
16421
16422
Return inode of the entry; cached per entry.
16423
[clinic start generated code]*/
16424
16425
static PyObject *
16426
os_DirEntry_inode_impl(DirEntry *self)
16427
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16428
0
{
16429
#ifdef MS_WINDOWS
16430
    if (!self->got_file_index) {
16431
        PyObject *unicode;
16432
        STRUCT_STAT stat;
16433
        int result;
16434
16435
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16436
            return NULL;
16437
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16438
        Py_DECREF(unicode);
16439
        result = LSTAT(path, &stat);
16440
16441
        int saved_errno = errno;
16442
        PyMem_Free(path);
16443
16444
        if (result != 0) {
16445
            errno = saved_errno;
16446
            return path_object_error(self->path);
16447
        }
16448
16449
        self->win32_file_index = stat.st_ino;
16450
        self->win32_file_index_high = stat.st_ino_high;
16451
        self->got_file_index = 1;
16452
    }
16453
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16454
#else /* POSIX */
16455
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16456
0
                  "DirEntry.d_ino is larger than unsigned long long");
16457
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16458
0
#endif
16459
0
}
16460
16461
static PyObject *
16462
DirEntry_repr(PyObject *op)
16463
0
{
16464
0
    DirEntry *self = DirEntry_CAST(op);
16465
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16466
0
}
16467
16468
/*[clinic input]
16469
os.DirEntry.__fspath__
16470
16471
Returns the path for the entry.
16472
[clinic start generated code]*/
16473
16474
static PyObject *
16475
os_DirEntry___fspath___impl(DirEntry *self)
16476
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16477
0
{
16478
0
    return Py_NewRef(self->path);
16479
0
}
16480
16481
static PyMemberDef DirEntry_members[] = {
16482
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16483
     "the entry's base filename, relative to scandir() \"path\" argument"},
16484
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16485
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16486
    {NULL}
16487
};
16488
16489
#include "clinic/posixmodule.c.h"
16490
16491
static PyMethodDef DirEntry_methods[] = {
16492
    OS_DIRENTRY_IS_DIR_METHODDEF
16493
    OS_DIRENTRY_IS_FILE_METHODDEF
16494
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16495
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16496
    OS_DIRENTRY_STAT_METHODDEF
16497
    OS_DIRENTRY_INODE_METHODDEF
16498
    OS_DIRENTRY___FSPATH___METHODDEF
16499
    {"__class_getitem__",       Py_GenericAlias,
16500
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16501
    {NULL}
16502
};
16503
16504
static PyType_Slot DirEntryType_slots[] = {
16505
    {Py_tp_dealloc, DirEntry_dealloc},
16506
    {Py_tp_repr, DirEntry_repr},
16507
    {Py_tp_methods, DirEntry_methods},
16508
    {Py_tp_members, DirEntry_members},
16509
    {0, 0},
16510
};
16511
16512
static PyType_Spec DirEntryType_spec = {
16513
    .name = MODNAME ".DirEntry",
16514
    .basicsize = sizeof(DirEntry),
16515
    .flags = (
16516
        Py_TPFLAGS_DEFAULT
16517
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16518
        | Py_TPFLAGS_IMMUTABLETYPE
16519
    ),
16520
    .slots = DirEntryType_slots
16521
};
16522
16523
16524
#ifdef MS_WINDOWS
16525
16526
static wchar_t *
16527
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16528
{
16529
    Py_ssize_t path_len;
16530
    Py_ssize_t size;
16531
    wchar_t *result;
16532
    wchar_t ch;
16533
16534
    if (!path_wide) { /* Default arg: "." */
16535
        path_wide = L".";
16536
        path_len = 1;
16537
    }
16538
    else {
16539
        path_len = wcslen(path_wide);
16540
    }
16541
16542
    /* The +1's are for the path separator and the NUL */
16543
    size = path_len + 1 + wcslen(filename) + 1;
16544
    result = PyMem_New(wchar_t, size);
16545
    if (!result) {
16546
        PyErr_NoMemory();
16547
        return NULL;
16548
    }
16549
    wcscpy(result, path_wide);
16550
    if (path_len > 0) {
16551
        ch = result[path_len - 1];
16552
        if (ch != SEP && ch != ALTSEP && ch != L':')
16553
            result[path_len++] = SEP;
16554
        wcscpy(result + path_len, filename);
16555
    }
16556
    return result;
16557
}
16558
16559
static PyObject *
16560
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16561
{
16562
    DirEntry *entry;
16563
    BY_HANDLE_FILE_INFORMATION file_info;
16564
    ULONG reparse_tag;
16565
    wchar_t *joined_path;
16566
16567
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16568
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16569
    if (!entry)
16570
        return NULL;
16571
    entry->name = NULL;
16572
    entry->path = NULL;
16573
    entry->stat = NULL;
16574
    entry->lstat = NULL;
16575
    entry->got_file_index = 0;
16576
16577
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16578
    if (!entry->name)
16579
        goto error;
16580
    int return_bytes = path->wide && PyBytes_Check(path->object);
16581
    if (return_bytes) {
16582
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16583
        if (!entry->name)
16584
            goto error;
16585
    }
16586
16587
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16588
    if (!joined_path)
16589
        goto error;
16590
16591
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16592
    PyMem_Free(joined_path);
16593
    if (!entry->path)
16594
        goto error;
16595
    if (return_bytes) {
16596
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16597
        if (!entry->path)
16598
            goto error;
16599
    }
16600
16601
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16602
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16603
16604
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16605
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16606
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16607
16608
    return (PyObject *)entry;
16609
16610
error:
16611
    Py_DECREF(entry);
16612
    return NULL;
16613
}
16614
16615
#else /* POSIX */
16616
16617
static char *
16618
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16619
0
{
16620
0
    Py_ssize_t path_len;
16621
0
    Py_ssize_t size;
16622
0
    char *result;
16623
16624
0
    if (!path_narrow) { /* Default arg: "." */
16625
0
        path_narrow = ".";
16626
0
        path_len = 1;
16627
0
    }
16628
0
    else {
16629
0
        path_len = strlen(path_narrow);
16630
0
    }
16631
16632
0
    if (filename_len == -1)
16633
0
        filename_len = strlen(filename);
16634
16635
    /* The +1's are for the path separator and the NUL */
16636
0
    size = path_len + 1 + filename_len + 1;
16637
0
    result = PyMem_New(char, size);
16638
0
    if (!result) {
16639
0
        PyErr_NoMemory();
16640
0
        return NULL;
16641
0
    }
16642
0
    strcpy(result, path_narrow);
16643
0
    if (path_len > 0 && result[path_len - 1] != '/')
16644
0
        result[path_len++] = '/';
16645
0
    strcpy(result + path_len, filename);
16646
0
    return result;
16647
0
}
16648
16649
static PyObject *
16650
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16651
                         Py_ssize_t name_len, ino_t d_ino
16652
#ifdef HAVE_DIRENT_D_TYPE
16653
                         , unsigned char d_type
16654
#endif
16655
                         )
16656
189k
{
16657
189k
    DirEntry *entry;
16658
189k
    char *joined_path;
16659
16660
189k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16661
189k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16662
189k
    if (!entry)
16663
0
        return NULL;
16664
189k
    entry->name = NULL;
16665
189k
    entry->path = NULL;
16666
189k
    entry->stat = NULL;
16667
189k
    entry->lstat = NULL;
16668
16669
189k
    if (path->is_fd) {
16670
189k
        entry->dir_fd = path->fd;
16671
189k
        joined_path = NULL;
16672
189k
    }
16673
0
    else {
16674
0
        entry->dir_fd = DEFAULT_DIR_FD;
16675
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16676
0
        if (!joined_path)
16677
0
            goto error;
16678
0
    }
16679
16680
189k
    if (!path->narrow || !PyBytes_Check(path->object)) {
16681
189k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16682
189k
        if (joined_path)
16683
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16684
189k
    }
16685
0
    else {
16686
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16687
0
        if (joined_path)
16688
0
            entry->path = PyBytes_FromString(joined_path);
16689
0
    }
16690
189k
    PyMem_Free(joined_path);
16691
189k
    if (!entry->name)
16692
0
        goto error;
16693
16694
189k
    if (path->is_fd) {
16695
189k
        entry->path = Py_NewRef(entry->name);
16696
189k
    }
16697
0
    else if (!entry->path)
16698
0
        goto error;
16699
16700
189k
#ifdef HAVE_DIRENT_D_TYPE
16701
189k
    entry->d_type = d_type;
16702
189k
#endif
16703
189k
    entry->d_ino = d_ino;
16704
16705
189k
    return (PyObject *)entry;
16706
16707
0
error:
16708
0
    Py_XDECREF(entry);
16709
0
    return NULL;
16710
189k
}
16711
16712
#endif
16713
16714
16715
typedef struct {
16716
    PyObject_HEAD
16717
    path_t path;
16718
#ifdef MS_WINDOWS
16719
    HANDLE handle;
16720
    WIN32_FIND_DATAW file_data;
16721
    int first_time;
16722
#else /* POSIX */
16723
    DIR *dirp;
16724
#endif
16725
#ifdef HAVE_FDOPENDIR
16726
    int fd;
16727
#endif
16728
} ScandirIterator;
16729
16730
691k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16731
16732
#ifdef MS_WINDOWS
16733
16734
static int
16735
ScandirIterator_is_closed(ScandirIterator *iterator)
16736
{
16737
    return iterator->handle == INVALID_HANDLE_VALUE;
16738
}
16739
16740
static void
16741
ScandirIterator_closedir(ScandirIterator *iterator)
16742
{
16743
    HANDLE handle = iterator->handle;
16744
16745
    if (handle == INVALID_HANDLE_VALUE)
16746
        return;
16747
16748
    iterator->handle = INVALID_HANDLE_VALUE;
16749
    Py_BEGIN_ALLOW_THREADS
16750
    FindClose(handle);
16751
    Py_END_ALLOW_THREADS
16752
}
16753
16754
static PyObject *
16755
ScandirIterator_iternext(PyObject *op)
16756
{
16757
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16758
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16759
    BOOL success;
16760
    PyObject *entry;
16761
16762
    /* Happens if the iterator is iterated twice, or closed explicitly */
16763
    if (iterator->handle == INVALID_HANDLE_VALUE)
16764
        return NULL;
16765
16766
    while (1) {
16767
        if (!iterator->first_time) {
16768
            Py_BEGIN_ALLOW_THREADS
16769
            success = FindNextFileW(iterator->handle, file_data);
16770
            Py_END_ALLOW_THREADS
16771
            if (!success) {
16772
                /* Error or no more files */
16773
                if (GetLastError() != ERROR_NO_MORE_FILES)
16774
                    path_error(&iterator->path);
16775
                break;
16776
            }
16777
        }
16778
        iterator->first_time = 0;
16779
16780
        /* Skip over . and .. */
16781
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16782
            wcscmp(file_data->cFileName, L"..") != 0)
16783
        {
16784
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16785
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16786
            if (!entry)
16787
                break;
16788
            return entry;
16789
        }
16790
16791
        /* Loop till we get a non-dot directory or finish iterating */
16792
    }
16793
16794
    /* Error or no more files */
16795
    ScandirIterator_closedir(iterator);
16796
    return NULL;
16797
}
16798
16799
#else /* POSIX */
16800
16801
static int
16802
ScandirIterator_is_closed(ScandirIterator *iterator)
16803
167k
{
16804
167k
    return !iterator->dirp;
16805
167k
}
16806
16807
static void
16808
ScandirIterator_closedir(ScandirIterator *iterator)
16809
334k
{
16810
334k
    DIR *dirp = iterator->dirp;
16811
16812
334k
    if (!dirp)
16813
167k
        return;
16814
16815
167k
    iterator->dirp = NULL;
16816
167k
    Py_BEGIN_ALLOW_THREADS
16817
167k
#ifdef HAVE_FDOPENDIR
16818
167k
    if (iterator->path.is_fd) {
16819
167k
        rewinddir(dirp);
16820
167k
    }
16821
167k
#endif
16822
167k
    closedir(dirp);
16823
167k
    Py_END_ALLOW_THREADS
16824
167k
    return;
16825
334k
}
16826
16827
static PyObject *
16828
ScandirIterator_iternext(PyObject *op)
16829
357k
{
16830
357k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16831
357k
    struct dirent *direntp;
16832
357k
    Py_ssize_t name_len;
16833
357k
    int is_dot;
16834
357k
    PyObject *entry;
16835
16836
    /* Happens if the iterator is iterated twice, or closed explicitly */
16837
357k
    if (!iterator->dirp)
16838
0
        return NULL;
16839
16840
691k
    while (1) {
16841
691k
        errno = 0;
16842
691k
        Py_BEGIN_ALLOW_THREADS
16843
691k
        direntp = readdir(iterator->dirp);
16844
691k
        Py_END_ALLOW_THREADS
16845
16846
691k
        if (!direntp) {
16847
            /* Error or no more files */
16848
167k
            if (errno != 0)
16849
0
                path_error(&iterator->path);
16850
167k
            break;
16851
167k
        }
16852
16853
        /* Skip over . and .. */
16854
524k
        name_len = NAMLEN(direntp);
16855
524k
        is_dot = direntp->d_name[0] == '.' &&
16856
336k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16857
524k
        if (!is_dot) {
16858
189k
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16859
189k
            entry = DirEntry_from_posix_info(module,
16860
189k
                                             &iterator->path, direntp->d_name,
16861
189k
                                             name_len, direntp->d_ino
16862
189k
#ifdef HAVE_DIRENT_D_TYPE
16863
189k
                                             , direntp->d_type
16864
189k
#endif
16865
189k
                                            );
16866
189k
            if (!entry)
16867
0
                break;
16868
189k
            return entry;
16869
189k
        }
16870
16871
        /* Loop till we get a non-dot directory or finish iterating */
16872
524k
    }
16873
16874
    /* Error or no more files */
16875
167k
    ScandirIterator_closedir(iterator);
16876
167k
    return NULL;
16877
357k
}
16878
16879
#endif
16880
16881
static PyObject *
16882
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16883
0
{
16884
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16885
0
    ScandirIterator_closedir(self);
16886
0
    Py_RETURN_NONE;
16887
0
}
16888
16889
static PyObject *
16890
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16891
167k
{
16892
167k
    return Py_NewRef(self);
16893
167k
}
16894
16895
static PyObject *
16896
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16897
167k
{
16898
167k
    ScandirIterator *self = ScandirIterator_CAST(op);
16899
167k
    ScandirIterator_closedir(self);
16900
167k
    Py_RETURN_NONE;
16901
167k
}
16902
16903
static void
16904
ScandirIterator_finalize(PyObject *op)
16905
167k
{
16906
167k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16907
    /* Save the current exception, if any. */
16908
167k
    PyObject *exc = PyErr_GetRaisedException();
16909
16910
167k
    if (!ScandirIterator_is_closed(iterator)) {
16911
0
        ScandirIterator_closedir(iterator);
16912
16913
0
        if (PyErr_ResourceWarning(op, 1,
16914
0
                                  "unclosed scandir iterator %R", iterator))
16915
0
        {
16916
            /* Spurious errors can appear at shutdown */
16917
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16918
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16919
0
                                       "scandir iterator %R", iterator);
16920
0
            }
16921
0
        }
16922
0
    }
16923
16924
167k
    path_cleanup(&iterator->path);
16925
16926
    /* Restore the saved exception. */
16927
167k
    PyErr_SetRaisedException(exc);
16928
167k
}
16929
16930
static void
16931
ScandirIterator_dealloc(PyObject *op)
16932
167k
{
16933
167k
    PyTypeObject *tp = Py_TYPE(op);
16934
167k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16935
0
        return;
16936
16937
167k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16938
167k
    free_func(op);
16939
167k
    Py_DECREF(tp);
16940
167k
}
16941
16942
static PyMethodDef ScandirIterator_methods[] = {
16943
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16944
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16945
    {"close", ScandirIterator_close, METH_NOARGS},
16946
    {NULL}
16947
};
16948
16949
static PyType_Slot ScandirIteratorType_slots[] = {
16950
    {Py_tp_dealloc, ScandirIterator_dealloc},
16951
    {Py_tp_finalize, ScandirIterator_finalize},
16952
    {Py_tp_iter, PyObject_SelfIter},
16953
    {Py_tp_iternext, ScandirIterator_iternext},
16954
    {Py_tp_methods, ScandirIterator_methods},
16955
    {0, 0},
16956
};
16957
16958
static PyType_Spec ScandirIteratorType_spec = {
16959
    .name = MODNAME ".ScandirIterator",
16960
    .basicsize = sizeof(ScandirIterator),
16961
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16962
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16963
    .flags = (
16964
        Py_TPFLAGS_DEFAULT
16965
        | Py_TPFLAGS_HAVE_FINALIZE
16966
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16967
        | Py_TPFLAGS_IMMUTABLETYPE
16968
    ),
16969
    .slots = ScandirIteratorType_slots
16970
};
16971
16972
/*[clinic input]
16973
os.scandir
16974
16975
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16976
16977
Return an iterator of DirEntry objects for given path.
16978
16979
path can be specified as either str, bytes, or a path-like object.  If path
16980
is bytes, the names of yielded DirEntry objects will also be bytes; in
16981
all other circumstances they will be str.
16982
16983
If path is None, uses the path='.'.
16984
[clinic start generated code]*/
16985
16986
static PyObject *
16987
os_scandir_impl(PyObject *module, path_t *path)
16988
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16989
167k
{
16990
167k
    ScandirIterator *iterator;
16991
#ifdef MS_WINDOWS
16992
    wchar_t *path_strW;
16993
#else
16994
167k
    const char *path_str;
16995
167k
#ifdef HAVE_FDOPENDIR
16996
167k
    int fd = -1;
16997
167k
#endif
16998
167k
#endif
16999
17000
167k
    if (PySys_Audit("os.scandir", "O",
17001
167k
                    path->object ? path->object : Py_None) < 0) {
17002
0
        return NULL;
17003
0
    }
17004
17005
167k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
17006
167k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
17007
167k
    if (!iterator)
17008
0
        return NULL;
17009
17010
#ifdef MS_WINDOWS
17011
    iterator->handle = INVALID_HANDLE_VALUE;
17012
#else
17013
167k
    iterator->dirp = NULL;
17014
167k
#endif
17015
17016
    /* Move the ownership to iterator->path */
17017
167k
    memcpy(&iterator->path, path, sizeof(path_t));
17018
167k
    memset(path, 0, sizeof(path_t));
17019
17020
#ifdef MS_WINDOWS
17021
    iterator->first_time = 1;
17022
17023
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
17024
    if (!path_strW)
17025
        goto error;
17026
17027
    Py_BEGIN_ALLOW_THREADS
17028
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17029
    Py_END_ALLOW_THREADS
17030
17031
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17032
        path_error(&iterator->path);
17033
        PyMem_Free(path_strW);
17034
        goto error;
17035
    }
17036
    PyMem_Free(path_strW);
17037
#else /* POSIX */
17038
167k
    errno = 0;
17039
167k
#ifdef HAVE_FDOPENDIR
17040
167k
    if (iterator->path.is_fd) {
17041
167k
      if (HAVE_FDOPENDIR_RUNTIME) {
17042
        /* closedir() closes the FD, so we duplicate it */
17043
167k
        fd = _Py_dup(iterator->path.fd);
17044
167k
        if (fd == -1)
17045
0
            goto error;
17046
17047
167k
        Py_BEGIN_ALLOW_THREADS
17048
167k
        iterator->dirp = fdopendir(fd);
17049
167k
        Py_END_ALLOW_THREADS
17050
167k
      } else {
17051
0
        PyErr_SetString(PyExc_TypeError,
17052
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17053
0
        return NULL;
17054
0
      }
17055
167k
    }
17056
0
    else
17057
0
#endif
17058
0
    {
17059
0
        if (iterator->path.narrow)
17060
0
            path_str = iterator->path.narrow;
17061
0
        else
17062
0
            path_str = ".";
17063
17064
0
        Py_BEGIN_ALLOW_THREADS
17065
0
        iterator->dirp = opendir(path_str);
17066
0
        Py_END_ALLOW_THREADS
17067
0
    }
17068
17069
167k
    if (!iterator->dirp) {
17070
0
        path_error(&iterator->path);
17071
0
#ifdef HAVE_FDOPENDIR
17072
0
        if (fd != -1) {
17073
0
            Py_BEGIN_ALLOW_THREADS
17074
0
            close(fd);
17075
0
            Py_END_ALLOW_THREADS
17076
0
        }
17077
0
#endif
17078
0
        goto error;
17079
0
    }
17080
167k
#endif
17081
17082
167k
    return (PyObject *)iterator;
17083
17084
0
error:
17085
0
    Py_DECREF(iterator);
17086
0
    return NULL;
17087
167k
}
17088
17089
/*
17090
    Return the file system path representation of the object.
17091
17092
    If the object is str or bytes, then allow it to pass through with
17093
    an incremented refcount. If the object defines __fspath__(), then
17094
    return the result of that method. All other types raise a TypeError.
17095
*/
17096
PyObject *
17097
PyOS_FSPath(PyObject *path)
17098
1.56M
{
17099
    /* For error message reasons, this function is manually inlined in
17100
       path_converter(). */
17101
1.56M
    PyObject *func = NULL;
17102
1.56M
    PyObject *path_repr = NULL;
17103
17104
1.56M
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17105
1.56M
        return Py_NewRef(path);
17106
1.56M
    }
17107
17108
274
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17109
274
    if ((NULL == func) || (func == Py_None)) {
17110
0
        return PyErr_Format(PyExc_TypeError,
17111
0
                            "expected str, bytes or os.PathLike object, "
17112
0
                            "not %.200s",
17113
0
                            _PyType_Name(Py_TYPE(path)));
17114
0
    }
17115
17116
274
    path_repr = _PyObject_CallNoArgs(func);
17117
274
    Py_DECREF(func);
17118
274
    if (NULL == path_repr) {
17119
0
        return NULL;
17120
0
    }
17121
17122
274
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17123
0
        PyErr_Format(PyExc_TypeError,
17124
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17125
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17126
0
                     _PyType_Name(Py_TYPE(path_repr)));
17127
0
        Py_DECREF(path_repr);
17128
0
        return NULL;
17129
0
    }
17130
17131
274
    return path_repr;
17132
274
}
17133
17134
/*[clinic input]
17135
@permit_long_docstring_body
17136
os.fspath
17137
17138
    path: object
17139
17140
Return the file system path representation of the object.
17141
17142
If the object is str or bytes, then allow it to pass through as-is. If the
17143
object defines __fspath__(), then return the result of that method. All other
17144
types raise a TypeError.
17145
[clinic start generated code]*/
17146
17147
static PyObject *
17148
os_fspath_impl(PyObject *module, PyObject *path)
17149
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
17150
1.12M
{
17151
1.12M
    return PyOS_FSPath(path);
17152
1.12M
}
17153
17154
#ifdef HAVE_GETRANDOM_SYSCALL
17155
/*[clinic input]
17156
os.getrandom
17157
17158
    size: Py_ssize_t
17159
    flags: int=0
17160
17161
Obtain a series of random bytes.
17162
[clinic start generated code]*/
17163
17164
static PyObject *
17165
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17166
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17167
0
{
17168
0
    if (size < 0) {
17169
0
        errno = EINVAL;
17170
0
        return posix_error();
17171
0
    }
17172
17173
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17174
0
    if (writer == NULL) {
17175
0
        return NULL;
17176
0
    }
17177
0
    void *data = PyBytesWriter_GetData(writer);
17178
17179
0
    Py_ssize_t n;
17180
0
    while (1) {
17181
0
        n = syscall(SYS_getrandom, data, size, flags);
17182
0
        if (n < 0 && errno == EINTR) {
17183
0
            if (PyErr_CheckSignals() < 0) {
17184
0
                goto error;
17185
0
            }
17186
17187
            /* getrandom() was interrupted by a signal: retry */
17188
0
            continue;
17189
0
        }
17190
0
        break;
17191
0
    }
17192
17193
0
    if (n < 0) {
17194
0
        PyErr_SetFromErrno(PyExc_OSError);
17195
0
        goto error;
17196
0
    }
17197
17198
0
    return PyBytesWriter_FinishWithSize(writer, n);
17199
17200
0
error:
17201
0
    PyBytesWriter_Discard(writer);
17202
0
    return NULL;
17203
0
}
17204
#endif   /* HAVE_GETRANDOM_SYSCALL */
17205
17206
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17207
17208
/* bpo-36085: Helper functions for managing DLL search directories
17209
 * on win32
17210
 */
17211
17212
/*[clinic input]
17213
os._add_dll_directory
17214
17215
    path: path_t
17216
17217
Add a path to the DLL search path.
17218
17219
This search path is used when resolving dependencies for imported
17220
extension modules (the module itself is resolved through sys.path),
17221
and also by ctypes.
17222
17223
Returns an opaque value that may be passed to os.remove_dll_directory
17224
to remove this directory from the search path.
17225
[clinic start generated code]*/
17226
17227
static PyObject *
17228
os__add_dll_directory_impl(PyObject *module, path_t *path)
17229
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17230
{
17231
    DLL_DIRECTORY_COOKIE cookie = 0;
17232
    DWORD err = 0;
17233
17234
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17235
        return NULL;
17236
    }
17237
17238
    Py_BEGIN_ALLOW_THREADS
17239
    if (!(cookie = AddDllDirectory(path->wide))) {
17240
        err = GetLastError();
17241
    }
17242
    Py_END_ALLOW_THREADS
17243
17244
    if (err) {
17245
        return win32_error_object_err("add_dll_directory",
17246
                                      path->object, err);
17247
    }
17248
17249
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17250
}
17251
17252
/*[clinic input]
17253
os._remove_dll_directory
17254
17255
    cookie: object
17256
17257
Removes a path from the DLL search path.
17258
17259
The parameter is an opaque value that was returned from
17260
os.add_dll_directory. You can only remove directories that you added
17261
yourself.
17262
[clinic start generated code]*/
17263
17264
static PyObject *
17265
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17266
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17267
{
17268
    DLL_DIRECTORY_COOKIE cookieValue;
17269
    DWORD err = 0;
17270
17271
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17272
        PyErr_SetString(PyExc_TypeError,
17273
            "Provided cookie was not returned from os.add_dll_directory");
17274
        return NULL;
17275
    }
17276
17277
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17278
        cookie, "DLL directory cookie");
17279
17280
    Py_BEGIN_ALLOW_THREADS
17281
    if (!RemoveDllDirectory(cookieValue)) {
17282
        err = GetLastError();
17283
    }
17284
    Py_END_ALLOW_THREADS
17285
17286
    if (err) {
17287
        return win32_error_object_err("remove_dll_directory",
17288
                                      NULL, err);
17289
    }
17290
17291
    if (PyCapsule_SetName(cookie, NULL)) {
17292
        return NULL;
17293
    }
17294
17295
    Py_RETURN_NONE;
17296
}
17297
17298
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17299
17300
17301
/* Only check if WIFEXITED is available: expect that it comes
17302
   with WEXITSTATUS, WIFSIGNALED, etc.
17303
17304
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17305
   subprocess can safely call it during late Python finalization without
17306
   risking that used os attributes were set to None by finalize_modules(). */
17307
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17308
/*[clinic input]
17309
os.waitstatus_to_exitcode
17310
17311
    status as status_obj: object
17312
17313
Convert a wait status to an exit code.
17314
17315
On Unix:
17316
17317
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17318
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17319
* Otherwise, raise a ValueError.
17320
17321
On Windows, return status shifted right by 8 bits.
17322
17323
On Unix, if the process is being traced or if waitpid() was called with
17324
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
17325
This function must not be called if WIFSTOPPED(status) is true.
17326
[clinic start generated code]*/
17327
17328
static PyObject *
17329
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17330
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
17331
0
{
17332
0
#ifndef MS_WINDOWS
17333
0
    int status = PyLong_AsInt(status_obj);
17334
0
    if (status == -1 && PyErr_Occurred()) {
17335
0
        return NULL;
17336
0
    }
17337
17338
0
    WAIT_TYPE wait_status;
17339
0
    WAIT_STATUS_INT(wait_status) = status;
17340
0
    int exitcode;
17341
0
    if (WIFEXITED(wait_status)) {
17342
0
        exitcode = WEXITSTATUS(wait_status);
17343
        /* Sanity check to provide warranty on the function behavior.
17344
           It should not occur in practice */
17345
0
        if (exitcode < 0) {
17346
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17347
0
            return NULL;
17348
0
        }
17349
0
    }
17350
0
    else if (WIFSIGNALED(wait_status)) {
17351
0
        int signum = WTERMSIG(wait_status);
17352
        /* Sanity check to provide warranty on the function behavior.
17353
           It should not occurs in practice */
17354
0
        if (signum <= 0) {
17355
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17356
0
            return NULL;
17357
0
        }
17358
0
        exitcode = -signum;
17359
0
    } else if (WIFSTOPPED(wait_status)) {
17360
        /* Status only received if the process is being traced
17361
           or if waitpid() was called with WUNTRACED option. */
17362
0
        int signum = WSTOPSIG(wait_status);
17363
0
        PyErr_Format(PyExc_ValueError,
17364
0
                     "process stopped by delivery of signal %i",
17365
0
                     signum);
17366
0
        return NULL;
17367
0
    }
17368
0
    else {
17369
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17370
0
        return NULL;
17371
0
    }
17372
0
    return PyLong_FromLong(exitcode);
17373
#else
17374
    /* Windows implementation: see os.waitpid() implementation
17375
       which uses _cwait(). */
17376
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17377
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17378
        return NULL;
17379
    }
17380
17381
    unsigned long long exitcode = (status >> 8);
17382
    /* ExitProcess() accepts an UINT type:
17383
       reject exit code which doesn't fit in an UINT */
17384
    if (exitcode > UINT_MAX) {
17385
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17386
        return NULL;
17387
    }
17388
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17389
#endif
17390
0
}
17391
#endif
17392
17393
#if defined(MS_WINDOWS)
17394
/*[clinic input]
17395
os._supports_virtual_terminal
17396
17397
Checks if virtual terminal is supported in windows
17398
[clinic start generated code]*/
17399
17400
static PyObject *
17401
os__supports_virtual_terminal_impl(PyObject *module)
17402
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17403
{
17404
#ifdef HAVE_WINDOWS_CONSOLE_IO
17405
    DWORD mode = 0;
17406
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17407
    if (!GetConsoleMode(handle, &mode)) {
17408
        Py_RETURN_FALSE;
17409
    }
17410
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17411
#else
17412
    Py_RETURN_FALSE;
17413
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17414
}
17415
#endif
17416
17417
/*[clinic input]
17418
os._inputhook
17419
17420
Calls PyOS_InputHook dropping the GIL first
17421
[clinic start generated code]*/
17422
17423
static PyObject *
17424
os__inputhook_impl(PyObject *module)
17425
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17426
0
{
17427
0
     int result = 0;
17428
0
     if (PyOS_InputHook) {
17429
0
         Py_BEGIN_ALLOW_THREADS;
17430
0
         result = PyOS_InputHook();
17431
0
         Py_END_ALLOW_THREADS;
17432
0
     }
17433
0
     return PyLong_FromLong(result);
17434
0
}
17435
17436
/*[clinic input]
17437
os._is_inputhook_installed
17438
17439
Checks if PyOS_InputHook is set
17440
[clinic start generated code]*/
17441
17442
static PyObject *
17443
os__is_inputhook_installed_impl(PyObject *module)
17444
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17445
0
{
17446
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17447
0
}
17448
17449
/*[clinic input]
17450
os._create_environ
17451
17452
Create the environment dictionary.
17453
[clinic start generated code]*/
17454
17455
static PyObject *
17456
os__create_environ_impl(PyObject *module)
17457
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17458
0
{
17459
0
    return convertenviron();
17460
0
}
17461
17462
17463
#ifdef __EMSCRIPTEN__
17464
/*[clinic input]
17465
os._emscripten_debugger
17466
17467
Create a breakpoint for the JavaScript debugger. Emscripten only.
17468
[clinic start generated code]*/
17469
17470
static PyObject *
17471
os__emscripten_debugger_impl(PyObject *module)
17472
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17473
{
17474
    emscripten_debugger();
17475
    Py_RETURN_NONE;
17476
}
17477
17478
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17479
    console.warn(UTF8ToString(arg));
17480
});
17481
17482
/*[clinic input]
17483
os._emscripten_log
17484
   arg: str
17485
17486
Log something to the JS console. Emscripten only.
17487
[clinic start generated code]*/
17488
17489
static PyObject *
17490
os__emscripten_log_impl(PyObject *module, const char *arg)
17491
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17492
{
17493
    emscripten_log_impl_js(arg);
17494
    Py_RETURN_NONE;
17495
}
17496
#endif /* __EMSCRIPTEN__ */
17497
17498
17499
static PyMethodDef posix_methods[] = {
17500
    OS_STAT_METHODDEF
17501
    OS_STATX_METHODDEF
17502
    OS_ACCESS_METHODDEF
17503
    OS_TTYNAME_METHODDEF
17504
    OS_CHDIR_METHODDEF
17505
    OS_CHFLAGS_METHODDEF
17506
    OS_CHMOD_METHODDEF
17507
    OS_FCHMOD_METHODDEF
17508
    OS_LCHMOD_METHODDEF
17509
    OS_CHOWN_METHODDEF
17510
    OS_FCHOWN_METHODDEF
17511
    OS_LCHOWN_METHODDEF
17512
    OS_LCHFLAGS_METHODDEF
17513
    OS_CHROOT_METHODDEF
17514
    OS_CTERMID_METHODDEF
17515
    OS_GETCWD_METHODDEF
17516
    OS_GETCWDB_METHODDEF
17517
    OS_LINK_METHODDEF
17518
    OS_LISTDIR_METHODDEF
17519
    OS_LISTDRIVES_METHODDEF
17520
    OS_LISTMOUNTS_METHODDEF
17521
    OS_LISTVOLUMES_METHODDEF
17522
    OS_LSTAT_METHODDEF
17523
    OS_MKDIR_METHODDEF
17524
    OS_NICE_METHODDEF
17525
    OS_GETPRIORITY_METHODDEF
17526
    OS_SETPRIORITY_METHODDEF
17527
    OS_POSIX_SPAWN_METHODDEF
17528
    OS_POSIX_SPAWNP_METHODDEF
17529
    OS_READLINK_METHODDEF
17530
    OS_COPY_FILE_RANGE_METHODDEF
17531
    OS_SPLICE_METHODDEF
17532
    OS_RENAME_METHODDEF
17533
    OS_REPLACE_METHODDEF
17534
    OS_RMDIR_METHODDEF
17535
    OS_SYMLINK_METHODDEF
17536
    OS_SYSTEM_METHODDEF
17537
    OS_UMASK_METHODDEF
17538
    OS_UNAME_METHODDEF
17539
    OS_UNLINK_METHODDEF
17540
    OS_REMOVE_METHODDEF
17541
    OS_UTIME_METHODDEF
17542
    OS_TIMES_METHODDEF
17543
    OS__EXIT_METHODDEF
17544
    OS__FCOPYFILE_METHODDEF
17545
    OS_EXECV_METHODDEF
17546
    OS_EXECVE_METHODDEF
17547
    OS_SPAWNV_METHODDEF
17548
    OS_SPAWNVE_METHODDEF
17549
    OS_FORK1_METHODDEF
17550
    OS_FORK_METHODDEF
17551
    OS_REGISTER_AT_FORK_METHODDEF
17552
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17553
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17554
    OS_SCHED_GETPARAM_METHODDEF
17555
    OS_SCHED_GETSCHEDULER_METHODDEF
17556
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17557
    OS_SCHED_SETPARAM_METHODDEF
17558
    OS_SCHED_SETSCHEDULER_METHODDEF
17559
    OS_SCHED_YIELD_METHODDEF
17560
    OS_SCHED_SETAFFINITY_METHODDEF
17561
    OS_SCHED_GETAFFINITY_METHODDEF
17562
    OS_POSIX_OPENPT_METHODDEF
17563
    OS_GRANTPT_METHODDEF
17564
    OS_UNLOCKPT_METHODDEF
17565
    OS_PTSNAME_METHODDEF
17566
    OS_OPENPTY_METHODDEF
17567
    OS_LOGIN_TTY_METHODDEF
17568
    OS_FORKPTY_METHODDEF
17569
    OS_GETEGID_METHODDEF
17570
    OS_GETEUID_METHODDEF
17571
    OS_GETGID_METHODDEF
17572
    OS_GETGROUPLIST_METHODDEF
17573
    OS_GETGROUPS_METHODDEF
17574
    OS_GETPID_METHODDEF
17575
    OS_GETPGRP_METHODDEF
17576
    OS_GETPPID_METHODDEF
17577
    OS_GETUID_METHODDEF
17578
    OS_GETLOGIN_METHODDEF
17579
    OS_KILL_METHODDEF
17580
    OS_KILLPG_METHODDEF
17581
    OS_PLOCK_METHODDEF
17582
    OS_STARTFILE_METHODDEF
17583
    OS_SETUID_METHODDEF
17584
    OS_SETEUID_METHODDEF
17585
    OS_SETREUID_METHODDEF
17586
    OS_SETGID_METHODDEF
17587
    OS_SETEGID_METHODDEF
17588
    OS_SETREGID_METHODDEF
17589
    OS_SETGROUPS_METHODDEF
17590
    OS_INITGROUPS_METHODDEF
17591
    OS_GETPGID_METHODDEF
17592
    OS_SETPGRP_METHODDEF
17593
    OS_WAIT_METHODDEF
17594
    OS_WAIT3_METHODDEF
17595
    OS_WAIT4_METHODDEF
17596
    OS_WAITID_METHODDEF
17597
    OS_WAITPID_METHODDEF
17598
    OS_PIDFD_OPEN_METHODDEF
17599
    OS_GETSID_METHODDEF
17600
    OS_SETSID_METHODDEF
17601
    OS_SETPGID_METHODDEF
17602
    OS_TCGETPGRP_METHODDEF
17603
    OS_TCSETPGRP_METHODDEF
17604
    OS_OPEN_METHODDEF
17605
    OS_CLOSE_METHODDEF
17606
    OS_CLOSERANGE_METHODDEF
17607
    OS_DEVICE_ENCODING_METHODDEF
17608
    OS_DUP_METHODDEF
17609
    OS_DUP2_METHODDEF
17610
    OS_LOCKF_METHODDEF
17611
    OS_LSEEK_METHODDEF
17612
    OS_READ_METHODDEF
17613
    OS_READINTO_METHODDEF
17614
    OS_READV_METHODDEF
17615
    OS_PREAD_METHODDEF
17616
    OS_PREADV_METHODDEF
17617
    OS_WRITE_METHODDEF
17618
    OS_WRITEV_METHODDEF
17619
    OS_PWRITE_METHODDEF
17620
    OS_PWRITEV_METHODDEF
17621
    OS_SENDFILE_METHODDEF
17622
    OS_FSTAT_METHODDEF
17623
    OS_ISATTY_METHODDEF
17624
    OS_PIPE_METHODDEF
17625
    OS_PIPE2_METHODDEF
17626
    OS_MKFIFO_METHODDEF
17627
    OS_MKNOD_METHODDEF
17628
    OS_MAJOR_METHODDEF
17629
    OS_MINOR_METHODDEF
17630
    OS_MAKEDEV_METHODDEF
17631
    OS_FTRUNCATE_METHODDEF
17632
    OS_TRUNCATE_METHODDEF
17633
    OS_POSIX_FALLOCATE_METHODDEF
17634
    OS_POSIX_FADVISE_METHODDEF
17635
    OS_PUTENV_METHODDEF
17636
    OS_UNSETENV_METHODDEF
17637
    OS__CLEARENV_METHODDEF
17638
    OS_STRERROR_METHODDEF
17639
    OS_FCHDIR_METHODDEF
17640
    OS_FSYNC_METHODDEF
17641
    OS_SYNC_METHODDEF
17642
    OS_FDATASYNC_METHODDEF
17643
    OS_WCOREDUMP_METHODDEF
17644
    OS_WIFCONTINUED_METHODDEF
17645
    OS_WIFSTOPPED_METHODDEF
17646
    OS_WIFSIGNALED_METHODDEF
17647
    OS_WIFEXITED_METHODDEF
17648
    OS_WEXITSTATUS_METHODDEF
17649
    OS_WTERMSIG_METHODDEF
17650
    OS_WSTOPSIG_METHODDEF
17651
    OS_FSTATVFS_METHODDEF
17652
    OS_STATVFS_METHODDEF
17653
    OS_CONFSTR_METHODDEF
17654
    OS_SYSCONF_METHODDEF
17655
    OS_FPATHCONF_METHODDEF
17656
    OS_PATHCONF_METHODDEF
17657
    OS_ABORT_METHODDEF
17658
    OS__GETFULLPATHNAME_METHODDEF
17659
    OS__GETDISKUSAGE_METHODDEF
17660
    OS__GETFINALPATHNAME_METHODDEF
17661
    OS__FINDFIRSTFILE_METHODDEF
17662
    OS__GETVOLUMEPATHNAME_METHODDEF
17663
    OS__PATH_SPLITROOT_METHODDEF
17664
    OS__PATH_SPLITROOT_EX_METHODDEF
17665
    OS__PATH_NORMPATH_METHODDEF
17666
    OS_GETLOADAVG_METHODDEF
17667
    OS_URANDOM_METHODDEF
17668
    OS_SETRESUID_METHODDEF
17669
    OS_SETRESGID_METHODDEF
17670
    OS_GETRESUID_METHODDEF
17671
    OS_GETRESGID_METHODDEF
17672
17673
    OS_GETXATTR_METHODDEF
17674
    OS_SETXATTR_METHODDEF
17675
    OS_REMOVEXATTR_METHODDEF
17676
    OS_LISTXATTR_METHODDEF
17677
17678
    OS_GET_TERMINAL_SIZE_METHODDEF
17679
    OS_CPU_COUNT_METHODDEF
17680
    OS_GET_INHERITABLE_METHODDEF
17681
    OS_SET_INHERITABLE_METHODDEF
17682
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17683
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17684
    OS_GET_BLOCKING_METHODDEF
17685
    OS_SET_BLOCKING_METHODDEF
17686
    OS_SCANDIR_METHODDEF
17687
    OS_FSPATH_METHODDEF
17688
    OS_GETRANDOM_METHODDEF
17689
    OS_MEMFD_CREATE_METHODDEF
17690
    OS_EVENTFD_METHODDEF
17691
    OS_EVENTFD_READ_METHODDEF
17692
    OS_EVENTFD_WRITE_METHODDEF
17693
    OS__ADD_DLL_DIRECTORY_METHODDEF
17694
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17695
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17696
    OS_SETNS_METHODDEF
17697
    OS_UNSHARE_METHODDEF
17698
    OS_TIMERFD_CREATE_METHODDEF
17699
    OS_TIMERFD_SETTIME_METHODDEF
17700
    OS_TIMERFD_SETTIME_NS_METHODDEF
17701
    OS_TIMERFD_GETTIME_METHODDEF
17702
    OS_TIMERFD_GETTIME_NS_METHODDEF
17703
17704
    OS__PATH_ISDEVDRIVE_METHODDEF
17705
    OS__PATH_ISDIR_METHODDEF
17706
    OS__PATH_ISFILE_METHODDEF
17707
    OS__PATH_ISLINK_METHODDEF
17708
    OS__PATH_ISJUNCTION_METHODDEF
17709
    OS__PATH_EXISTS_METHODDEF
17710
    OS__PATH_LEXISTS_METHODDEF
17711
17712
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17713
    OS__INPUTHOOK_METHODDEF
17714
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17715
    OS__CREATE_ENVIRON_METHODDEF
17716
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17717
    OS__EMSCRIPTEN_LOG_METHODDEF
17718
    {NULL,              NULL}            /* Sentinel */
17719
};
17720
17721
static int
17722
all_ins(PyObject *m)
17723
34
{
17724
34
#ifdef F_OK
17725
34
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17726
34
#endif
17727
34
#ifdef R_OK
17728
34
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17729
34
#endif
17730
34
#ifdef W_OK
17731
34
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17732
34
#endif
17733
34
#ifdef X_OK
17734
34
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17735
34
#endif
17736
34
#ifdef NGROUPS_MAX
17737
34
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17738
34
#endif
17739
34
#ifdef TMP_MAX
17740
34
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17741
34
#endif
17742
34
#ifdef WCONTINUED
17743
34
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17744
34
#endif
17745
34
#ifdef WNOHANG
17746
34
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17747
34
#endif
17748
34
#ifdef WUNTRACED
17749
34
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17750
34
#endif
17751
34
#ifdef O_RDONLY
17752
34
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17753
34
#endif
17754
34
#ifdef O_WRONLY
17755
34
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17756
34
#endif
17757
34
#ifdef O_RDWR
17758
34
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17759
34
#endif
17760
34
#ifdef O_NDELAY
17761
34
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17762
34
#endif
17763
34
#ifdef O_NONBLOCK
17764
34
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17765
34
#endif
17766
34
#ifdef O_APPEND
17767
34
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17768
34
#endif
17769
34
#ifdef O_DSYNC
17770
34
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17771
34
#endif
17772
34
#ifdef O_RSYNC
17773
34
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17774
34
#endif
17775
34
#ifdef O_SYNC
17776
34
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17777
34
#endif
17778
34
#ifdef O_NOCTTY
17779
34
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17780
34
#endif
17781
34
#ifdef O_CREAT
17782
34
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17783
34
#endif
17784
34
#ifdef O_EXCL
17785
34
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17786
34
#endif
17787
34
#ifdef O_TRUNC
17788
34
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17789
34
#endif
17790
#ifdef O_BINARY
17791
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17792
#endif
17793
#ifdef O_TEXT
17794
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17795
#endif
17796
#ifdef O_XATTR
17797
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17798
#endif
17799
34
#ifdef O_LARGEFILE
17800
34
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17801
34
#endif
17802
34
#ifndef __GNU__
17803
#ifdef O_SHLOCK
17804
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17805
#endif
17806
#ifdef O_EXLOCK
17807
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17808
#endif
17809
34
#endif
17810
#ifdef O_EXEC
17811
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17812
#endif
17813
#ifdef O_SEARCH
17814
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17815
#endif
17816
34
#ifdef O_PATH
17817
34
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17818
34
#endif
17819
#ifdef O_TTY_INIT
17820
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17821
#endif
17822
34
#ifdef O_TMPFILE
17823
34
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17824
34
#endif
17825
34
#ifdef PRIO_PROCESS
17826
34
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17827
34
#endif
17828
34
#ifdef PRIO_PGRP
17829
34
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17830
34
#endif
17831
34
#ifdef PRIO_USER
17832
34
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17833
34
#endif
17834
#ifdef PRIO_DARWIN_THREAD
17835
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17836
#endif
17837
#ifdef PRIO_DARWIN_PROCESS
17838
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17839
#endif
17840
#ifdef PRIO_DARWIN_BG
17841
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17842
#endif
17843
#ifdef PRIO_DARWIN_NONUI
17844
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17845
#endif
17846
34
#ifdef O_CLOEXEC
17847
34
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17848
34
#endif
17849
34
#ifdef O_ACCMODE
17850
34
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17851
34
#endif
17852
#ifdef O_EVTONLY
17853
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17854
#endif
17855
34
#ifdef O_FSYNC
17856
34
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17857
34
#endif
17858
#ifdef O_SYMLINK
17859
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17860
#endif
17861
17862
34
#ifdef SEEK_HOLE
17863
34
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17864
34
#endif
17865
34
#ifdef SEEK_DATA
17866
34
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17867
34
#endif
17868
17869
/* MS Windows */
17870
#ifdef O_NOINHERIT
17871
    /* Don't inherit in child processes. */
17872
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17873
#endif
17874
#ifdef _O_SHORT_LIVED
17875
    /* Optimize for short life (keep in memory). */
17876
    /* MS forgot to define this one with a non-underscore form too. */
17877
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17878
#endif
17879
#ifdef O_TEMPORARY
17880
    /* Automatically delete when last handle is closed. */
17881
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17882
#endif
17883
#ifdef O_RANDOM
17884
    /* Optimize for random access. */
17885
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17886
#endif
17887
#ifdef O_SEQUENTIAL
17888
    /* Optimize for sequential access. */
17889
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17890
#endif
17891
17892
/* GNU extensions. */
17893
34
#ifdef O_ASYNC
17894
    /* Send a SIGIO signal whenever input or output
17895
       becomes available on file descriptor */
17896
34
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17897
34
#endif
17898
34
#ifdef O_DIRECT
17899
    /* Direct disk access. */
17900
34
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17901
34
#endif
17902
34
#ifdef O_DIRECTORY
17903
    /* Must be a directory.      */
17904
34
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17905
34
#endif
17906
34
#ifdef O_NOFOLLOW
17907
    /* Do not follow links.      */
17908
34
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17909
34
#endif
17910
#ifdef O_NOFOLLOW_ANY
17911
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17912
#endif
17913
#ifdef O_NOLINKS
17914
    /* Fails if link count of the named file is greater than 1 */
17915
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17916
#endif
17917
34
#ifdef O_NOATIME
17918
    /* Do not update the access time. */
17919
34
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17920
34
#endif
17921
17922
    /* These come from sysexits.h */
17923
34
#ifdef EX_OK
17924
34
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17925
34
#endif /* EX_OK */
17926
34
#ifdef EX_USAGE
17927
34
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17928
34
#endif /* EX_USAGE */
17929
34
#ifdef EX_DATAERR
17930
34
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17931
34
#endif /* EX_DATAERR */
17932
34
#ifdef EX_NOINPUT
17933
34
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17934
34
#endif /* EX_NOINPUT */
17935
34
#ifdef EX_NOUSER
17936
34
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17937
34
#endif /* EX_NOUSER */
17938
34
#ifdef EX_NOHOST
17939
34
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17940
34
#endif /* EX_NOHOST */
17941
34
#ifdef EX_UNAVAILABLE
17942
34
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17943
34
#endif /* EX_UNAVAILABLE */
17944
34
#ifdef EX_SOFTWARE
17945
34
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17946
34
#endif /* EX_SOFTWARE */
17947
34
#ifdef EX_OSERR
17948
34
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17949
34
#endif /* EX_OSERR */
17950
34
#ifdef EX_OSFILE
17951
34
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17952
34
#endif /* EX_OSFILE */
17953
34
#ifdef EX_CANTCREAT
17954
34
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17955
34
#endif /* EX_CANTCREAT */
17956
34
#ifdef EX_IOERR
17957
34
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17958
34
#endif /* EX_IOERR */
17959
34
#ifdef EX_TEMPFAIL
17960
34
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17961
34
#endif /* EX_TEMPFAIL */
17962
34
#ifdef EX_PROTOCOL
17963
34
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17964
34
#endif /* EX_PROTOCOL */
17965
34
#ifdef EX_NOPERM
17966
34
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17967
34
#endif /* EX_NOPERM */
17968
34
#ifdef EX_CONFIG
17969
34
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17970
34
#endif /* EX_CONFIG */
17971
#ifdef EX_NOTFOUND
17972
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17973
#endif /* EX_NOTFOUND */
17974
17975
    /* statvfs */
17976
34
#ifdef ST_RDONLY
17977
34
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17978
34
#endif /* ST_RDONLY */
17979
34
#ifdef ST_NOSUID
17980
34
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17981
34
#endif /* ST_NOSUID */
17982
17983
       /* GNU extensions */
17984
34
#ifdef ST_NODEV
17985
34
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17986
34
#endif /* ST_NODEV */
17987
34
#ifdef ST_NOEXEC
17988
34
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17989
34
#endif /* ST_NOEXEC */
17990
34
#ifdef ST_SYNCHRONOUS
17991
34
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17992
34
#endif /* ST_SYNCHRONOUS */
17993
34
#ifdef ST_MANDLOCK
17994
34
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17995
34
#endif /* ST_MANDLOCK */
17996
34
#ifdef ST_WRITE
17997
34
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17998
34
#endif /* ST_WRITE */
17999
34
#ifdef ST_APPEND
18000
34
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
18001
34
#endif /* ST_APPEND */
18002
34
#ifdef ST_NOATIME
18003
34
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
18004
34
#endif /* ST_NOATIME */
18005
34
#ifdef ST_NODIRATIME
18006
34
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
18007
34
#endif /* ST_NODIRATIME */
18008
34
#ifdef ST_RELATIME
18009
34
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18010
34
#endif /* ST_RELATIME */
18011
18012
    /* FreeBSD sendfile() constants */
18013
#ifdef SF_NODISKIO
18014
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18015
#endif
18016
    /* is obsolete since the 11.x release */
18017
#ifdef SF_MNOWAIT
18018
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18019
#endif
18020
#ifdef SF_SYNC
18021
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18022
#endif
18023
#ifdef SF_NOCACHE
18024
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18025
#endif
18026
18027
34
#ifdef TFD_NONBLOCK
18028
34
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18029
34
#endif
18030
34
#ifdef TFD_CLOEXEC
18031
34
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18032
34
#endif
18033
34
#ifdef TFD_TIMER_ABSTIME
18034
34
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18035
34
#endif
18036
34
#ifdef TFD_TIMER_CANCEL_ON_SET
18037
34
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18038
34
#endif
18039
18040
    /* constants for posix_fadvise */
18041
34
#ifdef POSIX_FADV_NORMAL
18042
34
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18043
34
#endif
18044
34
#ifdef POSIX_FADV_SEQUENTIAL
18045
34
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18046
34
#endif
18047
34
#ifdef POSIX_FADV_RANDOM
18048
34
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18049
34
#endif
18050
34
#ifdef POSIX_FADV_NOREUSE
18051
34
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18052
34
#endif
18053
34
#ifdef POSIX_FADV_WILLNEED
18054
34
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18055
34
#endif
18056
34
#ifdef POSIX_FADV_DONTNEED
18057
34
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18058
34
#endif
18059
18060
    /* constants for waitid */
18061
34
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18062
34
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18063
34
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18064
34
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18065
34
#ifdef P_PIDFD
18066
34
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18067
34
#endif
18068
#ifdef PIDFD_NONBLOCK
18069
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18070
#endif
18071
34
#endif
18072
34
#ifdef WEXITED
18073
34
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18074
34
#endif
18075
34
#ifdef WNOWAIT
18076
34
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18077
34
#endif
18078
34
#ifdef WSTOPPED
18079
34
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18080
34
#endif
18081
34
#ifdef CLD_EXITED
18082
34
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18083
34
#endif
18084
34
#ifdef CLD_KILLED
18085
34
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18086
34
#endif
18087
34
#ifdef CLD_DUMPED
18088
34
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18089
34
#endif
18090
34
#ifdef CLD_TRAPPED
18091
34
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18092
34
#endif
18093
34
#ifdef CLD_STOPPED
18094
34
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18095
34
#endif
18096
34
#ifdef CLD_CONTINUED
18097
34
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18098
34
#endif
18099
18100
    /* constants for lockf */
18101
34
#ifdef F_LOCK
18102
34
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18103
34
#endif
18104
34
#ifdef F_TLOCK
18105
34
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18106
34
#endif
18107
34
#ifdef F_ULOCK
18108
34
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18109
34
#endif
18110
34
#ifdef F_TEST
18111
34
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18112
34
#endif
18113
18114
34
#ifdef RWF_DSYNC
18115
34
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18116
34
#endif
18117
34
#ifdef RWF_HIPRI
18118
34
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18119
34
#endif
18120
34
#ifdef RWF_SYNC
18121
34
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18122
34
#endif
18123
34
#ifdef RWF_NOWAIT
18124
34
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18125
34
#endif
18126
#ifdef RWF_DONTCACHE
18127
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18128
#endif
18129
#ifdef RWF_ATOMIC
18130
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18131
#endif
18132
34
#ifdef RWF_APPEND
18133
34
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18134
34
#endif
18135
18136
/* constants for splice */
18137
34
#if defined(HAVE_SPLICE) && defined(__linux__)
18138
34
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18139
34
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18140
34
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18141
34
#endif
18142
18143
/* constants for posix_spawn */
18144
34
#ifdef HAVE_POSIX_SPAWN
18145
34
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18146
34
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18147
34
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18148
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18149
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18150
#endif
18151
34
#endif
18152
18153
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18154
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18155
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18156
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18157
#endif
18158
#ifdef HAVE_SPAWNV
18159
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18160
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18161
#endif
18162
18163
34
#ifdef HAVE_SCHED_H
18164
34
#ifdef SCHED_OTHER
18165
34
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18166
34
#endif
18167
34
#ifdef SCHED_DEADLINE
18168
34
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18169
34
#endif
18170
34
#ifdef SCHED_FIFO
18171
34
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18172
34
#endif
18173
34
#ifdef SCHED_NORMAL
18174
34
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18175
34
#endif
18176
34
#ifdef SCHED_RR
18177
34
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18178
34
#endif
18179
#ifdef SCHED_SPORADIC
18180
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18181
#endif
18182
34
#ifdef SCHED_BATCH
18183
34
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18184
34
#endif
18185
34
#ifdef SCHED_IDLE
18186
34
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18187
34
#endif
18188
34
#ifdef SCHED_RESET_ON_FORK
18189
34
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18190
34
#endif
18191
#ifdef SCHED_SYS
18192
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18193
#endif
18194
#ifdef SCHED_IA
18195
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18196
#endif
18197
#ifdef SCHED_FSS
18198
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18199
#endif
18200
#ifdef SCHED_FX
18201
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18202
#endif
18203
18204
/* constants for namespaces */
18205
34
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18206
34
#ifdef CLONE_FS
18207
34
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18208
34
#endif
18209
34
#ifdef CLONE_FILES
18210
34
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18211
34
#endif
18212
34
#ifdef CLONE_NEWNS
18213
34
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18214
34
#endif
18215
34
#ifdef CLONE_NEWCGROUP
18216
34
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18217
34
#endif
18218
34
#ifdef CLONE_NEWUTS
18219
34
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18220
34
#endif
18221
34
#ifdef CLONE_NEWIPC
18222
34
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18223
34
#endif
18224
34
#ifdef CLONE_NEWUSER
18225
34
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18226
34
#endif
18227
34
#ifdef CLONE_NEWPID
18228
34
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18229
34
#endif
18230
34
#ifdef CLONE_NEWNET
18231
34
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18232
34
#endif
18233
#ifdef CLONE_NEWTIME
18234
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18235
#endif
18236
34
#ifdef CLONE_SYSVSEM
18237
34
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18238
34
#endif
18239
34
#ifdef CLONE_THREAD
18240
34
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18241
34
#endif
18242
34
#ifdef CLONE_SIGHAND
18243
34
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18244
34
#endif
18245
34
#ifdef CLONE_VM
18246
34
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18247
34
#endif
18248
34
#endif
18249
18250
34
#endif
18251
18252
34
#ifdef USE_XATTRS
18253
34
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18254
34
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18255
34
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18256
34
#endif
18257
18258
34
#if HAVE_DECL_RTLD_LAZY
18259
34
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18260
34
#endif
18261
34
#if HAVE_DECL_RTLD_NOW
18262
34
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18263
34
#endif
18264
34
#if HAVE_DECL_RTLD_GLOBAL
18265
34
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18266
34
#endif
18267
34
#if HAVE_DECL_RTLD_LOCAL
18268
34
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18269
34
#endif
18270
34
#if HAVE_DECL_RTLD_NODELETE
18271
34
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18272
34
#endif
18273
34
#if HAVE_DECL_RTLD_NOLOAD
18274
34
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18275
34
#endif
18276
34
#if HAVE_DECL_RTLD_DEEPBIND
18277
34
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18278
34
#endif
18279
#if HAVE_DECL_RTLD_MEMBER
18280
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18281
#endif
18282
18283
34
#ifdef HAVE_GETRANDOM_SYSCALL
18284
34
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18285
34
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18286
34
#endif
18287
34
#ifdef HAVE_MEMFD_CREATE
18288
34
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18289
34
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18290
34
#ifdef MFD_HUGETLB
18291
34
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18292
34
#endif
18293
34
#ifdef MFD_HUGE_SHIFT
18294
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18295
34
#endif
18296
34
#ifdef MFD_HUGE_MASK
18297
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18298
34
#endif
18299
34
#ifdef MFD_HUGE_64KB
18300
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18301
34
#endif
18302
34
#ifdef MFD_HUGE_512KB
18303
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18304
34
#endif
18305
34
#ifdef MFD_HUGE_1MB
18306
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18307
34
#endif
18308
34
#ifdef MFD_HUGE_2MB
18309
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18310
34
#endif
18311
34
#ifdef MFD_HUGE_8MB
18312
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18313
34
#endif
18314
34
#ifdef MFD_HUGE_16MB
18315
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18316
34
#endif
18317
34
#ifdef MFD_HUGE_32MB
18318
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18319
34
#endif
18320
34
#ifdef MFD_HUGE_256MB
18321
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18322
34
#endif
18323
34
#ifdef MFD_HUGE_512MB
18324
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18325
34
#endif
18326
34
#ifdef MFD_HUGE_1GB
18327
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18328
34
#endif
18329
34
#ifdef MFD_HUGE_2GB
18330
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18331
34
#endif
18332
34
#ifdef MFD_HUGE_16GB
18333
34
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18334
34
#endif
18335
34
#endif /* HAVE_MEMFD_CREATE */
18336
18337
34
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18338
34
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18339
34
#ifdef EFD_NONBLOCK
18340
34
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18341
34
#endif
18342
34
#ifdef EFD_SEMAPHORE
18343
34
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18344
34
#endif
18345
34
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18346
18347
34
#ifdef NODEV
18348
34
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18349
34
#endif
18350
18351
34
#ifdef AT_NO_AUTOMOUNT
18352
34
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18353
34
#endif
18354
18355
34
#ifdef HAVE_STATX
18356
34
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18357
34
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18358
34
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18359
34
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18360
34
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18361
34
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18362
34
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18363
34
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18364
34
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18365
34
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18366
34
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18367
34
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18368
34
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18369
#ifdef STATX_MNT_ID
18370
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18371
#endif
18372
#ifdef STATX_DIOALIGN
18373
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18374
#endif
18375
#ifdef STATX_MNT_ID_UNIQUE
18376
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18377
#endif
18378
#ifdef STATX_SUBVOL
18379
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18380
#endif
18381
#ifdef STATX_WRITE_ATOMIC
18382
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18383
#endif
18384
#ifdef STATX_DIO_READ_ALIGN
18385
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18386
#endif
18387
    /* STATX_ALL intentionally omitted because it is deprecated */
18388
34
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18389
34
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18390
34
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18391
    /* STATX_ATTR_* constants are in the stat module */
18392
34
#endif /* HAVE_STATX */
18393
18394
#if defined(__APPLE__)
18395
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18396
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18397
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18398
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18399
#endif
18400
18401
#ifdef MS_WINDOWS
18402
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18403
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18404
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18405
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18406
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18407
#endif
18408
18409
34
    return 0;
18410
34
}
18411
18412
18413
18414
#define PROBE(name, test) \
18415
   static int name(void)  \
18416
578
   {                      \
18417
578
      if (test) {        \
18418
578
          return 1;       \
18419
578
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
578
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_futimens
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_linkat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_openat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_renameat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18416
34
   {                      \
18417
34
      if (test) {        \
18418
34
          return 1;       \
18419
34
      } else {            \
18420
0
          return 0;       \
18421
0
      }                   \
18422
34
   }
18423
18424
#ifdef HAVE_FSTATAT
18425
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18426
#endif
18427
18428
#ifdef HAVE_FACCESSAT
18429
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18430
#endif
18431
18432
#ifdef HAVE_FCHMODAT
18433
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18434
#endif
18435
18436
#ifdef HAVE_FCHOWNAT
18437
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18438
#endif
18439
18440
#ifdef HAVE_LINKAT
18441
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18442
#endif
18443
18444
#ifdef HAVE_FDOPENDIR
18445
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18446
#endif
18447
18448
#ifdef HAVE_MKDIRAT
18449
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18450
#endif
18451
18452
#ifdef HAVE_MKFIFOAT
18453
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18454
#endif
18455
18456
#ifdef HAVE_MKNODAT
18457
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18458
#endif
18459
18460
#ifdef HAVE_RENAMEAT
18461
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18462
#endif
18463
18464
#ifdef HAVE_UNLINKAT
18465
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18466
#endif
18467
18468
#ifdef HAVE_OPENAT
18469
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18470
#endif
18471
18472
#ifdef HAVE_READLINKAT
18473
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18474
#endif
18475
18476
#ifdef HAVE_SYMLINKAT
18477
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18478
#endif
18479
18480
#ifdef HAVE_FUTIMENS
18481
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18482
#endif
18483
18484
#ifdef HAVE_UTIMENSAT
18485
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18486
#endif
18487
18488
#ifdef HAVE_PTSNAME_R
18489
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18490
#endif
18491
18492
18493
18494
static const struct have_function {
18495
    const char * const label;
18496
    int (*probe)(void);
18497
} have_functions[] = {
18498
18499
#ifdef HAVE_EVENTFD
18500
    {"HAVE_EVENTFD", NULL},
18501
#endif
18502
18503
#ifdef HAVE_TIMERFD_CREATE
18504
    {"HAVE_TIMERFD_CREATE", NULL},
18505
#endif
18506
18507
#ifdef HAVE_FACCESSAT
18508
    { "HAVE_FACCESSAT", probe_faccessat },
18509
#endif
18510
18511
#ifdef HAVE_FCHDIR
18512
    { "HAVE_FCHDIR", NULL },
18513
#endif
18514
18515
#ifdef HAVE_FCHMOD
18516
    { "HAVE_FCHMOD", NULL },
18517
#endif
18518
18519
#ifdef HAVE_FCHMODAT
18520
    { "HAVE_FCHMODAT", probe_fchmodat },
18521
#endif
18522
18523
#ifdef HAVE_FCHOWN
18524
    { "HAVE_FCHOWN", NULL },
18525
#endif
18526
18527
#ifdef HAVE_FCHOWNAT
18528
    { "HAVE_FCHOWNAT", probe_fchownat },
18529
#endif
18530
18531
#ifdef HAVE_FEXECVE
18532
    { "HAVE_FEXECVE", NULL },
18533
#endif
18534
18535
#ifdef HAVE_FDOPENDIR
18536
    { "HAVE_FDOPENDIR", probe_fdopendir },
18537
#endif
18538
18539
#ifdef HAVE_FPATHCONF
18540
    { "HAVE_FPATHCONF", NULL },
18541
#endif
18542
18543
#ifdef HAVE_FSTATAT
18544
    { "HAVE_FSTATAT", probe_fstatat },
18545
#endif
18546
18547
#ifdef HAVE_FSTATVFS
18548
    { "HAVE_FSTATVFS", NULL },
18549
#endif
18550
18551
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18552
    { "HAVE_FTRUNCATE", NULL },
18553
#endif
18554
18555
#ifdef HAVE_FUTIMENS
18556
    { "HAVE_FUTIMENS", probe_futimens },
18557
#endif
18558
18559
#ifdef HAVE_FUTIMES
18560
    { "HAVE_FUTIMES", NULL },
18561
#endif
18562
18563
#ifdef HAVE_FUTIMESAT
18564
    { "HAVE_FUTIMESAT", NULL },
18565
#endif
18566
18567
#ifdef HAVE_LINKAT
18568
    { "HAVE_LINKAT", probe_linkat },
18569
#endif
18570
18571
#ifdef HAVE_LCHFLAGS
18572
    { "HAVE_LCHFLAGS", NULL },
18573
#endif
18574
18575
#ifdef HAVE_LCHMOD
18576
    { "HAVE_LCHMOD", NULL },
18577
#endif
18578
18579
#ifdef HAVE_LCHOWN
18580
    { "HAVE_LCHOWN", NULL },
18581
#endif
18582
18583
#ifdef HAVE_LSTAT
18584
    { "HAVE_LSTAT", NULL },
18585
#endif
18586
18587
#ifdef HAVE_LUTIMES
18588
    { "HAVE_LUTIMES", NULL },
18589
#endif
18590
18591
#ifdef HAVE_MEMFD_CREATE
18592
    { "HAVE_MEMFD_CREATE", NULL },
18593
#endif
18594
18595
#ifdef HAVE_MKDIRAT
18596
    { "HAVE_MKDIRAT", probe_mkdirat },
18597
#endif
18598
18599
#ifdef HAVE_MKFIFOAT
18600
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18601
#endif
18602
18603
#ifdef HAVE_MKNODAT
18604
    { "HAVE_MKNODAT", probe_mknodat },
18605
#endif
18606
18607
#ifdef HAVE_OPENAT
18608
    { "HAVE_OPENAT", probe_openat },
18609
#endif
18610
18611
#ifdef HAVE_READLINKAT
18612
    { "HAVE_READLINKAT", probe_readlinkat },
18613
#endif
18614
18615
#ifdef HAVE_RENAMEAT
18616
    { "HAVE_RENAMEAT", probe_renameat },
18617
#endif
18618
18619
#ifdef HAVE_SYMLINKAT
18620
    { "HAVE_SYMLINKAT", probe_symlinkat },
18621
#endif
18622
18623
#ifdef HAVE_UNLINKAT
18624
    { "HAVE_UNLINKAT", probe_unlinkat },
18625
#endif
18626
18627
#ifdef HAVE_UTIMENSAT
18628
    { "HAVE_UTIMENSAT", probe_utimensat },
18629
#endif
18630
18631
#ifdef HAVE_PTSNAME_R
18632
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18633
#endif
18634
18635
#ifdef MS_WINDOWS
18636
    { "MS_WINDOWS", NULL },
18637
#endif
18638
18639
    { NULL, NULL }
18640
};
18641
18642
18643
static int
18644
posixmodule_exec(PyObject *m)
18645
34
{
18646
34
    _posixstate *state = get_posix_state(m);
18647
18648
34
#if defined(HAVE_PWRITEV)
18649
34
    if (HAVE_PWRITEV_RUNTIME) {} else {
18650
0
        PyObject* dct = PyModule_GetDict(m);
18651
18652
0
        if (dct == NULL) {
18653
0
            return -1;
18654
0
        }
18655
18656
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18657
0
            return -1;
18658
0
        }
18659
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18660
0
            return -1;
18661
0
        }
18662
0
    }
18663
34
#endif
18664
18665
34
#ifdef HAVE_STATX
18666
34
    if (statx == NULL) {
18667
0
        PyObject* dct = PyModule_GetDict(m);
18668
0
        if (dct == NULL) {
18669
0
            return -1;
18670
0
        }
18671
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18672
0
            return -1;
18673
0
        }
18674
0
    }
18675
34
    else {
18676
34
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18677
34
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18678
0
            return -1;
18679
0
        }
18680
34
    }
18681
34
#endif
18682
18683
    /* Initialize environ dictionary */
18684
34
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18685
0
        return -1;
18686
0
    }
18687
18688
34
    if (all_ins(m))
18689
0
        return -1;
18690
18691
34
    if (setup_confname_tables(m))
18692
0
        return -1;
18693
18694
34
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18695
0
        return -1;
18696
0
    }
18697
18698
34
#if defined(HAVE_WAITID)
18699
34
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18700
34
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18701
0
        return -1;
18702
0
    }
18703
34
#endif
18704
18705
34
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18706
34
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18707
34
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18708
34
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18709
34
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18710
0
        return -1;
18711
0
    }
18712
34
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18713
34
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18714
18715
34
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18716
34
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18717
0
        return -1;
18718
0
    }
18719
18720
34
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18721
34
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18722
34
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18723
0
        return -1;
18724
0
    }
18725
34
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18726
34
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18727
34
                          &os_sched_param_reduce_method) < 0)
18728
0
    {
18729
0
        return -1;
18730
0
    }
18731
34
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18732
34
#endif
18733
18734
    /* initialize TerminalSize_info */
18735
34
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18736
34
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18737
0
        return -1;
18738
0
    }
18739
18740
    /* initialize scandir types */
18741
34
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18742
34
    if (ScandirIteratorType == NULL) {
18743
0
        return -1;
18744
0
    }
18745
34
    state->ScandirIteratorType = ScandirIteratorType;
18746
18747
34
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18748
34
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18749
0
        return -1;
18750
0
    }
18751
18752
34
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18753
34
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18754
0
        return -1;
18755
0
    }
18756
18757
34
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18758
34
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18759
0
        return -1;
18760
0
    }
18761
18762
34
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18763
0
        return -1;
18764
34
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18765
34
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18766
34
    if (state->struct_rusage == NULL)
18767
0
        return -1;
18768
34
#endif
18769
34
    state->st_mode = PyUnicode_InternFromString("st_mode");
18770
34
    if (state->st_mode == NULL)
18771
0
        return -1;
18772
18773
    /* suppress "function not used" warnings */
18774
34
    {
18775
34
    int ignored;
18776
34
    fd_specified("", -1);
18777
34
    follow_symlinks_specified("", 1);
18778
34
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18779
34
    dir_fd_converter(Py_None, &ignored);
18780
34
    dir_fd_unavailable(Py_None, &ignored);
18781
34
    }
18782
18783
    /*
18784
     * provide list of locally available functions
18785
     * so os.py can populate support_* lists
18786
     */
18787
34
    PyObject *list = PyList_New(0);
18788
34
    if (!list) {
18789
0
        return -1;
18790
0
    }
18791
1.12k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18792
1.08k
        PyObject *unicode;
18793
1.08k
        if (trace->probe && !trace->probe()) continue;
18794
1.08k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18795
1.08k
        if (!unicode)
18796
0
            return -1;
18797
1.08k
        if (PyList_Append(list, unicode))
18798
0
            return -1;
18799
1.08k
        Py_DECREF(unicode);
18800
1.08k
    }
18801
18802
34
#ifndef MS_WINDOWS
18803
34
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18804
0
        PyErr_SetString(PyExc_RuntimeError,
18805
0
                        "cannot read ticks_per_second");
18806
0
        return -1;
18807
0
    }
18808
34
    assert(state->ticks_per_second >= 1);
18809
34
#endif
18810
18811
34
    return PyModule_Add(m, "_have_functions", list);
18812
34
}
18813
18814
18815
static PyModuleDef_Slot posixmodile_slots[] = {
18816
    {Py_mod_exec, posixmodule_exec},
18817
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18818
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18819
    {0, NULL}
18820
};
18821
18822
static struct PyModuleDef posixmodule = {
18823
    PyModuleDef_HEAD_INIT,
18824
    .m_name = MODNAME,
18825
    .m_doc = posix__doc__,
18826
    .m_size = sizeof(_posixstate),
18827
    .m_methods = posix_methods,
18828
    .m_slots = posixmodile_slots,
18829
    .m_traverse = _posix_traverse,
18830
    .m_clear = _posix_clear,
18831
    .m_free = _posix_free,
18832
};
18833
18834
PyMODINIT_FUNC
18835
INITFUNC(void)
18836
34
{
18837
34
    return PyModuleDef_Init(&posixmodule);
18838
34
}