Coverage Report

Created: 2025-11-24 06:11

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
424k
#  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
280k
#  define STAT stat
407
8.20k
#  define LSTAT lstat
408
138k
#  define FSTAT fstat
409
561k
#  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
134k
#  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
138k
#  define HAVE_FDOPENDIR_RUNTIME 1
608
0
#  define HAVE_MKDIRAT_RUNTIME 1
609
0
#  define HAVE_RENAMEAT_RUNTIME 1
610
135k
#  define HAVE_UNLINKAT_RUNTIME 1
611
134k
#  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
28
#  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
24
{
798
24
    if (func == NULL)  /* nothing to register? do nothing. */
799
16
        return 0;
800
8
    if (*lst == NULL) {
801
6
        *lst = PyList_New(0);
802
6
        if (*lst == NULL)
803
0
            return -1;
804
6
    }
805
8
    return PyList_Append(*lst, func);
806
8
}
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
319k
{
835
319k
    if (uid == (uid_t)-1)
836
0
        return PyLong_FromLong(-1);
837
319k
    return PyLong_FromUnsignedLong(uid);
838
319k
}
839
840
PyObject *
841
_PyLong_FromGid(gid_t gid)
842
319k
{
843
319k
    if (gid == (gid_t)-1)
844
0
        return PyLong_FromLong(-1);
845
319k
    return PyLong_FromUnsignedLong(gid);
846
319k
}
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
638k
{
1066
638k
#ifdef NODEV
1067
638k
    if (dev == NODEV) {
1068
28
        return PyLong_FromLongLong((long long)dev);
1069
28
    }
1070
638k
#endif
1071
638k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1072
638k
}
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.42M
#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
408k
{
1137
408k
    int overflow;
1138
408k
    long long_value;
1139
1140
408k
    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
408k
    PyObject *index = _PyNumber_Index(o);
1148
408k
    if (index == NULL) {
1149
0
        return 0;
1150
0
    }
1151
1152
408k
    assert(PyLong_Check(index));
1153
408k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1154
408k
    Py_DECREF(index);
1155
408k
    assert(!PyErr_Occurred());
1156
408k
    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
408k
    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
408k
    *p = (int)long_value;
1168
408k
    return 1;
1169
408k
}
1170
1171
static int
1172
dir_fd_converter(PyObject *o, void *p)
1173
286k
{
1174
286k
    if (o == Py_None) {
1175
16.0k
        *(int *)p = DEFAULT_DIR_FD;
1176
16.0k
        return 1;
1177
16.0k
    }
1178
269k
    else if (PyIndex_Check(o)) {
1179
269k
        return _fd_converter(o, (int *)p);
1180
269k
    }
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
286k
}
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
594k
{
1222
594k
    void *state = _PyModule_GetState(module);
1223
594k
    assert(state != NULL);
1224
594k
    return (_posixstate *)state;
1225
594k
}
1226
1227
/*
1228
 * A PyArg_ParseTuple "converter" function
1229
 * that handles filesystem paths in the manner
1230
 * preferred by the os module.
1231
 *
1232
 * path_converter accepts (Unicode) strings and their
1233
 * subclasses, and bytes and their subclasses.  What
1234
 * it does with the argument depends on path.make_wide:
1235
 *
1236
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1237
 *     string we extract the wchar_t * and return it; if we
1238
 *     get bytes we decode to wchar_t * and return that.
1239
 *
1240
 *   * If path.make_wide is zero, if we get bytes we extract
1241
 *     the char_t * and return it; if we get a (Unicode)
1242
 *     string we encode to char_t * and return that.
1243
 *
1244
 * path_converter also optionally accepts signed
1245
 * integers (representing open file descriptors) instead
1246
 * of path strings.
1247
 *
1248
 * Input fields:
1249
 *   path.nullable
1250
 *     If nonzero, the path is permitted to be None.
1251
 *   path.nonstrict
1252
 *     If nonzero, the path is permitted to contain
1253
 *     embedded null characters and have any length.
1254
 *   path.make_wide
1255
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1256
 *     it always uses narrow, encoding if necessary. The default value is
1257
 *     nonzero on Windows, else zero.
1258
 *   path.suppress_value_error
1259
 *     If nonzero, raising ValueError is suppressed.
1260
 *   path.allow_fd
1261
 *     If nonzero, the path is permitted to be a file handle
1262
 *     (a signed int) instead of a string.
1263
 *   path.function_name
1264
 *     If non-NULL, path_converter will use that as the name
1265
 *     of the function in error messages.
1266
 *     (If path.function_name is NULL it omits the function name.)
1267
 *   path.argument_name
1268
 *     If non-NULL, path_converter will use that as the name
1269
 *     of the parameter in error messages.
1270
 *     (If path.argument_name is NULL it uses "path".)
1271
 *
1272
 * Output fields:
1273
 *   path.wide
1274
 *     Points to the path if it was expressed as Unicode
1275
 *     or if it was bytes and decoded to Unicode.
1276
 *   path.narrow
1277
 *     Points to the path if it was expressed as bytes,
1278
 *     or if it was Unicode and encoded to bytes.
1279
 *   path.fd
1280
 *     Contains a file descriptor if path.accept_fd was true
1281
 *     and the caller provided a signed integer instead of any
1282
 *     sort of string.
1283
 *
1284
 *     WARNING: if your "path" parameter is optional, and is
1285
 *     unspecified, path_converter will never get called.
1286
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1287
 *     yourself!
1288
 *   path.value_error
1289
 *     If nonzero, then suppress_value_error was specified and a ValueError
1290
 *     occurred.
1291
 *   path.length
1292
 *     The length of the path in characters, if specified as
1293
 *     a string.
1294
 *   path.object
1295
 *     The original object passed in (if get a PathLike object,
1296
 *     the result of PyOS_FSPath() is treated as the original object).
1297
 *     Own a reference to the object.
1298
 *   path.cleanup
1299
 *     For internal use only.  May point to a temporary object.
1300
 *     (Pay no attention to the man behind the curtain.)
1301
 *
1302
 *   At most one of path.wide or path.narrow will be non-NULL.
1303
 *   If path was None and path.nullable was set,
1304
 *     or if path was an integer and path.allow_fd was set,
1305
 *     both path.wide and path.narrow will be NULL
1306
 *     and path.length will be 0.
1307
 *
1308
 *   path_converter takes care to not write to the path_t
1309
 *   unless it's successful.  However it must reset the
1310
 *   "cleanup" field each time it's called.
1311
 *
1312
 * Use as follows:
1313
 *      path_t path;
1314
 *      memset(&path, 0, sizeof(path));
1315
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1316
 *      // ... use values from path ...
1317
 *      path_cleanup(&path);
1318
 *
1319
 * (Note that if PyArg_Parse fails you don't need to call
1320
 * path_cleanup().  However it is safe to do so.)
1321
 */
1322
typedef struct {
1323
    // Input fields
1324
    const char *function_name;
1325
    const char *argument_name;
1326
    int nullable;
1327
    int nonstrict;
1328
    int make_wide;
1329
    int suppress_value_error;
1330
    int allow_fd;
1331
    // Output fields
1332
    const wchar_t *wide;
1333
    const char *narrow;
1334
    int fd;
1335
    int value_error;
1336
    Py_ssize_t length;
1337
    PyObject *object;
1338
    PyObject *cleanup;
1339
} path_t;
1340
1341
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1342
                          make_wide, suppress_value_error, allow_fd) \
1343
994k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1344
994k
     suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL}
1345
#ifdef MS_WINDOWS
1346
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1347
                            nonstrict, suppress_value_error, allow_fd) \
1348
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1349
                      suppress_value_error, allow_fd)
1350
#else
1351
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1352
                            nonstrict, suppress_value_error, allow_fd) \
1353
845k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1354
845k
                      suppress_value_error, allow_fd)
1355
#endif
1356
1357
static void
1358
path_cleanup(path_t *path)
1359
1.13M
{
1360
1.13M
    wchar_t *wide = (wchar_t *)path->wide;
1361
1.13M
    path->wide = NULL;
1362
1.13M
    PyMem_Free(wide);
1363
1.13M
    Py_CLEAR(path->object);
1364
1.13M
    Py_CLEAR(path->cleanup);
1365
1.13M
}
1366
1367
static int
1368
path_converter(PyObject *o, void *p)
1369
994k
{
1370
994k
    path_t *path = (path_t *)p;
1371
994k
    PyObject *bytes = NULL;
1372
994k
    Py_ssize_t length = 0;
1373
994k
    int is_index, is_bytes, is_unicode;
1374
994k
    const char *narrow;
1375
994k
    PyObject *wo = NULL;
1376
994k
    wchar_t *wide = NULL;
1377
1378
994k
#define FORMAT_EXCEPTION(exc, fmt) \
1379
994k
    PyErr_Format(exc, "%s%s" fmt, \
1380
0
        path->function_name ? path->function_name : "", \
1381
0
        path->function_name ? ": "                : "", \
1382
0
        path->argument_name ? path->argument_name : "path")
1383
1384
    /* Py_CLEANUP_SUPPORTED support */
1385
994k
    if (o == NULL) {
1386
0
        path_cleanup(path);
1387
0
        return 1;
1388
0
    }
1389
1390
    /* Ensure it's always safe to call path_cleanup(). */
1391
994k
    path->object = path->cleanup = NULL;
1392
    /* path->object owns a reference to the original object */
1393
994k
    Py_INCREF(o);
1394
1395
994k
    if ((o == Py_None) && path->nullable) {
1396
0
        path->wide = NULL;
1397
0
        path->narrow = NULL;
1398
0
        path->fd = -1;
1399
0
        goto success_exit;
1400
0
    }
1401
1402
    /* Only call this here so that we don't treat the return value of
1403
       os.fspath() as an fd or buffer. */
1404
994k
    is_index = path->allow_fd && PyIndex_Check(o);
1405
994k
    is_bytes = PyBytes_Check(o);
1406
994k
    is_unicode = PyUnicode_Check(o);
1407
1408
994k
    if (!is_index && !is_unicode && !is_bytes) {
1409
        /* Inline PyOS_FSPath() for better error messages. */
1410
0
        PyObject *func, *res;
1411
1412
0
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1413
0
        if ((NULL == func) || (func == Py_None)) {
1414
0
            goto error_format;
1415
0
        }
1416
0
        res = _PyObject_CallNoArgs(func);
1417
0
        Py_DECREF(func);
1418
0
        if (NULL == res) {
1419
0
            goto error_exit;
1420
0
        }
1421
0
        else if (PyUnicode_Check(res)) {
1422
0
            is_unicode = 1;
1423
0
        }
1424
0
        else if (PyBytes_Check(res)) {
1425
0
            is_bytes = 1;
1426
0
        }
1427
0
        else {
1428
0
            PyErr_Format(PyExc_TypeError,
1429
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1430
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1431
0
                 _PyType_Name(Py_TYPE(res)));
1432
0
            Py_DECREF(res);
1433
0
            goto error_exit;
1434
0
        }
1435
1436
        /* still owns a reference to the original object */
1437
0
        Py_SETREF(o, res);
1438
0
    }
1439
1440
994k
    if (is_unicode) {
1441
855k
        if (path->make_wide) {
1442
149k
            wide = PyUnicode_AsWideCharString(o, &length);
1443
149k
            if (!wide) {
1444
0
                goto error_exit;
1445
0
            }
1446
#ifdef MS_WINDOWS
1447
            if (!path->nonstrict && length > 32767) {
1448
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1449
                goto error_exit;
1450
            }
1451
#endif
1452
149k
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1453
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1454
0
                                 "embedded null character in %s");
1455
0
                goto error_exit;
1456
0
            }
1457
1458
149k
            path->wide = wide;
1459
149k
            path->narrow = NULL;
1460
149k
            path->fd = -1;
1461
149k
            wide = NULL;
1462
149k
            goto success_exit;
1463
149k
        }
1464
706k
        bytes = PyUnicode_EncodeFSDefault(o);
1465
706k
        if (!bytes) {
1466
0
            goto error_exit;
1467
0
        }
1468
706k
    }
1469
138k
    else if (is_bytes) {
1470
0
        bytes = Py_NewRef(o);
1471
0
    }
1472
138k
    else if (is_index) {
1473
138k
        if (!_fd_converter(o, &path->fd)) {
1474
0
            goto error_exit;
1475
0
        }
1476
138k
        path->wide = NULL;
1477
138k
        path->narrow = NULL;
1478
138k
        goto success_exit;
1479
138k
    }
1480
0
    else {
1481
0
 error_format:
1482
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1483
0
            path->function_name ? path->function_name : "",
1484
0
            path->function_name ? ": "                : "",
1485
0
            path->argument_name ? path->argument_name : "path",
1486
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1487
0
                                               "integer or None" :
1488
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1489
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1490
0
                             "string, bytes or os.PathLike",
1491
0
            _PyType_Name(Py_TYPE(o)));
1492
0
        goto error_exit;
1493
0
    }
1494
1495
706k
    length = PyBytes_GET_SIZE(bytes);
1496
706k
    narrow = PyBytes_AS_STRING(bytes);
1497
706k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1498
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1499
0
        goto error_exit;
1500
0
    }
1501
1502
706k
    if (path->make_wide) {
1503
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1504
0
        if (!wo) {
1505
0
            goto error_exit;
1506
0
        }
1507
1508
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1509
0
        Py_DECREF(wo);
1510
0
        if (!wide) {
1511
0
            goto error_exit;
1512
0
        }
1513
#ifdef MS_WINDOWS
1514
        if (!path->nonstrict && length > 32767) {
1515
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1516
            goto error_exit;
1517
        }
1518
#endif
1519
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1520
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1521
0
                             "embedded null character in %s");
1522
0
            goto error_exit;
1523
0
        }
1524
0
        path->wide = wide;
1525
0
        path->narrow = NULL;
1526
0
        Py_DECREF(bytes);
1527
0
        wide = NULL;
1528
0
    }
1529
706k
    else {
1530
706k
        path->wide = NULL;
1531
706k
        path->narrow = narrow;
1532
706k
        if (bytes == o) {
1533
            /* Still a reference owned by path->object, don't have to
1534
            worry about path->narrow is used after free. */
1535
0
            Py_DECREF(bytes);
1536
0
        }
1537
706k
        else {
1538
706k
            path->cleanup = bytes;
1539
706k
        }
1540
706k
    }
1541
706k
    path->fd = -1;
1542
1543
994k
 success_exit:
1544
994k
    path->value_error = 0;
1545
994k
    path->length = length;
1546
994k
    path->object = o;
1547
994k
    return Py_CLEANUP_SUPPORTED;
1548
1549
0
 error_exit:
1550
0
    Py_XDECREF(o);
1551
0
    Py_XDECREF(bytes);
1552
0
    PyMem_Free(wide);
1553
0
    if (!path->suppress_value_error ||
1554
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1555
0
    {
1556
0
        return 0;
1557
0
    }
1558
0
    PyErr_Clear();
1559
0
    path->wide = NULL;
1560
0
    path->narrow = NULL;
1561
0
    path->fd = -1;
1562
0
    path->value_error = 1;
1563
0
    path->length = 0;
1564
0
    path->object = NULL;
1565
0
    return Py_CLEANUP_SUPPORTED;
1566
0
}
1567
1568
static void
1569
argument_unavailable_error(const char *function_name, const char *argument_name)
1570
0
{
1571
0
    PyErr_Format(PyExc_NotImplementedError,
1572
0
        "%s%s%s unavailable on this platform",
1573
0
        (function_name != NULL) ? function_name : "",
1574
0
        (function_name != NULL) ? ": ": "",
1575
0
        argument_name);
1576
0
}
1577
1578
static int
1579
dir_fd_unavailable(PyObject *o, void *p)
1580
28
{
1581
28
    int dir_fd;
1582
28
    if (!dir_fd_converter(o, &dir_fd))
1583
0
        return 0;
1584
28
    if (dir_fd != DEFAULT_DIR_FD) {
1585
0
        argument_unavailable_error(NULL, "dir_fd");
1586
0
        return 0;
1587
0
    }
1588
28
    *(int *)p = dir_fd;
1589
28
    return 1;
1590
28
}
1591
1592
static int
1593
fd_specified(const char *function_name, int fd)
1594
28
{
1595
28
    if (fd == -1)
1596
28
        return 0;
1597
1598
0
    argument_unavailable_error(function_name, "fd");
1599
0
    return 1;
1600
28
}
1601
1602
static int
1603
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1604
28
{
1605
28
    if (follow_symlinks)
1606
28
        return 0;
1607
1608
0
    argument_unavailable_error(function_name, "follow_symlinks");
1609
0
    return 1;
1610
28
}
1611
1612
static int
1613
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1614
288k
{
1615
288k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1616
0
        PyErr_Format(PyExc_ValueError,
1617
0
                     "%s: can't specify dir_fd without matching path",
1618
0
                     function_name);
1619
0
        return 1;
1620
0
    }
1621
288k
    return 0;
1622
288k
}
1623
1624
static int
1625
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1626
288k
{
1627
288k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1628
0
        PyErr_Format(PyExc_ValueError,
1629
0
                     "%s: can't specify both dir_fd and fd",
1630
0
                     function_name);
1631
0
        return 1;
1632
0
    }
1633
288k
    return 0;
1634
288k
}
1635
1636
static int
1637
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1638
                               int follow_symlinks)
1639
288k
{
1640
288k
    if ((fd > 0) && (!follow_symlinks)) {
1641
0
        PyErr_Format(PyExc_ValueError,
1642
0
                     "%s: cannot use fd and follow_symlinks together",
1643
0
                     function_name);
1644
0
        return 1;
1645
0
    }
1646
288k
    return 0;
1647
288k
}
1648
1649
static int
1650
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1651
                                   int follow_symlinks)
1652
28
{
1653
28
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1654
0
        PyErr_Format(PyExc_ValueError,
1655
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1656
0
                     function_name);
1657
0
        return 1;
1658
0
    }
1659
28
    return 0;
1660
28
}
1661
1662
#if defined(HAVE_WAITID)
1663
static int
1664
idtype_t_converter(PyObject *arg, void *addr)
1665
0
{
1666
0
    int value = PyLong_AsInt(arg);
1667
0
    if (value == -1 && PyErr_Occurred()) {
1668
0
        return 0;
1669
0
    }
1670
0
    *((idtype_t *)addr) = (idtype_t)(value);
1671
0
    return 1;
1672
0
}
1673
#endif
1674
1675
#ifdef MS_WINDOWS
1676
    typedef long long Py_off_t;
1677
#else
1678
    typedef off_t Py_off_t;
1679
#endif
1680
1681
static int
1682
Py_off_t_converter(PyObject *arg, void *addr)
1683
0
{
1684
#ifdef HAVE_LARGEFILE_SUPPORT
1685
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1686
#else
1687
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1688
0
#endif
1689
0
    if (PyErr_Occurred())
1690
0
        return 0;
1691
0
    return 1;
1692
0
}
1693
1694
static PyObject *
1695
PyLong_FromPy_off_t(Py_off_t offset)
1696
0
{
1697
#ifdef HAVE_LARGEFILE_SUPPORT
1698
    return PyLong_FromLongLong(offset);
1699
#else
1700
0
    return PyLong_FromLong(offset);
1701
0
#endif
1702
0
}
1703
1704
#ifdef HAVE_SIGSET_T
1705
/* Convert an iterable of integers to a sigset.
1706
   Return 1 on success, return 0 and raise an exception on error. */
1707
int
1708
_Py_Sigset_Converter(PyObject *obj, void *addr)
1709
0
{
1710
0
    sigset_t *mask = (sigset_t *)addr;
1711
0
    PyObject *iterator, *item;
1712
0
    long signum;
1713
0
    int overflow;
1714
1715
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1716
0
    if (sigemptyset(mask) < (0)) {
1717
        /* Probably only if mask == NULL. */
1718
0
        PyErr_SetFromErrno(PyExc_OSError);
1719
0
        return 0;
1720
0
    }
1721
1722
0
    iterator = PyObject_GetIter(obj);
1723
0
    if (iterator == NULL) {
1724
0
        return 0;
1725
0
    }
1726
1727
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1728
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1729
0
        Py_DECREF(item);
1730
0
        if (signum <= 0 || signum >= Py_NSIG) {
1731
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1732
0
                PyErr_Format(PyExc_ValueError,
1733
0
                             "signal number %ld out of range [1; %i]",
1734
0
                             signum, Py_NSIG - 1);
1735
0
            }
1736
0
            goto error;
1737
0
        }
1738
0
        if (sigaddset(mask, (int)signum)) {
1739
0
            if (errno != EINVAL) {
1740
                /* Probably impossible */
1741
0
                PyErr_SetFromErrno(PyExc_OSError);
1742
0
                goto error;
1743
0
            }
1744
            /* For backwards compatibility, allow idioms such as
1745
             * `range(1, NSIG)` but warn about invalid signal numbers
1746
             */
1747
0
            const char msg[] =
1748
0
                "invalid signal number %ld, please use valid_signals()";
1749
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1750
0
                goto error;
1751
0
            }
1752
0
        }
1753
0
    }
1754
0
    if (!PyErr_Occurred()) {
1755
0
        Py_DECREF(iterator);
1756
0
        return 1;
1757
0
    }
1758
1759
0
error:
1760
0
    Py_DECREF(iterator);
1761
0
    return 0;
1762
0
}
1763
#endif /* HAVE_SIGSET_T */
1764
1765
/* Return a dictionary corresponding to the POSIX environment table */
1766
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1767
/* On Darwin/MacOSX a shared library or framework has no access to
1768
** environ directly, we must obtain it with _NSGetEnviron(). See also
1769
** man environ(7).
1770
*/
1771
#include <crt_externs.h>
1772
#define USE_DARWIN_NS_GET_ENVIRON 1
1773
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1774
extern char **environ;
1775
#endif /* !_MSC_VER */
1776
1777
static PyObject *
1778
convertenviron(void)
1779
28
{
1780
28
    PyObject *d;
1781
#ifdef MS_WINDOWS
1782
    wchar_t **e;
1783
#else
1784
28
    char **e;
1785
28
#endif
1786
1787
28
    d = PyDict_New();
1788
28
    if (d == NULL)
1789
0
        return NULL;
1790
#ifdef MS_WINDOWS
1791
    /* _wenviron must be initialized in this way if the program is started
1792
       through main() instead of wmain(). */
1793
    (void)_wgetenv(L"");
1794
    e = _wenviron;
1795
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1796
    /* environ is not accessible as an extern in a shared object on OSX; use
1797
       _NSGetEnviron to resolve it. The value changes if you add environment
1798
       variables between calls to Py_Initialize, so don't cache the value. */
1799
    e = *_NSGetEnviron();
1800
#else
1801
28
    e = environ;
1802
28
#endif
1803
28
    if (e == NULL)
1804
0
        return d;
1805
980
    for (; *e != NULL; e++) {
1806
952
        PyObject *k;
1807
952
        PyObject *v;
1808
#ifdef MS_WINDOWS
1809
        const wchar_t *p = wcschr(*e, L'=');
1810
#else
1811
952
        const char *p = strchr(*e, '=');
1812
952
#endif
1813
952
        if (p == NULL)
1814
0
            continue;
1815
#ifdef MS_WINDOWS
1816
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1817
#else
1818
952
        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1819
952
#endif
1820
952
        if (k == NULL) {
1821
0
            Py_DECREF(d);
1822
0
            return NULL;
1823
0
        }
1824
#ifdef MS_WINDOWS
1825
        v = PyUnicode_FromWideChar(p+1, -1);
1826
#else
1827
952
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1828
952
#endif
1829
952
        if (v == NULL) {
1830
0
            Py_DECREF(k);
1831
0
            Py_DECREF(d);
1832
0
            return NULL;
1833
0
        }
1834
952
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1835
0
            Py_DECREF(v);
1836
0
            Py_DECREF(k);
1837
0
            Py_DECREF(d);
1838
0
            return NULL;
1839
0
        }
1840
952
        Py_DECREF(k);
1841
952
        Py_DECREF(v);
1842
952
    }
1843
28
    return d;
1844
28
}
1845
1846
/* Set a POSIX-specific error from errno, and return NULL */
1847
1848
static PyObject *
1849
posix_error(void)
1850
0
{
1851
0
    return PyErr_SetFromErrno(PyExc_OSError);
1852
0
}
1853
1854
#ifdef MS_WINDOWS
1855
static PyObject *
1856
win32_error(const char* function, const char* filename)
1857
{
1858
    /* XXX We should pass the function name along in the future.
1859
       (winreg.c also wants to pass the function name.)
1860
       This would however require an additional param to the
1861
       Windows error object, which is non-trivial.
1862
    */
1863
    errno = GetLastError();
1864
    if (filename)
1865
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1866
    else
1867
        return PyErr_SetFromWindowsErr(errno);
1868
}
1869
1870
static PyObject *
1871
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1872
{
1873
    /* XXX - see win32_error for comments on 'function' */
1874
    if (filename)
1875
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1876
                    PyExc_OSError,
1877
                    err,
1878
                    filename);
1879
    else
1880
        return PyErr_SetFromWindowsErr(err);
1881
}
1882
1883
static PyObject *
1884
win32_error_object(const char* function, PyObject* filename)
1885
{
1886
    errno = GetLastError();
1887
    return win32_error_object_err(function, filename, errno);
1888
}
1889
1890
#endif /* MS_WINDOWS */
1891
1892
static PyObject *
1893
posix_path_object_error(PyObject *path)
1894
242k
{
1895
242k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1896
242k
}
1897
1898
static PyObject *
1899
path_object_error(PyObject *path)
1900
242k
{
1901
#ifdef MS_WINDOWS
1902
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1903
                PyExc_OSError, 0, path);
1904
#else
1905
242k
    return posix_path_object_error(path);
1906
242k
#endif
1907
242k
}
1908
1909
static PyObject *
1910
path_object_error2(PyObject *path, PyObject *path2)
1911
0
{
1912
#ifdef MS_WINDOWS
1913
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1914
                PyExc_OSError, 0, path, path2);
1915
#else
1916
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1917
0
#endif
1918
0
}
1919
1920
static PyObject *
1921
path_error(path_t *path)
1922
242k
{
1923
242k
    return path_object_error(path->object);
1924
242k
}
1925
1926
static PyObject *
1927
posix_path_error(path_t *path)
1928
0
{
1929
0
    return posix_path_object_error(path->object);
1930
0
}
1931
1932
static PyObject *
1933
path_error2(path_t *path, path_t *path2)
1934
0
{
1935
0
    return path_object_error2(path->object, path2->object);
1936
0
}
1937
1938
1939
/* POSIX generic methods */
1940
1941
static PyObject *
1942
posix_fildes_fd(int fd, int (*func)(int))
1943
0
{
1944
0
    int res;
1945
0
    int async_err = 0;
1946
1947
0
    do {
1948
0
        Py_BEGIN_ALLOW_THREADS
1949
0
        _Py_BEGIN_SUPPRESS_IPH
1950
0
        res = (*func)(fd);
1951
0
        _Py_END_SUPPRESS_IPH
1952
0
        Py_END_ALLOW_THREADS
1953
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1954
0
    if (res != 0)
1955
0
        return (!async_err) ? posix_error() : NULL;
1956
0
    Py_RETURN_NONE;
1957
0
}
1958
1959
1960
#ifdef MS_WINDOWS
1961
/* This is a reimplementation of the C library's chdir function,
1962
   but one that produces Win32 errors instead of DOS error codes.
1963
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1964
   it also needs to set "magic" environment variables indicating
1965
   the per-drive current directory, which are of the form =<drive>: */
1966
static BOOL __stdcall
1967
win32_wchdir(LPCWSTR path)
1968
{
1969
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1970
    int result;
1971
    wchar_t env[4] = L"=x:";
1972
1973
    if(!SetCurrentDirectoryW(path))
1974
        return FALSE;
1975
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1976
    if (!result)
1977
        return FALSE;
1978
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1979
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1980
        if (!new_path) {
1981
            SetLastError(ERROR_OUTOFMEMORY);
1982
            return FALSE;
1983
        }
1984
        result = GetCurrentDirectoryW(result, new_path);
1985
        if (!result) {
1986
            PyMem_RawFree(new_path);
1987
            return FALSE;
1988
        }
1989
    }
1990
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1991
                            wcsncmp(new_path, L"//", 2) == 0);
1992
    if (!is_unc_like_path) {
1993
        env[1] = new_path[0];
1994
        result = SetEnvironmentVariableW(env, new_path);
1995
    }
1996
    if (new_path != path_buf)
1997
        PyMem_RawFree(new_path);
1998
    return result ? TRUE : FALSE;
1999
}
2000
#endif
2001
2002
#ifdef MS_WINDOWS
2003
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2004
   - time stamps are restricted to second resolution
2005
   - file modification times suffer from forth-and-back conversions between
2006
     UTC and local time
2007
   Therefore, we implement our own stat, based on the Win32 API directly.
2008
*/
2009
#define HAVE_STAT_NSEC 1
2010
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2011
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2012
2013
static void
2014
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2015
                       BY_HANDLE_FILE_INFORMATION *info,
2016
                       ULONG *reparse_tag)
2017
{
2018
    memset(info, 0, sizeof(*info));
2019
    info->dwFileAttributes = pFileData->dwFileAttributes;
2020
    info->ftCreationTime   = pFileData->ftCreationTime;
2021
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
2022
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
2023
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
2024
    info->nFileSizeLow     = pFileData->nFileSizeLow;
2025
/*  info->nNumberOfLinks   = 1; */
2026
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2027
        *reparse_tag = pFileData->dwReserved0;
2028
    else
2029
        *reparse_tag = 0;
2030
}
2031
2032
static BOOL
2033
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
2034
{
2035
    HANDLE hFindFile;
2036
    WIN32_FIND_DATAW FileData;
2037
    LPCWSTR filename = pszFile;
2038
    size_t n = wcslen(pszFile);
2039
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2040
        // cannot use PyMem_Malloc here because we do not hold the GIL
2041
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2042
        if(!filename) {
2043
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2044
            return FALSE;
2045
        }
2046
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2047
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2048
            ((LPWSTR)filename)[n] = L'\0';
2049
        }
2050
        if (!n || (n == 1 && filename[1] == L':')) {
2051
            // Nothing left to query
2052
            free((void *)filename);
2053
            return FALSE;
2054
        }
2055
    }
2056
    hFindFile = FindFirstFileW(filename, &FileData);
2057
    if (pszFile != filename) {
2058
        free((void *)filename);
2059
    }
2060
    if (hFindFile == INVALID_HANDLE_VALUE) {
2061
        return FALSE;
2062
    }
2063
    FindClose(hFindFile);
2064
    find_data_to_file_info(&FileData, info, reparse_tag);
2065
    return TRUE;
2066
}
2067
2068
2069
static void
2070
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2071
                         struct _Py_stat_struct *result)
2072
{
2073
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2074
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2075
           the filename has an extension that is commonly used by files
2076
           that CreateProcessW can execute. A real implementation calls
2077
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2078
           AccessCheck to check for generic read, write, and execute
2079
           access. */
2080
        const wchar_t *fileExtension = wcsrchr(path, '.');
2081
        if (fileExtension) {
2082
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2083
                _wcsicmp(fileExtension, L".bat") == 0 ||
2084
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2085
                _wcsicmp(fileExtension, L".com") == 0) {
2086
                result->st_mode |= 0111;
2087
            }
2088
        }
2089
    }
2090
}
2091
2092
2093
static int
2094
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2095
                      BOOL traverse)
2096
{
2097
    HANDLE hFile;
2098
    BY_HANDLE_FILE_INFORMATION fileInfo;
2099
    FILE_BASIC_INFO basicInfo;
2100
    FILE_BASIC_INFO *pBasicInfo = NULL;
2101
    FILE_ID_INFO idInfo;
2102
    FILE_ID_INFO *pIdInfo = NULL;
2103
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2104
    DWORD fileType, error;
2105
    BOOL isUnhandledTag = FALSE;
2106
    int retval = 0;
2107
2108
    DWORD access = FILE_READ_ATTRIBUTES;
2109
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2110
    if (!traverse) {
2111
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2112
    }
2113
2114
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2115
    if (hFile == INVALID_HANDLE_VALUE) {
2116
        /* Either the path doesn't exist, or the caller lacks access. */
2117
        error = GetLastError();
2118
        switch (error) {
2119
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2120
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2121
            /* Try reading the parent directory. */
2122
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2123
                /* Cannot read the parent directory. */
2124
                switch (GetLastError()) {
2125
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2126
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2127
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2128
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2129
                    break;
2130
                /* Restore the error from CreateFileW(). */
2131
                default:
2132
                    SetLastError(error);
2133
                }
2134
2135
                return -1;
2136
            }
2137
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2138
                if (traverse ||
2139
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2140
                    /* The stat call has to traverse but cannot, so fail. */
2141
                    SetLastError(error);
2142
                    return -1;
2143
                }
2144
            }
2145
            break;
2146
2147
        case ERROR_INVALID_PARAMETER:
2148
            /* \\.\con requires read or write access. */
2149
            hFile = CreateFileW(path, access | GENERIC_READ,
2150
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2151
                        OPEN_EXISTING, flags, NULL);
2152
            if (hFile == INVALID_HANDLE_VALUE) {
2153
                SetLastError(error);
2154
                return -1;
2155
            }
2156
            break;
2157
2158
        case ERROR_CANT_ACCESS_FILE:
2159
            /* bpo37834: open unhandled reparse points if traverse fails. */
2160
            if (traverse) {
2161
                traverse = FALSE;
2162
                isUnhandledTag = TRUE;
2163
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2164
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2165
            }
2166
            if (hFile == INVALID_HANDLE_VALUE) {
2167
                SetLastError(error);
2168
                return -1;
2169
            }
2170
            break;
2171
2172
        default:
2173
            return -1;
2174
        }
2175
    }
2176
2177
    if (hFile != INVALID_HANDLE_VALUE) {
2178
        /* Handle types other than files on disk. */
2179
        fileType = GetFileType(hFile);
2180
        if (fileType != FILE_TYPE_DISK) {
2181
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2182
                retval = -1;
2183
                goto cleanup;
2184
            }
2185
            DWORD fileAttributes = GetFileAttributesW(path);
2186
            memset(result, 0, sizeof(*result));
2187
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2188
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2189
                /* \\.\pipe\ or \\.\mailslot\ */
2190
                result->st_mode = _S_IFDIR;
2191
            } else if (fileType == FILE_TYPE_CHAR) {
2192
                /* \\.\nul */
2193
                result->st_mode = _S_IFCHR;
2194
            } else if (fileType == FILE_TYPE_PIPE) {
2195
                /* \\.\pipe\spam */
2196
                result->st_mode = _S_IFIFO;
2197
            }
2198
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2199
            goto cleanup;
2200
        }
2201
2202
        /* Query the reparse tag, and traverse a non-link. */
2203
        if (!traverse) {
2204
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2205
                    &tagInfo, sizeof(tagInfo))) {
2206
                /* Allow devices that do not support FileAttributeTagInfo. */
2207
                switch (GetLastError()) {
2208
                case ERROR_INVALID_PARAMETER:
2209
                case ERROR_INVALID_FUNCTION:
2210
                case ERROR_NOT_SUPPORTED:
2211
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2212
                    tagInfo.ReparseTag = 0;
2213
                    break;
2214
                default:
2215
                    retval = -1;
2216
                    goto cleanup;
2217
                }
2218
            } else if (tagInfo.FileAttributes &
2219
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2220
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2221
                    if (isUnhandledTag) {
2222
                        /* Traversing previously failed for either this link
2223
                           or its target. */
2224
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2225
                        retval = -1;
2226
                        goto cleanup;
2227
                    }
2228
                /* Traverse a non-link, but not if traversing already failed
2229
                   for an unhandled tag. */
2230
                } else if (!isUnhandledTag) {
2231
                    CloseHandle(hFile);
2232
                    return win32_xstat_slow_impl(path, result, TRUE);
2233
                }
2234
            }
2235
        }
2236
2237
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2238
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2239
                                          &basicInfo, sizeof(basicInfo))) {
2240
            switch (GetLastError()) {
2241
            case ERROR_INVALID_PARAMETER:
2242
            case ERROR_INVALID_FUNCTION:
2243
            case ERROR_NOT_SUPPORTED:
2244
                /* Volumes and physical disks are block devices, e.g.
2245
                   \\.\C: and \\.\PhysicalDrive0. */
2246
                memset(result, 0, sizeof(*result));
2247
                result->st_mode = 0x6000; /* S_IFBLK */
2248
                goto cleanup;
2249
            }
2250
            retval = -1;
2251
            goto cleanup;
2252
        }
2253
2254
        /* Successfully got FileBasicInfo, so we'll pass it along */
2255
        pBasicInfo = &basicInfo;
2256
2257
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2258
            /* Successfully got FileIdInfo, so pass it along */
2259
            pIdInfo = &idInfo;
2260
        }
2261
    }
2262
2263
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2264
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2265
2266
cleanup:
2267
    if (hFile != INVALID_HANDLE_VALUE) {
2268
        /* Preserve last error if we are failing */
2269
        error = retval ? GetLastError() : 0;
2270
        if (!CloseHandle(hFile)) {
2271
            retval = -1;
2272
        } else if (retval) {
2273
            /* Restore last error */
2274
            SetLastError(error);
2275
        }
2276
    }
2277
2278
    return retval;
2279
}
2280
2281
static int
2282
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2283
                 BOOL traverse)
2284
{
2285
    FILE_STAT_BASIC_INFORMATION statInfo;
2286
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2287
                                     &statInfo, sizeof(statInfo))) {
2288
        if (// Cannot use fast path for reparse points ...
2289
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2290
            // ... unless it's a name surrogate (symlink) and we're not following
2291
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2292
        ) {
2293
            _Py_stat_basic_info_to_stat(&statInfo, result);
2294
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2295
            return 0;
2296
        }
2297
    } else {
2298
        switch(GetLastError()) {
2299
        case ERROR_FILE_NOT_FOUND:
2300
        case ERROR_PATH_NOT_FOUND:
2301
        case ERROR_NOT_READY:
2302
        case ERROR_BAD_NET_NAME:
2303
            /* These errors aren't worth retrying with the slow path */
2304
            return -1;
2305
        case ERROR_NOT_SUPPORTED:
2306
            /* indicates the API couldn't be loaded */
2307
            break;
2308
        }
2309
    }
2310
2311
    return win32_xstat_slow_impl(path, result, traverse);
2312
}
2313
2314
static int
2315
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2316
{
2317
    /* Protocol violation: we explicitly clear errno, instead of
2318
       setting it to a POSIX error. Callers should use GetLastError. */
2319
    int code = win32_xstat_impl(path, result, traverse);
2320
    errno = 0;
2321
2322
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2323
    result->st_ctime = result->st_birthtime;
2324
    result->st_ctime_nsec = result->st_birthtime_nsec;
2325
    return code;
2326
}
2327
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2328
2329
   In Posix, stat automatically traverses symlinks and returns the stat
2330
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2331
   default does not traverse symlinks and instead returns attributes for
2332
   the symlink.
2333
2334
   Instead, we will open the file (which *does* traverse symlinks by default)
2335
   and GetFileInformationByHandle(). */
2336
2337
static int
2338
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2339
{
2340
    return win32_xstat(path, result, FALSE);
2341
}
2342
2343
static int
2344
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2345
{
2346
    return win32_xstat(path, result, TRUE);
2347
}
2348
2349
#endif /* MS_WINDOWS */
2350
2351
PyDoc_STRVAR(stat_result__doc__,
2352
"stat_result: Result from stat, fstat, or lstat.\n\n\
2353
This object may be accessed either as a tuple of\n\
2354
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2355
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2356
\n\
2357
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2358
or st_flags, they are available as attributes only.\n\
2359
\n\
2360
See os.stat for more information.");
2361
2362
static PyStructSequence_Field stat_result_fields[] = {
2363
    {"st_mode",    "protection bits"},
2364
    {"st_ino",     "inode"},
2365
    {"st_dev",     "device"},
2366
    {"st_nlink",   "number of hard links"},
2367
    {"st_uid",     "user ID of owner"},
2368
    {"st_gid",     "group ID of owner"},
2369
    {"st_size",    "total size, in bytes"},
2370
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2371
    {NULL,   "integer time of last access"},
2372
    {NULL,   "integer time of last modification"},
2373
    {NULL,   "integer time of last change"},
2374
    {"st_atime",   "time of last access"},
2375
    {"st_mtime",   "time of last modification"},
2376
    {"st_ctime",   "time of last change"},
2377
    {"st_atime_ns",   "time of last access in nanoseconds"},
2378
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2379
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2380
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2381
    {"st_blksize", "blocksize for filesystem I/O"},
2382
#endif
2383
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2384
    {"st_blocks",  "number of blocks allocated"},
2385
#endif
2386
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2387
    {"st_rdev",    "device type (if inode device)"},
2388
#endif
2389
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2390
    {"st_flags",   "user defined flags for file"},
2391
#endif
2392
#ifdef HAVE_STRUCT_STAT_ST_GEN
2393
    {"st_gen",    "generation number"},
2394
#endif
2395
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2396
    {"st_birthtime",   "time of creation"},
2397
#endif
2398
#ifdef MS_WINDOWS
2399
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2400
#endif
2401
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2402
    {"st_file_attributes", "Windows file attribute bits"},
2403
#endif
2404
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2405
    {"st_fstype",  "Type of filesystem"},
2406
#endif
2407
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2408
    {"st_reparse_tag", "Windows reparse tag"},
2409
#endif
2410
    {0}
2411
};
2412
2413
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2414
#define ST_BLKSIZE_IDX 16
2415
#else
2416
#define ST_BLKSIZE_IDX 15
2417
#endif
2418
2419
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2420
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2421
#else
2422
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2423
#endif
2424
2425
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2426
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2427
#else
2428
#define ST_RDEV_IDX ST_BLOCKS_IDX
2429
#endif
2430
2431
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2432
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2433
#else
2434
#define ST_FLAGS_IDX ST_RDEV_IDX
2435
#endif
2436
2437
#ifdef HAVE_STRUCT_STAT_ST_GEN
2438
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2439
#else
2440
#define ST_GEN_IDX ST_FLAGS_IDX
2441
#endif
2442
2443
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2444
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2445
#else
2446
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2447
#endif
2448
2449
#ifdef MS_WINDOWS
2450
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2451
#else
2452
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2453
#endif
2454
2455
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2456
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2457
#else
2458
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2459
#endif
2460
2461
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2462
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2463
#else
2464
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2465
#endif
2466
2467
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2468
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2469
#else
2470
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2471
#endif
2472
2473
static PyStructSequence_Desc stat_result_desc = {
2474
    "os.stat_result", /* name; see issue gh-63408 */
2475
    stat_result__doc__, /* doc */
2476
    stat_result_fields,
2477
    10
2478
};
2479
2480
PyDoc_STRVAR(statvfs_result__doc__,
2481
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2482
This object may be accessed either as a tuple of\n\
2483
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2484
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2485
\n\
2486
See os.statvfs for more information.");
2487
2488
static PyStructSequence_Field statvfs_result_fields[] = {
2489
    {"f_bsize",  },
2490
    {"f_frsize", },
2491
    {"f_blocks", },
2492
    {"f_bfree",  },
2493
    {"f_bavail", },
2494
    {"f_files",  },
2495
    {"f_ffree",  },
2496
    {"f_favail", },
2497
    {"f_flag",   },
2498
    {"f_namemax",},
2499
    {"f_fsid",   },
2500
    {0}
2501
};
2502
2503
static PyStructSequence_Desc statvfs_result_desc = {
2504
    "os.statvfs_result", /* name; see issue gh-63408 */
2505
    statvfs_result__doc__, /* doc */
2506
    statvfs_result_fields,
2507
    10
2508
};
2509
2510
#if defined(HAVE_WAITID)
2511
PyDoc_STRVAR(waitid_result__doc__,
2512
"waitid_result: Result from waitid.\n\n\
2513
This object may be accessed either as a tuple of\n\
2514
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2515
or via the attributes si_pid, si_uid, and so on.\n\
2516
\n\
2517
See os.waitid for more information.");
2518
2519
static PyStructSequence_Field waitid_result_fields[] = {
2520
    {"si_pid",  },
2521
    {"si_uid", },
2522
    {"si_signo", },
2523
    {"si_status",  },
2524
    {"si_code", },
2525
    {0}
2526
};
2527
2528
static PyStructSequence_Desc waitid_result_desc = {
2529
    MODNAME ".waitid_result", /* name */
2530
    waitid_result__doc__, /* doc */
2531
    waitid_result_fields,
2532
    5
2533
};
2534
#endif
2535
2536
static PyObject *
2537
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2538
0
{
2539
0
    PyStructSequence *result;
2540
0
    int i;
2541
2542
    // ht_module doesn't get set in PyStructSequence_NewType(),
2543
    // so we can't use PyType_GetModule().
2544
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2545
0
    if (mod == NULL) {
2546
0
        return NULL;
2547
0
    }
2548
0
    _posixstate *state = get_posix_state(mod);
2549
0
    Py_DECREF(mod);
2550
0
    if (state == NULL) {
2551
0
        return NULL;
2552
0
    }
2553
0
#define structseq_new state->statresult_new_orig
2554
2555
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2556
0
    if (!result)
2557
0
        return NULL;
2558
    /* If we have been initialized from a tuple,
2559
       st_?time might be set to None. Initialize it
2560
       from the int slots.  */
2561
0
    for (i = 7; i <= 9; i++) {
2562
0
        if (result->ob_item[i+3] == Py_None) {
2563
0
            Py_DECREF(Py_None);
2564
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2565
0
        }
2566
0
    }
2567
0
    return (PyObject*)result;
2568
0
}
2569
2570
static int
2571
_posix_clear(PyObject *module)
2572
0
{
2573
0
    _posixstate *state = get_posix_state(module);
2574
0
    Py_CLEAR(state->billion);
2575
0
    Py_CLEAR(state->DirEntryType);
2576
0
    Py_CLEAR(state->ScandirIteratorType);
2577
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2578
0
    Py_CLEAR(state->SchedParamType);
2579
0
#endif
2580
0
    Py_CLEAR(state->StatResultType);
2581
0
#ifdef HAVE_STATX
2582
0
    Py_CLEAR(state->StatxResultType);
2583
0
#endif
2584
0
    Py_CLEAR(state->StatVFSResultType);
2585
0
    Py_CLEAR(state->TerminalSizeType);
2586
0
    Py_CLEAR(state->TimesResultType);
2587
0
    Py_CLEAR(state->UnameResultType);
2588
0
#if defined(HAVE_WAITID)
2589
0
    Py_CLEAR(state->WaitidResultType);
2590
0
#endif
2591
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2592
0
    Py_CLEAR(state->struct_rusage);
2593
0
#endif
2594
0
    Py_CLEAR(state->st_mode);
2595
0
    return 0;
2596
0
}
2597
2598
static int
2599
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2600
1.35k
{
2601
1.35k
    _posixstate *state = get_posix_state(module);
2602
1.35k
    Py_VISIT(state->billion);
2603
1.35k
    Py_VISIT(state->DirEntryType);
2604
1.35k
    Py_VISIT(state->ScandirIteratorType);
2605
1.35k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2606
1.35k
    Py_VISIT(state->SchedParamType);
2607
1.35k
#endif
2608
1.35k
    Py_VISIT(state->StatResultType);
2609
1.35k
#ifdef HAVE_STATX
2610
1.35k
    Py_VISIT(state->StatxResultType);
2611
1.35k
#endif
2612
1.35k
    Py_VISIT(state->StatVFSResultType);
2613
1.35k
    Py_VISIT(state->TerminalSizeType);
2614
1.35k
    Py_VISIT(state->TimesResultType);
2615
1.35k
    Py_VISIT(state->UnameResultType);
2616
1.35k
#if defined(HAVE_WAITID)
2617
1.35k
    Py_VISIT(state->WaitidResultType);
2618
1.35k
#endif
2619
1.35k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2620
1.35k
    Py_VISIT(state->struct_rusage);
2621
1.35k
#endif
2622
1.35k
    Py_VISIT(state->st_mode);
2623
1.35k
    return 0;
2624
1.35k
}
2625
2626
static void
2627
_posix_free(void *module)
2628
0
{
2629
0
   _posix_clear((PyObject *)module);
2630
0
}
2631
2632
2633
2.87M
#define SEC_TO_NS (1000000000LL)
2634
static PyObject *
2635
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2636
958k
{
2637
#if SIZEOF_TIME_T == 4
2638
    return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2639
#else
2640
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2641
958k
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2642
958k
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2643
958k
    }
2644
0
    else
2645
0
    {
2646
0
        PyObject *ns_total = NULL;
2647
0
        PyObject *s_in_ns = NULL;
2648
0
        PyObject *s = _PyLong_FromTime_t(sec);
2649
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2650
0
        if (s == NULL || ns_fractional == NULL) {
2651
0
            goto exit;
2652
0
        }
2653
2654
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2655
0
        if (s_in_ns == NULL) {
2656
0
            goto exit;
2657
0
        }
2658
2659
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2660
2661
0
    exit:
2662
0
        Py_XDECREF(s);
2663
0
        Py_XDECREF(ns_fractional);
2664
0
        Py_XDECREF(s_in_ns);
2665
0
        return ns_total;
2666
0
    }
2667
958k
#endif
2668
958k
}
2669
2670
static int
2671
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2672
          int ns_index, time_t sec, unsigned long nsec)
2673
958k
{
2674
958k
    assert(!PyErr_Occurred());
2675
958k
    assert(nsec < SEC_TO_NS);
2676
2677
958k
    if (s_index >= 0) {
2678
958k
        PyObject *s = _PyLong_FromTime_t(sec);
2679
958k
        if (s == NULL) {
2680
0
            return -1;
2681
0
        }
2682
958k
        PyStructSequence_SET_ITEM(v, s_index, s);
2683
958k
    }
2684
2685
958k
    if (f_index >= 0) {
2686
958k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2687
958k
        if (float_s == NULL) {
2688
0
            return -1;
2689
0
        }
2690
958k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2691
958k
    }
2692
2693
958k
    if (ns_index >= 0) {
2694
958k
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2695
958k
        if (ns_total == NULL) {
2696
0
            return -1;
2697
0
        }
2698
958k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2699
958k
    }
2700
2701
958k
    assert(!PyErr_Occurred());
2702
958k
    return 0;
2703
958k
}
2704
#undef SEC_TO_NS
2705
2706
#ifdef MS_WINDOWS
2707
static PyObject*
2708
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2709
{
2710
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2711
    if (!o_low || !high) {
2712
        return o_low;
2713
    }
2714
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2715
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2716
    if (!l64) {
2717
        Py_XDECREF(o_high);
2718
        Py_DECREF(o_low);
2719
        return NULL;
2720
    }
2721
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2722
    Py_DECREF(l64);
2723
    if (!o_high) {
2724
        Py_DECREF(o_low);
2725
        return NULL;
2726
    }
2727
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2728
    Py_DECREF(o_high);
2729
    return o_low;
2730
}
2731
#endif
2732
2733
/* pack a system stat C structure into the Python stat tuple
2734
   (used by posix_stat() and posix_fstat()) */
2735
static PyObject*
2736
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2737
319k
{
2738
319k
    assert(!PyErr_Occurred());
2739
2740
319k
    _posixstate *state = get_posix_state(module);
2741
319k
    PyObject *StatResultType = state->StatResultType;
2742
319k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2743
319k
    if (v == NULL) {
2744
0
        return NULL;
2745
0
    }
2746
2747
319k
#define SET_ITEM(pos, expr) \
2748
3.19M
    do { \
2749
3.19M
        PyObject *obj = (expr); \
2750
3.19M
        if (obj == NULL) { \
2751
0
            goto error; \
2752
0
        } \
2753
3.19M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2754
3.19M
    } while (0)
2755
2756
319k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2757
#ifdef MS_WINDOWS
2758
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2759
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2760
#else
2761
319k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2762
319k
                  "stat.st_ino is larger than unsigned long long");
2763
319k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2764
319k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2765
319k
#endif
2766
319k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2767
#if defined(MS_WINDOWS)
2768
    SET_ITEM(4, PyLong_FromLong(0));
2769
    SET_ITEM(5, PyLong_FromLong(0));
2770
#else
2771
319k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2772
319k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2773
319k
#endif
2774
319k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2775
319k
                  "stat.st_size is larger than long long");
2776
319k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2777
2778
    // Set st_atime, st_mtime and st_ctime
2779
319k
    unsigned long ansec, mnsec, cnsec;
2780
319k
#if defined(HAVE_STAT_TV_NSEC)
2781
319k
    ansec = st->st_atim.tv_nsec;
2782
319k
    mnsec = st->st_mtim.tv_nsec;
2783
319k
    cnsec = st->st_ctim.tv_nsec;
2784
#elif defined(HAVE_STAT_TV_NSEC2)
2785
    ansec = st->st_atimespec.tv_nsec;
2786
    mnsec = st->st_mtimespec.tv_nsec;
2787
    cnsec = st->st_ctimespec.tv_nsec;
2788
#elif defined(HAVE_STAT_NSEC)
2789
    ansec = st->st_atime_nsec;
2790
    mnsec = st->st_mtime_nsec;
2791
    cnsec = st->st_ctime_nsec;
2792
#else
2793
    ansec = mnsec = cnsec = 0;
2794
#endif
2795
319k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2796
0
        goto error;
2797
0
    }
2798
319k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2799
0
        goto error;
2800
0
    }
2801
319k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2802
0
        goto error;
2803
0
    }
2804
2805
319k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2806
319k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2807
319k
#endif
2808
319k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2809
319k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2810
319k
#endif
2811
319k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2812
319k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2813
319k
#endif
2814
#ifdef HAVE_STRUCT_STAT_ST_GEN
2815
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2816
#endif
2817
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2818
    {
2819
      unsigned long bsec, bnsec;
2820
      bsec = (long)st->st_birthtime;
2821
#ifdef HAVE_STAT_TV_NSEC2
2822
      bnsec = st->st_birthtimespec.tv_nsec;
2823
#else
2824
      bnsec = 0;
2825
#endif
2826
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2827
    }
2828
#elif defined(MS_WINDOWS)
2829
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2830
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2831
        goto error;
2832
    }
2833
#endif
2834
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2835
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2836
#endif
2837
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2838
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2839
             PyLong_FromUnsignedLong(st->st_file_attributes));
2840
#endif
2841
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2842
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2843
#endif
2844
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2845
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2846
#endif
2847
2848
319k
    assert(!PyErr_Occurred());
2849
319k
    return v;
2850
2851
0
error:
2852
0
    Py_DECREF(v);
2853
0
    return NULL;
2854
2855
319k
#undef SET_ITEM
2856
319k
}
2857
2858
/* POSIX methods */
2859
2860
2861
static PyObject *
2862
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2863
              int dir_fd, int follow_symlinks)
2864
288k
{
2865
288k
    STRUCT_STAT st;
2866
288k
    int result;
2867
2868
288k
#ifdef HAVE_FSTATAT
2869
288k
    int fstatat_unavailable = 0;
2870
288k
#endif
2871
2872
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2873
    if (follow_symlinks_specified(function_name, follow_symlinks))
2874
        return NULL;
2875
#endif
2876
2877
288k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2878
288k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2879
288k
        fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2880
0
        return NULL;
2881
2882
288k
    Py_BEGIN_ALLOW_THREADS
2883
288k
    if (path->fd != -1)
2884
0
        result = FSTAT(path->fd, &st);
2885
#ifdef MS_WINDOWS
2886
    else if (follow_symlinks)
2887
        result = win32_stat(path->wide, &st);
2888
    else
2889
        result = win32_lstat(path->wide, &st);
2890
#else
2891
288k
    else
2892
288k
#if defined(HAVE_LSTAT)
2893
288k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2894
8.20k
        result = LSTAT(path->narrow, &st);
2895
280k
    else
2896
280k
#endif /* HAVE_LSTAT */
2897
280k
#ifdef HAVE_FSTATAT
2898
280k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2899
0
        if (HAVE_FSTATAT_RUNTIME) {
2900
0
            result = fstatat(dir_fd, path->narrow, &st,
2901
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2902
2903
0
        } else {
2904
0
            fstatat_unavailable = 1;
2905
0
        }
2906
0
    } else
2907
280k
#endif /* HAVE_FSTATAT */
2908
280k
        result = STAT(path->narrow, &st);
2909
288k
#endif /* MS_WINDOWS */
2910
288k
    Py_END_ALLOW_THREADS
2911
2912
288k
#ifdef HAVE_FSTATAT
2913
288k
    if (fstatat_unavailable) {
2914
0
        argument_unavailable_error("stat", "dir_fd");
2915
0
        return NULL;
2916
0
    }
2917
288k
#endif
2918
2919
288k
    if (result != 0) {
2920
242k
        return path_error(path);
2921
242k
    }
2922
2923
46.3k
    return _pystat_fromstructstat(module, &st);
2924
288k
}
2925
2926
/*[python input]
2927
2928
for s in """
2929
2930
FACCESSAT
2931
FCHMODAT
2932
FCHOWNAT
2933
FSTATAT
2934
LINKAT
2935
MKDIRAT
2936
MKFIFOAT
2937
MKNODAT
2938
OPENAT
2939
READLINKAT
2940
SYMLINKAT
2941
UNLINKAT
2942
2943
""".strip().split():
2944
    s = s.strip()
2945
    print("""
2946
#ifdef HAVE_{s}
2947
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2948
#else
2949
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2950
#endif
2951
""".rstrip().format(s=s))
2952
2953
for s in """
2954
2955
FCHDIR
2956
FCHMOD
2957
FCHOWN
2958
FDOPENDIR
2959
FEXECVE
2960
FPATHCONF
2961
FSTATVFS
2962
FTRUNCATE
2963
2964
""".strip().split():
2965
    s = s.strip()
2966
    print("""
2967
#ifdef HAVE_{s}
2968
    #define PATH_HAVE_{s} 1
2969
#else
2970
    #define PATH_HAVE_{s} 0
2971
#endif
2972
2973
""".rstrip().format(s=s))
2974
[python start generated code]*/
2975
2976
#ifdef HAVE_FACCESSAT
2977
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2978
#else
2979
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2980
#endif
2981
2982
#ifdef HAVE_FCHMODAT
2983
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2984
#else
2985
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2986
#endif
2987
2988
#ifdef HAVE_FCHOWNAT
2989
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2990
#else
2991
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2992
#endif
2993
2994
#ifdef HAVE_FSTATAT
2995
7.99k
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2996
#else
2997
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2998
#endif
2999
3000
#ifdef HAVE_LINKAT
3001
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
3002
#else
3003
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3004
#endif
3005
3006
#ifdef HAVE_MKDIRAT
3007
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3008
#else
3009
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3010
#endif
3011
3012
#ifdef HAVE_MKFIFOAT
3013
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3014
#else
3015
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3016
#endif
3017
3018
#ifdef HAVE_MKNODAT
3019
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3020
#else
3021
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3022
#endif
3023
3024
#ifdef HAVE_OPENAT
3025
138k
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3026
#else
3027
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3028
#endif
3029
3030
#ifdef HAVE_READLINKAT
3031
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3032
#else
3033
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3034
#endif
3035
3036
#ifdef HAVE_SYMLINKAT
3037
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3038
#else
3039
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3040
#endif
3041
3042
#ifdef HAVE_UNLINKAT
3043
139k
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3044
#else
3045
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3046
#endif
3047
3048
#ifdef HAVE_FCHDIR
3049
    #define PATH_HAVE_FCHDIR 1
3050
#else
3051
    #define PATH_HAVE_FCHDIR 0
3052
#endif
3053
3054
#ifdef HAVE_FCHMOD
3055
    #define PATH_HAVE_FCHMOD 1
3056
#else
3057
    #define PATH_HAVE_FCHMOD 0
3058
#endif
3059
3060
#ifdef HAVE_FCHOWN
3061
    #define PATH_HAVE_FCHOWN 1
3062
#else
3063
    #define PATH_HAVE_FCHOWN 0
3064
#endif
3065
3066
#ifdef HAVE_FDOPENDIR
3067
    #define PATH_HAVE_FDOPENDIR 1
3068
#else
3069
    #define PATH_HAVE_FDOPENDIR 0
3070
#endif
3071
3072
#ifdef HAVE_FEXECVE
3073
    #define PATH_HAVE_FEXECVE 1
3074
#else
3075
    #define PATH_HAVE_FEXECVE 0
3076
#endif
3077
3078
#ifdef HAVE_FPATHCONF
3079
    #define PATH_HAVE_FPATHCONF 1
3080
#else
3081
    #define PATH_HAVE_FPATHCONF 0
3082
#endif
3083
3084
#ifdef HAVE_FSTATVFS
3085
    #define PATH_HAVE_FSTATVFS 1
3086
#else
3087
    #define PATH_HAVE_FSTATVFS 0
3088
#endif
3089
3090
#ifdef HAVE_FTRUNCATE
3091
    #define PATH_HAVE_FTRUNCATE 1
3092
#else
3093
    #define PATH_HAVE_FTRUNCATE 0
3094
#endif
3095
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3096
3097
#ifdef MS_WINDOWS
3098
    #undef PATH_HAVE_FTRUNCATE
3099
    #define PATH_HAVE_FTRUNCATE 1
3100
    #undef PATH_HAVE_FCHMOD
3101
    #define PATH_HAVE_FCHMOD 1
3102
#endif
3103
3104
/*[python input]
3105
3106
class path_t_converter(CConverter):
3107
3108
    type = "path_t"
3109
    impl_by_reference = True
3110
    parse_by_reference = True
3111
3112
    converter = 'path_converter'
3113
3114
    def converter_init(self, *, allow_fd=False, make_wide=None,
3115
                       nonstrict=False, nullable=False,
3116
                       suppress_value_error=False):
3117
        # right now path_t doesn't support default values.
3118
        # to support a default value, you'll need to override initialize().
3119
        if self.default not in (unspecified, None):
3120
            fail("Can't specify a default to the path_t converter!")
3121
3122
        if self.c_default not in (None, 'Py_None'):
3123
            raise RuntimeError("Can't specify a c_default to the path_t converter!")
3124
3125
        self.nullable = nullable
3126
        self.nonstrict = nonstrict
3127
        self.make_wide = make_wide
3128
        self.suppress_value_error = suppress_value_error
3129
        self.allow_fd = allow_fd
3130
3131
    def pre_render(self):
3132
        def strify(value):
3133
            if isinstance(value, str):
3134
                return value
3135
            return str(int(bool(value)))
3136
3137
        # add self.py_name here when merging with posixmodule conversion
3138
        if self.make_wide is None:
3139
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3140
                self.function.name,
3141
                self.name,
3142
                strify(self.nullable),
3143
                strify(self.nonstrict),
3144
                strify(self.suppress_value_error),
3145
                strify(self.allow_fd),
3146
            )
3147
        else:
3148
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3149
                self.function.name,
3150
                self.name,
3151
                strify(self.nullable),
3152
                strify(self.nonstrict),
3153
                strify(self.make_wide),
3154
                strify(self.suppress_value_error),
3155
                strify(self.allow_fd),
3156
            )
3157
3158
    def cleanup(self):
3159
        return "path_cleanup(&" + self.name + ");\n"
3160
3161
3162
class dir_fd_converter(CConverter):
3163
    type = 'int'
3164
3165
    def converter_init(self, requires=None):
3166
        if self.default in (unspecified, None):
3167
            self.c_default = 'DEFAULT_DIR_FD'
3168
        if isinstance(requires, str):
3169
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3170
        else:
3171
            self.converter = 'dir_fd_converter'
3172
3173
class uid_t_converter(CConverter):
3174
    type = "uid_t"
3175
    converter = '_Py_Uid_Converter'
3176
3177
class gid_t_converter(CConverter):
3178
    type = "gid_t"
3179
    converter = '_Py_Gid_Converter'
3180
3181
class dev_t_converter(CConverter):
3182
    type = 'dev_t'
3183
    converter = '_Py_Dev_Converter'
3184
3185
class dev_t_return_converter(unsigned_long_return_converter):
3186
    type = 'dev_t'
3187
    conversion_fn = '_PyLong_FromDev'
3188
    unsigned_cast = '(dev_t)'
3189
3190
class pid_t_converter(CConverter):
3191
    type = 'pid_t'
3192
    format_unit = '" _Py_PARSE_PID "'
3193
3194
    def parse_arg(self, argname, displayname, *, limited_capi):
3195
        return self.format_code("""
3196
            {paramname} = PyLong_AsPid({argname});
3197
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3198
                goto exit;
3199
            }}}}
3200
            """, argname=argname)
3201
3202
class idtype_t_converter(CConverter):
3203
    type = 'idtype_t'
3204
    converter = 'idtype_t_converter'
3205
3206
class id_t_converter(CConverter):
3207
    type = 'id_t'
3208
    format_unit = '" _Py_PARSE_PID "'
3209
3210
    def parse_arg(self, argname, displayname, *, limited_capi):
3211
        return self.format_code("""
3212
            {paramname} = (id_t)PyLong_AsPid({argname});
3213
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3214
                goto exit;
3215
            }}}}
3216
            """, argname=argname)
3217
3218
class intptr_t_converter(CConverter):
3219
    type = 'intptr_t'
3220
    format_unit = '" _Py_PARSE_INTPTR "'
3221
3222
    def parse_arg(self, argname, displayname, *, limited_capi):
3223
        return self.format_code("""
3224
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3225
            if (!{paramname} && PyErr_Occurred()) {{{{
3226
                goto exit;
3227
            }}}}
3228
            """, argname=argname)
3229
3230
class Py_off_t_converter(CConverter):
3231
    type = 'Py_off_t'
3232
    converter = 'Py_off_t_converter'
3233
3234
class Py_off_t_return_converter(long_return_converter):
3235
    type = 'Py_off_t'
3236
    conversion_fn = 'PyLong_FromPy_off_t'
3237
3238
class confname_converter(CConverter):
3239
    type="int"
3240
    converter="conv_confname"
3241
3242
    def converter_init(self, *, table):
3243
        self.table = table
3244
3245
    def parse_arg(self, argname, displayname, *, limited_capi):
3246
        return self.format_code("""
3247
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3248
                goto exit;
3249
            }}}}
3250
        """, argname=argname, converter=self.converter, table=self.table)
3251
3252
[python start generated code]*/
3253
/*[python end generated code: output=da39a3ee5e6b4b0d input=d2759f2332cd39b3]*/
3254
3255
/*[clinic input]
3256
3257
os.stat
3258
3259
    path : path_t(allow_fd=True)
3260
        Path to be examined; can be string, bytes, a path-like object or
3261
        open-file-descriptor int.
3262
3263
    *
3264
3265
    dir_fd : dir_fd(requires='fstatat') = None
3266
        If not None, it should be a file descriptor open to a directory,
3267
        and path should be a relative string; path will then be relative to
3268
        that directory.
3269
3270
    follow_symlinks: bool = True
3271
        If False, and the last element of the path is a symbolic link,
3272
        stat will examine the symbolic link itself instead of the file
3273
        the link points to.
3274
3275
Perform a stat system call on the given path.
3276
3277
dir_fd and follow_symlinks may not be implemented
3278
  on your platform.  If they are unavailable, using them will raise a
3279
  NotImplementedError.
3280
3281
It's an error to use dir_fd or follow_symlinks when specifying path as
3282
  an open file descriptor.
3283
3284
[clinic start generated code]*/
3285
3286
static PyObject *
3287
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3288
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3289
280k
{
3290
280k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3291
280k
}
3292
3293
3294
/*[clinic input]
3295
@permit_long_summary
3296
os.lstat
3297
3298
    path : path_t
3299
3300
    *
3301
3302
    dir_fd : dir_fd(requires='fstatat') = None
3303
3304
Perform a stat system call on the given path, without following symbolic links.
3305
3306
Like stat(), but do not follow symbolic links.
3307
Equivalent to stat(path, follow_symlinks=False).
3308
[clinic start generated code]*/
3309
3310
static PyObject *
3311
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3312
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3313
8.20k
{
3314
8.20k
    int follow_symlinks = 0;
3315
8.20k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3316
8.20k
}
3317
3318
3319
#ifdef HAVE_STATX
3320
typedef struct {
3321
    PyObject_HEAD
3322
    dev_t rdev, dev;
3323
    struct statx stx;
3324
} Py_statx_result;
3325
3326
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3327
3328
#define M(attr, type, offset, doc) \
3329
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3330
#define MM(attr, type, member, doc) \
3331
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3332
#define MX(attr, type, member, doc) \
3333
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3334
3335
static PyMemberDef pystatx_result_members[] = {
3336
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3337
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3338
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3339
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3340
        "Mask of supported bits in stx_attributes"),
3341
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3342
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3343
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3344
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3345
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3346
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3347
    {NULL},
3348
};
3349
3350
#undef MX
3351
#undef MM
3352
#undef M
3353
3354
3355
#define STATX_GET_UINT(ATTR, MASK) \
3356
    static PyObject* \
3357
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3358
0
    { \
3359
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3360
0
        if (!(self->stx.stx_mask & MASK)) { \
3361
0
            Py_RETURN_NONE; \
3362
0
        } \
3363
0
        unsigned long value = self->stx.ATTR; \
3364
0
        return PyLong_FromUnsignedLong(value); \
3365
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_nlink
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_uid
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_gid
3366
3367
STATX_GET_UINT(stx_uid, STATX_UID)
3368
STATX_GET_UINT(stx_gid, STATX_GID)
3369
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3370
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3371
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3372
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3373
#endif
3374
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3375
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3376
#endif
3377
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3378
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3379
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3380
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3381
#endif
3382
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3383
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3384
#endif
3385
3386
3387
static PyObject*
3388
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3389
0
{
3390
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3391
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3392
0
        Py_RETURN_NONE;
3393
0
    }
3394
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3395
0
}
3396
3397
3398
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3399
    static PyObject* \
3400
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3401
0
    { \
3402
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3403
0
        if (!(self->stx.stx_mask & MASK)) { \
3404
0
            Py_RETURN_NONE; \
3405
0
        } \
3406
0
        unsigned long long value = self->stx.ATTR; \
3407
0
        return PyLong_FromUnsignedLongLong(value); \
3408
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_ino
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_size
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_blocks
3409
3410
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3411
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3412
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3413
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3414
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3415
#endif
3416
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3417
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3418
#endif
3419
3420
3421
#define STATX_GET_DOUBLE(ATTR, MASK) \
3422
    static PyObject* \
3423
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3424
0
    { \
3425
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3426
0
        if (!(self->stx.stx_mask & MASK)) { \
3427
0
            Py_RETURN_NONE; \
3428
0
        } \
3429
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3430
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3431
0
        return PyFloat_FromDouble(sec); \
3432
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_atime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_btime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_ctime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_mtime
3433
3434
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3435
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3436
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3437
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3438
3439
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3440
    static PyObject* \
3441
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3442
0
    { \
3443
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3444
0
        if (!(self->stx.stx_mask & MASK)) { \
3445
0
            Py_RETURN_NONE; \
3446
0
        } \
3447
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3448
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3449
0
        assert(state != NULL); \
3450
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3451
0
    }
3452
3453
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3454
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3455
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3456
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3457
3458
#define G(attr, doc) \
3459
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3460
3461
static PyGetSetDef pystatx_result_getset[] = {
3462
    G(stx_mode, "protection bits"),
3463
    G(stx_nlink, "number of hard links"),
3464
    G(stx_uid, "user ID of owner"),
3465
    G(stx_gid, "group ID of owner"),
3466
    G(stx_ino, "inode"),
3467
    G(stx_size, "total size, in bytes"),
3468
    G(stx_blocks, "number of blocks allocated"),
3469
    G(stx_atime, "time of last access"),
3470
    G(stx_atime_ns, "time of last access in nanoseconds"),
3471
    G(stx_btime, "time of creation"),
3472
    G(stx_btime_ns, "time of creation in nanoseconds"),
3473
    G(stx_ctime, "time of last change"),
3474
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3475
    G(stx_mtime, "time of last modification"),
3476
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3477
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3478
    G(stx_mnt_id, "mount ID"),
3479
#endif
3480
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3481
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3482
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3483
#endif
3484
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3485
    G(stx_subvol, "subvolume ID"),
3486
#endif
3487
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3488
    G(stx_atomic_write_unit_min,
3489
      "minimum size for direct I/O with torn-write protection"),
3490
    G(stx_atomic_write_unit_max,
3491
        "maximum size for direct I/O with torn-write protection"),
3492
    G(stx_atomic_write_segments_max,
3493
        "maximum iovecs for direct I/O with torn-write protection"),
3494
#endif
3495
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3496
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3497
#endif
3498
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3499
    G(stx_atomic_write_unit_max_opt,
3500
        "maximum optimized size for direct I/O with torn-write protection"),
3501
#endif
3502
    {NULL},
3503
};
3504
3505
#undef G
3506
3507
static PyObject *
3508
pystatx_result_repr(PyObject *op)
3509
0
{
3510
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3511
0
    if (writer == NULL) {
3512
0
        return NULL;
3513
0
    }
3514
0
#define WRITE_ASCII(s) \
3515
0
    do { \
3516
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3517
0
            goto error; \
3518
0
        } \
3519
0
    } while (0)
3520
3521
0
    WRITE_ASCII("os.statx_result(");
3522
3523
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3524
0
        if (i > 0) {
3525
0
            WRITE_ASCII(", ");
3526
0
        }
3527
3528
0
        PyMemberDef *d = &pystatx_result_members[i];
3529
0
        WRITE_ASCII(d->name);
3530
0
        WRITE_ASCII("=");
3531
3532
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3533
0
        if (o == NULL) {
3534
0
            goto error;
3535
0
        }
3536
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3537
0
            Py_DECREF(o);
3538
0
            goto error;
3539
0
        }
3540
0
        Py_DECREF(o);
3541
0
    }
3542
3543
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3544
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3545
0
        PyObject *o = d->get(op, d->closure);
3546
0
        if (o == NULL) {
3547
0
            goto error;
3548
0
        }
3549
0
        if (o == Py_None) {
3550
0
            continue;
3551
0
        }
3552
3553
0
        WRITE_ASCII(", ");
3554
0
        WRITE_ASCII(d->name);
3555
0
        WRITE_ASCII("=");
3556
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3557
0
            Py_DECREF(o);
3558
0
            goto error;
3559
0
        }
3560
0
        Py_DECREF(o);
3561
0
    }
3562
3563
0
    WRITE_ASCII(")");
3564
0
    return PyUnicodeWriter_Finish(writer);
3565
0
#undef WRITE_ASCII
3566
3567
0
error:
3568
0
    PyUnicodeWriter_Discard(writer);
3569
0
    return NULL;
3570
0
}
3571
3572
static int
3573
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3574
0
{
3575
0
    Py_VISIT(Py_TYPE(self));
3576
0
    return 0;
3577
0
}
3578
3579
static void
3580
pystatx_result_dealloc(PyObject *op)
3581
0
{
3582
0
    Py_statx_result *self = (Py_statx_result *) op;
3583
0
    PyTypeObject *tp = Py_TYPE(self);
3584
0
    PyObject_GC_UnTrack(self);
3585
0
    tp->tp_free(self);
3586
0
    Py_DECREF(tp);
3587
0
}
3588
3589
static PyType_Slot pystatx_result_slots[] = {
3590
    {Py_tp_repr, pystatx_result_repr},
3591
    {Py_tp_traverse, pystatx_result_traverse},
3592
    {Py_tp_dealloc, pystatx_result_dealloc},
3593
    {Py_tp_members, pystatx_result_members},
3594
    {Py_tp_getset, pystatx_result_getset},
3595
    {0, NULL},
3596
};
3597
3598
static PyType_Spec pystatx_result_spec = {
3599
    .name = "os.statx_result",
3600
    .basicsize = sizeof(Py_statx_result),
3601
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3602
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3603
    .slots = pystatx_result_slots,
3604
};
3605
3606
/*[clinic input]
3607
3608
os.statx
3609
3610
    path : path_t(allow_fd=True)
3611
        Path to be examined; can be string, bytes, a path-like object or
3612
        open-file-descriptor int.
3613
3614
    mask: unsigned_int(bitwise=True)
3615
        A bitmask of STATX_* constants defining the requested information.
3616
3617
    *
3618
3619
    flags: int = 0
3620
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3621
3622
    dir_fd : dir_fd = None
3623
        If not None, it should be a file descriptor open to a directory,
3624
        and path should be a relative string; path will then be relative to
3625
        that directory.
3626
3627
    follow_symlinks: bool = True
3628
        If False, and the last element of the path is a symbolic link,
3629
        statx will examine the symbolic link itself instead of the file
3630
        the link points to.
3631
3632
Perform a statx system call on the given path.
3633
3634
It's an error to use dir_fd or follow_symlinks when specifying path as
3635
  an open file descriptor.
3636
3637
[clinic start generated code]*/
3638
3639
static PyObject *
3640
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3641
              int dir_fd, int follow_symlinks)
3642
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3643
0
{
3644
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3645
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3646
0
        fd_and_follow_symlinks_invalid("statx", path->fd, follow_symlinks)) {
3647
0
        return NULL;
3648
0
    }
3649
3650
    /* reject flags covered by kwargs, but allow unknown flags that may be
3651
       future AT_STATX_* extensions */
3652
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3653
0
        PyErr_Format(PyExc_ValueError,
3654
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3655
0
        return NULL;
3656
0
    }
3657
0
    if (flags & AT_EMPTY_PATH) {
3658
0
        PyErr_Format(PyExc_ValueError,
3659
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3660
0
        return NULL;
3661
0
    }
3662
3663
    /* Future bits may refer to members beyond the current size of struct
3664
       statx, so we need to mask them off to prevent memory corruption. */
3665
0
    mask &= _Py_STATX_KNOWN;
3666
3667
0
    _posixstate *state = get_posix_state(module);
3668
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3669
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3670
0
    if (v == NULL) {
3671
0
        return NULL;
3672
0
    }
3673
3674
0
    int result;
3675
0
    Py_BEGIN_ALLOW_THREADS
3676
0
    if (path->fd != -1) {
3677
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3678
0
    }
3679
0
    else {
3680
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3681
0
    }
3682
0
    Py_END_ALLOW_THREADS
3683
3684
0
    if (result != 0) {
3685
0
        Py_DECREF(v);
3686
0
        return path_error(path);
3687
0
    }
3688
3689
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3690
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3691
3692
0
    assert(!PyErr_Occurred());
3693
0
    return (PyObject *)v;
3694
0
}
3695
#endif /* HAVE_STATX */
3696
3697
3698
/*[clinic input]
3699
os.access -> bool
3700
3701
    path: path_t
3702
        Path to be tested; can be string, bytes, or a path-like object.
3703
3704
    mode: int
3705
        Operating-system mode bitfield.  Can be F_OK to test existence,
3706
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3707
3708
    *
3709
3710
    dir_fd : dir_fd(requires='faccessat') = None
3711
        If not None, it should be a file descriptor open to a directory,
3712
        and path should be relative; path will then be relative to that
3713
        directory.
3714
3715
    effective_ids: bool = False
3716
        If True, access will use the effective uid/gid instead of
3717
        the real uid/gid.
3718
3719
    follow_symlinks: bool = True
3720
        If False, and the last element of the path is a symbolic link,
3721
        access will examine the symbolic link itself instead of the file
3722
        the link points to.
3723
3724
Use the real uid/gid to test for access to a path.
3725
3726
{parameters}
3727
dir_fd, effective_ids, and follow_symlinks may not be implemented
3728
  on your platform.  If they are unavailable, using them will raise a
3729
  NotImplementedError.
3730
3731
Note that most operations will use the effective uid/gid, therefore this
3732
  routine can be used in a suid/sgid environment to test if the invoking
3733
  user has the specified access to the path.
3734
3735
[clinic start generated code]*/
3736
3737
static int
3738
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3739
               int effective_ids, int follow_symlinks)
3740
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3741
0
{
3742
0
    int return_value;
3743
3744
#ifdef MS_WINDOWS
3745
    DWORD attr;
3746
#else
3747
0
    int result;
3748
0
#endif
3749
3750
0
#ifdef HAVE_FACCESSAT
3751
0
    int faccessat_unavailable = 0;
3752
0
#endif
3753
3754
#ifndef HAVE_FACCESSAT
3755
    if (follow_symlinks_specified("access", follow_symlinks))
3756
        return -1;
3757
3758
    if (effective_ids) {
3759
        argument_unavailable_error("access", "effective_ids");
3760
        return -1;
3761
    }
3762
#endif
3763
3764
#ifdef MS_WINDOWS
3765
    Py_BEGIN_ALLOW_THREADS
3766
    attr = GetFileAttributesW(path->wide);
3767
    Py_END_ALLOW_THREADS
3768
3769
    /*
3770
     * Access is possible if
3771
     *   * we didn't get a -1, and
3772
     *     * write access wasn't requested,
3773
     *     * or the file isn't read-only,
3774
     *     * or it's a directory.
3775
     * (Directories cannot be read-only on Windows.)
3776
    */
3777
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3778
            (!(mode & 2) ||
3779
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3780
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3781
#else
3782
3783
0
    Py_BEGIN_ALLOW_THREADS
3784
0
#ifdef HAVE_FACCESSAT
3785
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3786
0
        effective_ids ||
3787
0
        !follow_symlinks) {
3788
3789
0
        if (HAVE_FACCESSAT_RUNTIME) {
3790
0
            int flags = 0;
3791
0
            if (!follow_symlinks)
3792
0
                flags |= AT_SYMLINK_NOFOLLOW;
3793
0
            if (effective_ids)
3794
0
                flags |= AT_EACCESS;
3795
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3796
0
        } else {
3797
0
            faccessat_unavailable = 1;
3798
0
        }
3799
0
    }
3800
0
    else
3801
0
#endif
3802
0
        result = access(path->narrow, mode);
3803
0
    Py_END_ALLOW_THREADS
3804
3805
0
#ifdef HAVE_FACCESSAT
3806
0
    if (faccessat_unavailable) {
3807
0
        if (dir_fd != DEFAULT_DIR_FD) {
3808
0
            argument_unavailable_error("access", "dir_fd");
3809
0
            return -1;
3810
0
        }
3811
0
        if (follow_symlinks_specified("access", follow_symlinks))
3812
0
            return -1;
3813
3814
0
        if (effective_ids) {
3815
0
            argument_unavailable_error("access", "effective_ids");
3816
0
            return -1;
3817
0
        }
3818
        /* should be unreachable */
3819
0
        return -1;
3820
0
    }
3821
0
#endif
3822
0
    return_value = !result;
3823
0
#endif
3824
3825
0
    return return_value;
3826
0
}
3827
3828
#ifndef F_OK
3829
#define F_OK 0
3830
#endif
3831
#ifndef R_OK
3832
#define R_OK 4
3833
#endif
3834
#ifndef W_OK
3835
#define W_OK 2
3836
#endif
3837
#ifndef X_OK
3838
#define X_OK 1
3839
#endif
3840
3841
3842
#ifdef HAVE_TTYNAME_R
3843
/*[clinic input]
3844
os.ttyname
3845
3846
    fd: int
3847
        Integer file descriptor handle.
3848
3849
    /
3850
3851
Return the name of the terminal device connected to 'fd'.
3852
[clinic start generated code]*/
3853
3854
static PyObject *
3855
os_ttyname_impl(PyObject *module, int fd)
3856
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3857
0
{
3858
3859
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3860
0
    if (size == -1) {
3861
0
        return posix_error();
3862
0
    }
3863
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3864
0
    if (buffer == NULL) {
3865
0
        return PyErr_NoMemory();
3866
0
    }
3867
0
    int ret = ttyname_r(fd, buffer, size);
3868
0
    if (ret != 0) {
3869
0
        PyMem_RawFree(buffer);
3870
0
        errno = ret;
3871
0
        return posix_error();
3872
0
    }
3873
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3874
0
    PyMem_RawFree(buffer);
3875
0
    return res;
3876
0
}
3877
#endif
3878
3879
#ifdef HAVE_CTERMID
3880
/*[clinic input]
3881
os.ctermid
3882
3883
Return the name of the controlling terminal for this process.
3884
[clinic start generated code]*/
3885
3886
static PyObject *
3887
os_ctermid_impl(PyObject *module)
3888
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3889
0
{
3890
0
    char *ret;
3891
0
    char buffer[L_ctermid];
3892
3893
#ifdef USE_CTERMID_R
3894
    ret = ctermid_r(buffer);
3895
#else
3896
0
    ret = ctermid(buffer);
3897
0
#endif
3898
0
    if (ret == NULL)
3899
0
        return posix_error();
3900
0
    return PyUnicode_DecodeFSDefault(buffer);
3901
0
}
3902
#endif /* HAVE_CTERMID */
3903
3904
3905
/*[clinic input]
3906
os.chdir
3907
3908
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3909
3910
Change the current working directory to the specified path.
3911
3912
path may always be specified as a string.
3913
On some platforms, path may also be specified as an open file descriptor.
3914
If this functionality is unavailable, using it raises an exception.
3915
[clinic start generated code]*/
3916
3917
static PyObject *
3918
os_chdir_impl(PyObject *module, path_t *path)
3919
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3920
0
{
3921
0
    int result;
3922
3923
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3924
0
        return NULL;
3925
0
    }
3926
3927
0
    Py_BEGIN_ALLOW_THREADS
3928
#ifdef MS_WINDOWS
3929
    /* on unix, success = 0, on windows, success = !0 */
3930
    result = !win32_wchdir(path->wide);
3931
#else
3932
0
#ifdef HAVE_FCHDIR
3933
0
    if (path->fd != -1)
3934
0
        result = fchdir(path->fd);
3935
0
    else
3936
0
#endif
3937
0
        result = chdir(path->narrow);
3938
0
#endif
3939
0
    Py_END_ALLOW_THREADS
3940
3941
0
    if (result) {
3942
0
        return path_error(path);
3943
0
    }
3944
3945
0
    Py_RETURN_NONE;
3946
0
}
3947
3948
3949
#ifdef HAVE_FCHDIR
3950
/*[clinic input]
3951
os.fchdir
3952
3953
    fd: fildes
3954
3955
Change to the directory of the given file descriptor.
3956
3957
fd must be opened on a directory, not a file.
3958
Equivalent to os.chdir(fd).
3959
3960
[clinic start generated code]*/
3961
3962
static PyObject *
3963
os_fchdir_impl(PyObject *module, int fd)
3964
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3965
0
{
3966
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3967
0
        return NULL;
3968
0
    }
3969
0
    return posix_fildes_fd(fd, fchdir);
3970
0
}
3971
#endif /* HAVE_FCHDIR */
3972
3973
#ifdef MS_WINDOWS
3974
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3975
#else
3976
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3977
#endif
3978
3979
#ifdef MS_WINDOWS
3980
static int
3981
win32_lchmod(LPCWSTR path, int mode)
3982
{
3983
    DWORD attr = GetFileAttributesW(path);
3984
    if (attr == INVALID_FILE_ATTRIBUTES) {
3985
        return 0;
3986
    }
3987
    if (mode & _S_IWRITE) {
3988
        attr &= ~FILE_ATTRIBUTE_READONLY;
3989
    }
3990
    else {
3991
        attr |= FILE_ATTRIBUTE_READONLY;
3992
    }
3993
    return SetFileAttributesW(path, attr);
3994
}
3995
3996
static int
3997
win32_hchmod(HANDLE hfile, int mode)
3998
{
3999
    FILE_BASIC_INFO info;
4000
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4001
                                      &info, sizeof(info)))
4002
    {
4003
        return 0;
4004
    }
4005
    if (mode & _S_IWRITE) {
4006
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4007
    }
4008
    else {
4009
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4010
    }
4011
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4012
                                      &info, sizeof(info));
4013
}
4014
4015
static int
4016
win32_fchmod(int fd, int mode)
4017
{
4018
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4019
    if (hfile == INVALID_HANDLE_VALUE) {
4020
        SetLastError(ERROR_INVALID_HANDLE);
4021
        return 0;
4022
    }
4023
    return win32_hchmod(hfile, mode);
4024
}
4025
4026
#endif /* MS_WINDOWS */
4027
4028
/*[clinic input]
4029
os.chmod
4030
4031
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4032
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
4033
        On some platforms, path may also be specified as an open file descriptor.
4034
        If this functionality is unavailable, using it raises an exception.
4035
4036
    mode: int
4037
        Operating-system mode bitfield.
4038
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4039
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4040
        Python.
4041
4042
    *
4043
4044
    dir_fd : dir_fd(requires='fchmodat') = None
4045
        If not None, it should be a file descriptor open to a directory,
4046
        and path should be relative; path will then be relative to that
4047
        directory.
4048
4049
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4050
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4051
        If False, and the last element of the path is a symbolic link,
4052
        chmod will modify the symbolic link itself instead of the file
4053
        the link points to.
4054
4055
Change the access permissions of a file.
4056
4057
It is an error to use dir_fd or follow_symlinks when specifying path as
4058
  an open file descriptor.
4059
dir_fd and follow_symlinks may not be implemented on your platform.
4060
  If they are unavailable, using them will raise a NotImplementedError.
4061
4062
[clinic start generated code]*/
4063
4064
static PyObject *
4065
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4066
              int follow_symlinks)
4067
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
4068
0
{
4069
0
    int result;
4070
4071
0
#ifdef HAVE_FCHMODAT
4072
0
    int fchmodat_nofollow_unsupported = 0;
4073
0
    int fchmodat_unsupported = 0;
4074
0
#endif
4075
4076
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4077
    if (follow_symlinks_specified("chmod", follow_symlinks))
4078
        return NULL;
4079
#endif
4080
4081
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4082
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4083
0
        return NULL;
4084
0
    }
4085
4086
#ifdef MS_WINDOWS
4087
    result = 0;
4088
    Py_BEGIN_ALLOW_THREADS
4089
    if (path->fd != -1) {
4090
        result = win32_fchmod(path->fd, mode);
4091
    }
4092
    else if (follow_symlinks) {
4093
        HANDLE hfile = CreateFileW(path->wide,
4094
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4095
                                   0, NULL,
4096
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4097
        if (hfile != INVALID_HANDLE_VALUE) {
4098
            result = win32_hchmod(hfile, mode);
4099
            (void)CloseHandle(hfile);
4100
        }
4101
    }
4102
    else {
4103
        result = win32_lchmod(path->wide, mode);
4104
    }
4105
    Py_END_ALLOW_THREADS
4106
    if (!result) {
4107
        return path_error(path);
4108
    }
4109
#else /* MS_WINDOWS */
4110
0
    Py_BEGIN_ALLOW_THREADS
4111
0
#ifdef HAVE_FCHMOD
4112
0
    if (path->fd != -1)
4113
0
        result = fchmod(path->fd, mode);
4114
0
    else
4115
0
#endif /* HAVE_CHMOD */
4116
#ifdef HAVE_LCHMOD
4117
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4118
        result = lchmod(path->narrow, mode);
4119
    else
4120
#endif /* HAVE_LCHMOD */
4121
0
#ifdef HAVE_FCHMODAT
4122
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4123
0
        if (HAVE_FCHMODAT_RUNTIME) {
4124
            /*
4125
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4126
             * The documentation specifically shows how to use it,
4127
             * and then says it isn't implemented yet.
4128
             * (true on linux with glibc 2.15, and openindiana 3.x)
4129
             *
4130
             * Once it is supported, os.chmod will automatically
4131
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4132
             * Until then, we need to be careful what exception we raise.
4133
             */
4134
0
            result = fchmodat(dir_fd, path->narrow, mode,
4135
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4136
            /*
4137
             * But wait!  We can't throw the exception without allowing threads,
4138
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4139
             */
4140
0
            fchmodat_nofollow_unsupported =
4141
0
                             result &&
4142
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4143
0
                             !follow_symlinks;
4144
0
        } else {
4145
0
            fchmodat_unsupported = 1;
4146
0
            fchmodat_nofollow_unsupported = 1;
4147
4148
0
            result = -1;
4149
0
        }
4150
0
    }
4151
0
    else
4152
0
#endif /* HAVE_FHCMODAT */
4153
0
    {
4154
0
#ifdef HAVE_CHMOD
4155
0
        result = chmod(path->narrow, mode);
4156
#elif defined(__wasi__)
4157
        // WASI SDK 15.0 does not support chmod.
4158
        // Ignore missing syscall for now.
4159
        result = 0;
4160
#else
4161
        result = -1;
4162
        errno = ENOSYS;
4163
#endif
4164
0
    }
4165
0
    Py_END_ALLOW_THREADS
4166
4167
0
    if (result) {
4168
0
#ifdef HAVE_FCHMODAT
4169
0
        if (fchmodat_unsupported) {
4170
0
            if (dir_fd != DEFAULT_DIR_FD) {
4171
0
                argument_unavailable_error("chmod", "dir_fd");
4172
0
                return NULL;
4173
0
            }
4174
0
        }
4175
4176
0
        if (fchmodat_nofollow_unsupported) {
4177
0
            if (dir_fd != DEFAULT_DIR_FD)
4178
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4179
0
                                                   dir_fd, follow_symlinks);
4180
0
            else
4181
0
                follow_symlinks_specified("chmod", follow_symlinks);
4182
0
            return NULL;
4183
0
        }
4184
0
        else
4185
0
#endif /* HAVE_FCHMODAT */
4186
0
        return path_error(path);
4187
0
    }
4188
0
#endif /* MS_WINDOWS */
4189
4190
0
    Py_RETURN_NONE;
4191
0
}
4192
4193
4194
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4195
/*[clinic input]
4196
os.fchmod
4197
4198
    fd: int
4199
        The file descriptor of the file to be modified.
4200
    mode: int
4201
        Operating-system mode bitfield.
4202
        Be careful when using number literals for *mode*. The conventional UNIX notation for
4203
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
4204
        Python.
4205
4206
Change the access permissions of the file given by file descriptor fd.
4207
4208
Equivalent to os.chmod(fd, mode).
4209
[clinic start generated code]*/
4210
4211
static PyObject *
4212
os_fchmod_impl(PyObject *module, int fd, int mode)
4213
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
4214
0
{
4215
0
    int res;
4216
4217
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4218
0
        return NULL;
4219
0
    }
4220
4221
#ifdef MS_WINDOWS
4222
    res = 0;
4223
    Py_BEGIN_ALLOW_THREADS
4224
    res = win32_fchmod(fd, mode);
4225
    Py_END_ALLOW_THREADS
4226
    if (!res) {
4227
        return PyErr_SetFromWindowsErr(0);
4228
    }
4229
#else /* MS_WINDOWS */
4230
0
    int async_err = 0;
4231
0
    do {
4232
0
        Py_BEGIN_ALLOW_THREADS
4233
0
        res = fchmod(fd, mode);
4234
0
        Py_END_ALLOW_THREADS
4235
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4236
0
    if (res != 0)
4237
0
        return (!async_err) ? posix_error() : NULL;
4238
0
#endif /* MS_WINDOWS */
4239
4240
0
    Py_RETURN_NONE;
4241
0
}
4242
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4243
4244
4245
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4246
/*[clinic input]
4247
os.lchmod
4248
4249
    path: path_t
4250
    mode: int
4251
4252
Change the access permissions of a file, without following symbolic links.
4253
4254
If path is a symlink, this affects the link itself rather than the target.
4255
Equivalent to chmod(path, mode, follow_symlinks=False)."
4256
[clinic start generated code]*/
4257
4258
static PyObject *
4259
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4260
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
4261
{
4262
    int res;
4263
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4264
        return NULL;
4265
    }
4266
#ifdef MS_WINDOWS
4267
    Py_BEGIN_ALLOW_THREADS
4268
    res = win32_lchmod(path->wide, mode);
4269
    Py_END_ALLOW_THREADS
4270
    if (!res) {
4271
        path_error(path);
4272
        return NULL;
4273
    }
4274
#else /* MS_WINDOWS */
4275
    Py_BEGIN_ALLOW_THREADS
4276
    res = lchmod(path->narrow, mode);
4277
    Py_END_ALLOW_THREADS
4278
    if (res < 0) {
4279
        path_error(path);
4280
        return NULL;
4281
    }
4282
#endif /* MS_WINDOWS */
4283
    Py_RETURN_NONE;
4284
}
4285
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4286
4287
4288
#ifdef HAVE_CHFLAGS
4289
/*[clinic input]
4290
os.chflags
4291
4292
    path: path_t
4293
    flags: unsigned_long(bitwise=True)
4294
    follow_symlinks: bool=True
4295
4296
Set file flags.
4297
4298
If follow_symlinks is False, and the last element of the path is a symbolic
4299
  link, chflags will change flags on the symbolic link itself instead of the
4300
  file the link points to.
4301
follow_symlinks may not be implemented on your platform.  If it is
4302
unavailable, using it will raise a NotImplementedError.
4303
4304
[clinic start generated code]*/
4305
4306
static PyObject *
4307
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4308
                int follow_symlinks)
4309
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
4310
{
4311
    int result;
4312
4313
#ifndef HAVE_LCHFLAGS
4314
    if (follow_symlinks_specified("chflags", follow_symlinks))
4315
        return NULL;
4316
#endif
4317
4318
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4319
        return NULL;
4320
    }
4321
4322
    Py_BEGIN_ALLOW_THREADS
4323
#ifdef HAVE_LCHFLAGS
4324
    if (!follow_symlinks)
4325
        result = lchflags(path->narrow, flags);
4326
    else
4327
#endif
4328
        result = chflags(path->narrow, flags);
4329
    Py_END_ALLOW_THREADS
4330
4331
    if (result)
4332
        return path_error(path);
4333
4334
    Py_RETURN_NONE;
4335
}
4336
#endif /* HAVE_CHFLAGS */
4337
4338
4339
#ifdef HAVE_LCHFLAGS
4340
/*[clinic input]
4341
os.lchflags
4342
4343
    path: path_t
4344
    flags: unsigned_long(bitwise=True)
4345
4346
Set file flags.
4347
4348
This function will not follow symbolic links.
4349
Equivalent to chflags(path, flags, follow_symlinks=False).
4350
[clinic start generated code]*/
4351
4352
static PyObject *
4353
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4354
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4355
{
4356
    int res;
4357
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4358
        return NULL;
4359
    }
4360
    Py_BEGIN_ALLOW_THREADS
4361
    res = lchflags(path->narrow, flags);
4362
    Py_END_ALLOW_THREADS
4363
    if (res < 0) {
4364
        return path_error(path);
4365
    }
4366
    Py_RETURN_NONE;
4367
}
4368
#endif /* HAVE_LCHFLAGS */
4369
4370
4371
#ifdef HAVE_CHROOT
4372
/*[clinic input]
4373
os.chroot
4374
    path: path_t
4375
4376
Change root directory to path.
4377
4378
[clinic start generated code]*/
4379
4380
static PyObject *
4381
os_chroot_impl(PyObject *module, path_t *path)
4382
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4383
0
{
4384
0
    int res;
4385
0
    Py_BEGIN_ALLOW_THREADS
4386
0
    res = chroot(path->narrow);
4387
0
    Py_END_ALLOW_THREADS
4388
0
    if (res < 0)
4389
0
        return path_error(path);
4390
0
    Py_RETURN_NONE;
4391
0
}
4392
#endif /* HAVE_CHROOT */
4393
4394
4395
#ifdef HAVE_FSYNC
4396
/*[clinic input]
4397
os.fsync
4398
4399
    fd: fildes
4400
4401
Force write of fd to disk.
4402
[clinic start generated code]*/
4403
4404
static PyObject *
4405
os_fsync_impl(PyObject *module, int fd)
4406
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4407
0
{
4408
0
    return posix_fildes_fd(fd, fsync);
4409
0
}
4410
#endif /* HAVE_FSYNC */
4411
4412
4413
#ifdef HAVE_SYNC
4414
/*[clinic input]
4415
os.sync
4416
4417
Force write of everything to disk.
4418
[clinic start generated code]*/
4419
4420
static PyObject *
4421
os_sync_impl(PyObject *module)
4422
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4423
0
{
4424
0
    Py_BEGIN_ALLOW_THREADS
4425
0
    sync();
4426
0
    Py_END_ALLOW_THREADS
4427
0
    Py_RETURN_NONE;
4428
0
}
4429
#endif /* HAVE_SYNC */
4430
4431
4432
#ifdef HAVE_FDATASYNC
4433
#ifdef __hpux
4434
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4435
#endif
4436
4437
/*[clinic input]
4438
os.fdatasync
4439
4440
    fd: fildes
4441
4442
Force write of fd to disk without forcing update of metadata.
4443
[clinic start generated code]*/
4444
4445
static PyObject *
4446
os_fdatasync_impl(PyObject *module, int fd)
4447
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4448
0
{
4449
0
    return posix_fildes_fd(fd, fdatasync);
4450
0
}
4451
#endif /* HAVE_FDATASYNC */
4452
4453
4454
#ifdef HAVE_CHOWN
4455
/*[clinic input]
4456
os.chown
4457
4458
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4459
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4460
4461
    uid: uid_t
4462
4463
    gid: gid_t
4464
4465
    *
4466
4467
    dir_fd : dir_fd(requires='fchownat') = None
4468
        If not None, it should be a file descriptor open to a directory,
4469
        and path should be relative; path will then be relative to that
4470
        directory.
4471
4472
    follow_symlinks: bool = True
4473
        If False, and the last element of the path is a symbolic link,
4474
        stat will examine the symbolic link itself instead of the file
4475
        the link points to.
4476
4477
Change the owner and group id of path to the numeric uid and gid.\
4478
4479
path may always be specified as a string.
4480
On some platforms, path may also be specified as an open file descriptor.
4481
  If this functionality is unavailable, using it raises an exception.
4482
If dir_fd is not None, it should be a file descriptor open to a directory,
4483
  and path should be relative; path will then be relative to that directory.
4484
If follow_symlinks is False, and the last element of the path is a symbolic
4485
  link, chown will modify the symbolic link itself instead of the file the
4486
  link points to.
4487
It is an error to use dir_fd or follow_symlinks when specifying path as
4488
  an open file descriptor.
4489
dir_fd and follow_symlinks may not be implemented on your platform.
4490
  If they are unavailable, using them will raise a NotImplementedError.
4491
4492
[clinic start generated code]*/
4493
4494
static PyObject *
4495
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4496
              int dir_fd, int follow_symlinks)
4497
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4498
0
{
4499
0
    int result;
4500
4501
0
#if defined(HAVE_FCHOWNAT)
4502
0
    int fchownat_unsupported = 0;
4503
0
#endif
4504
4505
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4506
    if (follow_symlinks_specified("chown", follow_symlinks))
4507
        return NULL;
4508
#endif
4509
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4510
0
        fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
4511
0
        return NULL;
4512
4513
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4514
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4515
0
        return NULL;
4516
0
    }
4517
4518
0
    Py_BEGIN_ALLOW_THREADS
4519
0
#ifdef HAVE_FCHOWN
4520
0
    if (path->fd != -1)
4521
0
        result = fchown(path->fd, uid, gid);
4522
0
    else
4523
0
#endif
4524
0
#ifdef HAVE_LCHOWN
4525
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4526
0
        result = lchown(path->narrow, uid, gid);
4527
0
    else
4528
0
#endif
4529
0
#ifdef HAVE_FCHOWNAT
4530
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4531
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4532
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4533
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4534
0
      } else {
4535
0
         fchownat_unsupported = 1;
4536
0
      }
4537
0
    } else
4538
0
#endif
4539
0
        result = chown(path->narrow, uid, gid);
4540
0
    Py_END_ALLOW_THREADS
4541
4542
0
#ifdef HAVE_FCHOWNAT
4543
0
    if (fchownat_unsupported) {
4544
        /* This would be incorrect if the current platform
4545
         * doesn't support lchown.
4546
         */
4547
0
        argument_unavailable_error(NULL, "dir_fd");
4548
0
        return NULL;
4549
0
    }
4550
0
#endif
4551
4552
0
    if (result)
4553
0
        return path_error(path);
4554
4555
0
    Py_RETURN_NONE;
4556
0
}
4557
#endif /* HAVE_CHOWN */
4558
4559
4560
#ifdef HAVE_FCHOWN
4561
/*[clinic input]
4562
os.fchown
4563
4564
    fd: int
4565
    uid: uid_t
4566
    gid: gid_t
4567
4568
Change the owner and group id of the file specified by file descriptor.
4569
4570
Equivalent to os.chown(fd, uid, gid).
4571
4572
[clinic start generated code]*/
4573
4574
static PyObject *
4575
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4576
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4577
0
{
4578
0
    int res;
4579
0
    int async_err = 0;
4580
4581
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4582
0
        return NULL;
4583
0
    }
4584
4585
0
    do {
4586
0
        Py_BEGIN_ALLOW_THREADS
4587
0
        res = fchown(fd, uid, gid);
4588
0
        Py_END_ALLOW_THREADS
4589
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4590
0
    if (res != 0)
4591
0
        return (!async_err) ? posix_error() : NULL;
4592
4593
0
    Py_RETURN_NONE;
4594
0
}
4595
#endif /* HAVE_FCHOWN */
4596
4597
4598
#ifdef HAVE_LCHOWN
4599
/*[clinic input]
4600
os.lchown
4601
4602
    path : path_t
4603
    uid: uid_t
4604
    gid: gid_t
4605
4606
Change the owner and group id of path to the numeric uid and gid.
4607
4608
This function will not follow symbolic links.
4609
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4610
[clinic start generated code]*/
4611
4612
static PyObject *
4613
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4614
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4615
0
{
4616
0
    int res;
4617
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4618
0
        return NULL;
4619
0
    }
4620
0
    Py_BEGIN_ALLOW_THREADS
4621
0
    res = lchown(path->narrow, uid, gid);
4622
0
    Py_END_ALLOW_THREADS
4623
0
    if (res < 0) {
4624
0
        return path_error(path);
4625
0
    }
4626
0
    Py_RETURN_NONE;
4627
0
}
4628
#endif /* HAVE_LCHOWN */
4629
4630
4631
static PyObject *
4632
posix_getcwd(int use_bytes)
4633
2
{
4634
#ifdef MS_WINDOWS
4635
    wchar_t wbuf[MAXPATHLEN];
4636
    wchar_t *wbuf2 = wbuf;
4637
    DWORD len;
4638
4639
    Py_BEGIN_ALLOW_THREADS
4640
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4641
    /* If the buffer is large enough, len does not include the
4642
       terminating \0. If the buffer is too small, len includes
4643
       the space needed for the terminator. */
4644
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4645
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4646
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4647
        }
4648
        else {
4649
            wbuf2 = NULL;
4650
        }
4651
        if (wbuf2) {
4652
            len = GetCurrentDirectoryW(len, wbuf2);
4653
        }
4654
    }
4655
    Py_END_ALLOW_THREADS
4656
4657
    if (!wbuf2) {
4658
        PyErr_NoMemory();
4659
        return NULL;
4660
    }
4661
    if (!len) {
4662
        PyErr_SetFromWindowsErr(0);
4663
        if (wbuf2 != wbuf)
4664
            PyMem_RawFree(wbuf2);
4665
        return NULL;
4666
    }
4667
4668
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4669
    if (wbuf2 != wbuf) {
4670
        PyMem_RawFree(wbuf2);
4671
    }
4672
4673
    if (use_bytes) {
4674
        if (resobj == NULL) {
4675
            return NULL;
4676
        }
4677
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4678
    }
4679
4680
    return resobj;
4681
#else
4682
2
    const size_t chunk = 1024;
4683
4684
2
    char *buf = NULL;
4685
2
    char *cwd = NULL;
4686
2
    size_t buflen = 0;
4687
4688
2
    Py_BEGIN_ALLOW_THREADS
4689
2
    do {
4690
2
        char *newbuf;
4691
2
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4692
2
            buflen += chunk;
4693
2
            newbuf = PyMem_RawRealloc(buf, buflen);
4694
2
        }
4695
0
        else {
4696
0
            newbuf = NULL;
4697
0
        }
4698
2
        if (newbuf == NULL) {
4699
0
            PyMem_RawFree(buf);
4700
0
            buf = NULL;
4701
0
            break;
4702
0
        }
4703
2
        buf = newbuf;
4704
4705
2
        cwd = getcwd(buf, buflen);
4706
2
    } while (cwd == NULL && errno == ERANGE);
4707
2
    Py_END_ALLOW_THREADS
4708
4709
2
    if (buf == NULL) {
4710
0
        return PyErr_NoMemory();
4711
0
    }
4712
2
    if (cwd == NULL) {
4713
0
        posix_error();
4714
0
        PyMem_RawFree(buf);
4715
0
        return NULL;
4716
0
    }
4717
4718
2
    PyObject *obj;
4719
2
    if (use_bytes) {
4720
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4721
0
    }
4722
2
    else {
4723
2
        obj = PyUnicode_DecodeFSDefault(buf);
4724
2
    }
4725
2
#ifdef __linux__
4726
2
    if (buf[0] != '/') {
4727
        /*
4728
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4729
         * relative pathname starting with '(unreachable)'. We detect this
4730
         * and fail with ENOENT, matching newer glibc behaviour.
4731
         */
4732
0
        errno = ENOENT;
4733
0
        path_object_error(obj);
4734
0
        PyMem_RawFree(buf);
4735
0
        return NULL;
4736
0
    }
4737
2
#endif
4738
2
    assert(buf[0] == '/');
4739
2
    PyMem_RawFree(buf);
4740
4741
2
    return obj;
4742
2
#endif   /* !MS_WINDOWS */
4743
2
}
4744
4745
4746
/*[clinic input]
4747
os.getcwd
4748
4749
Return a unicode string representing the current working directory.
4750
[clinic start generated code]*/
4751
4752
static PyObject *
4753
os_getcwd_impl(PyObject *module)
4754
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4755
2
{
4756
2
    return posix_getcwd(0);
4757
2
}
4758
4759
4760
/*[clinic input]
4761
os.getcwdb
4762
4763
Return a bytes string representing the current working directory.
4764
[clinic start generated code]*/
4765
4766
static PyObject *
4767
os_getcwdb_impl(PyObject *module)
4768
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4769
0
{
4770
0
    return posix_getcwd(1);
4771
0
}
4772
4773
4774
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4775
#define HAVE_LINK 1
4776
#endif
4777
4778
#ifdef HAVE_LINK
4779
/*[clinic input]
4780
4781
@permit_long_docstring_body
4782
os.link
4783
4784
    src : path_t
4785
    dst : path_t
4786
    *
4787
    src_dir_fd : dir_fd = None
4788
    dst_dir_fd : dir_fd = None
4789
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4790
4791
Create a hard link to a file.
4792
4793
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4794
  descriptor open to a directory, and the respective path string (src or dst)
4795
  should be relative; the path will then be relative to that directory.
4796
If follow_symlinks is False, and the last element of src is a symbolic
4797
  link, link will create a link to the symbolic link itself instead of the
4798
  file the link points to.
4799
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4800
  platform.  If they are unavailable, using them will raise a
4801
  NotImplementedError.
4802
[clinic start generated code]*/
4803
4804
static PyObject *
4805
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4806
             int dst_dir_fd, int follow_symlinks)
4807
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4808
0
{
4809
#ifdef MS_WINDOWS
4810
    BOOL result = FALSE;
4811
#else
4812
0
    int result;
4813
0
#endif
4814
4815
0
#ifdef HAVE_LINKAT
4816
0
    if (HAVE_LINKAT_RUNTIME) {
4817
0
        if (follow_symlinks < 0) {
4818
0
            follow_symlinks = 1;
4819
0
        }
4820
0
    }
4821
0
    else
4822
0
#endif
4823
0
    {
4824
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4825
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4826
0
            return NULL;
4827
0
        }
4828
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4829
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4830
0
#if defined(MS_WINDOWS) || defined(__linux__)
4831
0
        if (follow_symlinks == 1) {
4832
0
            argument_unavailable_error("link", "follow_symlinks=True");
4833
0
            return NULL;
4834
0
        }
4835
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4836
        if (follow_symlinks == 0) {
4837
            argument_unavailable_error("link", "follow_symlinks=False");
4838
            return NULL;
4839
        }
4840
#else
4841
        if (follow_symlinks >= 0) {
4842
            argument_unavailable_error("link", "follow_symlinks");
4843
            return NULL;
4844
        }
4845
#endif
4846
0
    }
4847
4848
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4849
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4850
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4851
0
        return NULL;
4852
0
    }
4853
4854
#ifdef MS_WINDOWS
4855
    Py_BEGIN_ALLOW_THREADS
4856
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4857
    Py_END_ALLOW_THREADS
4858
4859
    if (!result)
4860
        return path_error2(src, dst);
4861
#else
4862
0
    Py_BEGIN_ALLOW_THREADS
4863
0
#ifdef HAVE_LINKAT
4864
0
    if (HAVE_LINKAT_RUNTIME) {
4865
0
        result = linkat(src_dir_fd, src->narrow,
4866
0
            dst_dir_fd, dst->narrow,
4867
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4868
0
    }
4869
0
    else
4870
0
#endif
4871
0
    {
4872
        /* linkat not available */
4873
0
        result = link(src->narrow, dst->narrow);
4874
0
    }
4875
0
    Py_END_ALLOW_THREADS
4876
4877
0
    if (result)
4878
0
        return path_error2(src, dst);
4879
0
#endif /* MS_WINDOWS */
4880
4881
0
    Py_RETURN_NONE;
4882
0
}
4883
#endif
4884
4885
4886
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4887
static PyObject *
4888
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4889
{
4890
    PyObject *v;
4891
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4892
    BOOL result, return_bytes;
4893
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4894
    /* only claim to have space for MAX_PATH */
4895
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4896
    wchar_t *wnamebuf = NULL;
4897
4898
    WIN32_FIND_DATAW wFileData;
4899
    const wchar_t *po_wchars;
4900
4901
    if (!path->wide) { /* Default arg: "." */
4902
        po_wchars = L".";
4903
        len = 1;
4904
        return_bytes = 0;
4905
    } else {
4906
        po_wchars = path->wide;
4907
        len = wcslen(path->wide);
4908
        return_bytes = PyBytes_Check(path->object);
4909
    }
4910
    /* The +5 is so we can append "\\*.*\0" */
4911
    wnamebuf = PyMem_New(wchar_t, len + 5);
4912
    if (!wnamebuf) {
4913
        PyErr_NoMemory();
4914
        goto exit;
4915
    }
4916
    wcscpy(wnamebuf, po_wchars);
4917
    if (len > 0) {
4918
        wchar_t wch = wnamebuf[len-1];
4919
        if (wch != SEP && wch != ALTSEP && wch != L':')
4920
            wnamebuf[len++] = SEP;
4921
        wcscpy(wnamebuf + len, L"*.*");
4922
    }
4923
    if ((list = PyList_New(0)) == NULL) {
4924
        goto exit;
4925
    }
4926
    Py_BEGIN_ALLOW_THREADS
4927
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4928
    Py_END_ALLOW_THREADS
4929
    if (hFindFile == INVALID_HANDLE_VALUE) {
4930
        int error = GetLastError();
4931
        if (error == ERROR_FILE_NOT_FOUND)
4932
            goto exit;
4933
        path_error(path);
4934
        Py_CLEAR(list);
4935
        goto exit;
4936
    }
4937
    do {
4938
        /* Skip over . and .. */
4939
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4940
            wcscmp(wFileData.cFileName, L"..") != 0) {
4941
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4942
                                       wcslen(wFileData.cFileName));
4943
            if (return_bytes && v) {
4944
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4945
            }
4946
            if (v == NULL) {
4947
                Py_CLEAR(list);
4948
                break;
4949
            }
4950
            if (PyList_Append(list, v) != 0) {
4951
                Py_DECREF(v);
4952
                Py_CLEAR(list);
4953
                break;
4954
            }
4955
            Py_DECREF(v);
4956
        }
4957
        Py_BEGIN_ALLOW_THREADS
4958
        result = FindNextFileW(hFindFile, &wFileData);
4959
        Py_END_ALLOW_THREADS
4960
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4961
           it got to the end of the directory. */
4962
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4963
            path_error(path);
4964
            Py_CLEAR(list);
4965
            goto exit;
4966
        }
4967
    } while (result == TRUE);
4968
4969
exit:
4970
    if (hFindFile != INVALID_HANDLE_VALUE) {
4971
        if (FindClose(hFindFile) == FALSE) {
4972
            if (list != NULL) {
4973
                path_error(path);
4974
                Py_CLEAR(list);
4975
            }
4976
        }
4977
    }
4978
    PyMem_Free(wnamebuf);
4979
4980
    return list;
4981
}  /* end of _listdir_windows_no_opendir */
4982
4983
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4984
4985
static PyObject *
4986
_posix_listdir(path_t *path, PyObject *list)
4987
216
{
4988
216
    PyObject *v;
4989
216
    DIR *dirp = NULL;
4990
216
    struct dirent *ep;
4991
216
    int return_str; /* if false, return bytes */
4992
216
#ifdef HAVE_FDOPENDIR
4993
216
    int fd = -1;
4994
216
#endif
4995
4996
216
    errno = 0;
4997
216
#ifdef HAVE_FDOPENDIR
4998
216
    if (path->fd != -1) {
4999
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5000
        /* closedir() closes the FD, so we duplicate it */
5001
0
        fd = _Py_dup(path->fd);
5002
0
        if (fd == -1)
5003
0
            return NULL;
5004
5005
0
        return_str = 1;
5006
5007
0
        Py_BEGIN_ALLOW_THREADS
5008
0
        dirp = fdopendir(fd);
5009
0
        Py_END_ALLOW_THREADS
5010
0
      } else {
5011
0
        PyErr_SetString(PyExc_TypeError,
5012
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5013
0
        return NULL;
5014
0
      }
5015
0
    }
5016
216
    else
5017
216
#endif
5018
216
    {
5019
216
        const char *name;
5020
216
        if (path->narrow) {
5021
216
            name = path->narrow;
5022
            /* only return bytes if they specified a bytes object */
5023
216
            return_str = !PyBytes_Check(path->object);
5024
216
        }
5025
0
        else {
5026
0
            name = ".";
5027
0
            return_str = 1;
5028
0
        }
5029
5030
216
        Py_BEGIN_ALLOW_THREADS
5031
216
        dirp = opendir(name);
5032
216
        Py_END_ALLOW_THREADS
5033
216
    }
5034
5035
216
    if (dirp == NULL) {
5036
0
        path_error(path);
5037
0
        list = NULL;
5038
0
#ifdef HAVE_FDOPENDIR
5039
0
        if (fd != -1) {
5040
0
            Py_BEGIN_ALLOW_THREADS
5041
0
            close(fd);
5042
0
            Py_END_ALLOW_THREADS
5043
0
        }
5044
0
#endif
5045
0
        goto exit;
5046
0
    }
5047
216
    if ((list = PyList_New(0)) == NULL) {
5048
0
        goto exit;
5049
0
    }
5050
12.3k
    for (;;) {
5051
12.3k
        errno = 0;
5052
12.3k
        Py_BEGIN_ALLOW_THREADS
5053
12.3k
        ep = readdir(dirp);
5054
12.3k
        Py_END_ALLOW_THREADS
5055
12.3k
        if (ep == NULL) {
5056
216
            if (errno == 0) {
5057
216
                break;
5058
216
            } else {
5059
0
                path_error(path);
5060
0
                Py_CLEAR(list);
5061
0
                goto exit;
5062
0
            }
5063
216
        }
5064
12.1k
        if (ep->d_name[0] == '.' &&
5065
432
            (NAMLEN(ep) == 1 ||
5066
216
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5067
432
            continue;
5068
11.7k
        if (return_str)
5069
11.7k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5070
0
        else
5071
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5072
11.7k
        if (v == NULL) {
5073
0
            Py_CLEAR(list);
5074
0
            break;
5075
0
        }
5076
11.7k
        if (PyList_Append(list, v) != 0) {
5077
0
            Py_DECREF(v);
5078
0
            Py_CLEAR(list);
5079
0
            break;
5080
0
        }
5081
11.7k
        Py_DECREF(v);
5082
11.7k
    }
5083
5084
216
exit:
5085
216
    if (dirp != NULL) {
5086
216
        Py_BEGIN_ALLOW_THREADS
5087
216
#ifdef HAVE_FDOPENDIR
5088
216
        if (fd > -1)
5089
0
            rewinddir(dirp);
5090
216
#endif
5091
216
        closedir(dirp);
5092
216
        Py_END_ALLOW_THREADS
5093
216
    }
5094
5095
216
    return list;
5096
216
}  /* end of _posix_listdir */
5097
#endif  /* which OS */
5098
5099
5100
/*[clinic input]
5101
@permit_long_docstring_body
5102
os.listdir
5103
5104
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5105
5106
Return a list containing the names of the files in the directory.
5107
5108
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
5109
  the filenames returned will also be bytes; in all other circumstances
5110
  the filenames returned will be str.
5111
If path is None, uses the path='.'.
5112
On some platforms, path may also be specified as an open file descriptor;\
5113
  the file descriptor must refer to a directory.
5114
  If this functionality is unavailable, using it raises NotImplementedError.
5115
5116
The list is in arbitrary order.  It does not include the special
5117
entries '.' and '..' even if they are present in the directory.
5118
5119
5120
[clinic start generated code]*/
5121
5122
static PyObject *
5123
os_listdir_impl(PyObject *module, path_t *path)
5124
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
5125
216
{
5126
216
    if (PySys_Audit("os.listdir", "O",
5127
216
                    path->object ? path->object : Py_None) < 0) {
5128
0
        return NULL;
5129
0
    }
5130
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5131
    return _listdir_windows_no_opendir(path, NULL);
5132
#else
5133
216
    return _posix_listdir(path, NULL);
5134
216
#endif
5135
216
}
5136
5137
5138
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5139
5140
/*[clinic input]
5141
os.listdrives
5142
5143
Return a list containing the names of drives in the system.
5144
5145
A drive name typically looks like 'C:\\'.
5146
5147
[clinic start generated code]*/
5148
5149
static PyObject *
5150
os_listdrives_impl(PyObject *module)
5151
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5152
{
5153
    /* Number of possible drives is limited, so 256 should always be enough.
5154
       On the day when it is not, listmounts() will have to be used. */
5155
    wchar_t buffer[256];
5156
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5157
    PyObject *result = NULL;
5158
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5159
        return NULL;
5160
    }
5161
5162
    Py_BEGIN_ALLOW_THREADS;
5163
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5164
    Py_END_ALLOW_THREADS;
5165
5166
    if (!buflen) {
5167
        PyErr_SetFromWindowsErr(0);
5168
        return NULL;
5169
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5170
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5171
        return NULL;
5172
    }
5173
5174
    /* buflen includes a null terminator, so remove it */
5175
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5176
    if (str) {
5177
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5178
        if (nullchar) {
5179
            result = PyUnicode_Split(str, nullchar, -1);
5180
            Py_DECREF(nullchar);
5181
        }
5182
        Py_DECREF(str);
5183
    }
5184
    return result;
5185
}
5186
5187
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5188
5189
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5190
5191
/*[clinic input]
5192
os.listvolumes
5193
5194
Return a list containing the volumes in the system.
5195
5196
Volumes are typically represented as a GUID path.
5197
5198
[clinic start generated code]*/
5199
5200
static PyObject *
5201
os_listvolumes_impl(PyObject *module)
5202
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5203
{
5204
    PyObject *result = PyList_New(0);
5205
    HANDLE find = INVALID_HANDLE_VALUE;
5206
    wchar_t buffer[MAX_PATH + 1];
5207
    if (!result) {
5208
        return NULL;
5209
    }
5210
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5211
        Py_DECREF(result);
5212
        return NULL;
5213
    }
5214
5215
    int err = 0;
5216
    Py_BEGIN_ALLOW_THREADS;
5217
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5218
    if (find == INVALID_HANDLE_VALUE) {
5219
        err = GetLastError();
5220
    }
5221
    Py_END_ALLOW_THREADS;
5222
5223
    while (!err) {
5224
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5225
        if (!s || PyList_Append(result, s) < 0) {
5226
            Py_XDECREF(s);
5227
            Py_CLEAR(result);
5228
            break;
5229
        }
5230
        Py_DECREF(s);
5231
5232
        Py_BEGIN_ALLOW_THREADS;
5233
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5234
            err = GetLastError();
5235
        }
5236
        Py_END_ALLOW_THREADS;
5237
    }
5238
5239
    if (find != INVALID_HANDLE_VALUE) {
5240
        Py_BEGIN_ALLOW_THREADS;
5241
        FindVolumeClose(find);
5242
        Py_END_ALLOW_THREADS;
5243
    }
5244
    if (err && err != ERROR_NO_MORE_FILES) {
5245
        PyErr_SetFromWindowsErr(err);
5246
        Py_XDECREF(result);
5247
        result = NULL;
5248
    }
5249
    return result;
5250
}
5251
5252
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
5253
5254
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5255
5256
/*[clinic input]
5257
os.listmounts
5258
5259
    volume: path_t
5260
5261
Return a list containing mount points for a particular volume.
5262
5263
'volume' should be a GUID path as returned from os.listvolumes.
5264
5265
[clinic start generated code]*/
5266
5267
static PyObject *
5268
os_listmounts_impl(PyObject *module, path_t *volume)
5269
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5270
{
5271
    wchar_t default_buffer[MAX_PATH + 1];
5272
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5273
    LPWSTR buffer = default_buffer;
5274
    DWORD attributes;
5275
    PyObject *str = NULL;
5276
    PyObject *nullchar = NULL;
5277
    PyObject *result = NULL;
5278
5279
    /* Ensure we have a valid volume path before continuing */
5280
    Py_BEGIN_ALLOW_THREADS
5281
    attributes = GetFileAttributesW(volume->wide);
5282
    Py_END_ALLOW_THREADS
5283
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5284
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5285
    {
5286
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5287
    }
5288
5289
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5290
        return NULL;
5291
    }
5292
5293
    while (1) {
5294
        BOOL success;
5295
        Py_BEGIN_ALLOW_THREADS
5296
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5297
                                                   buflen, &buflen);
5298
        Py_END_ALLOW_THREADS
5299
        if (success) {
5300
            break;
5301
        }
5302
        if (GetLastError() != ERROR_MORE_DATA) {
5303
            PyErr_SetFromWindowsErr(0);
5304
            goto exit;
5305
        }
5306
        if (buffer != default_buffer) {
5307
            PyMem_Free((void *)buffer);
5308
        }
5309
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5310
        if (!buffer) {
5311
            PyErr_NoMemory();
5312
            goto exit;
5313
        }
5314
    }
5315
    if (buflen < 2) {
5316
        result = PyList_New(0);
5317
        goto exit;
5318
    }
5319
    // buflen includes two null terminators, one for the last string
5320
    // and one for the array of strings.
5321
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5322
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5323
    if (str && nullchar) {
5324
        result = PyUnicode_Split(str, nullchar, -1);
5325
    }
5326
exit:
5327
    if (buffer != default_buffer) {
5328
        PyMem_Free(buffer);
5329
    }
5330
    Py_XDECREF(nullchar);
5331
    Py_XDECREF(str);
5332
    return result;
5333
}
5334
5335
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5336
5337
#ifdef MS_WINDOWS
5338
5339
/*[clinic input]
5340
os._path_isdevdrive
5341
5342
    path: path_t
5343
5344
Determines whether the specified path is on a Windows Dev Drive.
5345
5346
[clinic start generated code]*/
5347
5348
static PyObject *
5349
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5350
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5351
{
5352
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5353
    /* This flag will be documented at
5354
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5355
       after release, and will be available in the latest WinSDK.
5356
       We include the flag to avoid a specific version dependency
5357
       on the latest WinSDK. */
5358
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5359
#endif
5360
    int err = 0;
5361
    PyObject *r = NULL;
5362
    wchar_t volume[MAX_PATH];
5363
5364
    Py_BEGIN_ALLOW_THREADS
5365
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5366
        /* invalid path of some kind */
5367
        /* Note that this also includes the case where a volume is mounted
5368
           in a path longer than 260 characters. This is likely to be rare
5369
           and problematic for other reasons, so a (soft) failure in this
5370
           check seems okay. */
5371
        err = GetLastError();
5372
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5373
        /* only care about local dev drives */
5374
        r = Py_False;
5375
    } else {
5376
        HANDLE hVolume = CreateFileW(
5377
            volume,
5378
            FILE_READ_ATTRIBUTES,
5379
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5380
            NULL,
5381
            OPEN_EXISTING,
5382
            FILE_FLAG_BACKUP_SEMANTICS,
5383
            NULL
5384
        );
5385
        if (hVolume == INVALID_HANDLE_VALUE) {
5386
            err = GetLastError();
5387
        } else {
5388
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5389
            volumeState.Version = 1;
5390
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5391
            if (!DeviceIoControl(
5392
                hVolume,
5393
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5394
                &volumeState,
5395
                sizeof(volumeState),
5396
                &volumeState,
5397
                sizeof(volumeState),
5398
                NULL,
5399
                NULL
5400
            )) {
5401
                err = GetLastError();
5402
            }
5403
            CloseHandle(hVolume);
5404
            if (err == ERROR_INVALID_PARAMETER) {
5405
                /* not supported on this platform */
5406
                r = Py_False;
5407
            } else if (!err) {
5408
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5409
                    ? Py_True : Py_False;
5410
            }
5411
        }
5412
    }
5413
    Py_END_ALLOW_THREADS
5414
5415
    if (err) {
5416
        PyErr_SetFromWindowsErr(err);
5417
        return NULL;
5418
    }
5419
5420
    if (r) {
5421
        return Py_NewRef(r);
5422
    }
5423
5424
    return NULL;
5425
}
5426
5427
5428
int
5429
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5430
{
5431
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5432
    DWORD result;
5433
5434
    result = GetFullPathNameW(path,
5435
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5436
                              NULL);
5437
    if (!result) {
5438
        return -1;
5439
    }
5440
5441
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5442
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5443
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5444
        }
5445
        else {
5446
            woutbufp = NULL;
5447
        }
5448
        if (!woutbufp) {
5449
            *abspath_p = NULL;
5450
            return 0;
5451
        }
5452
5453
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5454
        if (!result) {
5455
            PyMem_RawFree(woutbufp);
5456
            return -1;
5457
        }
5458
    }
5459
5460
    if (woutbufp != woutbuf) {
5461
        *abspath_p = woutbufp;
5462
        return 0;
5463
    }
5464
5465
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5466
    return 0;
5467
}
5468
5469
5470
/* A helper function for abspath on win32 */
5471
/*[clinic input]
5472
os._getfullpathname
5473
5474
    path: path_t
5475
    /
5476
5477
[clinic start generated code]*/
5478
5479
static PyObject *
5480
os__getfullpathname_impl(PyObject *module, path_t *path)
5481
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5482
{
5483
    wchar_t *abspath;
5484
5485
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5486
        return win32_error_object("GetFullPathNameW", path->object);
5487
    }
5488
    if (abspath == NULL) {
5489
        return PyErr_NoMemory();
5490
    }
5491
5492
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5493
    PyMem_RawFree(abspath);
5494
    if (str == NULL) {
5495
        return NULL;
5496
    }
5497
    if (PyBytes_Check(path->object)) {
5498
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5499
    }
5500
    return str;
5501
}
5502
5503
5504
/*[clinic input]
5505
os._getfinalpathname
5506
5507
    path: path_t
5508
    /
5509
5510
A helper function for samepath on windows.
5511
[clinic start generated code]*/
5512
5513
static PyObject *
5514
os__getfinalpathname_impl(PyObject *module, path_t *path)
5515
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5516
{
5517
    HANDLE hFile;
5518
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5519
    int buf_size = Py_ARRAY_LENGTH(buf);
5520
    int result_length;
5521
    PyObject *result;
5522
5523
    Py_BEGIN_ALLOW_THREADS
5524
    hFile = CreateFileW(
5525
        path->wide,
5526
        0, /* desired access */
5527
        0, /* share mode */
5528
        NULL, /* security attributes */
5529
        OPEN_EXISTING,
5530
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5531
        FILE_FLAG_BACKUP_SEMANTICS,
5532
        NULL);
5533
    Py_END_ALLOW_THREADS
5534
5535
    if (hFile == INVALID_HANDLE_VALUE) {
5536
        return win32_error_object("CreateFileW", path->object);
5537
    }
5538
5539
    /* We have a good handle to the target, use it to determine the
5540
       target path name. */
5541
    while (1) {
5542
        Py_BEGIN_ALLOW_THREADS
5543
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5544
                                                  buf_size, VOLUME_NAME_DOS);
5545
        Py_END_ALLOW_THREADS
5546
5547
        if (!result_length) {
5548
            result = win32_error_object("GetFinalPathNameByHandleW",
5549
                                         path->object);
5550
            goto cleanup;
5551
        }
5552
5553
        if (result_length < buf_size) {
5554
            break;
5555
        }
5556
5557
        wchar_t *tmp;
5558
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5559
                            result_length * sizeof(*tmp));
5560
        if (!tmp) {
5561
            result = PyErr_NoMemory();
5562
            goto cleanup;
5563
        }
5564
5565
        buf_size = result_length;
5566
        target_path = tmp;
5567
    }
5568
5569
    result = PyUnicode_FromWideChar(target_path, result_length);
5570
    if (result && PyBytes_Check(path->object)) {
5571
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5572
    }
5573
5574
cleanup:
5575
    if (target_path != buf) {
5576
        PyMem_Free(target_path);
5577
    }
5578
    CloseHandle(hFile);
5579
    return result;
5580
}
5581
5582
/*[clinic input]
5583
os._findfirstfile
5584
    path: path_t
5585
    /
5586
A function to get the real file name without accessing the file in Windows.
5587
[clinic start generated code]*/
5588
5589
static PyObject *
5590
os__findfirstfile_impl(PyObject *module, path_t *path)
5591
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5592
{
5593
    PyObject *result;
5594
    HANDLE hFindFile;
5595
    WIN32_FIND_DATAW wFileData;
5596
    WCHAR *wRealFileName;
5597
5598
    Py_BEGIN_ALLOW_THREADS
5599
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5600
    Py_END_ALLOW_THREADS
5601
5602
    if (hFindFile == INVALID_HANDLE_VALUE) {
5603
        path_error(path);
5604
        return NULL;
5605
    }
5606
5607
    wRealFileName = wFileData.cFileName;
5608
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5609
    FindClose(hFindFile);
5610
    return result;
5611
}
5612
5613
5614
/*[clinic input]
5615
os._getvolumepathname
5616
5617
    path: path_t
5618
5619
A helper function for ismount on Win32.
5620
[clinic start generated code]*/
5621
5622
static PyObject *
5623
os__getvolumepathname_impl(PyObject *module, path_t *path)
5624
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5625
{
5626
    PyObject *result;
5627
    wchar_t *mountpath=NULL;
5628
    size_t buflen;
5629
    BOOL ret;
5630
5631
    /* Volume path should be shorter than entire path */
5632
    buflen = Py_MAX(path->length, MAX_PATH);
5633
5634
    if (buflen > PY_DWORD_MAX) {
5635
        PyErr_SetString(PyExc_OverflowError, "path too long");
5636
        return NULL;
5637
    }
5638
5639
    mountpath = PyMem_New(wchar_t, buflen);
5640
    if (mountpath == NULL)
5641
        return PyErr_NoMemory();
5642
5643
    Py_BEGIN_ALLOW_THREADS
5644
    ret = GetVolumePathNameW(path->wide, mountpath,
5645
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5646
    Py_END_ALLOW_THREADS
5647
5648
    if (!ret) {
5649
        result = win32_error_object("_getvolumepathname", path->object);
5650
        goto exit;
5651
    }
5652
    result = PyUnicode_FromWideChar(mountpath, -1);
5653
    if (PyBytes_Check(path->object))
5654
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5655
5656
exit:
5657
    PyMem_Free(mountpath);
5658
    return result;
5659
}
5660
5661
5662
/*[clinic input]
5663
os._path_splitroot
5664
5665
    path: path_t,
5666
    /
5667
5668
Removes everything after the root on Win32.
5669
[clinic start generated code]*/
5670
5671
static PyObject *
5672
os__path_splitroot_impl(PyObject *module, path_t *path)
5673
/*[clinic end generated code: output=ab7f1a88b654581c input=42831e41f8458f6d]*/
5674
{
5675
    wchar_t *buffer;
5676
    wchar_t *end;
5677
    PyObject *result = NULL;
5678
    HRESULT ret;
5679
5680
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5681
    if (!buffer) {
5682
        return NULL;
5683
    }
5684
    wcscpy(buffer, path->wide);
5685
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5686
        *p = L'\\';
5687
    }
5688
5689
    Py_BEGIN_ALLOW_THREADS
5690
    ret = PathCchSkipRoot(buffer, &end);
5691
    Py_END_ALLOW_THREADS
5692
    if (FAILED(ret)) {
5693
        result = Py_BuildValue("sO", "", path->object);
5694
    } else if (end != buffer) {
5695
        size_t rootLen = (size_t)(end - buffer);
5696
        result = Py_BuildValue("NN",
5697
            PyUnicode_FromWideChar(path->wide, rootLen),
5698
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5699
        );
5700
    } else {
5701
        result = Py_BuildValue("Os", path->object, "");
5702
    }
5703
    PyMem_Free(buffer);
5704
5705
    return result;
5706
}
5707
5708
5709
#define PY_IFREG  1 // Regular file
5710
#define PY_IFDIR  2 // Directory
5711
#define PY_IFLNK  4 // Symlink
5712
#define PY_IFMNT  8 // Mount Point (junction)
5713
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5714
#define PY_IFRRP 32 // Regular Reparse Point
5715
5716
static inline BOOL
5717
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5718
{
5719
    switch (testedType) {
5720
    case PY_IFREG:
5721
        return diskDevice && attributes &&
5722
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5723
    case PY_IFDIR:
5724
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5725
    case PY_IFLNK:
5726
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5727
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5728
    case PY_IFMNT:
5729
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5730
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5731
    case PY_IFLRP:
5732
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5733
               IsReparseTagNameSurrogate(reparseTag);
5734
    case PY_IFRRP:
5735
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5736
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5737
    }
5738
5739
    return FALSE;
5740
}
5741
5742
static BOOL
5743
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5744
{
5745
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5746
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5747
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5748
5749
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5750
    if (diskOnly && !diskDevice) {
5751
        return FALSE;
5752
    }
5753
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5754
        FILE_ATTRIBUTE_TAG_INFO info;
5755
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5756
                                            sizeof(info)) &&
5757
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5758
                         testedType);
5759
    }
5760
    FILE_BASIC_INFO info;
5761
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5762
                                        sizeof(info)) &&
5763
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5764
}
5765
5766
static BOOL
5767
_testFileTypeByName(LPCWSTR path, int testedType)
5768
{
5769
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5770
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5771
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5772
5773
    FILE_STAT_BASIC_INFORMATION info;
5774
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5775
                                     sizeof(info)))
5776
    {
5777
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5778
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5779
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5780
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5781
                                diskDevice, testedType);
5782
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5783
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5784
        {
5785
            return result;
5786
        }
5787
    }
5788
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5789
                GetLastError()))
5790
    {
5791
        return FALSE;
5792
    }
5793
5794
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5795
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5796
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5797
    }
5798
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5799
                               OPEN_EXISTING, flags, NULL);
5800
    if (hfile != INVALID_HANDLE_VALUE) {
5801
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5802
        CloseHandle(hfile);
5803
        return result;
5804
    }
5805
5806
    switch (GetLastError()) {
5807
    case ERROR_ACCESS_DENIED:
5808
    case ERROR_SHARING_VIOLATION:
5809
    case ERROR_CANT_ACCESS_FILE:
5810
    case ERROR_INVALID_PARAMETER:
5811
        int rc;
5812
        STRUCT_STAT st;
5813
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5814
            rc = STAT(path, &st);
5815
        }
5816
        else {
5817
            // PY_IFRRP is not generally supported in this case, except for
5818
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5819
            rc = LSTAT(path, &st);
5820
        }
5821
        if (!rc) {
5822
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5823
                             st.st_mode & S_IFREG, testedType);
5824
        }
5825
    }
5826
5827
    return FALSE;
5828
}
5829
5830
5831
static BOOL
5832
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5833
{
5834
    FILE_STAT_BASIC_INFORMATION info;
5835
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5836
                                     sizeof(info)))
5837
    {
5838
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5839
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5840
        {
5841
            return TRUE;
5842
        }
5843
    }
5844
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5845
                    GetLastError()))
5846
    {
5847
        return FALSE;
5848
    }
5849
5850
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5851
    if (!followLinks) {
5852
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5853
    }
5854
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5855
                               OPEN_EXISTING, flags, NULL);
5856
    if (hfile != INVALID_HANDLE_VALUE) {
5857
        if (followLinks) {
5858
            CloseHandle(hfile);
5859
            return TRUE;
5860
        }
5861
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5862
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5863
        CloseHandle(hfile);
5864
        if (!result) {
5865
            return TRUE;
5866
        }
5867
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5868
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5869
        if (hfile != INVALID_HANDLE_VALUE) {
5870
            CloseHandle(hfile);
5871
            return TRUE;
5872
        }
5873
    }
5874
5875
    switch (GetLastError()) {
5876
    case ERROR_ACCESS_DENIED:
5877
    case ERROR_SHARING_VIOLATION:
5878
    case ERROR_CANT_ACCESS_FILE:
5879
    case ERROR_INVALID_PARAMETER:
5880
        STRUCT_STAT _st;
5881
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5882
    }
5883
5884
    return FALSE;
5885
}
5886
5887
5888
static BOOL
5889
_testFileExists(path_t *path, BOOL followLinks)
5890
{
5891
    BOOL result = FALSE;
5892
    if (path->value_error) {
5893
        return FALSE;
5894
    }
5895
5896
    Py_BEGIN_ALLOW_THREADS
5897
    if (path->fd != -1) {
5898
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5899
        if (hfile != INVALID_HANDLE_VALUE) {
5900
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5901
                result = TRUE;
5902
            }
5903
        }
5904
    }
5905
    else if (path->wide) {
5906
        result = _testFileExistsByName(path->wide, followLinks);
5907
    }
5908
    Py_END_ALLOW_THREADS
5909
5910
    return result;
5911
}
5912
5913
5914
static BOOL
5915
_testFileType(path_t *path, int testedType)
5916
{
5917
    BOOL result = FALSE;
5918
    if (path->value_error) {
5919
        return FALSE;
5920
    }
5921
5922
    Py_BEGIN_ALLOW_THREADS
5923
    if (path->fd != -1) {
5924
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5925
        if (hfile != INVALID_HANDLE_VALUE) {
5926
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5927
        }
5928
    }
5929
    else if (path->wide) {
5930
        result = _testFileTypeByName(path->wide, testedType);
5931
    }
5932
    Py_END_ALLOW_THREADS
5933
5934
    return result;
5935
}
5936
5937
5938
/*[clinic input]
5939
os._path_exists -> bool
5940
5941
    path: path_t(allow_fd=True, suppress_value_error=True)
5942
5943
Test whether a path exists.  Returns False for broken symbolic links.
5944
5945
[clinic start generated code]*/
5946
5947
static int
5948
os__path_exists_impl(PyObject *module, path_t *path)
5949
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5950
{
5951
    return _testFileExists(path, TRUE);
5952
}
5953
5954
5955
/*[clinic input]
5956
os._path_lexists -> bool
5957
5958
    path: path_t(allow_fd=True, suppress_value_error=True)
5959
5960
Test whether a path exists.  Returns True for broken symbolic links.
5961
5962
[clinic start generated code]*/
5963
5964
static int
5965
os__path_lexists_impl(PyObject *module, path_t *path)
5966
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5967
{
5968
    return _testFileExists(path, FALSE);
5969
}
5970
5971
5972
/*[clinic input]
5973
os._path_isdir -> bool
5974
5975
    path: path_t(allow_fd=True, suppress_value_error=True),
5976
    /
5977
5978
Return true if the pathname refers to an existing directory.
5979
5980
[clinic start generated code]*/
5981
5982
static int
5983
os__path_isdir_impl(PyObject *module, path_t *path)
5984
/*[clinic end generated code: output=d5786196f9e2fa7a input=0d3fd790564d244b]*/
5985
{
5986
    return _testFileType(path, PY_IFDIR);
5987
}
5988
5989
5990
/*[clinic input]
5991
os._path_isfile -> bool
5992
5993
    path: path_t(allow_fd=True, suppress_value_error=True)
5994
5995
Test whether a path is a regular file
5996
5997
[clinic start generated code]*/
5998
5999
static int
6000
os__path_isfile_impl(PyObject *module, path_t *path)
6001
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6002
{
6003
    return _testFileType(path, PY_IFREG);
6004
}
6005
6006
6007
/*[clinic input]
6008
os._path_islink -> bool
6009
6010
    path: path_t(allow_fd=True, suppress_value_error=True)
6011
6012
Test whether a path is a symbolic link
6013
6014
[clinic start generated code]*/
6015
6016
static int
6017
os__path_islink_impl(PyObject *module, path_t *path)
6018
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6019
{
6020
    return _testFileType(path, PY_IFLNK);
6021
}
6022
6023
6024
/*[clinic input]
6025
os._path_isjunction -> bool
6026
6027
    path: path_t(allow_fd=True, suppress_value_error=True)
6028
6029
Test whether a path is a junction
6030
6031
[clinic start generated code]*/
6032
6033
static int
6034
os__path_isjunction_impl(PyObject *module, path_t *path)
6035
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6036
{
6037
    return _testFileType(path, PY_IFMNT);
6038
}
6039
6040
#undef PY_IFREG
6041
#undef PY_IFDIR
6042
#undef PY_IFLNK
6043
#undef PY_IFMNT
6044
#undef PY_IFLRP
6045
#undef PY_IFRRP
6046
6047
#endif /* MS_WINDOWS */
6048
6049
6050
/*[clinic input]
6051
os._path_splitroot_ex
6052
6053
    path: path_t(make_wide=True, nonstrict=True),
6054
    /
6055
6056
Split a pathname into drive, root and tail.
6057
6058
The tail contains anything after the root.
6059
[clinic start generated code]*/
6060
6061
static PyObject *
6062
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6063
/*[clinic end generated code: output=4b0072b6cdf4b611 input=4ac47b394d68bd21]*/
6064
141k
{
6065
141k
    Py_ssize_t drvsize, rootsize;
6066
141k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6067
6068
141k
    const wchar_t *buffer = path->wide;
6069
141k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6070
141k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6071
141k
    if (drv == NULL) {
6072
0
        goto exit;
6073
0
    }
6074
141k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6075
141k
    if (root == NULL) {
6076
0
        goto exit;
6077
0
    }
6078
141k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6079
141k
                                  path->length - drvsize - rootsize);
6080
141k
    if (tail == NULL) {
6081
0
        goto exit;
6082
0
    }
6083
141k
    if (PyBytes_Check(path->object)) {
6084
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6085
0
        if (drv == NULL) {
6086
0
            goto exit;
6087
0
        }
6088
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6089
0
        if (root == NULL) {
6090
0
            goto exit;
6091
0
        }
6092
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6093
0
        if (tail == NULL) {
6094
0
            goto exit;
6095
0
        }
6096
0
    }
6097
141k
    result = PyTuple_Pack(3, drv, root, tail);
6098
141k
exit:
6099
141k
    Py_XDECREF(drv);
6100
141k
    Py_XDECREF(root);
6101
141k
    Py_XDECREF(tail);
6102
141k
    return result;
6103
141k
}
6104
6105
6106
/*[clinic input]
6107
os._path_normpath
6108
6109
    path: path_t(make_wide=True, nonstrict=True)
6110
6111
Normalize path, eliminating double slashes, etc.
6112
[clinic start generated code]*/
6113
6114
static PyObject *
6115
os__path_normpath_impl(PyObject *module, path_t *path)
6116
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6117
7.66k
{
6118
7.66k
    PyObject *result;
6119
7.66k
    Py_ssize_t norm_len;
6120
7.66k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6121
7.66k
                                               path->length, &norm_len);
6122
7.66k
    if (!norm_len) {
6123
0
        result = PyUnicode_FromOrdinal('.');
6124
0
    }
6125
7.66k
    else {
6126
7.66k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6127
7.66k
    }
6128
7.66k
    if (PyBytes_Check(path->object)) {
6129
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6130
0
    }
6131
7.66k
    return result;
6132
7.66k
}
6133
6134
/*[clinic input]
6135
os.mkdir
6136
6137
    path : path_t
6138
6139
    mode: int = 0o777
6140
6141
    *
6142
6143
    dir_fd : dir_fd(requires='mkdirat') = None
6144
6145
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
6146
6147
Create a directory.
6148
6149
If dir_fd is not None, it should be a file descriptor open to a directory,
6150
  and path should be relative; path will then be relative to that directory.
6151
dir_fd may not be implemented on your platform.
6152
  If it is unavailable, using it will raise a NotImplementedError.
6153
6154
The mode argument is ignored on Windows. Where it is used, the current umask
6155
value is first masked out.
6156
[clinic start generated code]*/
6157
6158
static PyObject *
6159
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6160
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
6161
138k
{
6162
138k
    int result;
6163
#ifdef MS_WINDOWS
6164
    int error = 0;
6165
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6166
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6167
#endif
6168
138k
#ifdef HAVE_MKDIRAT
6169
138k
    int mkdirat_unavailable = 0;
6170
138k
#endif
6171
6172
138k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6173
138k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6174
0
        return NULL;
6175
0
    }
6176
6177
#ifdef MS_WINDOWS
6178
    Py_BEGIN_ALLOW_THREADS
6179
    // For API sets that don't support these APIs, we have no choice
6180
    // but to silently create a directory with default ACL.
6181
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6182
    if (mode == 0700 /* 0o700 */) {
6183
        ULONG sdSize;
6184
        pSecAttr = &secAttr;
6185
        // Set a discretionary ACL (D) that is protected (P) and includes
6186
        // inheritable (OICI) entries that allow (A) full control (FA) to
6187
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6188
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6189
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6190
            SDDL_REVISION_1,
6191
            &secAttr.lpSecurityDescriptor,
6192
            &sdSize
6193
        )) {
6194
            error = GetLastError();
6195
        }
6196
    }
6197
#endif
6198
    if (!error) {
6199
        result = CreateDirectoryW(path->wide, pSecAttr);
6200
        if (secAttr.lpSecurityDescriptor &&
6201
            // uncommonly, LocalFree returns non-zero on error, but still uses
6202
            // GetLastError() to see what the error code is
6203
            LocalFree(secAttr.lpSecurityDescriptor)) {
6204
            error = GetLastError();
6205
        }
6206
    }
6207
    Py_END_ALLOW_THREADS
6208
6209
    if (error) {
6210
        return PyErr_SetFromWindowsErr(error);
6211
    }
6212
    if (!result) {
6213
        return path_error(path);
6214
    }
6215
#else
6216
138k
    Py_BEGIN_ALLOW_THREADS
6217
138k
#if HAVE_MKDIRAT
6218
138k
    if (dir_fd != DEFAULT_DIR_FD) {
6219
0
      if (HAVE_MKDIRAT_RUNTIME) {
6220
0
        result = mkdirat(dir_fd, path->narrow, mode);
6221
6222
0
      } else {
6223
0
        mkdirat_unavailable = 1;
6224
0
      }
6225
0
    } else
6226
138k
#endif
6227
#if defined(__WATCOMC__) && !defined(__QNX__)
6228
        result = mkdir(path->narrow);
6229
#else
6230
138k
        result = mkdir(path->narrow, mode);
6231
138k
#endif
6232
138k
    Py_END_ALLOW_THREADS
6233
6234
138k
#if HAVE_MKDIRAT
6235
138k
    if (mkdirat_unavailable) {
6236
0
        argument_unavailable_error(NULL, "dir_fd");
6237
0
        return NULL;
6238
0
    }
6239
138k
#endif
6240
6241
138k
    if (result < 0)
6242
414
        return path_error(path);
6243
138k
#endif /* MS_WINDOWS */
6244
138k
    Py_RETURN_NONE;
6245
138k
}
6246
6247
6248
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6249
#if defined(HAVE_SYS_RESOURCE_H)
6250
#include <sys/resource.h>
6251
#endif
6252
6253
6254
#ifdef HAVE_NICE
6255
/*[clinic input]
6256
os.nice
6257
6258
    increment: int
6259
    /
6260
6261
Add increment to the priority of process and return the new priority.
6262
[clinic start generated code]*/
6263
6264
static PyObject *
6265
os_nice_impl(PyObject *module, int increment)
6266
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6267
0
{
6268
0
    int value;
6269
6270
    /* There are two flavours of 'nice': one that returns the new
6271
       priority (as required by almost all standards out there) and the
6272
       Linux/FreeBSD one, which returns '0' on success and advices
6273
       the use of getpriority() to get the new priority.
6274
6275
       If we are of the nice family that returns the new priority, we
6276
       need to clear errno before the call, and check if errno is filled
6277
       before calling posix_error() on a returnvalue of -1, because the
6278
       -1 may be the actual new priority! */
6279
6280
0
    errno = 0;
6281
0
    value = nice(increment);
6282
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6283
    if (value == 0)
6284
        value = getpriority(PRIO_PROCESS, 0);
6285
#endif
6286
0
    if (value == -1 && errno != 0)
6287
        /* either nice() or getpriority() returned an error */
6288
0
        return posix_error();
6289
0
    return PyLong_FromLong((long) value);
6290
0
}
6291
#endif /* HAVE_NICE */
6292
6293
6294
#ifdef HAVE_GETPRIORITY
6295
/*[clinic input]
6296
os.getpriority
6297
6298
    which: int
6299
    who: int
6300
6301
Return program scheduling priority.
6302
[clinic start generated code]*/
6303
6304
static PyObject *
6305
os_getpriority_impl(PyObject *module, int which, int who)
6306
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6307
0
{
6308
0
    int retval;
6309
6310
0
    errno = 0;
6311
0
    retval = getpriority(which, who);
6312
0
    if (errno != 0)
6313
0
        return posix_error();
6314
0
    return PyLong_FromLong((long)retval);
6315
0
}
6316
#endif /* HAVE_GETPRIORITY */
6317
6318
6319
#ifdef HAVE_SETPRIORITY
6320
/*[clinic input]
6321
os.setpriority
6322
6323
    which: int
6324
    who: int
6325
    priority: int
6326
6327
Set program scheduling priority.
6328
[clinic start generated code]*/
6329
6330
static PyObject *
6331
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6332
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6333
0
{
6334
0
    int retval;
6335
6336
0
    retval = setpriority(which, who, priority);
6337
0
    if (retval == -1)
6338
0
        return posix_error();
6339
0
    Py_RETURN_NONE;
6340
0
}
6341
#endif /* HAVE_SETPRIORITY */
6342
6343
6344
static PyObject *
6345
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6346
265
{
6347
265
    const char *function_name = is_replace ? "replace" : "rename";
6348
265
    int dir_fd_specified;
6349
6350
265
#ifdef HAVE_RENAMEAT
6351
265
    int renameat_unavailable = 0;
6352
265
#endif
6353
6354
#ifdef MS_WINDOWS
6355
    BOOL result;
6356
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6357
#else
6358
265
    int result;
6359
265
#endif
6360
6361
265
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6362
265
                       (dst_dir_fd != DEFAULT_DIR_FD);
6363
#ifndef HAVE_RENAMEAT
6364
    if (dir_fd_specified) {
6365
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6366
        return NULL;
6367
    }
6368
#endif
6369
6370
265
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6371
265
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6372
265
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6373
0
        return NULL;
6374
0
    }
6375
6376
#ifdef MS_WINDOWS
6377
    Py_BEGIN_ALLOW_THREADS
6378
    result = MoveFileExW(src->wide, dst->wide, flags);
6379
    Py_END_ALLOW_THREADS
6380
6381
    if (!result)
6382
        return path_error2(src, dst);
6383
6384
#else
6385
265
    Py_BEGIN_ALLOW_THREADS
6386
265
#ifdef HAVE_RENAMEAT
6387
265
    if (dir_fd_specified) {
6388
0
        if (HAVE_RENAMEAT_RUNTIME) {
6389
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6390
0
        } else {
6391
0
            renameat_unavailable = 1;
6392
0
        }
6393
0
    } else
6394
265
#endif
6395
265
    result = rename(src->narrow, dst->narrow);
6396
265
    Py_END_ALLOW_THREADS
6397
6398
6399
265
#ifdef HAVE_RENAMEAT
6400
265
    if (renameat_unavailable) {
6401
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6402
0
        return NULL;
6403
0
    }
6404
265
#endif
6405
6406
265
    if (result)
6407
0
        return path_error2(src, dst);
6408
265
#endif
6409
265
    Py_RETURN_NONE;
6410
265
}
6411
6412
6413
/*[clinic input]
6414
@permit_long_docstring_body
6415
os.rename
6416
6417
    src : path_t
6418
    dst : path_t
6419
    *
6420
    src_dir_fd : dir_fd = None
6421
    dst_dir_fd : dir_fd = None
6422
6423
Rename a file or directory.
6424
6425
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6426
  descriptor open to a directory, and the respective path string (src or dst)
6427
  should be relative; the path will then be relative to that directory.
6428
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6429
  If they are unavailable, using them will raise a NotImplementedError.
6430
[clinic start generated code]*/
6431
6432
static PyObject *
6433
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6434
               int dst_dir_fd)
6435
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6436
0
{
6437
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6438
0
}
6439
6440
6441
/*[clinic input]
6442
@permit_long_docstring_body
6443
os.replace = os.rename
6444
6445
Rename a file or directory, overwriting the destination.
6446
6447
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6448
  descriptor open to a directory, and the respective path string (src or dst)
6449
  should be relative; the path will then be relative to that directory.
6450
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6451
  If they are unavailable, using them will raise a NotImplementedError.
6452
[clinic start generated code]*/
6453
6454
static PyObject *
6455
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6456
                int dst_dir_fd)
6457
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6458
265
{
6459
265
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6460
265
}
6461
6462
6463
/*[clinic input]
6464
os.rmdir
6465
6466
    path: path_t
6467
    *
6468
    dir_fd: dir_fd(requires='unlinkat') = None
6469
6470
Remove a directory.
6471
6472
If dir_fd is not None, it should be a file descriptor open to a directory,
6473
  and path should be relative; path will then be relative to that directory.
6474
dir_fd may not be implemented on your platform.
6475
  If it is unavailable, using it will raise a NotImplementedError.
6476
[clinic start generated code]*/
6477
6478
static PyObject *
6479
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6480
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6481
138k
{
6482
138k
    int result;
6483
138k
#ifdef HAVE_UNLINKAT
6484
138k
    int unlinkat_unavailable = 0;
6485
138k
#endif
6486
6487
138k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6488
138k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6489
0
        return NULL;
6490
0
    }
6491
6492
138k
    Py_BEGIN_ALLOW_THREADS
6493
#ifdef MS_WINDOWS
6494
    /* Windows, success=1, UNIX, success=0 */
6495
    result = !RemoveDirectoryW(path->wide);
6496
#else
6497
138k
#ifdef HAVE_UNLINKAT
6498
138k
    if (dir_fd != DEFAULT_DIR_FD) {
6499
134k
      if (HAVE_UNLINKAT_RUNTIME) {
6500
134k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6501
134k
      } else {
6502
0
        unlinkat_unavailable = 1;
6503
0
        result = -1;
6504
0
      }
6505
134k
    } else
6506
3.99k
#endif
6507
3.99k
        result = rmdir(path->narrow);
6508
138k
#endif
6509
138k
    Py_END_ALLOW_THREADS
6510
6511
138k
#ifdef HAVE_UNLINKAT
6512
138k
    if (unlinkat_unavailable) {
6513
0
        argument_unavailable_error("rmdir", "dir_fd");
6514
0
        return NULL;
6515
0
    }
6516
138k
#endif
6517
6518
138k
    if (result)
6519
0
        return path_error(path);
6520
6521
138k
    Py_RETURN_NONE;
6522
138k
}
6523
6524
6525
#ifdef HAVE_SYSTEM
6526
#ifdef MS_WINDOWS
6527
/*[clinic input]
6528
os.system -> long
6529
6530
    command: Py_UNICODE
6531
6532
Execute the command in a subshell.
6533
[clinic start generated code]*/
6534
6535
static long
6536
os_system_impl(PyObject *module, const wchar_t *command)
6537
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6538
{
6539
    long result;
6540
6541
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6542
        return -1;
6543
    }
6544
6545
    Py_BEGIN_ALLOW_THREADS
6546
    _Py_BEGIN_SUPPRESS_IPH
6547
    result = _wsystem(command);
6548
    _Py_END_SUPPRESS_IPH
6549
    Py_END_ALLOW_THREADS
6550
    return result;
6551
}
6552
#else /* MS_WINDOWS */
6553
/*[clinic input]
6554
os.system -> long
6555
6556
    command: unicode_fs_encoded
6557
6558
Execute the command in a subshell.
6559
[clinic start generated code]*/
6560
6561
static long
6562
os_system_impl(PyObject *module, PyObject *command)
6563
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6564
0
{
6565
0
    long result;
6566
0
    const char *bytes = PyBytes_AsString(command);
6567
6568
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6569
0
        return -1;
6570
0
    }
6571
6572
0
    Py_BEGIN_ALLOW_THREADS
6573
0
    result = system(bytes);
6574
0
    Py_END_ALLOW_THREADS
6575
0
    return result;
6576
0
}
6577
#endif
6578
#endif /* HAVE_SYSTEM */
6579
6580
6581
#ifdef HAVE_UMASK
6582
/*[clinic input]
6583
os.umask
6584
6585
    mask: int
6586
    /
6587
6588
Set the current numeric umask and return the previous umask.
6589
[clinic start generated code]*/
6590
6591
static PyObject *
6592
os_umask_impl(PyObject *module, int mask)
6593
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6594
0
{
6595
0
    int i = (int)umask(mask);
6596
0
    if (i < 0)
6597
0
        return posix_error();
6598
0
    return PyLong_FromLong((long)i);
6599
0
}
6600
#endif
6601
6602
#ifdef MS_WINDOWS
6603
6604
/* override the default DeleteFileW behavior so that directory
6605
symlinks can be removed with this function, the same as with
6606
Unix symlinks */
6607
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6608
{
6609
    WIN32_FILE_ATTRIBUTE_DATA info;
6610
    WIN32_FIND_DATAW find_data;
6611
    HANDLE find_data_handle;
6612
    int is_directory = 0;
6613
    int is_link = 0;
6614
6615
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6616
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6617
6618
        /* Get WIN32_FIND_DATA structure for the path to determine if
6619
           it is a symlink */
6620
        if(is_directory &&
6621
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6622
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6623
6624
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6625
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6626
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6627
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6628
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6629
                FindClose(find_data_handle);
6630
            }
6631
        }
6632
    }
6633
6634
    if (is_directory && is_link)
6635
        return RemoveDirectoryW(lpFileName);
6636
6637
    return DeleteFileW(lpFileName);
6638
}
6639
#endif /* MS_WINDOWS */
6640
6641
6642
/*[clinic input]
6643
os.unlink
6644
6645
    path: path_t
6646
    *
6647
    dir_fd: dir_fd(requires='unlinkat')=None
6648
6649
Remove a file (same as remove()).
6650
6651
If dir_fd is not None, it should be a file descriptor open to a directory,
6652
  and path should be relative; path will then be relative to that directory.
6653
dir_fd may not be implemented on your platform.
6654
  If it is unavailable, using it will raise a NotImplementedError.
6655
6656
[clinic start generated code]*/
6657
6658
static PyObject *
6659
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6660
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6661
858
{
6662
858
    int result;
6663
858
#ifdef HAVE_UNLINKAT
6664
858
    int unlinkat_unavailable = 0;
6665
858
#endif
6666
6667
858
    if (PySys_Audit("os.remove", "Oi", path->object,
6668
858
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6669
0
        return NULL;
6670
0
    }
6671
6672
858
    Py_BEGIN_ALLOW_THREADS
6673
858
    _Py_BEGIN_SUPPRESS_IPH
6674
#ifdef MS_WINDOWS
6675
    /* Windows, success=1, UNIX, success=0 */
6676
    result = !Py_DeleteFileW(path->wide);
6677
#else
6678
858
#ifdef HAVE_UNLINKAT
6679
858
    if (dir_fd != DEFAULT_DIR_FD) {
6680
856
      if (HAVE_UNLINKAT_RUNTIME) {
6681
6682
856
        result = unlinkat(dir_fd, path->narrow, 0);
6683
856
      } else {
6684
0
        unlinkat_unavailable = 1;
6685
0
      }
6686
856
    } else
6687
2
#endif /* HAVE_UNLINKAT */
6688
2
        result = unlink(path->narrow);
6689
858
#endif
6690
858
    _Py_END_SUPPRESS_IPH
6691
858
    Py_END_ALLOW_THREADS
6692
6693
858
#ifdef HAVE_UNLINKAT
6694
858
    if (unlinkat_unavailable) {
6695
0
        argument_unavailable_error(NULL, "dir_fd");
6696
0
        return NULL;
6697
0
    }
6698
858
#endif
6699
6700
858
    if (result)
6701
0
        return path_error(path);
6702
6703
858
    Py_RETURN_NONE;
6704
858
}
6705
6706
6707
/*[clinic input]
6708
os.remove = os.unlink
6709
6710
Remove a file (same as unlink()).
6711
6712
If dir_fd is not None, it should be a file descriptor open to a directory,
6713
  and path should be relative; path will then be relative to that directory.
6714
dir_fd may not be implemented on your platform.
6715
  If it is unavailable, using it will raise a NotImplementedError.
6716
[clinic start generated code]*/
6717
6718
static PyObject *
6719
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6720
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6721
0
{
6722
0
    return os_unlink_impl(module, path, dir_fd);
6723
0
}
6724
6725
6726
static PyStructSequence_Field uname_result_fields[] = {
6727
    {"sysname",    "operating system name"},
6728
    {"nodename",   "name of machine on network (implementation-defined)"},
6729
    {"release",    "operating system release"},
6730
    {"version",    "operating system version"},
6731
    {"machine",    "hardware identifier"},
6732
    {NULL}
6733
};
6734
6735
PyDoc_STRVAR(uname_result__doc__,
6736
"uname_result: Result from os.uname().\n\n\
6737
This object may be accessed either as a tuple of\n\
6738
  (sysname, nodename, release, version, machine),\n\
6739
or via the attributes sysname, nodename, release, version, and machine.\n\
6740
\n\
6741
See os.uname for more information.");
6742
6743
static PyStructSequence_Desc uname_result_desc = {
6744
    MODNAME ".uname_result", /* name */
6745
    uname_result__doc__, /* doc */
6746
    uname_result_fields,
6747
    5
6748
};
6749
6750
#ifdef HAVE_UNAME
6751
/*[clinic input]
6752
os.uname
6753
6754
Return an object identifying the current operating system.
6755
6756
The object behaves like a named tuple with the following fields:
6757
  (sysname, nodename, release, version, machine)
6758
6759
[clinic start generated code]*/
6760
6761
static PyObject *
6762
os_uname_impl(PyObject *module)
6763
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6764
0
{
6765
0
    struct utsname u;
6766
0
    int res;
6767
0
    PyObject *value;
6768
6769
0
    Py_BEGIN_ALLOW_THREADS
6770
0
    res = uname(&u);
6771
0
    Py_END_ALLOW_THREADS
6772
0
    if (res < 0)
6773
0
        return posix_error();
6774
6775
0
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6776
0
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6777
0
    if (value == NULL)
6778
0
        return NULL;
6779
6780
0
#define SET(i, field) \
6781
0
    { \
6782
0
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6783
0
    if (!o) { \
6784
0
        Py_DECREF(value); \
6785
0
        return NULL; \
6786
0
    } \
6787
0
    PyStructSequence_SET_ITEM(value, i, o); \
6788
0
    } \
6789
0
6790
0
    SET(0, u.sysname);
6791
0
    SET(1, u.nodename);
6792
0
    SET(2, u.release);
6793
0
    SET(3, u.version);
6794
0
    SET(4, u.machine);
6795
6796
0
#undef SET
6797
6798
0
    return value;
6799
0
}
6800
#endif /* HAVE_UNAME */
6801
6802
6803
6804
typedef struct {
6805
    int    now;
6806
    time_t atime_s;
6807
    long   atime_ns;
6808
    time_t mtime_s;
6809
    long   mtime_ns;
6810
} utime_t;
6811
6812
/*
6813
 * these macros assume that "ut" is a pointer to a utime_t
6814
 * they also intentionally leak the declaration of a pointer named "time"
6815
 */
6816
#define UTIME_TO_TIMESPEC \
6817
0
    struct timespec ts[2]; \
6818
0
    struct timespec *time; \
6819
0
    if (ut->now) \
6820
0
        time = NULL; \
6821
0
    else { \
6822
0
        ts[0].tv_sec = ut->atime_s; \
6823
0
        ts[0].tv_nsec = ut->atime_ns; \
6824
0
        ts[1].tv_sec = ut->mtime_s; \
6825
0
        ts[1].tv_nsec = ut->mtime_ns; \
6826
0
        time = ts; \
6827
0
    } \
6828
6829
#define UTIME_TO_TIMEVAL \
6830
0
    struct timeval tv[2]; \
6831
0
    struct timeval *time; \
6832
0
    if (ut->now) \
6833
0
        time = NULL; \
6834
0
    else { \
6835
0
        tv[0].tv_sec = ut->atime_s; \
6836
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6837
0
        tv[1].tv_sec = ut->mtime_s; \
6838
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6839
0
        time = tv; \
6840
0
    } \
6841
6842
#define UTIME_TO_UTIMBUF \
6843
    struct utimbuf u; \
6844
    struct utimbuf *time; \
6845
    if (ut->now) \
6846
        time = NULL; \
6847
    else { \
6848
        u.actime = ut->atime_s; \
6849
        u.modtime = ut->mtime_s; \
6850
        time = &u; \
6851
    }
6852
6853
#define UTIME_TO_TIME_T \
6854
    time_t timet[2]; \
6855
    time_t *time; \
6856
    if (ut->now) \
6857
        time = NULL; \
6858
    else { \
6859
        timet[0] = ut->atime_s; \
6860
        timet[1] = ut->mtime_s; \
6861
        time = timet; \
6862
    } \
6863
6864
6865
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6866
6867
static int
6868
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6869
0
{
6870
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6871
    if (HAVE_UTIMENSAT_RUNTIME) {
6872
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6873
        UTIME_TO_TIMESPEC;
6874
        return utimensat(dir_fd, path, time, flags);
6875
    }  else {
6876
        errno = ENOSYS;
6877
        return -1;
6878
    }
6879
#elif defined(HAVE_UTIMENSAT)
6880
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6881
0
    UTIME_TO_TIMESPEC;
6882
0
    return utimensat(dir_fd, path, time, flags);
6883
#elif defined(HAVE_FUTIMESAT)
6884
    UTIME_TO_TIMEVAL;
6885
    /*
6886
     * follow_symlinks will never be false here;
6887
     * we only allow !follow_symlinks and dir_fd together
6888
     * if we have utimensat()
6889
     */
6890
    assert(follow_symlinks);
6891
    return futimesat(dir_fd, path, time);
6892
#endif
6893
0
}
6894
6895
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6896
#else
6897
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6898
#endif
6899
6900
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6901
6902
static int
6903
utime_fd(utime_t *ut, int fd)
6904
0
{
6905
0
#ifdef HAVE_FUTIMENS
6906
6907
0
    if (HAVE_FUTIMENS_RUNTIME) {
6908
6909
0
    UTIME_TO_TIMESPEC;
6910
0
    return futimens(fd, time);
6911
6912
0
    } else
6913
#ifndef HAVE_FUTIMES
6914
    {
6915
        /* Not sure if this can happen */
6916
        PyErr_SetString(
6917
            PyExc_RuntimeError,
6918
            "neither futimens nor futimes are supported"
6919
            " on this system");
6920
        return -1;
6921
    }
6922
#endif
6923
6924
0
#endif
6925
0
#ifdef HAVE_FUTIMES
6926
0
    {
6927
0
    UTIME_TO_TIMEVAL;
6928
0
    return futimes(fd, time);
6929
0
    }
6930
0
#endif
6931
0
}
6932
6933
    #define PATH_UTIME_HAVE_FD 1
6934
#else
6935
    #define PATH_UTIME_HAVE_FD 0
6936
#endif
6937
6938
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6939
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6940
#endif
6941
6942
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6943
6944
static int
6945
utime_nofollow_symlinks(utime_t *ut, const char *path)
6946
0
{
6947
0
#ifdef HAVE_UTIMENSAT
6948
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6949
0
        UTIME_TO_TIMESPEC;
6950
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6951
0
    } else
6952
#ifndef HAVE_LUTIMES
6953
    {
6954
        /* Not sure if this can happen */
6955
        PyErr_SetString(
6956
            PyExc_RuntimeError,
6957
            "neither utimensat nor lutimes are supported"
6958
            " on this system");
6959
        return -1;
6960
    }
6961
#endif
6962
0
#endif
6963
6964
0
#ifdef HAVE_LUTIMES
6965
0
    {
6966
0
    UTIME_TO_TIMEVAL;
6967
0
    return lutimes(path, time);
6968
0
    }
6969
0
#endif
6970
0
}
6971
6972
#endif
6973
6974
#ifndef MS_WINDOWS
6975
6976
static int
6977
utime_default(utime_t *ut, const char *path)
6978
0
{
6979
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6980
    if (HAVE_UTIMENSAT_RUNTIME) {
6981
        UTIME_TO_TIMESPEC;
6982
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6983
    } else {
6984
        UTIME_TO_TIMEVAL;
6985
        return utimes(path, time);
6986
    }
6987
#elif defined(HAVE_UTIMENSAT)
6988
0
    UTIME_TO_TIMESPEC;
6989
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6990
#elif defined(HAVE_UTIMES)
6991
    UTIME_TO_TIMEVAL;
6992
    return utimes(path, time);
6993
#elif defined(HAVE_UTIME_H)
6994
    UTIME_TO_UTIMBUF;
6995
    return utime(path, time);
6996
#else
6997
    UTIME_TO_TIME_T;
6998
    return utime(path, time);
6999
#endif
7000
0
}
7001
7002
#endif
7003
7004
static int
7005
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7006
0
{
7007
0
    int result = 0;
7008
0
    PyObject *divmod;
7009
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7010
0
    if (!divmod)
7011
0
        goto exit;
7012
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7013
0
        PyErr_Format(PyExc_TypeError,
7014
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7015
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7016
0
        goto exit;
7017
0
    }
7018
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7019
0
    if ((*s == -1) && PyErr_Occurred())
7020
0
        goto exit;
7021
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7022
0
    if ((*ns == -1) && PyErr_Occurred())
7023
0
        goto exit;
7024
7025
0
    result = 1;
7026
0
exit:
7027
0
    Py_XDECREF(divmod);
7028
0
    return result;
7029
0
}
7030
7031
7032
/*[clinic input]
7033
os.utime
7034
7035
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7036
    times: object = None
7037
    *
7038
    ns: object = NULL
7039
    dir_fd: dir_fd(requires='futimensat') = None
7040
    follow_symlinks: bool=True
7041
7042
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
7043
7044
Set the access and modified time of path.
7045
7046
path may always be specified as a string.
7047
On some platforms, path may also be specified as an open file descriptor.
7048
  If this functionality is unavailable, using it raises an exception.
7049
7050
If times is not None, it must be a tuple (atime, mtime);
7051
    atime and mtime should be expressed as float seconds since the epoch.
7052
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7053
    atime_ns and mtime_ns should be expressed as integer nanoseconds
7054
    since the epoch.
7055
If times is None and ns is unspecified, utime uses the current time.
7056
Specifying tuples for both times and ns is an error.
7057
7058
If dir_fd is not None, it should be a file descriptor open to a directory,
7059
  and path should be relative; path will then be relative to that directory.
7060
If follow_symlinks is False, and the last element of the path is a symbolic
7061
  link, utime will modify the symbolic link itself instead of the file the
7062
  link points to.
7063
It is an error to use dir_fd or follow_symlinks when specifying path
7064
  as an open file descriptor.
7065
dir_fd and follow_symlinks may not be available on your platform.
7066
  If they are unavailable, using them will raise a NotImplementedError.
7067
7068
[clinic start generated code]*/
7069
7070
static PyObject *
7071
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7072
              int dir_fd, int follow_symlinks)
7073
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
7074
0
{
7075
#ifdef MS_WINDOWS
7076
    HANDLE hFile;
7077
    FILETIME atime, mtime;
7078
#else
7079
0
    int result;
7080
0
#endif
7081
7082
0
    utime_t utime;
7083
7084
0
    memset(&utime, 0, sizeof(utime_t));
7085
7086
0
    if (times != Py_None && ns) {
7087
0
        PyErr_SetString(PyExc_ValueError,
7088
0
                     "utime: you may specify either 'times'"
7089
0
                     " or 'ns' but not both");
7090
0
        return NULL;
7091
0
    }
7092
7093
0
    if (times != Py_None) {
7094
0
        time_t a_sec, m_sec;
7095
0
        long a_nsec, m_nsec;
7096
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7097
0
            PyErr_SetString(PyExc_TypeError,
7098
0
                         "utime: 'times' must be either"
7099
0
                         " a tuple of two numbers or None");
7100
0
            return NULL;
7101
0
        }
7102
0
        utime.now = 0;
7103
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7104
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7105
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7106
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7107
0
            return NULL;
7108
0
        }
7109
0
        utime.atime_s = a_sec;
7110
0
        utime.atime_ns = a_nsec;
7111
0
        utime.mtime_s = m_sec;
7112
0
        utime.mtime_ns = m_nsec;
7113
0
    }
7114
0
    else if (ns) {
7115
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7116
0
            PyErr_SetString(PyExc_TypeError,
7117
0
                         "utime: 'ns' must be a tuple of two ints");
7118
0
            return NULL;
7119
0
        }
7120
0
        utime.now = 0;
7121
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7122
0
                                      &utime.atime_s, &utime.atime_ns) ||
7123
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7124
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7125
0
            return NULL;
7126
0
        }
7127
0
    }
7128
0
    else {
7129
        /* times and ns are both None/unspecified. use "now". */
7130
0
        utime.now = 1;
7131
0
    }
7132
7133
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7134
    if (follow_symlinks_specified("utime", follow_symlinks))
7135
        return NULL;
7136
#endif
7137
7138
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7139
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7140
0
        fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
7141
0
        return NULL;
7142
7143
#if !defined(HAVE_UTIMENSAT)
7144
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7145
        PyErr_SetString(PyExc_ValueError,
7146
                     "utime: cannot use dir_fd and follow_symlinks "
7147
                     "together on this platform");
7148
        return NULL;
7149
    }
7150
#endif
7151
7152
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7153
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7154
0
        return NULL;
7155
0
    }
7156
7157
#ifdef MS_WINDOWS
7158
    Py_BEGIN_ALLOW_THREADS
7159
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7160
                        NULL, OPEN_EXISTING,
7161
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7162
    Py_END_ALLOW_THREADS
7163
    if (hFile == INVALID_HANDLE_VALUE) {
7164
        path_error(path);
7165
        return NULL;
7166
    }
7167
7168
    if (utime.now) {
7169
        GetSystemTimeAsFileTime(&mtime);
7170
        atime = mtime;
7171
    }
7172
    else {
7173
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7174
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7175
    }
7176
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7177
        path_error(path);
7178
        CloseHandle(hFile);
7179
        return NULL;
7180
    }
7181
    CloseHandle(hFile);
7182
#else /* MS_WINDOWS */
7183
0
    Py_BEGIN_ALLOW_THREADS
7184
7185
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7186
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7187
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7188
0
    else
7189
0
#endif
7190
7191
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7192
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7193
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7194
7195
0
    } else
7196
0
#endif
7197
7198
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7199
0
    if (path->fd != -1)
7200
0
        result = utime_fd(&utime, path->fd);
7201
0
    else
7202
0
#endif
7203
7204
0
    result = utime_default(&utime, path->narrow);
7205
7206
0
    Py_END_ALLOW_THREADS
7207
7208
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7209
    /* See utime_dir_fd implementation */
7210
    if (result == -1 && errno == ENOSYS) {
7211
        argument_unavailable_error(NULL, "dir_fd");
7212
        return NULL;
7213
    }
7214
#endif
7215
7216
0
    if (result < 0) {
7217
0
        path_error(path);
7218
0
        return NULL;
7219
0
    }
7220
7221
0
#endif /* MS_WINDOWS */
7222
7223
0
    Py_RETURN_NONE;
7224
0
}
7225
7226
/* Process operations */
7227
7228
7229
/*[clinic input]
7230
os._exit
7231
7232
    status: int
7233
7234
Exit to the system with specified status, without normal exit processing.
7235
[clinic start generated code]*/
7236
7237
static PyObject *
7238
os__exit_impl(PyObject *module, int status)
7239
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
7240
0
{
7241
0
    _exit(status);
7242
0
    return NULL; /* Make gcc -Wall happy */
7243
0
}
7244
7245
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7246
#define EXECV_CHAR wchar_t
7247
#else
7248
0
#define EXECV_CHAR char
7249
#endif
7250
7251
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7252
static void
7253
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7254
0
{
7255
0
    Py_ssize_t i;
7256
0
    for (i = 0; i < count; i++)
7257
0
        PyMem_Free(array[i]);
7258
0
    PyMem_Free(array);
7259
0
}
7260
7261
static int
7262
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7263
0
{
7264
0
    Py_ssize_t size;
7265
0
    PyObject *ub;
7266
0
    int result = 0;
7267
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7268
    if (!PyUnicode_FSDecoder(o, &ub))
7269
        return 0;
7270
    *out = PyUnicode_AsWideCharString(ub, &size);
7271
    if (*out)
7272
        result = 1;
7273
#else
7274
0
    if (!PyUnicode_FSConverter(o, &ub))
7275
0
        return 0;
7276
0
    size = PyBytes_GET_SIZE(ub);
7277
0
    *out = PyMem_Malloc(size + 1);
7278
0
    if (*out) {
7279
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7280
0
        result = 1;
7281
0
    } else
7282
0
        PyErr_NoMemory();
7283
0
#endif
7284
0
    Py_DECREF(ub);
7285
0
    return result;
7286
0
}
7287
#endif
7288
7289
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7290
static EXECV_CHAR**
7291
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7292
0
{
7293
0
    Py_ssize_t i, pos, envc;
7294
0
    PyObject *keys=NULL, *vals=NULL;
7295
0
    PyObject *key2, *val2, *keyval;
7296
0
    EXECV_CHAR **envlist;
7297
7298
0
    i = PyMapping_Size(env);
7299
0
    if (i < 0)
7300
0
        return NULL;
7301
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7302
0
    if (envlist == NULL) {
7303
0
        PyErr_NoMemory();
7304
0
        return NULL;
7305
0
    }
7306
0
    envc = 0;
7307
0
    keys = PyMapping_Keys(env);
7308
0
    if (!keys)
7309
0
        goto error;
7310
0
    vals = PyMapping_Values(env);
7311
0
    if (!vals)
7312
0
        goto error;
7313
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7314
0
        PyErr_Format(PyExc_TypeError,
7315
0
                     "env.keys() or env.values() is not a list");
7316
0
        goto error;
7317
0
    }
7318
7319
0
    for (pos = 0; pos < i; pos++) {
7320
0
        PyObject *key = PyList_GetItem(keys, pos);  // Borrowed ref.
7321
0
        if (key == NULL) {
7322
0
            goto error;
7323
0
        }
7324
0
        PyObject *val = PyList_GetItem(vals, pos);  // Borrowed ref.
7325
0
        if (val == NULL) {
7326
0
            goto error;
7327
0
        }
7328
7329
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7330
        if (!PyUnicode_FSDecoder(key, &key2))
7331
            goto error;
7332
        if (!PyUnicode_FSDecoder(val, &val2)) {
7333
            Py_DECREF(key2);
7334
            goto error;
7335
        }
7336
        /* Search from index 1 because on Windows starting '=' is allowed for
7337
           defining hidden environment variables. */
7338
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7339
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7340
        {
7341
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7342
            Py_DECREF(key2);
7343
            Py_DECREF(val2);
7344
            goto error;
7345
        }
7346
        keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7347
#else
7348
0
        if (!PyUnicode_FSConverter(key, &key2))
7349
0
            goto error;
7350
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7351
0
            Py_DECREF(key2);
7352
0
            goto error;
7353
0
        }
7354
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7355
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7356
0
        {
7357
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7358
0
            Py_DECREF(key2);
7359
0
            Py_DECREF(val2);
7360
0
            goto error;
7361
0
        }
7362
0
        keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7363
0
                                             PyBytes_AS_STRING(val2));
7364
0
#endif
7365
0
        Py_DECREF(key2);
7366
0
        Py_DECREF(val2);
7367
0
        if (!keyval)
7368
0
            goto error;
7369
7370
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7371
0
            Py_DECREF(keyval);
7372
0
            goto error;
7373
0
        }
7374
7375
0
        Py_DECREF(keyval);
7376
0
    }
7377
0
    Py_DECREF(vals);
7378
0
    Py_DECREF(keys);
7379
7380
0
    envlist[envc] = 0;
7381
0
    *envc_ptr = envc;
7382
0
    return envlist;
7383
7384
0
error:
7385
0
    Py_XDECREF(keys);
7386
0
    Py_XDECREF(vals);
7387
0
    free_string_array(envlist, envc);
7388
0
    return NULL;
7389
0
}
7390
7391
static EXECV_CHAR**
7392
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7393
0
{
7394
0
    int i;
7395
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7396
0
    if (argvlist == NULL) {
7397
0
        PyErr_NoMemory();
7398
0
        return NULL;
7399
0
    }
7400
0
    for (i = 0; i < *argc; i++) {
7401
0
        PyObject* item = PySequence_ITEM(argv, i);
7402
0
        if (item == NULL)
7403
0
            goto fail;
7404
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7405
0
            Py_DECREF(item);
7406
0
            goto fail;
7407
0
        }
7408
0
        Py_DECREF(item);
7409
0
    }
7410
0
    argvlist[*argc] = NULL;
7411
0
    return argvlist;
7412
0
fail:
7413
0
    *argc = i;
7414
0
    free_string_array(argvlist, *argc);
7415
0
    return NULL;
7416
0
}
7417
7418
#endif
7419
7420
7421
#ifdef HAVE_EXECV
7422
/*[clinic input]
7423
os.execv
7424
7425
    path: path_t
7426
        Path of executable file.
7427
    argv: object
7428
        Tuple or list of strings.
7429
    /
7430
7431
Execute an executable path with arguments, replacing current process.
7432
[clinic start generated code]*/
7433
7434
static PyObject *
7435
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7436
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7437
0
{
7438
0
    EXECV_CHAR **argvlist;
7439
0
    Py_ssize_t argc;
7440
7441
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7442
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7443
0
        PyErr_SetString(PyExc_RuntimeError,
7444
0
                        "exec not supported for isolated subinterpreters");
7445
0
        return NULL;
7446
0
    }
7447
7448
    /* execv has two arguments: (path, argv), where
7449
       argv is a list or tuple of strings. */
7450
7451
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7452
0
        PyErr_SetString(PyExc_TypeError,
7453
0
                        "execv() arg 2 must be a tuple or list");
7454
0
        return NULL;
7455
0
    }
7456
0
    argc = PySequence_Size(argv);
7457
0
    if (argc < 1) {
7458
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7459
0
        return NULL;
7460
0
    }
7461
7462
0
    argvlist = parse_arglist(argv, &argc);
7463
0
    if (argvlist == NULL) {
7464
0
        return NULL;
7465
0
    }
7466
0
    if (!argvlist[0][0]) {
7467
0
        PyErr_SetString(PyExc_ValueError,
7468
0
            "execv() arg 2 first element cannot be empty");
7469
0
        free_string_array(argvlist, argc);
7470
0
        return NULL;
7471
0
    }
7472
7473
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7474
0
        free_string_array(argvlist, argc);
7475
0
        return NULL;
7476
0
    }
7477
7478
0
    _Py_BEGIN_SUPPRESS_IPH
7479
#ifdef HAVE_WEXECV
7480
    _wexecv(path->wide, argvlist);
7481
#else
7482
0
    execv(path->narrow, argvlist);
7483
0
#endif
7484
0
    _Py_END_SUPPRESS_IPH
7485
7486
    /* If we get here it's definitely an error */
7487
7488
0
    posix_error();
7489
0
    free_string_array(argvlist, argc);
7490
0
    return NULL;
7491
0
}
7492
7493
7494
/*[clinic input]
7495
os.execve
7496
7497
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7498
        Path of executable file.
7499
    argv: object
7500
        Tuple or list of strings.
7501
    env: object
7502
        Dictionary of strings mapping to strings.
7503
7504
Execute an executable path with arguments, replacing current process.
7505
[clinic start generated code]*/
7506
7507
static PyObject *
7508
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7509
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7510
0
{
7511
0
    EXECV_CHAR **argvlist = NULL;
7512
0
    EXECV_CHAR **envlist;
7513
0
    Py_ssize_t argc, envc;
7514
7515
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7516
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7517
0
        PyErr_SetString(PyExc_RuntimeError,
7518
0
                        "exec not supported for isolated subinterpreters");
7519
0
        return NULL;
7520
0
    }
7521
7522
    /* execve has three arguments: (path, argv, env), where
7523
       argv is a list or tuple of strings and env is a dictionary
7524
       like posix.environ. */
7525
7526
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7527
0
        PyErr_SetString(PyExc_TypeError,
7528
0
                        "execve: argv must be a tuple or list");
7529
0
        goto fail_0;
7530
0
    }
7531
0
    argc = PySequence_Size(argv);
7532
0
    if (argc < 1) {
7533
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7534
0
        return NULL;
7535
0
    }
7536
7537
0
    if (!PyMapping_Check(env)) {
7538
0
        PyErr_SetString(PyExc_TypeError,
7539
0
                        "execve: environment must be a mapping object");
7540
0
        goto fail_0;
7541
0
    }
7542
7543
0
    argvlist = parse_arglist(argv, &argc);
7544
0
    if (argvlist == NULL) {
7545
0
        goto fail_0;
7546
0
    }
7547
0
    if (!argvlist[0][0]) {
7548
0
        PyErr_SetString(PyExc_ValueError,
7549
0
            "execve: argv first element cannot be empty");
7550
0
        goto fail_0;
7551
0
    }
7552
7553
0
    envlist = parse_envlist(env, &envc);
7554
0
    if (envlist == NULL)
7555
0
        goto fail_0;
7556
7557
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7558
0
        goto fail_1;
7559
0
    }
7560
7561
0
    _Py_BEGIN_SUPPRESS_IPH
7562
0
#ifdef HAVE_FEXECVE
7563
0
    if (path->fd > -1)
7564
0
        fexecve(path->fd, argvlist, envlist);
7565
0
    else
7566
0
#endif
7567
#ifdef HAVE_WEXECV
7568
        _wexecve(path->wide, argvlist, envlist);
7569
#else
7570
0
        execve(path->narrow, argvlist, envlist);
7571
0
#endif
7572
0
    _Py_END_SUPPRESS_IPH
7573
7574
    /* If we get here it's definitely an error */
7575
7576
0
    posix_path_error(path);
7577
0
  fail_1:
7578
0
    free_string_array(envlist, envc);
7579
0
  fail_0:
7580
0
    if (argvlist)
7581
0
        free_string_array(argvlist, argc);
7582
0
    return NULL;
7583
0
}
7584
7585
#endif /* HAVE_EXECV */
7586
7587
#ifdef HAVE_POSIX_SPAWN
7588
7589
enum posix_spawn_file_actions_identifier {
7590
    POSIX_SPAWN_OPEN,
7591
    POSIX_SPAWN_CLOSE,
7592
    POSIX_SPAWN_DUP2
7593
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7594
    ,POSIX_SPAWN_CLOSEFROM
7595
#endif
7596
};
7597
7598
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7599
static int
7600
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7601
#endif
7602
7603
static int
7604
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7605
                        int resetids, int setsid, PyObject *setsigmask,
7606
                        PyObject *setsigdef, PyObject *scheduler,
7607
                        posix_spawnattr_t *attrp)
7608
0
{
7609
0
    long all_flags = 0;
7610
7611
0
    errno = posix_spawnattr_init(attrp);
7612
0
    if (errno) {
7613
0
        posix_error();
7614
0
        return -1;
7615
0
    }
7616
7617
0
    if (setpgroup) {
7618
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7619
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7620
0
            goto fail;
7621
0
        }
7622
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7623
0
        if (errno) {
7624
0
            posix_error();
7625
0
            goto fail;
7626
0
        }
7627
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7628
0
    }
7629
7630
0
    if (resetids) {
7631
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7632
0
    }
7633
7634
0
    if (setsid) {
7635
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7636
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7637
#endif
7638
0
#ifdef POSIX_SPAWN_SETSID
7639
0
        all_flags |= POSIX_SPAWN_SETSID;
7640
#elif defined(POSIX_SPAWN_SETSID_NP)
7641
        all_flags |= POSIX_SPAWN_SETSID_NP;
7642
#else
7643
        argument_unavailable_error(func_name, "setsid");
7644
        return -1;
7645
#endif
7646
7647
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7648
        } else {
7649
            argument_unavailable_error(func_name, "setsid");
7650
            return -1;
7651
        }
7652
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7653
7654
0
    }
7655
7656
0
#ifdef HAVE_SIGSET_T
7657
0
   if (setsigmask) {
7658
0
        sigset_t set;
7659
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7660
0
            goto fail;
7661
0
        }
7662
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7663
0
        if (errno) {
7664
0
            posix_error();
7665
0
            goto fail;
7666
0
        }
7667
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7668
0
    }
7669
7670
0
    if (setsigdef) {
7671
0
        sigset_t set;
7672
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7673
0
            goto fail;
7674
0
        }
7675
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7676
0
        if (errno) {
7677
0
            posix_error();
7678
0
            goto fail;
7679
0
        }
7680
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7681
0
    }
7682
#else
7683
    if (setsigmask || setsigdef) {
7684
        PyErr_SetString(PyExc_NotImplementedError,
7685
                        "sigset is not supported on this platform");
7686
        goto fail;
7687
    }
7688
#endif
7689
7690
0
    if (scheduler) {
7691
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7692
0
        PyObject *py_schedpolicy;
7693
0
        PyObject *schedparam_obj;
7694
0
        struct sched_param schedparam;
7695
7696
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7697
0
                        ";A scheduler tuple must have two elements",
7698
0
                        &py_schedpolicy, &schedparam_obj)) {
7699
0
            goto fail;
7700
0
        }
7701
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7702
0
            goto fail;
7703
0
        }
7704
0
        if (py_schedpolicy != Py_None) {
7705
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7706
7707
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7708
0
                goto fail;
7709
0
            }
7710
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7711
0
            if (errno) {
7712
0
                posix_error();
7713
0
                goto fail;
7714
0
            }
7715
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7716
0
        }
7717
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7718
0
        if (errno) {
7719
0
            posix_error();
7720
0
            goto fail;
7721
0
        }
7722
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7723
#else
7724
        PyErr_SetString(PyExc_NotImplementedError,
7725
                "The scheduler option is not supported in this system.");
7726
        goto fail;
7727
#endif
7728
0
    }
7729
7730
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7731
0
    if (errno) {
7732
0
        posix_error();
7733
0
        goto fail;
7734
0
    }
7735
7736
0
    return 0;
7737
7738
0
fail:
7739
0
    (void)posix_spawnattr_destroy(attrp);
7740
0
    return -1;
7741
0
}
7742
7743
static int
7744
parse_file_actions(PyObject *file_actions,
7745
                   posix_spawn_file_actions_t *file_actionsp,
7746
                   PyObject *temp_buffer)
7747
0
{
7748
0
    PyObject *seq;
7749
0
    PyObject *file_action = NULL;
7750
0
    PyObject *tag_obj;
7751
7752
0
    seq = PySequence_Fast(file_actions,
7753
0
                          "file_actions must be a sequence or None");
7754
0
    if (seq == NULL) {
7755
0
        return -1;
7756
0
    }
7757
7758
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7759
0
    if (errno) {
7760
0
        posix_error();
7761
0
        Py_DECREF(seq);
7762
0
        return -1;
7763
0
    }
7764
7765
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7766
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7767
0
        Py_INCREF(file_action);
7768
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7769
0
            PyErr_SetString(PyExc_TypeError,
7770
0
                "Each file_actions element must be a non-empty tuple");
7771
0
            goto fail;
7772
0
        }
7773
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7774
0
        if (tag == -1 && PyErr_Occurred()) {
7775
0
            goto fail;
7776
0
        }
7777
7778
        /* Populate the file_actions object */
7779
0
        switch (tag) {
7780
0
            case POSIX_SPAWN_OPEN: {
7781
0
                int fd, oflag;
7782
0
                PyObject *path;
7783
0
                unsigned long mode;
7784
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7785
0
                        ";A open file_action tuple must have 5 elements",
7786
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7787
0
                        &oflag, &mode))
7788
0
                {
7789
0
                    goto fail;
7790
0
                }
7791
0
                if (PyList_Append(temp_buffer, path)) {
7792
0
                    Py_DECREF(path);
7793
0
                    goto fail;
7794
0
                }
7795
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7796
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7797
0
                if (errno) {
7798
0
                    posix_error();
7799
0
                    Py_DECREF(path);
7800
0
                    goto fail;
7801
0
                }
7802
0
                Py_DECREF(path);
7803
0
                break;
7804
0
            }
7805
0
            case POSIX_SPAWN_CLOSE: {
7806
0
                int fd;
7807
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7808
0
                        ";A close file_action tuple must have 2 elements",
7809
0
                        &tag_obj, &fd))
7810
0
                {
7811
0
                    goto fail;
7812
0
                }
7813
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7814
0
                if (errno) {
7815
0
                    posix_error();
7816
0
                    goto fail;
7817
0
                }
7818
0
                break;
7819
0
            }
7820
0
            case POSIX_SPAWN_DUP2: {
7821
0
                int fd1, fd2;
7822
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7823
0
                        ";A dup2 file_action tuple must have 3 elements",
7824
0
                        &tag_obj, &fd1, &fd2))
7825
0
                {
7826
0
                    goto fail;
7827
0
                }
7828
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7829
0
                                                         fd1, fd2);
7830
0
                if (errno) {
7831
0
                    posix_error();
7832
0
                    goto fail;
7833
0
                }
7834
0
                break;
7835
0
            }
7836
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7837
            case POSIX_SPAWN_CLOSEFROM: {
7838
                int fd;
7839
                if (!PyArg_ParseTuple(file_action, "Oi"
7840
                        ";A closefrom file_action tuple must have 2 elements",
7841
                        &tag_obj, &fd))
7842
                {
7843
                    goto fail;
7844
                }
7845
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7846
                                                                 fd);
7847
                if (errno) {
7848
                    posix_error();
7849
                    goto fail;
7850
                }
7851
                break;
7852
            }
7853
#endif
7854
0
            default: {
7855
0
                PyErr_SetString(PyExc_TypeError,
7856
0
                                "Unknown file_actions identifier");
7857
0
                goto fail;
7858
0
            }
7859
0
        }
7860
0
        Py_DECREF(file_action);
7861
0
    }
7862
7863
0
    Py_DECREF(seq);
7864
0
    return 0;
7865
7866
0
fail:
7867
0
    Py_DECREF(seq);
7868
0
    Py_DECREF(file_action);
7869
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7870
0
    return -1;
7871
0
}
7872
7873
7874
static PyObject *
7875
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7876
               PyObject *env, PyObject *file_actions,
7877
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7878
               PyObject *setsigdef, PyObject *scheduler)
7879
0
{
7880
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7881
0
    EXECV_CHAR **argvlist = NULL;
7882
0
    EXECV_CHAR **envlist = NULL;
7883
0
    posix_spawn_file_actions_t file_actions_buf;
7884
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7885
0
    posix_spawnattr_t attr;
7886
0
    posix_spawnattr_t *attrp = NULL;
7887
0
    Py_ssize_t argc, envc;
7888
0
    PyObject *result = NULL;
7889
0
    PyObject *temp_buffer = NULL;
7890
0
    pid_t pid;
7891
0
    int err_code;
7892
7893
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7894
       argv is a list or tuple of strings and env is a dictionary
7895
       like posix.environ. */
7896
7897
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7898
0
        PyErr_Format(PyExc_TypeError,
7899
0
                     "%s: argv must be a tuple or list", func_name);
7900
0
        goto exit;
7901
0
    }
7902
0
    argc = PySequence_Size(argv);
7903
0
    if (argc < 1) {
7904
0
        PyErr_Format(PyExc_ValueError,
7905
0
                     "%s: argv must not be empty", func_name);
7906
0
        return NULL;
7907
0
    }
7908
7909
0
    if (!PyMapping_Check(env) && env != Py_None) {
7910
0
        PyErr_Format(PyExc_TypeError,
7911
0
                     "%s: environment must be a mapping object or None", func_name);
7912
0
        goto exit;
7913
0
    }
7914
7915
0
    argvlist = parse_arglist(argv, &argc);
7916
0
    if (argvlist == NULL) {
7917
0
        goto exit;
7918
0
    }
7919
0
    if (!argvlist[0][0]) {
7920
0
        PyErr_Format(PyExc_ValueError,
7921
0
                     "%s: argv first element cannot be empty", func_name);
7922
0
        goto exit;
7923
0
    }
7924
7925
#ifdef USE_DARWIN_NS_GET_ENVIRON
7926
    // There is no environ global in this situation.
7927
    char **environ = NULL;
7928
#endif
7929
7930
0
    if (env == Py_None) {
7931
#ifdef USE_DARWIN_NS_GET_ENVIRON
7932
        environ = *_NSGetEnviron();
7933
#endif
7934
0
        envlist = environ;
7935
0
    } else {
7936
0
        envlist = parse_envlist(env, &envc);
7937
0
        if (envlist == NULL) {
7938
0
            goto exit;
7939
0
        }
7940
0
    }
7941
7942
0
    if (file_actions != NULL && file_actions != Py_None) {
7943
        /* There is a bug in old versions of glibc that makes some of the
7944
         * helper functions for manipulating file actions not copy the provided
7945
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7946
         * copy the value of path for some old versions of glibc (<2.20).
7947
         * The use of temp_buffer here is a workaround that keeps the
7948
         * python objects that own the buffers alive until posix_spawn gets called.
7949
         * Check https://bugs.python.org/issue33630 and
7950
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7951
0
        temp_buffer = PyList_New(0);
7952
0
        if (!temp_buffer) {
7953
0
            goto exit;
7954
0
        }
7955
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7956
0
            goto exit;
7957
0
        }
7958
0
        file_actionsp = &file_actions_buf;
7959
0
    }
7960
7961
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7962
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7963
0
        goto exit;
7964
0
    }
7965
0
    attrp = &attr;
7966
7967
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7968
0
        goto exit;
7969
0
    }
7970
7971
0
    _Py_BEGIN_SUPPRESS_IPH
7972
0
#ifdef HAVE_POSIX_SPAWNP
7973
0
    if (use_posix_spawnp) {
7974
0
        err_code = posix_spawnp(&pid, path->narrow,
7975
0
                                file_actionsp, attrp, argvlist, envlist);
7976
0
    }
7977
0
    else
7978
0
#endif /* HAVE_POSIX_SPAWNP */
7979
0
    {
7980
0
        err_code = posix_spawn(&pid, path->narrow,
7981
0
                               file_actionsp, attrp, argvlist, envlist);
7982
0
    }
7983
0
    _Py_END_SUPPRESS_IPH
7984
7985
0
    if (err_code) {
7986
0
        errno = err_code;
7987
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
7988
0
        goto exit;
7989
0
    }
7990
#ifdef _Py_MEMORY_SANITIZER
7991
    __msan_unpoison(&pid, sizeof(pid));
7992
#endif
7993
0
    result = PyLong_FromPid(pid);
7994
7995
0
exit:
7996
0
    if (file_actionsp) {
7997
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
7998
0
    }
7999
0
    if (attrp) {
8000
0
        (void)posix_spawnattr_destroy(attrp);
8001
0
    }
8002
0
    if (envlist && envlist != environ) {
8003
0
        free_string_array(envlist, envc);
8004
0
    }
8005
0
    if (argvlist) {
8006
0
        free_string_array(argvlist, argc);
8007
0
    }
8008
0
    Py_XDECREF(temp_buffer);
8009
0
    return result;
8010
0
}
8011
8012
8013
/*[clinic input]
8014
8015
os.posix_spawn
8016
    path: path_t
8017
        Path of executable file.
8018
    argv: object
8019
        Tuple or list of strings.
8020
    env: object
8021
        Dictionary of strings mapping to strings.
8022
    /
8023
    *
8024
    file_actions: object(c_default='NULL') = ()
8025
        A sequence of file action tuples.
8026
    setpgroup: object = NULL
8027
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8028
    resetids: bool = False
8029
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8030
    setsid: bool = False
8031
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8032
    setsigmask: object(c_default='NULL') = ()
8033
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8034
    setsigdef: object(c_default='NULL') = ()
8035
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8036
    scheduler: object = NULL
8037
        A tuple with the scheduler policy (optional) and parameters.
8038
8039
Execute the program specified by path in a new process.
8040
[clinic start generated code]*/
8041
8042
static PyObject *
8043
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8044
                    PyObject *env, PyObject *file_actions,
8045
                    PyObject *setpgroup, int resetids, int setsid,
8046
                    PyObject *setsigmask, PyObject *setsigdef,
8047
                    PyObject *scheduler)
8048
/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
8049
0
{
8050
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8051
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8052
0
                          scheduler);
8053
0
}
8054
 #endif /* HAVE_POSIX_SPAWN */
8055
8056
8057
8058
#ifdef HAVE_POSIX_SPAWNP
8059
/*[clinic input]
8060
8061
os.posix_spawnp
8062
    path: path_t
8063
        Path of executable file.
8064
    argv: object
8065
        Tuple or list of strings.
8066
    env: object
8067
        Dictionary of strings mapping to strings.
8068
    /
8069
    *
8070
    file_actions: object(c_default='NULL') = ()
8071
        A sequence of file action tuples.
8072
    setpgroup: object = NULL
8073
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8074
    resetids: bool = False
8075
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8076
    setsid: bool = False
8077
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
8078
    setsigmask: object(c_default='NULL') = ()
8079
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8080
    setsigdef: object(c_default='NULL') = ()
8081
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8082
    scheduler: object = NULL
8083
        A tuple with the scheduler policy (optional) and parameters.
8084
8085
Execute the program specified by path in a new process.
8086
[clinic start generated code]*/
8087
8088
static PyObject *
8089
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8090
                     PyObject *env, PyObject *file_actions,
8091
                     PyObject *setpgroup, int resetids, int setsid,
8092
                     PyObject *setsigmask, PyObject *setsigdef,
8093
                     PyObject *scheduler)
8094
/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
8095
0
{
8096
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8097
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8098
0
                          scheduler);
8099
0
}
8100
#endif /* HAVE_POSIX_SPAWNP */
8101
8102
#ifdef HAVE_RTPSPAWN
8103
static intptr_t
8104
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8105
               const char  *envp[])
8106
{
8107
     RTP_ID rtpid;
8108
     int status;
8109
     pid_t res;
8110
     int async_err = 0;
8111
8112
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8113
        uStackSize=0 cannot be used, the default stack size is too small for
8114
        Python. */
8115
     if (envp) {
8116
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8117
                          100, 0x1000000, 0, VX_FP_TASK);
8118
     }
8119
     else {
8120
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8121
                          100, 0x1000000, 0, VX_FP_TASK);
8122
     }
8123
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8124
         do {
8125
             res = waitpid((pid_t)rtpid, &status, 0);
8126
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8127
8128
         if (res < 0)
8129
             return RTP_ID_ERROR;
8130
         return ((intptr_t)status);
8131
     }
8132
     return ((intptr_t)rtpid);
8133
}
8134
#endif
8135
8136
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8137
/*[clinic input]
8138
os.spawnv
8139
8140
    mode: int
8141
        Mode of process creation.
8142
    path: path_t
8143
        Path of executable file.
8144
    argv: object
8145
        Tuple or list of strings.
8146
    /
8147
8148
Execute the program specified by path in a new process.
8149
[clinic start generated code]*/
8150
8151
static PyObject *
8152
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8153
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8154
{
8155
    EXECV_CHAR **argvlist;
8156
    int i;
8157
    Py_ssize_t argc;
8158
    intptr_t spawnval;
8159
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8160
8161
    /* spawnv has three arguments: (mode, path, argv), where
8162
       argv is a list or tuple of strings. */
8163
8164
    if (PyList_Check(argv)) {
8165
        argc = PyList_Size(argv);
8166
        getitem = PyList_GetItem;
8167
    }
8168
    else if (PyTuple_Check(argv)) {
8169
        argc = PyTuple_Size(argv);
8170
        getitem = PyTuple_GetItem;
8171
    }
8172
    else {
8173
        PyErr_SetString(PyExc_TypeError,
8174
                        "spawnv() arg 2 must be a tuple or list");
8175
        return NULL;
8176
    }
8177
    if (argc == 0) {
8178
        PyErr_SetString(PyExc_ValueError,
8179
            "spawnv() arg 2 cannot be empty");
8180
        return NULL;
8181
    }
8182
8183
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8184
    if (argvlist == NULL) {
8185
        return PyErr_NoMemory();
8186
    }
8187
    for (i = 0; i < argc; i++) {
8188
        if (!fsconvert_strdup((*getitem)(argv, i),
8189
                              &argvlist[i])) {
8190
            free_string_array(argvlist, i);
8191
            PyErr_SetString(
8192
                PyExc_TypeError,
8193
                "spawnv() arg 2 must contain only strings");
8194
            return NULL;
8195
        }
8196
        if (i == 0 && !argvlist[0][0]) {
8197
            free_string_array(argvlist, i + 1);
8198
            PyErr_SetString(
8199
                PyExc_ValueError,
8200
                "spawnv() arg 2 first element cannot be empty");
8201
            return NULL;
8202
        }
8203
    }
8204
    argvlist[argc] = NULL;
8205
8206
#if !defined(HAVE_RTPSPAWN)
8207
    if (mode == _OLD_P_OVERLAY)
8208
        mode = _P_OVERLAY;
8209
#endif
8210
8211
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8212
                    Py_None) < 0) {
8213
        free_string_array(argvlist, argc);
8214
        return NULL;
8215
    }
8216
8217
    Py_BEGIN_ALLOW_THREADS
8218
    _Py_BEGIN_SUPPRESS_IPH
8219
#ifdef HAVE_WSPAWNV
8220
    spawnval = _wspawnv(mode, path->wide, argvlist);
8221
#elif defined(HAVE_RTPSPAWN)
8222
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8223
#else
8224
    spawnval = _spawnv(mode, path->narrow, argvlist);
8225
#endif
8226
    _Py_END_SUPPRESS_IPH
8227
    Py_END_ALLOW_THREADS
8228
8229
    int saved_errno = errno;
8230
    free_string_array(argvlist, argc);
8231
8232
    if (spawnval == -1) {
8233
        errno = saved_errno;
8234
        posix_error();
8235
        return NULL;
8236
    }
8237
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8238
}
8239
8240
/*[clinic input]
8241
os.spawnve
8242
8243
    mode: int
8244
        Mode of process creation.
8245
    path: path_t
8246
        Path of executable file.
8247
    argv: object
8248
        Tuple or list of strings.
8249
    env: object
8250
        Dictionary of strings mapping to strings.
8251
    /
8252
8253
Execute the program specified by path in a new process.
8254
[clinic start generated code]*/
8255
8256
static PyObject *
8257
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8258
                PyObject *env)
8259
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8260
{
8261
    EXECV_CHAR **argvlist;
8262
    EXECV_CHAR **envlist;
8263
    PyObject *res = NULL;
8264
    Py_ssize_t argc, i, envc;
8265
    intptr_t spawnval;
8266
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
8267
    Py_ssize_t lastarg = 0;
8268
8269
    /* spawnve has four arguments: (mode, path, argv, env), where
8270
       argv is a list or tuple of strings and env is a dictionary
8271
       like posix.environ. */
8272
8273
    if (PyList_Check(argv)) {
8274
        argc = PyList_Size(argv);
8275
        getitem = PyList_GetItem;
8276
    }
8277
    else if (PyTuple_Check(argv)) {
8278
        argc = PyTuple_Size(argv);
8279
        getitem = PyTuple_GetItem;
8280
    }
8281
    else {
8282
        PyErr_SetString(PyExc_TypeError,
8283
                        "spawnve() arg 2 must be a tuple or list");
8284
        goto fail_0;
8285
    }
8286
    if (argc == 0) {
8287
        PyErr_SetString(PyExc_ValueError,
8288
            "spawnve() arg 2 cannot be empty");
8289
        goto fail_0;
8290
    }
8291
    if (!PyMapping_Check(env)) {
8292
        PyErr_SetString(PyExc_TypeError,
8293
                        "spawnve() arg 3 must be a mapping object");
8294
        goto fail_0;
8295
    }
8296
8297
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8298
    if (argvlist == NULL) {
8299
        PyErr_NoMemory();
8300
        goto fail_0;
8301
    }
8302
    for (i = 0; i < argc; i++) {
8303
        if (!fsconvert_strdup((*getitem)(argv, i),
8304
                              &argvlist[i]))
8305
        {
8306
            lastarg = i;
8307
            goto fail_1;
8308
        }
8309
        if (i == 0 && !argvlist[0][0]) {
8310
            lastarg = i + 1;
8311
            PyErr_SetString(
8312
                PyExc_ValueError,
8313
                "spawnv() arg 2 first element cannot be empty");
8314
            goto fail_1;
8315
        }
8316
    }
8317
    lastarg = argc;
8318
    argvlist[argc] = NULL;
8319
8320
    envlist = parse_envlist(env, &envc);
8321
    if (envlist == NULL)
8322
        goto fail_1;
8323
8324
#if !defined(HAVE_RTPSPAWN)
8325
    if (mode == _OLD_P_OVERLAY)
8326
        mode = _P_OVERLAY;
8327
#endif
8328
8329
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8330
        goto fail_2;
8331
    }
8332
8333
    Py_BEGIN_ALLOW_THREADS
8334
    _Py_BEGIN_SUPPRESS_IPH
8335
#ifdef HAVE_WSPAWNV
8336
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8337
#elif defined(HAVE_RTPSPAWN)
8338
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8339
                           (const char **)envlist);
8340
#else
8341
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8342
#endif
8343
    _Py_END_SUPPRESS_IPH
8344
    Py_END_ALLOW_THREADS
8345
8346
    if (spawnval == -1)
8347
        (void) posix_error();
8348
    else
8349
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8350
8351
  fail_2:
8352
    while (--envc >= 0) {
8353
        PyMem_Free(envlist[envc]);
8354
    }
8355
    PyMem_Free(envlist);
8356
  fail_1:
8357
    free_string_array(argvlist, lastarg);
8358
  fail_0:
8359
    return res;
8360
}
8361
8362
#endif /* HAVE_SPAWNV */
8363
8364
#ifdef HAVE_FORK
8365
8366
/* Helper function to validate arguments.
8367
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8368
   If obj is non-NULL it must be callable.  */
8369
static int
8370
check_null_or_callable(PyObject *obj, const char* obj_name)
8371
24
{
8372
24
    if (obj && !PyCallable_Check(obj)) {
8373
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8374
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8375
0
        return -1;
8376
0
    }
8377
24
    return 0;
8378
24
}
8379
8380
/*[clinic input]
8381
os.register_at_fork
8382
8383
    *
8384
    before: object=NULL
8385
        A callable to be called in the parent before the fork() syscall.
8386
    after_in_child: object=NULL
8387
        A callable to be called in the child after fork().
8388
    after_in_parent: object=NULL
8389
        A callable to be called in the parent after fork().
8390
8391
Register callables to be called when forking a new process.
8392
8393
'before' callbacks are called in reverse order.
8394
'after_in_child' and 'after_in_parent' callbacks are called in order.
8395
8396
[clinic start generated code]*/
8397
8398
static PyObject *
8399
os_register_at_fork_impl(PyObject *module, PyObject *before,
8400
                         PyObject *after_in_child, PyObject *after_in_parent)
8401
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8402
8
{
8403
8
    PyInterpreterState *interp;
8404
8405
8
    if (!before && !after_in_child && !after_in_parent) {
8406
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8407
0
        return NULL;
8408
0
    }
8409
8
    if (check_null_or_callable(before, "before") ||
8410
8
        check_null_or_callable(after_in_child, "after_in_child") ||
8411
8
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8412
0
        return NULL;
8413
0
    }
8414
8
    interp = _PyInterpreterState_GET();
8415
8416
8
    if (register_at_forker(&interp->before_forkers, before)) {
8417
0
        return NULL;
8418
0
    }
8419
8
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8420
0
        return NULL;
8421
0
    }
8422
8
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8423
0
        return NULL;
8424
0
    }
8425
8
    Py_RETURN_NONE;
8426
8
}
8427
#endif /* HAVE_FORK */
8428
8429
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8430
// Common code to raise a warning if we detect there is more than one thread
8431
// running in the process. Best effort, silent if unable to count threads.
8432
// Constraint: Quick. Never overcounts. Never leaves an error set.
8433
//
8434
// This MUST only be called from the parent process after
8435
// PyOS_AfterFork_Parent().
8436
static int
8437
warn_about_fork_with_threads(
8438
    const char* name,  // Name of the API to use in the warning message.
8439
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8440
)
8441
0
{
8442
    // It's not safe to issue the warning while the world is stopped, because
8443
    // other threads might be holding locks that we need, which would deadlock.
8444
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8445
8446
0
    Py_ssize_t num_python_threads = num_os_threads;
8447
0
    if (num_python_threads <= 0) {
8448
        // Fall back to just the number our threading module knows about.
8449
        // An incomplete view of the world, but better than nothing.
8450
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8451
0
        if (!threading) {
8452
0
            PyErr_Clear();
8453
0
            return 0;
8454
0
        }
8455
0
        PyObject *threading_active =
8456
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8457
0
        if (!threading_active) {
8458
0
            PyErr_Clear();
8459
0
            Py_DECREF(threading);
8460
0
            return 0;
8461
0
        }
8462
0
        PyObject *threading_limbo =
8463
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8464
0
        if (!threading_limbo) {
8465
0
            PyErr_Clear();
8466
0
            Py_DECREF(threading);
8467
0
            Py_DECREF(threading_active);
8468
0
            return 0;
8469
0
        }
8470
0
        Py_DECREF(threading);
8471
        // Duplicating what threading.active_count() does but without holding
8472
        // threading._active_limbo_lock so our count could be inaccurate if
8473
        // these dicts are mid-update from another thread.  Not a big deal.
8474
        // Worst case if someone replaced threading._active or threading._limbo
8475
        // with non-dicts, we get -1 from *Length() below and undercount.
8476
        // Nobody should, but we're best effort so we clear errors and move on.
8477
0
        num_python_threads = (PyMapping_Length(threading_active)
8478
0
                              + PyMapping_Length(threading_limbo));
8479
0
        PyErr_Clear();
8480
0
        Py_DECREF(threading_active);
8481
0
        Py_DECREF(threading_limbo);
8482
0
    }
8483
0
    if (num_python_threads > 1) {
8484
0
        return PyErr_WarnFormat(
8485
0
                PyExc_DeprecationWarning, 1,
8486
0
#ifdef HAVE_GETPID
8487
0
                "This process (pid=%d) is multi-threaded, "
8488
#else
8489
                "This process is multi-threaded, "
8490
#endif
8491
0
                "use of %s() may lead to deadlocks in the child.",
8492
0
#ifdef HAVE_GETPID
8493
0
                getpid(),
8494
0
#endif
8495
0
                name);
8496
0
    }
8497
0
    return 0;
8498
0
}
8499
8500
// If this returns <= 0, we were unable to successfully use any OS APIs.
8501
// Returns a positive number of threads otherwise.
8502
static Py_ssize_t get_number_of_os_threads(void)
8503
0
{
8504
    // TODO: Consider making an `os` module API to return the current number
8505
    // of threads in the process. That'd presumably use this platform code but
8506
    // raise an error rather than using the inaccurate fallback.
8507
0
    Py_ssize_t num_python_threads = 0;
8508
#if defined(__APPLE__) && defined(HAVE_GETPID)
8509
    mach_port_t macos_self = mach_task_self();
8510
    mach_port_t macos_task;
8511
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8512
        thread_array_t macos_threads;
8513
        mach_msg_type_number_t macos_n_threads;
8514
        if (task_threads(macos_task, &macos_threads,
8515
                         &macos_n_threads) == KERN_SUCCESS) {
8516
            num_python_threads = macos_n_threads;
8517
        }
8518
    }
8519
#elif defined(__linux__)
8520
    // Linux /proc/self/stat 20th field is the number of threads.
8521
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8522
0
    if (proc_stat) {
8523
0
        size_t n;
8524
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8525
        // observed on the author's workstation.
8526
0
        char stat_line[160];
8527
0
        n = fread(&stat_line, 1, 159, proc_stat);
8528
0
        stat_line[n] = '\0';
8529
0
        fclose(proc_stat);
8530
8531
0
        char *saveptr = NULL;
8532
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8533
0
        unsigned int idx;
8534
0
        for (idx = 19; idx && field; --idx) {
8535
0
            field = strtok_r(NULL, " ", &saveptr);
8536
0
        }
8537
0
        if (idx == 0 && field) {  // found the 20th field
8538
0
            num_python_threads = atoi(field);  // 0 on error
8539
0
        }
8540
0
    }
8541
0
#endif
8542
0
    return num_python_threads;
8543
0
}
8544
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8545
8546
#ifdef HAVE_FORK1
8547
/*[clinic input]
8548
os.fork1
8549
8550
Fork a child process with a single multiplexed (i.e., not bound) thread.
8551
8552
Return 0 to child process and PID of child to parent process.
8553
[clinic start generated code]*/
8554
8555
static PyObject *
8556
os_fork1_impl(PyObject *module)
8557
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8558
{
8559
    pid_t pid;
8560
8561
    PyInterpreterState *interp = _PyInterpreterState_GET();
8562
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8563
        PyErr_SetString(PyExc_PythonFinalizationError,
8564
                        "can't fork at interpreter shutdown");
8565
        return NULL;
8566
    }
8567
    if (!_Py_IsMainInterpreter(interp)) {
8568
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8569
        return NULL;
8570
    }
8571
    PyOS_BeforeFork();
8572
    pid = fork1();
8573
    int saved_errno = errno;
8574
    if (pid == 0) {
8575
        /* child: this clobbers and resets the import lock. */
8576
        PyOS_AfterFork_Child();
8577
    } else {
8578
        // Called before AfterFork_Parent in case those hooks start threads.
8579
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8580
        /* parent: release the import lock. */
8581
        PyOS_AfterFork_Parent();
8582
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8583
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8584
            return NULL;
8585
        }
8586
    }
8587
    if (pid == -1) {
8588
        errno = saved_errno;
8589
        return posix_error();
8590
    }
8591
    return PyLong_FromPid(pid);
8592
}
8593
#endif /* HAVE_FORK1 */
8594
8595
8596
#ifdef HAVE_FORK
8597
/*[clinic input]
8598
os.fork
8599
8600
Fork a child process.
8601
8602
Return 0 to child process and PID of child to parent process.
8603
[clinic start generated code]*/
8604
8605
static PyObject *
8606
os_fork_impl(PyObject *module)
8607
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8608
0
{
8609
0
    pid_t pid;
8610
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8611
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8612
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8613
0
                        "can't fork at interpreter shutdown");
8614
0
        return NULL;
8615
0
    }
8616
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8617
0
        PyErr_SetString(PyExc_RuntimeError,
8618
0
                        "fork not supported for isolated subinterpreters");
8619
0
        return NULL;
8620
0
    }
8621
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8622
0
        return NULL;
8623
0
    }
8624
0
    PyOS_BeforeFork();
8625
0
    pid = fork();
8626
0
    int saved_errno = errno;
8627
0
    if (pid == 0) {
8628
        /* child: this clobbers and resets the import lock. */
8629
0
        PyOS_AfterFork_Child();
8630
0
    } else {
8631
        // Called before AfterFork_Parent in case those hooks start threads.
8632
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8633
        /* parent: release the import lock. */
8634
0
        PyOS_AfterFork_Parent();
8635
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8636
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8637
0
            return NULL;
8638
0
    }
8639
0
    if (pid == -1) {
8640
0
        errno = saved_errno;
8641
0
        return posix_error();
8642
0
    }
8643
0
    return PyLong_FromPid(pid);
8644
0
}
8645
#endif /* HAVE_FORK */
8646
8647
8648
#ifdef HAVE_SCHED_H
8649
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8650
/*[clinic input]
8651
os.sched_get_priority_max
8652
8653
    policy: int
8654
8655
Get the maximum scheduling priority for policy.
8656
[clinic start generated code]*/
8657
8658
static PyObject *
8659
os_sched_get_priority_max_impl(PyObject *module, int policy)
8660
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8661
0
{
8662
    /* make sure that errno is cleared before the call */
8663
0
    errno = 0;
8664
0
    int max = sched_get_priority_max(policy);
8665
0
    if (max == -1 && errno)
8666
0
        return posix_error();
8667
0
    return PyLong_FromLong(max);
8668
0
}
8669
8670
8671
/*[clinic input]
8672
os.sched_get_priority_min
8673
8674
    policy: int
8675
8676
Get the minimum scheduling priority for policy.
8677
[clinic start generated code]*/
8678
8679
static PyObject *
8680
os_sched_get_priority_min_impl(PyObject *module, int policy)
8681
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8682
0
{
8683
    /* make sure that errno is cleared before the call */
8684
0
    errno = 0;
8685
0
    int min = sched_get_priority_min(policy);
8686
0
    if (min == -1 && errno)
8687
0
        return posix_error();
8688
0
    return PyLong_FromLong(min);
8689
0
}
8690
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8691
8692
8693
#ifdef HAVE_SCHED_SETSCHEDULER
8694
/*[clinic input]
8695
os.sched_getscheduler
8696
    pid: pid_t
8697
    /
8698
8699
Get the scheduling policy for the process identified by pid.
8700
8701
Passing 0 for pid returns the scheduling policy for the calling process.
8702
[clinic start generated code]*/
8703
8704
static PyObject *
8705
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8706
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8707
0
{
8708
0
    int policy;
8709
8710
0
    policy = sched_getscheduler(pid);
8711
0
    if (policy < 0)
8712
0
        return posix_error();
8713
0
    return PyLong_FromLong(policy);
8714
0
}
8715
#endif /* HAVE_SCHED_SETSCHEDULER */
8716
8717
8718
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8719
/*[clinic input]
8720
class os.sched_param "PyObject *" "SchedParamType"
8721
8722
@classmethod
8723
os.sched_param.__new__
8724
8725
    sched_priority: object
8726
        A scheduling parameter.
8727
8728
Currently has only one field: sched_priority
8729
[clinic start generated code]*/
8730
8731
static PyObject *
8732
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8733
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8734
0
{
8735
0
    PyObject *res;
8736
8737
0
    res = PyStructSequence_New(type);
8738
0
    if (!res)
8739
0
        return NULL;
8740
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8741
0
    return res;
8742
0
}
8743
8744
static PyObject *
8745
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8746
0
{
8747
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8748
0
}
8749
8750
static PyMethodDef os_sched_param_reduce_method = {
8751
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8752
};
8753
8754
PyDoc_VAR(os_sched_param__doc__);
8755
8756
static PyStructSequence_Field sched_param_fields[] = {
8757
    {"sched_priority", "the scheduling priority"},
8758
    {0}
8759
};
8760
8761
static PyStructSequence_Desc sched_param_desc = {
8762
    MODNAME ".sched_param", /* name */
8763
    os_sched_param__doc__, /* doc */
8764
    sched_param_fields,
8765
    1
8766
};
8767
8768
static int
8769
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8770
0
{
8771
0
    long priority;
8772
8773
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8774
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8775
0
        return 0;
8776
0
    }
8777
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8778
0
    if (priority == -1 && PyErr_Occurred())
8779
0
        return 0;
8780
0
    if (priority > INT_MAX || priority < INT_MIN) {
8781
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8782
0
        return 0;
8783
0
    }
8784
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8785
0
    return 1;
8786
0
}
8787
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8788
8789
8790
#ifdef HAVE_SCHED_SETSCHEDULER
8791
/*[clinic input]
8792
os.sched_setscheduler
8793
8794
    pid: pid_t
8795
    policy: int
8796
    param as param_obj: object
8797
    /
8798
8799
Set the scheduling policy for the process identified by pid.
8800
8801
If pid is 0, the calling process is changed.
8802
param is an instance of sched_param.
8803
[clinic start generated code]*/
8804
8805
static PyObject *
8806
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8807
                           PyObject *param_obj)
8808
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8809
0
{
8810
0
    struct sched_param param;
8811
0
    if (!convert_sched_param(module, param_obj, &param)) {
8812
0
        return NULL;
8813
0
    }
8814
8815
    /*
8816
    ** sched_setscheduler() returns 0 in Linux, but the previous
8817
    ** scheduling policy under Solaris/Illumos, and others.
8818
    ** On error, -1 is returned in all Operating Systems.
8819
    */
8820
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8821
0
        return posix_error();
8822
0
    Py_RETURN_NONE;
8823
0
}
8824
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8825
8826
8827
#ifdef HAVE_SCHED_SETPARAM
8828
/*[clinic input]
8829
os.sched_getparam
8830
    pid: pid_t
8831
    /
8832
8833
Returns scheduling parameters for the process identified by pid.
8834
8835
If pid is 0, returns parameters for the calling process.
8836
Return value is an instance of sched_param.
8837
[clinic start generated code]*/
8838
8839
static PyObject *
8840
os_sched_getparam_impl(PyObject *module, pid_t pid)
8841
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8842
0
{
8843
0
    struct sched_param param;
8844
0
    PyObject *result;
8845
0
    PyObject *priority;
8846
8847
0
    if (sched_getparam(pid, &param))
8848
0
        return posix_error();
8849
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8850
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8851
0
    if (!result)
8852
0
        return NULL;
8853
0
    priority = PyLong_FromLong(param.sched_priority);
8854
0
    if (!priority) {
8855
0
        Py_DECREF(result);
8856
0
        return NULL;
8857
0
    }
8858
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8859
0
    return result;
8860
0
}
8861
8862
8863
/*[clinic input]
8864
os.sched_setparam
8865
    pid: pid_t
8866
    param as param_obj: object
8867
    /
8868
8869
Set scheduling parameters for the process identified by pid.
8870
8871
If pid is 0, sets parameters for the calling process.
8872
param should be an instance of sched_param.
8873
[clinic start generated code]*/
8874
8875
static PyObject *
8876
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8877
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8878
0
{
8879
0
    struct sched_param param;
8880
0
    if (!convert_sched_param(module, param_obj, &param)) {
8881
0
        return NULL;
8882
0
    }
8883
8884
0
    if (sched_setparam(pid, &param))
8885
0
        return posix_error();
8886
0
    Py_RETURN_NONE;
8887
0
}
8888
#endif /* HAVE_SCHED_SETPARAM */
8889
8890
8891
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8892
/*[clinic input]
8893
@permit_long_summary
8894
os.sched_rr_get_interval -> double
8895
    pid: pid_t
8896
    /
8897
8898
Return the round-robin quantum for the process identified by pid, in seconds.
8899
8900
Value returned is a float.
8901
[clinic start generated code]*/
8902
8903
static double
8904
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8905
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8906
0
{
8907
0
    struct timespec interval;
8908
0
    if (sched_rr_get_interval(pid, &interval)) {
8909
0
        posix_error();
8910
0
        return -1.0;
8911
0
    }
8912
#ifdef _Py_MEMORY_SANITIZER
8913
    __msan_unpoison(&interval, sizeof(interval));
8914
#endif
8915
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8916
0
}
8917
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8918
8919
8920
/*[clinic input]
8921
os.sched_yield
8922
8923
Voluntarily relinquish the CPU.
8924
[clinic start generated code]*/
8925
8926
static PyObject *
8927
os_sched_yield_impl(PyObject *module)
8928
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8929
0
{
8930
0
    int result;
8931
0
    Py_BEGIN_ALLOW_THREADS
8932
0
    result = sched_yield();
8933
0
    Py_END_ALLOW_THREADS
8934
0
    if (result < 0) {
8935
0
        return posix_error();
8936
0
    }
8937
0
    Py_RETURN_NONE;
8938
0
}
8939
8940
#ifdef HAVE_SCHED_SETAFFINITY
8941
/* The minimum number of CPUs allocated in a cpu_set_t */
8942
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8943
8944
/*[clinic input]
8945
os.sched_setaffinity
8946
    pid: pid_t
8947
    mask : object
8948
    /
8949
8950
Set the CPU affinity of the process identified by pid to mask.
8951
8952
mask should be an iterable of integers identifying CPUs.
8953
[clinic start generated code]*/
8954
8955
static PyObject *
8956
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8957
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8958
0
{
8959
0
    int ncpus;
8960
0
    size_t setsize;
8961
0
    cpu_set_t *cpu_set = NULL;
8962
0
    PyObject *iterator = NULL, *item;
8963
8964
0
    iterator = PyObject_GetIter(mask);
8965
0
    if (iterator == NULL)
8966
0
        return NULL;
8967
8968
0
    ncpus = NCPUS_START;
8969
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8970
0
    cpu_set = CPU_ALLOC(ncpus);
8971
0
    if (cpu_set == NULL) {
8972
0
        PyErr_NoMemory();
8973
0
        goto error;
8974
0
    }
8975
0
    CPU_ZERO_S(setsize, cpu_set);
8976
8977
0
    while ((item = PyIter_Next(iterator))) {
8978
0
        long cpu;
8979
0
        if (!PyIndex_Check(item)) {
8980
0
            PyErr_Format(PyExc_TypeError,
8981
0
                        "expected an iterator of ints, "
8982
0
                        "but iterator yielded %R",
8983
0
                        Py_TYPE(item));
8984
0
            Py_DECREF(item);
8985
0
            goto error;
8986
0
        }
8987
0
        cpu = PyLong_AsLong(item);
8988
0
        Py_DECREF(item);
8989
0
        if (cpu < 0) {
8990
0
            if (!PyErr_Occurred())
8991
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
8992
0
            goto error;
8993
0
        }
8994
0
        if (cpu > INT_MAX - 1) {
8995
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
8996
0
            goto error;
8997
0
        }
8998
0
        if (cpu >= ncpus) {
8999
            /* Grow CPU mask to fit the CPU number */
9000
0
            int newncpus = ncpus;
9001
0
            cpu_set_t *newmask;
9002
0
            size_t newsetsize;
9003
0
            while (newncpus <= cpu) {
9004
0
                if (newncpus > INT_MAX / 2)
9005
0
                    newncpus = cpu + 1;
9006
0
                else
9007
0
                    newncpus = newncpus * 2;
9008
0
            }
9009
0
            newmask = CPU_ALLOC(newncpus);
9010
0
            if (newmask == NULL) {
9011
0
                PyErr_NoMemory();
9012
0
                goto error;
9013
0
            }
9014
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9015
0
            CPU_ZERO_S(newsetsize, newmask);
9016
0
            memcpy(newmask, cpu_set, setsize);
9017
0
            CPU_FREE(cpu_set);
9018
0
            setsize = newsetsize;
9019
0
            cpu_set = newmask;
9020
0
            ncpus = newncpus;
9021
0
        }
9022
0
        CPU_SET_S(cpu, setsize, cpu_set);
9023
0
    }
9024
0
    if (PyErr_Occurred()) {
9025
0
        goto error;
9026
0
    }
9027
0
    Py_CLEAR(iterator);
9028
9029
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9030
0
        posix_error();
9031
0
        goto error;
9032
0
    }
9033
0
    CPU_FREE(cpu_set);
9034
0
    Py_RETURN_NONE;
9035
9036
0
error:
9037
0
    if (cpu_set)
9038
0
        CPU_FREE(cpu_set);
9039
0
    Py_XDECREF(iterator);
9040
0
    return NULL;
9041
0
}
9042
9043
9044
/*[clinic input]
9045
@permit_long_summary
9046
os.sched_getaffinity
9047
    pid: pid_t
9048
    /
9049
9050
Return the affinity of the process identified by pid (or the current process if zero).
9051
9052
The affinity is returned as a set of CPU identifiers.
9053
[clinic start generated code]*/
9054
9055
static PyObject *
9056
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9057
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9058
0
{
9059
0
    int ncpus = NCPUS_START;
9060
0
    size_t setsize;
9061
0
    cpu_set_t *mask;
9062
9063
0
    while (1) {
9064
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9065
0
        mask = CPU_ALLOC(ncpus);
9066
0
        if (mask == NULL) {
9067
0
            return PyErr_NoMemory();
9068
0
        }
9069
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9070
0
            break;
9071
0
        }
9072
0
        CPU_FREE(mask);
9073
0
        if (errno != EINVAL) {
9074
0
            return posix_error();
9075
0
        }
9076
0
        if (ncpus > INT_MAX / 2) {
9077
0
            PyErr_SetString(PyExc_OverflowError,
9078
0
                            "could not allocate a large enough CPU set");
9079
0
            return NULL;
9080
0
        }
9081
0
        ncpus *= 2;
9082
0
    }
9083
9084
0
    PyObject *res = PySet_New(NULL);
9085
0
    if (res == NULL) {
9086
0
        goto error;
9087
0
    }
9088
9089
0
    int cpu = 0;
9090
0
    int count = CPU_COUNT_S(setsize, mask);
9091
0
    for (; count; cpu++) {
9092
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9093
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9094
0
            --count;
9095
0
            if (cpu_num == NULL) {
9096
0
                goto error;
9097
0
            }
9098
0
            if (PySet_Add(res, cpu_num)) {
9099
0
                Py_DECREF(cpu_num);
9100
0
                goto error;
9101
0
            }
9102
0
            Py_DECREF(cpu_num);
9103
0
        }
9104
0
    }
9105
0
    CPU_FREE(mask);
9106
0
    return res;
9107
9108
0
error:
9109
0
    if (mask) {
9110
0
        CPU_FREE(mask);
9111
0
    }
9112
0
    Py_XDECREF(res);
9113
0
    return NULL;
9114
0
}
9115
#endif /* HAVE_SCHED_SETAFFINITY */
9116
9117
#endif /* HAVE_SCHED_H */
9118
9119
9120
#ifdef HAVE_POSIX_OPENPT
9121
/*[clinic input]
9122
os.posix_openpt -> int
9123
9124
    oflag: int
9125
    /
9126
9127
Open and return a file descriptor for a master pseudo-terminal device.
9128
9129
Performs a posix_openpt() C function call. The oflag argument is used to
9130
set file status flags and file access modes as specified in the manual page
9131
of posix_openpt() of your system.
9132
[clinic start generated code]*/
9133
9134
static int
9135
os_posix_openpt_impl(PyObject *module, int oflag)
9136
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
9137
0
{
9138
0
    int fd;
9139
9140
0
#if defined(O_CLOEXEC)
9141
0
    oflag |= O_CLOEXEC;
9142
0
#endif
9143
9144
0
    fd = posix_openpt(oflag);
9145
0
    if (fd == -1) {
9146
0
        posix_error();
9147
0
        return -1;
9148
0
    }
9149
9150
    // Just in case, likely a no-op given O_CLOEXEC above.
9151
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9152
0
        close(fd);
9153
0
        return -1;
9154
0
    }
9155
9156
0
    return fd;
9157
0
}
9158
#endif /* HAVE_POSIX_OPENPT */
9159
9160
#ifdef HAVE_GRANTPT
9161
/*[clinic input]
9162
os.grantpt
9163
9164
    fd: fildes
9165
        File descriptor of a master pseudo-terminal device.
9166
    /
9167
9168
Grant access to the slave pseudo-terminal device.
9169
9170
Performs a grantpt() C function call.
9171
[clinic start generated code]*/
9172
9173
static PyObject *
9174
os_grantpt_impl(PyObject *module, int fd)
9175
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9176
0
{
9177
0
    int ret;
9178
0
    int saved_errno;
9179
0
    PyOS_sighandler_t sig_saved;
9180
9181
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9182
9183
0
    ret = grantpt(fd);
9184
0
    if (ret == -1)
9185
0
        saved_errno = errno;
9186
9187
0
    PyOS_setsig(SIGCHLD, sig_saved);
9188
9189
0
    if (ret == -1) {
9190
0
        errno = saved_errno;
9191
0
        return posix_error();
9192
0
    }
9193
9194
0
    Py_RETURN_NONE;
9195
0
}
9196
#endif /* HAVE_GRANTPT */
9197
9198
#ifdef HAVE_UNLOCKPT
9199
/*[clinic input]
9200
os.unlockpt
9201
9202
    fd: fildes
9203
        File descriptor of a master pseudo-terminal device.
9204
    /
9205
9206
Unlock a pseudo-terminal master/slave pair.
9207
9208
Performs an unlockpt() C function call.
9209
[clinic start generated code]*/
9210
9211
static PyObject *
9212
os_unlockpt_impl(PyObject *module, int fd)
9213
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9214
0
{
9215
0
    if (unlockpt(fd) == -1)
9216
0
        return posix_error();
9217
9218
0
    Py_RETURN_NONE;
9219
0
}
9220
#endif /* HAVE_UNLOCKPT */
9221
9222
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9223
static PyObject *
9224
py_ptsname(int fd)
9225
0
{
9226
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9227
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9228
0
    errno = 0;
9229
0
    char *name = ptsname(fd);
9230
0
    if (name == NULL) {
9231
0
        return posix_error();
9232
0
    }
9233
0
    return PyUnicode_DecodeFSDefault(name);
9234
0
}
9235
9236
/*[clinic input]
9237
os.ptsname
9238
9239
    fd: fildes
9240
        File descriptor of a master pseudo-terminal device.
9241
    /
9242
9243
Return the name of the slave pseudo-terminal device.
9244
9245
If the ptsname_r() C function is available, it is called;
9246
otherwise, performs a ptsname() C function call.
9247
[clinic start generated code]*/
9248
9249
static PyObject *
9250
os_ptsname_impl(PyObject *module, int fd)
9251
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9252
0
{
9253
0
#ifdef HAVE_PTSNAME_R
9254
0
    int ret;
9255
0
    char name[MAXPATHLEN+1];
9256
9257
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9258
0
        ret = ptsname_r(fd, name, sizeof(name));
9259
0
    }
9260
0
    else {
9261
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9262
0
        return py_ptsname(fd);
9263
0
    }
9264
0
    if (ret != 0) {
9265
0
        errno = ret;
9266
0
        return posix_error();
9267
0
    }
9268
9269
0
    return PyUnicode_DecodeFSDefault(name);
9270
#else
9271
    return py_ptsname(fd);
9272
#endif /* HAVE_PTSNAME_R */
9273
0
}
9274
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9275
9276
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9277
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9278
#  define DEV_PTY_FILE "/dev/ptc"
9279
#  define HAVE_DEV_PTMX
9280
#else
9281
#  define DEV_PTY_FILE "/dev/ptmx"
9282
#endif
9283
9284
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9285
#ifdef HAVE_PTY_H
9286
#include <pty.h>
9287
#elif defined(HAVE_LIBUTIL_H)
9288
#include <libutil.h>
9289
#elif defined(HAVE_UTIL_H)
9290
#include <util.h>
9291
#endif /* HAVE_PTY_H */
9292
#ifdef HAVE_UTMP_H
9293
#include <utmp.h>
9294
#endif /* HAVE_UTMP_H */
9295
#ifdef HAVE_STROPTS_H
9296
#include <stropts.h>
9297
#endif
9298
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9299
9300
9301
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9302
/*[clinic input]
9303
os.openpty
9304
9305
Open a pseudo-terminal.
9306
9307
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9308
for both the master and slave ends.
9309
[clinic start generated code]*/
9310
9311
static PyObject *
9312
os_openpty_impl(PyObject *module)
9313
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9314
0
{
9315
0
    int master_fd = -1, slave_fd = -1;
9316
#ifndef HAVE_OPENPTY
9317
    char * slave_name;
9318
#endif
9319
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9320
    PyOS_sighandler_t sig_saved;
9321
#if defined(__sun) && defined(__SVR4)
9322
    extern char *ptsname(int fildes);
9323
#endif
9324
#endif
9325
9326
0
#ifdef HAVE_OPENPTY
9327
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9328
0
        goto posix_error;
9329
9330
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9331
0
        goto error;
9332
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9333
0
        goto error;
9334
9335
#elif defined(HAVE__GETPTY)
9336
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9337
    if (slave_name == NULL)
9338
        goto posix_error;
9339
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9340
        goto error;
9341
9342
    slave_fd = _Py_open(slave_name, O_RDWR);
9343
    if (slave_fd < 0)
9344
        goto error;
9345
9346
#else
9347
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9348
    if (master_fd < 0)
9349
        goto posix_error;
9350
9351
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9352
9353
    /* change permission of slave */
9354
    if (grantpt(master_fd) < 0) {
9355
        int saved_errno = errno;
9356
        PyOS_setsig(SIGCHLD, sig_saved);
9357
        errno = saved_errno;
9358
        goto posix_error;
9359
    }
9360
9361
    /* unlock slave */
9362
    if (unlockpt(master_fd) < 0) {
9363
        int saved_errno = errno;
9364
        PyOS_setsig(SIGCHLD, sig_saved);
9365
        errno = saved_errno;
9366
        goto posix_error;
9367
    }
9368
9369
    PyOS_setsig(SIGCHLD, sig_saved);
9370
9371
    slave_name = ptsname(master_fd); /* get name of slave */
9372
    if (slave_name == NULL)
9373
        goto posix_error;
9374
9375
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9376
    if (slave_fd == -1)
9377
        goto error;
9378
9379
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9380
        goto posix_error;
9381
9382
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
9383
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9384
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9385
#ifndef __hpux
9386
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9387
#endif /* __hpux */
9388
#endif /* HAVE_CYGWIN */
9389
#endif /* HAVE_OPENPTY */
9390
9391
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9392
9393
0
posix_error:
9394
0
    posix_error();
9395
0
error:
9396
0
    if (master_fd != -1)
9397
0
        close(master_fd);
9398
0
    if (slave_fd != -1)
9399
0
        close(slave_fd);
9400
0
    return NULL;
9401
0
}
9402
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9403
9404
9405
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9406
#define HAVE_FALLBACK_LOGIN_TTY 1
9407
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9408
9409
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9410
/*[clinic input]
9411
os.login_tty
9412
9413
    fd: fildes
9414
    /
9415
9416
Prepare the tty of which fd is a file descriptor for a new login session.
9417
9418
Make the calling process a session leader; make the tty the
9419
controlling tty, the stdin, the stdout, and the stderr of the
9420
calling process; close fd.
9421
[clinic start generated code]*/
9422
9423
static PyObject *
9424
os_login_tty_impl(PyObject *module, int fd)
9425
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
9426
0
{
9427
0
#ifdef HAVE_LOGIN_TTY
9428
0
    if (login_tty(fd) == -1) {
9429
0
        return posix_error();
9430
0
    }
9431
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9432
    /* Establish a new session. */
9433
    if (setsid() == -1) {
9434
        return posix_error();
9435
    }
9436
9437
    /* The tty becomes the controlling terminal. */
9438
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9439
        return posix_error();
9440
    }
9441
9442
    /* The tty becomes stdin/stdout/stderr */
9443
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9444
        return posix_error();
9445
    }
9446
    if (fd > 2) {
9447
        close(fd);
9448
    }
9449
#endif /* HAVE_LOGIN_TTY */
9450
0
    Py_RETURN_NONE;
9451
0
}
9452
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9453
9454
9455
#ifdef HAVE_FORKPTY
9456
/*[clinic input]
9457
os.forkpty
9458
9459
Fork a new process with a new pseudo-terminal as controlling tty.
9460
9461
Returns a tuple of (pid, master_fd).
9462
Like fork(), return pid of 0 to the child process,
9463
and pid of child to the parent process.
9464
To both, return fd of newly opened pseudo-terminal.
9465
The master_fd is non-inheritable.
9466
[clinic start generated code]*/
9467
9468
static PyObject *
9469
os_forkpty_impl(PyObject *module)
9470
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9471
0
{
9472
0
    int master_fd = -1;
9473
0
    pid_t pid;
9474
9475
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9476
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9477
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9478
0
                        "can't fork at interpreter shutdown");
9479
0
        return NULL;
9480
0
    }
9481
0
    if (!_Py_IsMainInterpreter(interp)) {
9482
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9483
0
        return NULL;
9484
0
    }
9485
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9486
0
        return NULL;
9487
0
    }
9488
0
    PyOS_BeforeFork();
9489
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9490
0
    if (pid == 0) {
9491
        /* child: this clobbers and resets the import lock. */
9492
0
        PyOS_AfterFork_Child();
9493
0
    } else {
9494
        // Called before AfterFork_Parent in case those hooks start threads.
9495
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9496
        /* parent: release the import lock. */
9497
0
        PyOS_AfterFork_Parent();
9498
        /* set O_CLOEXEC on master_fd */
9499
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9500
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9501
0
                                   "non-inheritable in forkpty()");
9502
0
        }
9503
9504
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9505
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9506
0
            return NULL;
9507
0
    }
9508
0
    if (pid == -1) {
9509
0
        return posix_error();
9510
0
    }
9511
9512
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9513
0
}
9514
#endif /* HAVE_FORKPTY */
9515
9516
9517
#ifdef HAVE_GETEGID
9518
/*[clinic input]
9519
os.getegid
9520
9521
Return the current process's effective group id.
9522
[clinic start generated code]*/
9523
9524
static PyObject *
9525
os_getegid_impl(PyObject *module)
9526
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9527
28
{
9528
28
    return _PyLong_FromGid(getegid());
9529
28
}
9530
#endif /* HAVE_GETEGID */
9531
9532
9533
#ifdef HAVE_GETEUID
9534
/*[clinic input]
9535
os.geteuid
9536
9537
Return the current process's effective user id.
9538
[clinic start generated code]*/
9539
9540
static PyObject *
9541
os_geteuid_impl(PyObject *module)
9542
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9543
28
{
9544
28
    return _PyLong_FromUid(geteuid());
9545
28
}
9546
#endif /* HAVE_GETEUID */
9547
9548
9549
#ifdef HAVE_GETGID
9550
/*[clinic input]
9551
os.getgid
9552
9553
Return the current process's group id.
9554
[clinic start generated code]*/
9555
9556
static PyObject *
9557
os_getgid_impl(PyObject *module)
9558
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9559
28
{
9560
28
    return _PyLong_FromGid(getgid());
9561
28
}
9562
#endif /* HAVE_GETGID */
9563
9564
9565
#if defined(HAVE_GETPID)
9566
/*[clinic input]
9567
os.getpid
9568
9569
Return the current process id.
9570
[clinic start generated code]*/
9571
9572
static PyObject *
9573
os_getpid_impl(PyObject *module)
9574
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9575
4.00k
{
9576
4.00k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9577
4.00k
    return PyLong_FromPid(getpid());
9578
#else
9579
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9580
#endif
9581
4.00k
}
9582
#endif /* defined(HAVE_GETPID) */
9583
9584
#ifdef NGROUPS_MAX
9585
0
#define MAX_GROUPS NGROUPS_MAX
9586
#else
9587
    /* defined to be 16 on Solaris7, so this should be a small number */
9588
#define MAX_GROUPS 64
9589
#endif
9590
9591
#ifdef HAVE_GETGROUPLIST
9592
9593
#ifdef __APPLE__
9594
/*[clinic input]
9595
os.getgrouplist
9596
9597
    user: str
9598
        username to lookup
9599
    group as basegid: int
9600
        base group id of the user
9601
    /
9602
9603
Returns a list of groups to which a user belongs.
9604
[clinic start generated code]*/
9605
9606
static PyObject *
9607
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9608
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9609
#else
9610
/*[clinic input]
9611
os.getgrouplist
9612
9613
    user: str
9614
        username to lookup
9615
    group as basegid: gid_t
9616
        base group id of the user
9617
    /
9618
9619
Returns a list of groups to which a user belongs.
9620
[clinic start generated code]*/
9621
9622
static PyObject *
9623
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9624
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9625
#endif
9626
0
{
9627
0
    int i, ngroups;
9628
0
    PyObject *list;
9629
#ifdef __APPLE__
9630
    int *groups;
9631
#else
9632
0
    gid_t *groups;
9633
0
#endif
9634
9635
    /*
9636
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9637
     * number of supplemental groups a users can belong to.
9638
     * We have to increment it by one because
9639
     * getgrouplist() returns both the supplemental groups
9640
     * and the primary group, i.e. all of the groups the
9641
     * user belongs to.
9642
     */
9643
0
    ngroups = 1 + MAX_GROUPS;
9644
9645
0
    while (1) {
9646
#ifdef __APPLE__
9647
        groups = PyMem_New(int, ngroups);
9648
#else
9649
0
        groups = PyMem_New(gid_t, ngroups);
9650
0
#endif
9651
0
        if (groups == NULL) {
9652
0
            return PyErr_NoMemory();
9653
0
        }
9654
9655
0
        int old_ngroups = ngroups;
9656
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9657
            /* Success */
9658
0
            break;
9659
0
        }
9660
9661
        /* getgrouplist() fails if the group list is too small */
9662
0
        PyMem_Free(groups);
9663
9664
0
        if (ngroups > old_ngroups) {
9665
            /* If the group list is too small, the glibc implementation of
9666
               getgrouplist() sets ngroups to the total number of groups and
9667
               returns -1. */
9668
0
        }
9669
0
        else {
9670
            /* Double the group list size */
9671
0
            if (ngroups > INT_MAX / 2) {
9672
0
                return PyErr_NoMemory();
9673
0
            }
9674
0
            ngroups *= 2;
9675
0
        }
9676
9677
        /* Retry getgrouplist() with a larger group list */
9678
0
    }
9679
9680
#ifdef _Py_MEMORY_SANITIZER
9681
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9682
    __msan_unpoison(&ngroups, sizeof(ngroups));
9683
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9684
#endif
9685
9686
0
    list = PyList_New(ngroups);
9687
0
    if (list == NULL) {
9688
0
        PyMem_Free(groups);
9689
0
        return NULL;
9690
0
    }
9691
9692
0
    for (i = 0; i < ngroups; i++) {
9693
#ifdef __APPLE__
9694
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9695
#else
9696
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9697
0
#endif
9698
0
        if (o == NULL) {
9699
0
            Py_DECREF(list);
9700
0
            PyMem_Free(groups);
9701
0
            return NULL;
9702
0
        }
9703
0
        PyList_SET_ITEM(list, i, o);
9704
0
    }
9705
9706
0
    PyMem_Free(groups);
9707
9708
0
    return list;
9709
0
}
9710
#endif /* HAVE_GETGROUPLIST */
9711
9712
9713
#ifdef HAVE_GETGROUPS
9714
/*[clinic input]
9715
os.getgroups
9716
9717
Return list of supplemental group IDs for the process.
9718
[clinic start generated code]*/
9719
9720
static PyObject *
9721
os_getgroups_impl(PyObject *module)
9722
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9723
0
{
9724
    // Call getgroups with length 0 to get the actual number of groups
9725
0
    int n = getgroups(0, NULL);
9726
0
    if (n < 0) {
9727
0
        return posix_error();
9728
0
    }
9729
9730
0
    if (n == 0) {
9731
0
        return PyList_New(0);
9732
0
    }
9733
9734
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9735
0
    if (grouplist == NULL) {
9736
0
        return PyErr_NoMemory();
9737
0
    }
9738
9739
0
    n = getgroups(n, grouplist);
9740
0
    if (n == -1) {
9741
0
        posix_error();
9742
0
        PyMem_Free(grouplist);
9743
0
        return NULL;
9744
0
    }
9745
9746
0
    PyObject *result = PyList_New(n);
9747
0
    if (result == NULL) {
9748
0
        goto error;
9749
0
    }
9750
9751
0
    for (int i = 0; i < n; ++i) {
9752
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9753
0
        if (group == NULL) {
9754
0
            goto error;
9755
0
        }
9756
0
        PyList_SET_ITEM(result, i, group);
9757
0
    }
9758
0
    PyMem_Free(grouplist);
9759
9760
0
    return result;
9761
9762
0
error:
9763
0
    PyMem_Free(grouplist);
9764
0
    Py_XDECREF(result);
9765
0
    return NULL;
9766
0
}
9767
#endif /* HAVE_GETGROUPS */
9768
9769
#ifdef HAVE_INITGROUPS
9770
#ifdef __APPLE__
9771
/*[clinic input]
9772
os.initgroups
9773
9774
    username as oname: unicode_fs_encoded
9775
    gid: int
9776
    /
9777
9778
Initialize the group access list.
9779
9780
Call the system initgroups() to initialize the group access list with all of
9781
the groups of which the specified username is a member, plus the specified
9782
group id.
9783
[clinic start generated code]*/
9784
9785
static PyObject *
9786
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9787
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9788
#else
9789
/*[clinic input]
9790
os.initgroups
9791
9792
    username as oname: unicode_fs_encoded
9793
    gid: gid_t
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, gid_t gid)
9805
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9806
#endif
9807
0
{
9808
0
    const char *username = PyBytes_AS_STRING(oname);
9809
9810
0
    if (initgroups(username, gid) == -1)
9811
0
        return PyErr_SetFromErrno(PyExc_OSError);
9812
9813
0
    Py_RETURN_NONE;
9814
0
}
9815
#endif /* HAVE_INITGROUPS */
9816
9817
9818
#ifdef HAVE_GETPGID
9819
/*[clinic input]
9820
os.getpgid
9821
9822
    pid: pid_t
9823
9824
Call the system call getpgid(), and return the result.
9825
[clinic start generated code]*/
9826
9827
static PyObject *
9828
os_getpgid_impl(PyObject *module, pid_t pid)
9829
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9830
0
{
9831
0
    pid_t pgid = getpgid(pid);
9832
0
    if (pgid < 0)
9833
0
        return posix_error();
9834
0
    return PyLong_FromPid(pgid);
9835
0
}
9836
#endif /* HAVE_GETPGID */
9837
9838
9839
#ifdef HAVE_GETPGRP
9840
/*[clinic input]
9841
os.getpgrp
9842
9843
Return the current process group id.
9844
[clinic start generated code]*/
9845
9846
static PyObject *
9847
os_getpgrp_impl(PyObject *module)
9848
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9849
0
{
9850
#ifdef GETPGRP_HAVE_ARG
9851
    return PyLong_FromPid(getpgrp(0));
9852
#else /* GETPGRP_HAVE_ARG */
9853
0
    return PyLong_FromPid(getpgrp());
9854
0
#endif /* GETPGRP_HAVE_ARG */
9855
0
}
9856
#endif /* HAVE_GETPGRP */
9857
9858
9859
#ifdef HAVE_SETPGRP
9860
/*[clinic input]
9861
os.setpgrp
9862
9863
Make the current process the leader of its process group.
9864
[clinic start generated code]*/
9865
9866
static PyObject *
9867
os_setpgrp_impl(PyObject *module)
9868
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9869
0
{
9870
#ifdef SETPGRP_HAVE_ARG
9871
    if (setpgrp(0, 0) < 0)
9872
#else /* SETPGRP_HAVE_ARG */
9873
0
    if (setpgrp() < 0)
9874
0
#endif /* SETPGRP_HAVE_ARG */
9875
0
        return posix_error();
9876
0
    Py_RETURN_NONE;
9877
0
}
9878
#endif /* HAVE_SETPGRP */
9879
9880
#ifdef HAVE_GETPPID
9881
9882
#ifdef MS_WINDOWS
9883
#include <winternl.h>
9884
#include <ProcessSnapshot.h>
9885
9886
// The structure definition in winternl.h may be incomplete.
9887
// This structure is the full version from the MSDN documentation.
9888
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9889
    NTSTATUS ExitStatus;
9890
    PVOID PebBaseAddress;
9891
    ULONG_PTR AffinityMask;
9892
    LONG BasePriority;
9893
    ULONG_PTR UniqueProcessId;
9894
    ULONG_PTR InheritedFromUniqueProcessId;
9895
} PROCESS_BASIC_INFORMATION_FULL;
9896
9897
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9898
    IN    HANDLE           ProcessHandle,
9899
    IN    PROCESSINFOCLASS ProcessInformationClass,
9900
    OUT   PVOID            ProcessInformation,
9901
    IN    ULONG            ProcessInformationLength,
9902
    OUT   PULONG           ReturnLength OPTIONAL);
9903
9904
// This function returns the process ID of the parent process.
9905
// Returns 0 on failure.
9906
static ULONG
9907
win32_getppid_fast(void)
9908
{
9909
    NTSTATUS status;
9910
    HMODULE ntdll;
9911
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9912
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9913
    static ULONG cached_ppid = 0;
9914
9915
    if (cached_ppid) {
9916
        // No need to query the kernel again.
9917
        return cached_ppid;
9918
    }
9919
9920
    ntdll = GetModuleHandleW(L"ntdll.dll");
9921
    if (!ntdll) {
9922
        return 0;
9923
    }
9924
9925
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9926
    if (!pNtQueryInformationProcess) {
9927
        return 0;
9928
    }
9929
9930
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9931
                                        ProcessBasicInformation,
9932
                                        &basic_information,
9933
                                        sizeof(basic_information),
9934
                                        NULL);
9935
9936
    if (!NT_SUCCESS(status)) {
9937
        return 0;
9938
    }
9939
9940
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9941
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9942
    // zero and (ULONG) -1.
9943
9944
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9945
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9946
    {
9947
        return 0;
9948
    }
9949
9950
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9951
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9952
    // process. This process ID will be correctly returned even if the parent process has
9953
    // exited or been terminated.
9954
9955
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9956
    return cached_ppid;
9957
}
9958
9959
static PyObject*
9960
win32_getppid(void)
9961
{
9962
    DWORD error;
9963
    PyObject* result = NULL;
9964
    HANDLE process = GetCurrentProcess();
9965
    HPSS snapshot = NULL;
9966
    ULONG pid;
9967
9968
    pid = win32_getppid_fast();
9969
    if (pid != 0) {
9970
        return PyLong_FromUnsignedLong(pid);
9971
    }
9972
9973
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9974
9975
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9976
    if (error != ERROR_SUCCESS) {
9977
        return PyErr_SetFromWindowsErr(error);
9978
    }
9979
9980
    PSS_PROCESS_INFORMATION info;
9981
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
9982
                             sizeof(info));
9983
    if (error == ERROR_SUCCESS) {
9984
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
9985
    }
9986
    else {
9987
        result = PyErr_SetFromWindowsErr(error);
9988
    }
9989
9990
    PssFreeSnapshot(process, snapshot);
9991
    return result;
9992
}
9993
#endif /*MS_WINDOWS*/
9994
9995
9996
/*[clinic input]
9997
os.getppid
9998
9999
Return the parent's process id.
10000
10001
If the parent process has already exited, Windows machines will still
10002
return its id; others systems will return the id of the 'init' process (1).
10003
[clinic start generated code]*/
10004
10005
static PyObject *
10006
os_getppid_impl(PyObject *module)
10007
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
10008
0
{
10009
#ifdef MS_WINDOWS
10010
    return win32_getppid();
10011
#else
10012
0
    return PyLong_FromPid(getppid());
10013
0
#endif
10014
0
}
10015
#endif /* HAVE_GETPPID */
10016
10017
10018
#ifdef HAVE_GETLOGIN
10019
/*[clinic input]
10020
os.getlogin
10021
10022
Return the actual login name.
10023
[clinic start generated code]*/
10024
10025
static PyObject *
10026
os_getlogin_impl(PyObject *module)
10027
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10028
0
{
10029
0
    PyObject *result = NULL;
10030
#ifdef MS_WINDOWS
10031
    wchar_t user_name[UNLEN + 1];
10032
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10033
10034
    if (GetUserNameW(user_name, &num_chars)) {
10035
        /* num_chars is the number of unicode chars plus null terminator */
10036
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10037
    }
10038
    else
10039
        result = PyErr_SetFromWindowsErr(GetLastError());
10040
#elif defined (HAVE_GETLOGIN_R)
10041
# if defined (HAVE_MAXLOGNAME)
10042
    char name[MAXLOGNAME + 1];
10043
# elif defined (HAVE_UT_NAMESIZE)
10044
    char name[UT_NAMESIZE + 1];
10045
# else
10046
    char name[256];
10047
# endif
10048
0
    int err = getlogin_r(name, sizeof(name));
10049
0
    if (err) {
10050
0
        int old_errno = errno;
10051
0
        errno = err;
10052
0
        posix_error();
10053
0
        errno = old_errno;
10054
0
    }
10055
0
    else {
10056
0
        result = PyUnicode_DecodeFSDefault(name);
10057
0
    }
10058
#else
10059
    char *name;
10060
    int old_errno = errno;
10061
10062
    errno = 0;
10063
    name = getlogin();
10064
    if (name == NULL) {
10065
        if (errno)
10066
            posix_error();
10067
        else
10068
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10069
    }
10070
    else
10071
        result = PyUnicode_DecodeFSDefault(name);
10072
    errno = old_errno;
10073
#endif
10074
0
    return result;
10075
0
}
10076
#endif /* HAVE_GETLOGIN */
10077
10078
10079
#ifdef HAVE_GETUID
10080
/*[clinic input]
10081
os.getuid
10082
10083
Return the current process's user id.
10084
[clinic start generated code]*/
10085
10086
static PyObject *
10087
os_getuid_impl(PyObject *module)
10088
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10089
28
{
10090
28
    return _PyLong_FromUid(getuid());
10091
28
}
10092
#endif /* HAVE_GETUID */
10093
10094
10095
#ifdef MS_WINDOWS
10096
#define HAVE_KILL
10097
#endif /* MS_WINDOWS */
10098
10099
#ifdef HAVE_KILL
10100
/*[clinic input]
10101
os.kill
10102
10103
    pid: pid_t
10104
    signal: Py_ssize_t
10105
    /
10106
10107
Kill a process with a signal.
10108
[clinic start generated code]*/
10109
10110
static PyObject *
10111
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10112
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10113
0
{
10114
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10115
0
        return NULL;
10116
0
    }
10117
0
#ifndef MS_WINDOWS
10118
0
    if (kill(pid, (int)signal) == -1) {
10119
0
        return posix_error();
10120
0
    }
10121
10122
    // Check immediately if the signal was sent to the current process.
10123
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10124
    // is cheap.
10125
0
    if (PyErr_CheckSignals()) {
10126
0
        return NULL;
10127
0
    }
10128
10129
0
    Py_RETURN_NONE;
10130
#else /* !MS_WINDOWS */
10131
    DWORD sig = (DWORD)signal;
10132
10133
#ifdef HAVE_WINDOWS_CONSOLE_IO
10134
    /* Console processes which share a common console can be sent CTRL+C or
10135
       CTRL+BREAK events, provided they handle said events. */
10136
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10137
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10138
            return PyErr_SetFromWindowsErr(0);
10139
        }
10140
        Py_RETURN_NONE;
10141
    }
10142
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10143
10144
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10145
       attempt to open and terminate the process. */
10146
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10147
    if (handle == NULL) {
10148
        return PyErr_SetFromWindowsErr(0);
10149
    }
10150
10151
    BOOL res = TerminateProcess(handle, sig);
10152
    CloseHandle(handle);
10153
    if (res == 0) {
10154
        return PyErr_SetFromWindowsErr(0);
10155
    }
10156
10157
    Py_RETURN_NONE;
10158
#endif /* !MS_WINDOWS */
10159
0
}
10160
#endif /* HAVE_KILL */
10161
10162
10163
#ifdef HAVE_KILLPG
10164
/*[clinic input]
10165
os.killpg
10166
10167
    pgid: pid_t
10168
    signal: int
10169
    /
10170
10171
Kill a process group with a signal.
10172
[clinic start generated code]*/
10173
10174
static PyObject *
10175
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10176
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10177
0
{
10178
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10179
0
        return NULL;
10180
0
    }
10181
    /* XXX some man pages make the `pgid` parameter an int, others
10182
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10183
       take the same type. Moreover, pid_t is always at least as wide as
10184
       int (else compilation of this module fails), which is safe. */
10185
0
    if (killpg(pgid, signal) == -1)
10186
0
        return posix_error();
10187
0
    Py_RETURN_NONE;
10188
0
}
10189
#endif /* HAVE_KILLPG */
10190
10191
10192
#ifdef HAVE_PLOCK
10193
#ifdef HAVE_SYS_LOCK_H
10194
#include <sys/lock.h>
10195
#endif
10196
10197
/*[clinic input]
10198
os.plock
10199
    op: int
10200
    /
10201
10202
Lock program segments into memory.");
10203
[clinic start generated code]*/
10204
10205
static PyObject *
10206
os_plock_impl(PyObject *module, int op)
10207
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10208
{
10209
    if (plock(op) == -1)
10210
        return posix_error();
10211
    Py_RETURN_NONE;
10212
}
10213
#endif /* HAVE_PLOCK */
10214
10215
10216
#ifdef HAVE_SETUID
10217
/*[clinic input]
10218
os.setuid
10219
10220
    uid: uid_t
10221
    /
10222
10223
Set the current process's user id.
10224
[clinic start generated code]*/
10225
10226
static PyObject *
10227
os_setuid_impl(PyObject *module, uid_t uid)
10228
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10229
0
{
10230
0
    if (setuid(uid) < 0)
10231
0
        return posix_error();
10232
0
    Py_RETURN_NONE;
10233
0
}
10234
#endif /* HAVE_SETUID */
10235
10236
10237
#ifdef HAVE_SETEUID
10238
/*[clinic input]
10239
os.seteuid
10240
10241
    euid: uid_t
10242
    /
10243
10244
Set the current process's effective user id.
10245
[clinic start generated code]*/
10246
10247
static PyObject *
10248
os_seteuid_impl(PyObject *module, uid_t euid)
10249
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10250
0
{
10251
0
    if (seteuid(euid) < 0)
10252
0
        return posix_error();
10253
0
    Py_RETURN_NONE;
10254
0
}
10255
#endif /* HAVE_SETEUID */
10256
10257
10258
#ifdef HAVE_SETEGID
10259
/*[clinic input]
10260
os.setegid
10261
10262
    egid: gid_t
10263
    /
10264
10265
Set the current process's effective group id.
10266
[clinic start generated code]*/
10267
10268
static PyObject *
10269
os_setegid_impl(PyObject *module, gid_t egid)
10270
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10271
0
{
10272
0
    if (setegid(egid) < 0)
10273
0
        return posix_error();
10274
0
    Py_RETURN_NONE;
10275
0
}
10276
#endif /* HAVE_SETEGID */
10277
10278
10279
#ifdef HAVE_SETREUID
10280
/*[clinic input]
10281
os.setreuid
10282
10283
    ruid: uid_t
10284
    euid: uid_t
10285
    /
10286
10287
Set the current process's real and effective user ids.
10288
[clinic start generated code]*/
10289
10290
static PyObject *
10291
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10292
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10293
0
{
10294
0
    if (setreuid(ruid, euid) < 0) {
10295
0
        return posix_error();
10296
0
    } else {
10297
0
        Py_RETURN_NONE;
10298
0
    }
10299
0
}
10300
#endif /* HAVE_SETREUID */
10301
10302
10303
#ifdef HAVE_SETREGID
10304
/*[clinic input]
10305
os.setregid
10306
10307
    rgid: gid_t
10308
    egid: gid_t
10309
    /
10310
10311
Set the current process's real and effective group ids.
10312
[clinic start generated code]*/
10313
10314
static PyObject *
10315
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10316
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10317
0
{
10318
0
    if (setregid(rgid, egid) < 0)
10319
0
        return posix_error();
10320
0
    Py_RETURN_NONE;
10321
0
}
10322
#endif /* HAVE_SETREGID */
10323
10324
10325
#ifdef HAVE_SETGID
10326
/*[clinic input]
10327
os.setgid
10328
    gid: gid_t
10329
    /
10330
10331
Set the current process's group id.
10332
[clinic start generated code]*/
10333
10334
static PyObject *
10335
os_setgid_impl(PyObject *module, gid_t gid)
10336
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10337
0
{
10338
0
    if (setgid(gid) < 0)
10339
0
        return posix_error();
10340
0
    Py_RETURN_NONE;
10341
0
}
10342
#endif /* HAVE_SETGID */
10343
10344
10345
#ifdef HAVE_SETGROUPS
10346
/*[clinic input]
10347
os.setgroups
10348
10349
    groups: object
10350
    /
10351
10352
Set the groups of the current process to list.
10353
[clinic start generated code]*/
10354
10355
static PyObject *
10356
os_setgroups(PyObject *module, PyObject *groups)
10357
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10358
0
{
10359
0
    if (!PySequence_Check(groups)) {
10360
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10361
0
        return NULL;
10362
0
    }
10363
0
    Py_ssize_t len = PySequence_Size(groups);
10364
0
    if (len < 0) {
10365
0
        return NULL;
10366
0
    }
10367
0
    if (len > MAX_GROUPS) {
10368
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10369
0
        return NULL;
10370
0
    }
10371
10372
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10373
0
    if (grouplist == NULL) {
10374
0
        PyErr_NoMemory();
10375
0
        return NULL;
10376
0
    }
10377
0
    for (Py_ssize_t i = 0; i < len; i++) {
10378
0
        PyObject *elem;
10379
0
        elem = PySequence_GetItem(groups, i);
10380
0
        if (!elem) {
10381
0
            PyMem_Free(grouplist);
10382
0
            return NULL;
10383
0
        }
10384
0
        if (!PyIndex_Check(elem)) {
10385
0
            PyErr_SetString(PyExc_TypeError,
10386
0
                            "groups must be integers");
10387
0
            Py_DECREF(elem);
10388
0
            PyMem_Free(grouplist);
10389
0
            return NULL;
10390
0
        } else {
10391
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10392
0
                Py_DECREF(elem);
10393
0
                PyMem_Free(grouplist);
10394
0
                return NULL;
10395
0
            }
10396
0
        }
10397
0
        Py_DECREF(elem);
10398
0
    }
10399
10400
0
    if (setgroups(len, grouplist) < 0) {
10401
0
        posix_error();
10402
0
        PyMem_Free(grouplist);
10403
0
        return NULL;
10404
0
    }
10405
0
    PyMem_Free(grouplist);
10406
0
    Py_RETURN_NONE;
10407
0
}
10408
#endif /* HAVE_SETGROUPS */
10409
10410
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10411
static PyObject *
10412
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10413
0
{
10414
0
    PyObject *result;
10415
0
    PyObject *struct_rusage;
10416
10417
0
    if (pid == -1)
10418
0
        return posix_error();
10419
10420
    // If wait succeeded but no child was ready to report status, ru will not
10421
    // have been populated.
10422
0
    if (pid == 0) {
10423
0
        memset(ru, 0, sizeof(*ru));
10424
0
    }
10425
10426
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10427
0
    if (struct_rusage == NULL)
10428
0
        return NULL;
10429
10430
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10431
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10432
0
    Py_DECREF(struct_rusage);
10433
0
    if (!result)
10434
0
        return NULL;
10435
10436
0
    int pos = 0;
10437
10438
0
#ifndef doubletime
10439
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10440
0
#endif
10441
10442
0
#define SET_RESULT(CALL)                                     \
10443
0
    do {                                                     \
10444
0
        PyObject *item = (CALL);                             \
10445
0
        if (item == NULL) {                                  \
10446
0
            Py_DECREF(result);                               \
10447
0
            return NULL;                                     \
10448
0
        }                                                    \
10449
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10450
0
    } while(0)
10451
10452
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10453
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10454
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10455
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10456
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10457
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10458
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10459
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10460
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10461
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10462
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10463
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10464
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10465
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10466
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10467
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10468
0
#undef SET_RESULT
10469
10470
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10471
0
}
10472
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10473
10474
10475
#ifdef HAVE_WAIT3
10476
/*[clinic input]
10477
os.wait3
10478
10479
    options: int
10480
Wait for completion of a child process.
10481
10482
Returns a tuple of information about the child process:
10483
  (pid, status, rusage)
10484
[clinic start generated code]*/
10485
10486
static PyObject *
10487
os_wait3_impl(PyObject *module, int options)
10488
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10489
0
{
10490
0
    pid_t pid;
10491
0
    struct rusage ru;
10492
0
    int async_err = 0;
10493
0
    WAIT_TYPE status;
10494
0
    WAIT_STATUS_INT(status) = 0;
10495
10496
0
    do {
10497
0
        Py_BEGIN_ALLOW_THREADS
10498
0
        pid = wait3(&status, options, &ru);
10499
0
        Py_END_ALLOW_THREADS
10500
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10501
0
    if (pid < 0)
10502
0
        return (!async_err) ? posix_error() : NULL;
10503
10504
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10505
0
}
10506
#endif /* HAVE_WAIT3 */
10507
10508
10509
#ifdef HAVE_WAIT4
10510
/*[clinic input]
10511
10512
os.wait4
10513
10514
    pid: pid_t
10515
    options: int
10516
10517
Wait for completion of a specific child process.
10518
10519
Returns a tuple of information about the child process:
10520
  (pid, status, rusage)
10521
[clinic start generated code]*/
10522
10523
static PyObject *
10524
os_wait4_impl(PyObject *module, pid_t pid, int options)
10525
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10526
0
{
10527
0
    pid_t res;
10528
0
    struct rusage ru;
10529
0
    int async_err = 0;
10530
0
    WAIT_TYPE status;
10531
0
    WAIT_STATUS_INT(status) = 0;
10532
10533
0
    do {
10534
0
        Py_BEGIN_ALLOW_THREADS
10535
0
        res = wait4(pid, &status, options, &ru);
10536
0
        Py_END_ALLOW_THREADS
10537
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10538
0
    if (res < 0)
10539
0
        return (!async_err) ? posix_error() : NULL;
10540
10541
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10542
0
}
10543
#endif /* HAVE_WAIT4 */
10544
10545
10546
#if defined(HAVE_WAITID)
10547
/*[clinic input]
10548
os.waitid
10549
10550
    idtype: idtype_t
10551
        Must be one of be P_PID, P_PGID or P_ALL.
10552
    id: id_t
10553
        The id to wait on.
10554
    options: int
10555
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10556
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10557
    /
10558
10559
Returns the result of waiting for a process or processes.
10560
10561
Returns either waitid_result or None if WNOHANG is specified and there are
10562
no children in a waitable state.
10563
[clinic start generated code]*/
10564
10565
static PyObject *
10566
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10567
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10568
0
{
10569
0
    PyObject *result;
10570
0
    int res;
10571
0
    int async_err = 0;
10572
0
    siginfo_t si;
10573
0
    si.si_pid = 0;
10574
10575
0
    do {
10576
0
        Py_BEGIN_ALLOW_THREADS
10577
0
        res = waitid(idtype, id, &si, options);
10578
0
        Py_END_ALLOW_THREADS
10579
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10580
0
    if (res < 0)
10581
0
        return (!async_err) ? posix_error() : NULL;
10582
10583
0
    if (si.si_pid == 0)
10584
0
        Py_RETURN_NONE;
10585
10586
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10587
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10588
0
    if (!result)
10589
0
        return NULL;
10590
10591
0
    int pos = 0;
10592
10593
0
#define SET_RESULT(CALL)                                     \
10594
0
    do {                                                     \
10595
0
        PyObject *item = (CALL);                             \
10596
0
        if (item == NULL) {                                  \
10597
0
            Py_DECREF(result);                               \
10598
0
            return NULL;                                     \
10599
0
        }                                                    \
10600
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10601
0
    } while(0)
10602
10603
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10604
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10605
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10606
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10607
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10608
10609
0
#undef SET_RESULT
10610
10611
0
    return result;
10612
0
}
10613
#endif /* defined(HAVE_WAITID) */
10614
10615
10616
#if defined(HAVE_WAITPID)
10617
/*[clinic input]
10618
os.waitpid
10619
    pid: pid_t
10620
    options: int
10621
    /
10622
10623
Wait for completion of a given child process.
10624
10625
Returns a tuple of information regarding the child process:
10626
    (pid, status)
10627
10628
The options argument is ignored on Windows.
10629
[clinic start generated code]*/
10630
10631
static PyObject *
10632
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10633
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10634
0
{
10635
0
    pid_t res;
10636
0
    int async_err = 0;
10637
0
    WAIT_TYPE status;
10638
0
    WAIT_STATUS_INT(status) = 0;
10639
10640
0
    do {
10641
0
        Py_BEGIN_ALLOW_THREADS
10642
0
        res = waitpid(pid, &status, options);
10643
0
        Py_END_ALLOW_THREADS
10644
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10645
0
    if (res < 0)
10646
0
        return (!async_err) ? posix_error() : NULL;
10647
10648
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10649
0
}
10650
#elif defined(HAVE_CWAIT)
10651
/* MS C has a variant of waitpid() that's usable for most purposes. */
10652
/*[clinic input]
10653
os.waitpid
10654
    pid: intptr_t
10655
    options: int
10656
    /
10657
10658
Wait for completion of a given process.
10659
10660
Returns a tuple of information regarding the process:
10661
    (pid, status << 8)
10662
10663
The options argument is ignored on Windows.
10664
[clinic start generated code]*/
10665
10666
static PyObject *
10667
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10668
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10669
{
10670
    int status;
10671
    intptr_t res;
10672
    int async_err = 0;
10673
10674
    do {
10675
        Py_BEGIN_ALLOW_THREADS
10676
        _Py_BEGIN_SUPPRESS_IPH
10677
        res = _cwait(&status, pid, options);
10678
        _Py_END_SUPPRESS_IPH
10679
        Py_END_ALLOW_THREADS
10680
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10681
    if (res < 0)
10682
        return (!async_err) ? posix_error() : NULL;
10683
10684
    unsigned long long ustatus = (unsigned int)status;
10685
10686
    /* shift the status left a byte so this is more like the POSIX waitpid */
10687
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10688
}
10689
#endif
10690
10691
10692
#ifdef HAVE_WAIT
10693
/*[clinic input]
10694
os.wait
10695
10696
Wait for completion of a child process.
10697
10698
Returns a tuple of information about the child process:
10699
    (pid, status)
10700
[clinic start generated code]*/
10701
10702
static PyObject *
10703
os_wait_impl(PyObject *module)
10704
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10705
0
{
10706
0
    pid_t pid;
10707
0
    int async_err = 0;
10708
0
    WAIT_TYPE status;
10709
0
    WAIT_STATUS_INT(status) = 0;
10710
10711
0
    do {
10712
0
        Py_BEGIN_ALLOW_THREADS
10713
0
        pid = wait(&status);
10714
0
        Py_END_ALLOW_THREADS
10715
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10716
0
    if (pid < 0)
10717
0
        return (!async_err) ? posix_error() : NULL;
10718
10719
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10720
0
}
10721
#endif /* HAVE_WAIT */
10722
10723
10724
// This system call always crashes on older Android versions.
10725
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10726
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10727
/*[clinic input]
10728
os.pidfd_open
10729
  pid: pid_t
10730
  flags: unsigned_int = 0
10731
10732
Return a file descriptor referring to the process *pid*.
10733
10734
The descriptor can be used to perform process management without races and
10735
signals.
10736
[clinic start generated code]*/
10737
10738
static PyObject *
10739
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10740
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10741
0
{
10742
0
    int fd = syscall(__NR_pidfd_open, pid, flags);
10743
0
    if (fd < 0) {
10744
0
        return posix_error();
10745
0
    }
10746
0
    return PyLong_FromLong(fd);
10747
0
}
10748
#endif
10749
10750
10751
#ifdef HAVE_SETNS
10752
/*[clinic input]
10753
os.setns
10754
  fd: fildes
10755
    A file descriptor to a namespace.
10756
  nstype: int = 0
10757
    Type of namespace.
10758
10759
Move the calling thread into different namespaces.
10760
[clinic start generated code]*/
10761
10762
static PyObject *
10763
os_setns_impl(PyObject *module, int fd, int nstype)
10764
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10765
0
{
10766
0
    int res;
10767
10768
0
    Py_BEGIN_ALLOW_THREADS
10769
0
    res = setns(fd, nstype);
10770
0
    Py_END_ALLOW_THREADS
10771
10772
0
    if (res != 0) {
10773
0
        return posix_error();
10774
0
    }
10775
10776
0
    Py_RETURN_NONE;
10777
0
}
10778
#endif
10779
10780
10781
#ifdef HAVE_UNSHARE
10782
/*[clinic input]
10783
os.unshare
10784
  flags: int
10785
    Namespaces to be unshared.
10786
10787
Disassociate parts of a process (or thread) execution context.
10788
[clinic start generated code]*/
10789
10790
static PyObject *
10791
os_unshare_impl(PyObject *module, int flags)
10792
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10793
0
{
10794
0
    int res;
10795
10796
0
    Py_BEGIN_ALLOW_THREADS
10797
0
    res = unshare(flags);
10798
0
    Py_END_ALLOW_THREADS
10799
10800
0
    if (res != 0) {
10801
0
        return posix_error();
10802
0
    }
10803
10804
0
    Py_RETURN_NONE;
10805
0
}
10806
#endif
10807
10808
10809
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10810
/*[clinic input]
10811
os.readlink
10812
10813
    path: path_t
10814
    *
10815
    dir_fd: dir_fd(requires='readlinkat') = None
10816
10817
Return a string representing the path to which the symbolic link points.
10818
10819
If dir_fd is not None, it should be a file descriptor open to a directory,
10820
and path should be relative; path will then be relative to that directory.
10821
10822
dir_fd may not be implemented on your platform.  If it is unavailable,
10823
using it will raise a NotImplementedError.
10824
[clinic start generated code]*/
10825
10826
static PyObject *
10827
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10828
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10829
0
{
10830
0
#if defined(HAVE_READLINK)
10831
0
    char buffer[MAXPATHLEN+1];
10832
0
    ssize_t length;
10833
0
#ifdef HAVE_READLINKAT
10834
0
    int readlinkat_unavailable = 0;
10835
0
#endif
10836
10837
0
    Py_BEGIN_ALLOW_THREADS
10838
0
#ifdef HAVE_READLINKAT
10839
0
    if (dir_fd != DEFAULT_DIR_FD) {
10840
0
        if (HAVE_READLINKAT_RUNTIME) {
10841
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10842
0
        } else {
10843
0
            readlinkat_unavailable = 1;
10844
0
        }
10845
0
    } else
10846
0
#endif
10847
0
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10848
0
    Py_END_ALLOW_THREADS
10849
10850
0
#ifdef HAVE_READLINKAT
10851
0
    if (readlinkat_unavailable) {
10852
0
        argument_unavailable_error(NULL, "dir_fd");
10853
0
        return NULL;
10854
0
    }
10855
0
#endif
10856
10857
0
    if (length < 0) {
10858
0
        return path_error(path);
10859
0
    }
10860
0
    buffer[length] = '\0';
10861
10862
0
    if (PyUnicode_Check(path->object))
10863
0
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10864
0
    else
10865
0
        return PyBytes_FromStringAndSize(buffer, length);
10866
#elif defined(MS_WINDOWS)
10867
    DWORD n_bytes_returned;
10868
    DWORD io_result = 0;
10869
    HANDLE reparse_point_handle;
10870
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10871
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10872
    PyObject *result = NULL;
10873
10874
    /* First get a handle to the reparse point */
10875
    Py_BEGIN_ALLOW_THREADS
10876
    reparse_point_handle = CreateFileW(
10877
        path->wide,
10878
        0,
10879
        0,
10880
        0,
10881
        OPEN_EXISTING,
10882
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10883
        0);
10884
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10885
        /* New call DeviceIoControl to read the reparse point */
10886
        io_result = DeviceIoControl(
10887
            reparse_point_handle,
10888
            FSCTL_GET_REPARSE_POINT,
10889
            0, 0, /* in buffer */
10890
            target_buffer, sizeof(target_buffer),
10891
            &n_bytes_returned,
10892
            0 /* we're not using OVERLAPPED_IO */
10893
            );
10894
        CloseHandle(reparse_point_handle);
10895
    }
10896
    Py_END_ALLOW_THREADS
10897
10898
    if (io_result == 0) {
10899
        return path_error(path);
10900
    }
10901
10902
    wchar_t *name = NULL;
10903
    Py_ssize_t nameLen = 0;
10904
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10905
    {
10906
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10907
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10908
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10909
    }
10910
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10911
    {
10912
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10913
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10914
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10915
    }
10916
    else
10917
    {
10918
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10919
    }
10920
    if (name) {
10921
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10922
            /* Our buffer is mutable, so this is okay */
10923
            name[1] = L'\\';
10924
        }
10925
        result = PyUnicode_FromWideChar(name, nameLen);
10926
        if (result && PyBytes_Check(path->object)) {
10927
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10928
        }
10929
    }
10930
    return result;
10931
#endif
10932
0
}
10933
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10934
10935
#if defined(MS_WINDOWS)
10936
10937
/* Remove the last portion of the path - return 0 on success */
10938
static int
10939
_dirnameW(WCHAR *path)
10940
{
10941
    WCHAR *ptr;
10942
    size_t length = wcsnlen_s(path, MAX_PATH);
10943
    if (length == MAX_PATH) {
10944
        return -1;
10945
    }
10946
10947
    /* walk the path from the end until a backslash is encountered */
10948
    for(ptr = path + length; ptr != path; ptr--) {
10949
        if (*ptr == L'\\' || *ptr == L'/') {
10950
            break;
10951
        }
10952
    }
10953
    *ptr = 0;
10954
    return 0;
10955
}
10956
10957
#endif
10958
10959
#ifdef HAVE_SYMLINK
10960
10961
#if defined(MS_WINDOWS)
10962
10963
/* Is this path absolute? */
10964
static int
10965
_is_absW(const WCHAR *path)
10966
{
10967
    return path[0] == L'\\' || path[0] == L'/' ||
10968
        (path[0] && path[1] == L':');
10969
}
10970
10971
/* join root and rest with a backslash - return 0 on success */
10972
static int
10973
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10974
{
10975
    if (_is_absW(rest)) {
10976
        return wcscpy_s(dest_path, MAX_PATH, rest);
10977
    }
10978
10979
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
10980
        return -1;
10981
    }
10982
10983
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
10984
        return -1;
10985
    }
10986
10987
    return wcscat_s(dest_path, MAX_PATH, rest);
10988
}
10989
10990
/* Return True if the path at src relative to dest is a directory */
10991
static int
10992
_check_dirW(LPCWSTR src, LPCWSTR dest)
10993
{
10994
    WIN32_FILE_ATTRIBUTE_DATA src_info;
10995
    WCHAR dest_parent[MAX_PATH];
10996
    WCHAR src_resolved[MAX_PATH] = L"";
10997
10998
    /* dest_parent = os.path.dirname(dest) */
10999
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11000
        _dirnameW(dest_parent)) {
11001
        return 0;
11002
    }
11003
    /* src_resolved = os.path.join(dest_parent, src) */
11004
    if (_joinW(src_resolved, dest_parent, src)) {
11005
        return 0;
11006
    }
11007
    return (
11008
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11009
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11010
    );
11011
}
11012
#endif
11013
11014
11015
/*[clinic input]
11016
os.symlink
11017
    src: path_t
11018
    dst: path_t
11019
    target_is_directory: bool = False
11020
    *
11021
    dir_fd: dir_fd(requires='symlinkat')=None
11022
11023
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
11024
11025
Create a symbolic link pointing to src named dst.
11026
11027
target_is_directory is required on Windows if the target is to be
11028
  interpreted as a directory.  (On Windows, symlink requires
11029
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
11030
  target_is_directory is ignored on non-Windows platforms.
11031
11032
If dir_fd is not None, it should be a file descriptor open to a directory,
11033
  and path should be relative; path will then be relative to that directory.
11034
dir_fd may not be implemented on your platform.
11035
  If it is unavailable, using it will raise a NotImplementedError.
11036
11037
[clinic start generated code]*/
11038
11039
static PyObject *
11040
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11041
                int target_is_directory, int dir_fd)
11042
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
11043
0
{
11044
#ifdef MS_WINDOWS
11045
    DWORD result;
11046
    DWORD flags = 0;
11047
11048
    /* Assumed true, set to false if detected to not be available. */
11049
    static int windows_has_symlink_unprivileged_flag = TRUE;
11050
#else
11051
0
    int result;
11052
0
#ifdef HAVE_SYMLINKAT
11053
0
    int symlinkat_unavailable = 0;
11054
0
#endif
11055
0
#endif
11056
11057
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11058
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11059
0
        return NULL;
11060
0
    }
11061
11062
#ifdef MS_WINDOWS
11063
11064
    if (windows_has_symlink_unprivileged_flag) {
11065
        /* Allow non-admin symlinks if system allows it. */
11066
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11067
    }
11068
11069
    Py_BEGIN_ALLOW_THREADS
11070
    _Py_BEGIN_SUPPRESS_IPH
11071
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11072
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11073
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11074
    }
11075
11076
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11077
    _Py_END_SUPPRESS_IPH
11078
    Py_END_ALLOW_THREADS
11079
11080
    if (windows_has_symlink_unprivileged_flag && !result &&
11081
        ERROR_INVALID_PARAMETER == GetLastError()) {
11082
11083
        Py_BEGIN_ALLOW_THREADS
11084
        _Py_BEGIN_SUPPRESS_IPH
11085
        /* This error might be caused by
11086
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11087
        Try again, and update windows_has_symlink_unprivileged_flag if we
11088
        are successful this time.
11089
11090
        NOTE: There is a risk of a race condition here if there are other
11091
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11092
        another process (or thread) changes that condition in between our
11093
        calls to CreateSymbolicLink.
11094
        */
11095
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11096
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11097
        _Py_END_SUPPRESS_IPH
11098
        Py_END_ALLOW_THREADS
11099
11100
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11101
            windows_has_symlink_unprivileged_flag = FALSE;
11102
        }
11103
    }
11104
11105
    if (!result)
11106
        return path_error2(src, dst);
11107
11108
#else
11109
11110
0
    Py_BEGIN_ALLOW_THREADS
11111
0
#ifdef HAVE_SYMLINKAT
11112
0
    if (dir_fd != DEFAULT_DIR_FD) {
11113
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11114
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11115
0
        } else {
11116
0
            symlinkat_unavailable = 1;
11117
0
        }
11118
0
    } else
11119
0
#endif
11120
0
        result = symlink(src->narrow, dst->narrow);
11121
0
    Py_END_ALLOW_THREADS
11122
11123
0
#ifdef HAVE_SYMLINKAT
11124
0
    if (symlinkat_unavailable) {
11125
0
          argument_unavailable_error(NULL, "dir_fd");
11126
0
          return NULL;
11127
0
    }
11128
0
#endif
11129
11130
0
    if (result)
11131
0
        return path_error2(src, dst);
11132
0
#endif
11133
11134
0
    Py_RETURN_NONE;
11135
0
}
11136
#endif /* HAVE_SYMLINK */
11137
11138
11139
static PyStructSequence_Field times_result_fields[] = {
11140
    {"user",    "user time"},
11141
    {"system",   "system time"},
11142
    {"children_user",    "user time of children"},
11143
    {"children_system",    "system time of children"},
11144
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11145
    {NULL}
11146
};
11147
11148
PyDoc_STRVAR(times_result__doc__,
11149
"times_result: Result from os.times().\n\n\
11150
This object may be accessed either as a tuple of\n\
11151
  (user, system, children_user, children_system, elapsed),\n\
11152
or via the attributes user, system, children_user, children_system,\n\
11153
and elapsed.\n\
11154
\n\
11155
See os.times for more information.");
11156
11157
static PyStructSequence_Desc times_result_desc = {
11158
    MODNAME ".times_result", /* name */
11159
    times_result__doc__, /* doc */
11160
    times_result_fields,
11161
    5
11162
};
11163
11164
static PyObject *
11165
build_times_result(PyObject *module, double user, double system,
11166
    double children_user, double children_system,
11167
    double elapsed)
11168
0
{
11169
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11170
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11171
0
    if (value == NULL)
11172
0
        return NULL;
11173
11174
0
#define SET(i, field) \
11175
0
    { \
11176
0
    PyObject *o = PyFloat_FromDouble(field); \
11177
0
    if (!o) { \
11178
0
        Py_DECREF(value); \
11179
0
        return NULL; \
11180
0
    } \
11181
0
    PyStructSequence_SET_ITEM(value, i, o); \
11182
0
    } \
11183
0
11184
0
    SET(0, user);
11185
0
    SET(1, system);
11186
0
    SET(2, children_user);
11187
0
    SET(3, children_system);
11188
0
    SET(4, elapsed);
11189
11190
0
#undef SET
11191
11192
0
    return value;
11193
0
}
11194
11195
11196
/*[clinic input]
11197
os.times
11198
11199
Return a collection containing process timing information.
11200
11201
The object returned behaves like a named tuple with these fields:
11202
  (utime, stime, cutime, cstime, elapsed_time)
11203
All fields are floating-point numbers.
11204
[clinic start generated code]*/
11205
11206
static PyObject *
11207
os_times_impl(PyObject *module)
11208
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11209
0
{
11210
#ifdef MS_WINDOWS
11211
    FILETIME create, exit, kernel, user;
11212
    HANDLE hProc;
11213
    hProc = GetCurrentProcess();
11214
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11215
    /* The fields of a FILETIME structure are the hi and lo part
11216
       of a 64-bit value expressed in 100 nanosecond units.
11217
       1e7 is one second in such units; 1e-7 the inverse.
11218
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11219
    */
11220
    return build_times_result(module,
11221
        (double)(user.dwHighDateTime*429.4967296 +
11222
                 user.dwLowDateTime*1e-7),
11223
        (double)(kernel.dwHighDateTime*429.4967296 +
11224
                 kernel.dwLowDateTime*1e-7),
11225
        (double)0,
11226
        (double)0,
11227
        (double)0);
11228
#else /* MS_WINDOWS */
11229
0
    _posixstate *state = get_posix_state(module);
11230
0
    long ticks_per_second = state->ticks_per_second;
11231
11232
0
    struct tms process;
11233
0
    clock_t elapsed;
11234
0
    errno = 0;
11235
0
    elapsed = times(&process);
11236
0
    if (elapsed == (clock_t) -1) {
11237
0
        return posix_error();
11238
0
    }
11239
11240
0
    return build_times_result(module,
11241
0
        (double)process.tms_utime / ticks_per_second,
11242
0
        (double)process.tms_stime / ticks_per_second,
11243
0
        (double)process.tms_cutime / ticks_per_second,
11244
0
        (double)process.tms_cstime / ticks_per_second,
11245
0
        (double)elapsed / ticks_per_second);
11246
0
#endif /* MS_WINDOWS */
11247
0
}
11248
11249
11250
#if defined(HAVE_TIMERFD_CREATE)
11251
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11252
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11253
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11254
11255
static PyObject *
11256
build_itimerspec(const struct itimerspec* curr_value)
11257
0
{
11258
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11259
0
                                                          curr_value->it_value.tv_nsec);
11260
0
    PyObject *value = PyFloat_FromDouble(_value);
11261
0
    if (value == NULL) {
11262
0
        return NULL;
11263
0
    }
11264
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11265
0
                                                   curr_value->it_interval.tv_nsec);
11266
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11267
0
    if (interval == NULL) {
11268
0
        Py_DECREF(value);
11269
0
        return NULL;
11270
0
    }
11271
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
11272
0
    Py_DECREF(interval);
11273
0
    Py_DECREF(value);
11274
0
    return tuple;
11275
0
}
11276
11277
static PyObject *
11278
build_itimerspec_ns(const struct itimerspec* curr_value)
11279
0
{
11280
0
    PyTime_t value, interval;
11281
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11282
0
        return NULL;
11283
0
    }
11284
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11285
0
        return NULL;
11286
0
    }
11287
0
    return Py_BuildValue("LL", value, interval);
11288
0
}
11289
11290
/*[clinic input]
11291
os.timerfd_create
11292
11293
    clockid: int
11294
        A valid clock ID constant as timer file descriptor.
11295
11296
        time.CLOCK_REALTIME
11297
        time.CLOCK_MONOTONIC
11298
        time.CLOCK_BOOTTIME
11299
    /
11300
    *
11301
    flags: int = 0
11302
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11303
11304
        os.TFD_NONBLOCK
11305
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11306
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11307
11308
        os.TFD_CLOEXEC
11309
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11310
11311
Create and return a timer file descriptor.
11312
[clinic start generated code]*/
11313
11314
static PyObject *
11315
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11316
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11317
11318
0
{
11319
0
    int fd;
11320
0
    Py_BEGIN_ALLOW_THREADS
11321
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11322
0
    fd = timerfd_create(clockid, flags);
11323
0
    Py_END_ALLOW_THREADS
11324
0
    if (fd == -1) {
11325
0
        return PyErr_SetFromErrno(PyExc_OSError);
11326
0
    }
11327
0
    return PyLong_FromLong(fd);
11328
0
}
11329
11330
/*[clinic input]
11331
os.timerfd_settime
11332
11333
    fd: fildes
11334
        A timer file descriptor.
11335
    /
11336
    *
11337
    flags: int = 0
11338
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11339
    initial as initial_double: double = 0.0
11340
        The initial expiration time, in seconds.
11341
    interval as interval_double: double = 0.0
11342
        The timer's interval, in seconds.
11343
11344
Alter a timer file descriptor's internal timer in seconds.
11345
[clinic start generated code]*/
11346
11347
static PyObject *
11348
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11349
                        double initial_double, double interval_double)
11350
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11351
0
{
11352
0
    PyTime_t initial, interval;
11353
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11354
0
                                  &initial) < 0) {
11355
0
        return NULL;
11356
0
    }
11357
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11358
0
                                  &interval) < 0) {
11359
0
        return NULL;
11360
0
    }
11361
11362
0
    struct itimerspec new_value, old_value;
11363
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11364
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11365
0
        return NULL;
11366
0
    }
11367
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11368
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11369
0
        return NULL;
11370
0
    }
11371
11372
0
    int result;
11373
0
    Py_BEGIN_ALLOW_THREADS
11374
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11375
0
    Py_END_ALLOW_THREADS
11376
0
    if (result == -1) {
11377
0
        return PyErr_SetFromErrno(PyExc_OSError);
11378
0
    }
11379
0
    return build_itimerspec(&old_value);
11380
0
}
11381
11382
11383
/*[clinic input]
11384
os.timerfd_settime_ns
11385
11386
    fd: fildes
11387
        A timer file descriptor.
11388
    /
11389
    *
11390
    flags: int = 0
11391
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11392
    initial: long_long = 0
11393
        initial expiration timing in seconds.
11394
    interval: long_long = 0
11395
        interval for the timer in seconds.
11396
11397
Alter a timer file descriptor's internal timer in nanoseconds.
11398
[clinic start generated code]*/
11399
11400
static PyObject *
11401
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11402
                           long long initial, long long interval)
11403
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
11404
0
{
11405
0
    struct itimerspec new_value;
11406
0
    struct itimerspec old_value;
11407
0
    int result;
11408
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11409
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11410
0
        return NULL;
11411
0
    }
11412
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11413
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11414
0
        return NULL;
11415
0
    }
11416
0
    Py_BEGIN_ALLOW_THREADS
11417
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11418
0
    Py_END_ALLOW_THREADS
11419
0
    if (result == -1) {
11420
0
        return PyErr_SetFromErrno(PyExc_OSError);
11421
0
    }
11422
0
    return build_itimerspec_ns(&old_value);
11423
0
}
11424
11425
/*[clinic input]
11426
@permit_long_summary
11427
os.timerfd_gettime
11428
11429
    fd: fildes
11430
        A timer file descriptor.
11431
    /
11432
11433
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
11434
[clinic start generated code]*/
11435
11436
static PyObject *
11437
os_timerfd_gettime_impl(PyObject *module, int fd)
11438
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11439
0
{
11440
0
    struct itimerspec curr_value;
11441
0
    int result;
11442
0
    Py_BEGIN_ALLOW_THREADS
11443
0
    result = timerfd_gettime(fd, &curr_value);
11444
0
    Py_END_ALLOW_THREADS
11445
0
    if (result == -1) {
11446
0
        return PyErr_SetFromErrno(PyExc_OSError);
11447
0
    }
11448
0
    return build_itimerspec(&curr_value);
11449
0
}
11450
11451
11452
/*[clinic input]
11453
@permit_long_summary
11454
os.timerfd_gettime_ns
11455
11456
    fd: fildes
11457
        A timer file descriptor.
11458
    /
11459
11460
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11461
[clinic start generated code]*/
11462
11463
static PyObject *
11464
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11465
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11466
0
{
11467
0
    struct itimerspec curr_value;
11468
0
    int result;
11469
0
    Py_BEGIN_ALLOW_THREADS
11470
0
    result = timerfd_gettime(fd, &curr_value);
11471
0
    Py_END_ALLOW_THREADS
11472
0
    if (result == -1) {
11473
0
        return PyErr_SetFromErrno(PyExc_OSError);
11474
0
    }
11475
0
    return build_itimerspec_ns(&curr_value);
11476
0
}
11477
11478
#undef ONE_SECOND_IN_NS
11479
#undef EXTRACT_NSEC
11480
11481
#endif  /* HAVE_TIMERFD_CREATE */
11482
11483
#ifdef HAVE_GETSID
11484
/*[clinic input]
11485
os.getsid
11486
11487
    pid: pid_t
11488
    /
11489
11490
Call the system call getsid(pid) and return the result.
11491
[clinic start generated code]*/
11492
11493
static PyObject *
11494
os_getsid_impl(PyObject *module, pid_t pid)
11495
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11496
0
{
11497
0
    int sid;
11498
0
    sid = getsid(pid);
11499
0
    if (sid < 0)
11500
0
        return posix_error();
11501
0
    return PyLong_FromLong((long)sid);
11502
0
}
11503
#endif /* HAVE_GETSID */
11504
11505
11506
#ifdef HAVE_SETSID
11507
/*[clinic input]
11508
os.setsid
11509
11510
Call the system call setsid().
11511
[clinic start generated code]*/
11512
11513
static PyObject *
11514
os_setsid_impl(PyObject *module)
11515
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11516
0
{
11517
0
    if (setsid() < 0)
11518
0
        return posix_error();
11519
0
    Py_RETURN_NONE;
11520
0
}
11521
#endif /* HAVE_SETSID */
11522
11523
11524
#ifdef HAVE_SETPGID
11525
/*[clinic input]
11526
os.setpgid
11527
11528
    pid: pid_t
11529
    pgrp: pid_t
11530
    /
11531
11532
Call the system call setpgid(pid, pgrp).
11533
[clinic start generated code]*/
11534
11535
static PyObject *
11536
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11537
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11538
0
{
11539
0
    if (setpgid(pid, pgrp) < 0)
11540
0
        return posix_error();
11541
0
    Py_RETURN_NONE;
11542
0
}
11543
#endif /* HAVE_SETPGID */
11544
11545
11546
#ifdef HAVE_TCGETPGRP
11547
/*[clinic input]
11548
os.tcgetpgrp
11549
11550
    fd: int
11551
    /
11552
11553
Return the process group associated with the terminal specified by fd.
11554
[clinic start generated code]*/
11555
11556
static PyObject *
11557
os_tcgetpgrp_impl(PyObject *module, int fd)
11558
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11559
0
{
11560
0
    pid_t pgid = tcgetpgrp(fd);
11561
0
    if (pgid < 0)
11562
0
        return posix_error();
11563
0
    return PyLong_FromPid(pgid);
11564
0
}
11565
#endif /* HAVE_TCGETPGRP */
11566
11567
11568
#ifdef HAVE_TCSETPGRP
11569
/*[clinic input]
11570
os.tcsetpgrp
11571
11572
    fd: int
11573
    pgid: pid_t
11574
    /
11575
11576
Set the process group associated with the terminal specified by fd.
11577
[clinic start generated code]*/
11578
11579
static PyObject *
11580
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11581
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11582
0
{
11583
0
    if (tcsetpgrp(fd, pgid) < 0)
11584
0
        return posix_error();
11585
0
    Py_RETURN_NONE;
11586
0
}
11587
#endif /* HAVE_TCSETPGRP */
11588
11589
/* Functions acting on file descriptors */
11590
11591
#ifdef O_CLOEXEC
11592
extern int _Py_open_cloexec_works;
11593
#endif
11594
11595
11596
/*[clinic input]
11597
os.open -> int
11598
    path: path_t
11599
    flags: int
11600
    mode: int = 0o777
11601
    *
11602
    dir_fd: dir_fd(requires='openat') = None
11603
11604
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11605
11606
Open a file for low level IO.  Returns a file descriptor (integer).
11607
11608
If dir_fd is not None, it should be a file descriptor open to a directory,
11609
  and path should be relative; path will then be relative to that directory.
11610
dir_fd may not be implemented on your platform.
11611
  If it is unavailable, using it will raise a NotImplementedError.
11612
[clinic start generated code]*/
11613
11614
static int
11615
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11616
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11617
138k
{
11618
138k
    int fd;
11619
138k
    int async_err = 0;
11620
138k
#ifdef HAVE_OPENAT
11621
138k
    int openat_unavailable = 0;
11622
138k
#endif
11623
11624
138k
#ifdef O_CLOEXEC
11625
138k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11626
#elif !defined(MS_WINDOWS)
11627
    int *atomic_flag_works = NULL;
11628
#endif
11629
11630
#ifdef MS_WINDOWS
11631
    flags |= O_NOINHERIT;
11632
#elif defined(O_CLOEXEC)
11633
138k
    flags |= O_CLOEXEC;
11634
138k
#endif
11635
11636
138k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11637
0
        return -1;
11638
0
    }
11639
11640
138k
    _Py_BEGIN_SUPPRESS_IPH
11641
138k
    do {
11642
138k
        Py_BEGIN_ALLOW_THREADS
11643
#ifdef MS_WINDOWS
11644
        fd = _wopen(path->wide, flags, mode);
11645
#else
11646
138k
#ifdef HAVE_OPENAT
11647
138k
        if (dir_fd != DEFAULT_DIR_FD) {
11648
134k
            if (HAVE_OPENAT_RUNTIME) {
11649
134k
                fd = openat(dir_fd, path->narrow, flags, mode);
11650
11651
134k
            } else {
11652
0
                openat_unavailable = 1;
11653
0
                fd = -1;
11654
0
            }
11655
134k
        } else
11656
4.26k
#endif /* HAVE_OPENAT */
11657
4.26k
            fd = open(path->narrow, flags, mode);
11658
138k
#endif /* !MS_WINDOWS */
11659
138k
        Py_END_ALLOW_THREADS
11660
138k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11661
138k
    _Py_END_SUPPRESS_IPH
11662
11663
138k
#ifdef HAVE_OPENAT
11664
138k
    if (openat_unavailable) {
11665
0
        argument_unavailable_error(NULL, "dir_fd");
11666
0
        return -1;
11667
0
    }
11668
138k
#endif
11669
11670
138k
    if (fd < 0) {
11671
0
        if (!async_err)
11672
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11673
0
        return -1;
11674
0
    }
11675
11676
138k
#ifndef MS_WINDOWS
11677
138k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11678
0
        close(fd);
11679
0
        return -1;
11680
0
    }
11681
138k
#endif
11682
11683
138k
    return fd;
11684
138k
}
11685
11686
11687
/*[clinic input]
11688
os.close
11689
11690
    fd: int
11691
11692
Close a file descriptor.
11693
[clinic start generated code]*/
11694
11695
static PyObject *
11696
os_close_impl(PyObject *module, int fd)
11697
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11698
138k
{
11699
138k
    int res;
11700
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11701
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11702
     * for more details.
11703
     */
11704
138k
    Py_BEGIN_ALLOW_THREADS
11705
138k
    _Py_BEGIN_SUPPRESS_IPH
11706
138k
    res = close(fd);
11707
138k
    _Py_END_SUPPRESS_IPH
11708
138k
    Py_END_ALLOW_THREADS
11709
138k
    if (res < 0)
11710
0
        return posix_error();
11711
138k
    Py_RETURN_NONE;
11712
138k
}
11713
11714
/*[clinic input]
11715
os.closerange
11716
11717
    fd_low: int
11718
    fd_high: int
11719
    /
11720
11721
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11722
[clinic start generated code]*/
11723
11724
static PyObject *
11725
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11726
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11727
0
{
11728
0
    Py_BEGIN_ALLOW_THREADS
11729
0
    _Py_closerange(fd_low, fd_high - 1);
11730
0
    Py_END_ALLOW_THREADS
11731
0
    Py_RETURN_NONE;
11732
0
}
11733
11734
11735
/*[clinic input]
11736
os.dup -> int
11737
11738
    fd: int
11739
    /
11740
11741
Return a duplicate of a file descriptor.
11742
[clinic start generated code]*/
11743
11744
static int
11745
os_dup_impl(PyObject *module, int fd)
11746
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11747
0
{
11748
0
    return _Py_dup(fd);
11749
0
}
11750
11751
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11752
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11753
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11754
/*[clinic input]
11755
os.dup2 -> int
11756
    fd: int
11757
    fd2: int
11758
    inheritable: bool=True
11759
11760
Duplicate file descriptor.
11761
[clinic start generated code]*/
11762
11763
static int
11764
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11765
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11766
0
{
11767
0
    int res = 0;
11768
0
#if defined(HAVE_DUP3) && \
11769
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11770
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11771
0
    static int dup3_works = -1;
11772
0
#endif
11773
11774
    /* dup2() can fail with EINTR if the target FD is already open, because it
11775
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11776
     * upon close(), and therefore below.
11777
     */
11778
#ifdef MS_WINDOWS
11779
    Py_BEGIN_ALLOW_THREADS
11780
    _Py_BEGIN_SUPPRESS_IPH
11781
    res = dup2(fd, fd2);
11782
    _Py_END_SUPPRESS_IPH
11783
    Py_END_ALLOW_THREADS
11784
    if (res < 0) {
11785
        posix_error();
11786
        return -1;
11787
    }
11788
    res = fd2; // msvcrt dup2 returns 0 on success.
11789
11790
    /* Character files like console cannot be make non-inheritable */
11791
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11792
        close(fd2);
11793
        return -1;
11794
    }
11795
11796
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11797
    Py_BEGIN_ALLOW_THREADS
11798
    if (!inheritable)
11799
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11800
    else
11801
        res = dup2(fd, fd2);
11802
    Py_END_ALLOW_THREADS
11803
    if (res < 0) {
11804
        posix_error();
11805
        return -1;
11806
    }
11807
11808
#else
11809
11810
0
#ifdef HAVE_DUP3
11811
0
    if (!inheritable && dup3_works != 0) {
11812
0
        Py_BEGIN_ALLOW_THREADS
11813
0
        res = dup3(fd, fd2, O_CLOEXEC);
11814
0
        Py_END_ALLOW_THREADS
11815
0
        if (res < 0) {
11816
0
            if (dup3_works == -1)
11817
0
                dup3_works = (errno != ENOSYS);
11818
0
            if (dup3_works) {
11819
0
                posix_error();
11820
0
                return -1;
11821
0
            }
11822
0
        }
11823
0
    }
11824
11825
0
    if (inheritable || dup3_works == 0)
11826
0
    {
11827
0
#endif
11828
0
        Py_BEGIN_ALLOW_THREADS
11829
0
        res = dup2(fd, fd2);
11830
0
        Py_END_ALLOW_THREADS
11831
0
        if (res < 0) {
11832
0
            posix_error();
11833
0
            return -1;
11834
0
        }
11835
11836
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11837
0
            close(fd2);
11838
0
            return -1;
11839
0
        }
11840
0
#ifdef HAVE_DUP3
11841
0
    }
11842
0
#endif
11843
11844
0
#endif
11845
11846
0
    return res;
11847
0
}
11848
#endif
11849
11850
11851
#ifdef HAVE_LOCKF
11852
/*[clinic input]
11853
os.lockf
11854
11855
    fd: int
11856
        An open file descriptor.
11857
    command: int
11858
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11859
    length: Py_off_t
11860
        The number of bytes to lock, starting at the current position.
11861
    /
11862
11863
Apply, test or remove a POSIX lock on an open file descriptor.
11864
11865
[clinic start generated code]*/
11866
11867
static PyObject *
11868
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11869
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11870
0
{
11871
0
    int res;
11872
11873
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11874
0
        return NULL;
11875
0
    }
11876
11877
0
    Py_BEGIN_ALLOW_THREADS
11878
0
    res = lockf(fd, command, length);
11879
0
    Py_END_ALLOW_THREADS
11880
11881
0
    if (res < 0)
11882
0
        return posix_error();
11883
11884
0
    Py_RETURN_NONE;
11885
0
}
11886
#endif /* HAVE_LOCKF */
11887
11888
11889
/*[clinic input]
11890
@permit_long_docstring_body
11891
os.lseek -> Py_off_t
11892
11893
    fd: int
11894
        An open file descriptor, as returned by os.open().
11895
    position: Py_off_t
11896
        Position, interpreted relative to 'whence'.
11897
    whence as how: int
11898
        The relative position to seek from. Valid values are:
11899
        - SEEK_SET: seek from the start of the file.
11900
        - SEEK_CUR: seek from the current file position.
11901
        - SEEK_END: seek from the end of the file.
11902
    /
11903
11904
Set the position of a file descriptor.  Return the new position.
11905
11906
The return value is the number of bytes relative to the beginning of the file.
11907
[clinic start generated code]*/
11908
11909
static Py_off_t
11910
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11911
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11912
0
{
11913
0
    Py_off_t result;
11914
11915
0
#ifdef SEEK_SET
11916
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11917
0
    switch (how) {
11918
0
        case 0: how = SEEK_SET; break;
11919
0
        case 1: how = SEEK_CUR; break;
11920
0
        case 2: how = SEEK_END; break;
11921
0
    }
11922
0
#endif /* SEEK_END */
11923
11924
0
    Py_BEGIN_ALLOW_THREADS
11925
0
    _Py_BEGIN_SUPPRESS_IPH
11926
#ifdef MS_WINDOWS
11927
    result = _lseeki64(fd, position, how);
11928
#else
11929
0
    result = lseek(fd, position, how);
11930
0
#endif
11931
0
    _Py_END_SUPPRESS_IPH
11932
0
    Py_END_ALLOW_THREADS
11933
0
    if (result < 0)
11934
0
        posix_error();
11935
11936
0
    return result;
11937
0
}
11938
11939
11940
/*[clinic input]
11941
os.read
11942
    fd: int
11943
    length: Py_ssize_t
11944
    /
11945
11946
Read from a file descriptor.  Returns a bytes object.
11947
[clinic start generated code]*/
11948
11949
static PyObject *
11950
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11951
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11952
0
{
11953
0
    if (length < 0) {
11954
0
        errno = EINVAL;
11955
0
        return posix_error();
11956
0
    }
11957
11958
0
    length = Py_MIN(length, _PY_READ_MAX);
11959
11960
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11961
0
    if (writer == NULL) {
11962
0
        return NULL;
11963
0
    }
11964
11965
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11966
0
    if (n == -1) {
11967
0
        PyBytesWriter_Discard(writer);
11968
0
        return NULL;
11969
0
    }
11970
11971
0
    return PyBytesWriter_FinishWithSize(writer, n);
11972
0
}
11973
11974
/*[clinic input]
11975
@permit_long_docstring_body
11976
os.readinto -> Py_ssize_t
11977
    fd: int
11978
    buffer: Py_buffer(accept={rwbuffer})
11979
    /
11980
11981
Read into a buffer object from a file descriptor.
11982
11983
The buffer should be mutable and bytes-like. On success, returns the number of
11984
bytes read. Less bytes may be read than the size of the buffer. The underlying
11985
system call will be retried when interrupted by a signal, unless the signal
11986
handler raises an exception. Other errors will not be retried and an error will
11987
be raised.
11988
11989
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
11990
(which can be used to check for errors without reading data). Never returns
11991
negative.
11992
[clinic start generated code]*/
11993
11994
static Py_ssize_t
11995
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
11996
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
11997
0
{
11998
0
    assert(buffer->len >= 0);
11999
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12000
    /* Ensure negative is never returned without an error. Simplifies calling
12001
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12002
        error. */
12003
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12004
0
    return result;
12005
0
}
12006
12007
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12008
                                || defined(__APPLE__))) \
12009
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12010
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12011
static int
12012
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12013
0
{
12014
0
    Py_ssize_t i, j;
12015
12016
0
    *iov = PyMem_New(struct iovec, cnt);
12017
0
    if (*iov == NULL) {
12018
0
        PyErr_NoMemory();
12019
0
        return -1;
12020
0
    }
12021
12022
0
    *buf = PyMem_New(Py_buffer, cnt);
12023
0
    if (*buf == NULL) {
12024
0
        PyMem_Free(*iov);
12025
0
        PyErr_NoMemory();
12026
0
        return -1;
12027
0
    }
12028
12029
0
    for (i = 0; i < cnt; i++) {
12030
0
        PyObject *item = PySequence_GetItem(seq, i);
12031
0
        if (item == NULL)
12032
0
            goto fail;
12033
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12034
0
            Py_DECREF(item);
12035
0
            goto fail;
12036
0
        }
12037
0
        Py_DECREF(item);
12038
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12039
0
        (*iov)[i].iov_len = (*buf)[i].len;
12040
0
    }
12041
0
    return 0;
12042
12043
0
fail:
12044
0
    PyMem_Free(*iov);
12045
0
    for (j = 0; j < i; j++) {
12046
0
        PyBuffer_Release(&(*buf)[j]);
12047
0
    }
12048
0
    PyMem_Free(*buf);
12049
0
    return -1;
12050
0
}
12051
12052
static void
12053
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12054
0
{
12055
0
    int i;
12056
0
    PyMem_Free(iov);
12057
0
    for (i = 0; i < cnt; i++) {
12058
0
        PyBuffer_Release(&buf[i]);
12059
0
    }
12060
0
    PyMem_Free(buf);
12061
0
}
12062
#endif
12063
12064
12065
#ifdef HAVE_READV
12066
/*[clinic input]
12067
os.readv -> Py_ssize_t
12068
12069
    fd: int
12070
    buffers: object
12071
    /
12072
12073
Read from a file descriptor fd into an iterable of buffers.
12074
12075
The buffers should be mutable buffers accepting bytes.
12076
readv will transfer data into each buffer until it is full
12077
and then move on to the next buffer in the sequence to hold
12078
the rest of the data.
12079
12080
readv returns the total number of bytes read,
12081
which may be less than the total capacity of all the buffers.
12082
[clinic start generated code]*/
12083
12084
static Py_ssize_t
12085
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12086
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12087
0
{
12088
0
    Py_ssize_t cnt, n;
12089
0
    int async_err = 0;
12090
0
    struct iovec *iov;
12091
0
    Py_buffer *buf;
12092
12093
0
    if (!PySequence_Check(buffers)) {
12094
0
        PyErr_SetString(PyExc_TypeError,
12095
0
            "readv() arg 2 must be a sequence");
12096
0
        return -1;
12097
0
    }
12098
12099
0
    cnt = PySequence_Size(buffers);
12100
0
    if (cnt < 0)
12101
0
        return -1;
12102
12103
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12104
0
        return -1;
12105
12106
0
    do {
12107
0
        Py_BEGIN_ALLOW_THREADS
12108
0
        n = readv(fd, iov, cnt);
12109
0
        Py_END_ALLOW_THREADS
12110
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12111
12112
0
    int saved_errno = errno;
12113
0
    iov_cleanup(iov, buf, cnt);
12114
0
    if (n < 0) {
12115
0
        if (!async_err) {
12116
0
            errno = saved_errno;
12117
0
            posix_error();
12118
0
        }
12119
0
        return -1;
12120
0
    }
12121
12122
0
    return n;
12123
0
}
12124
#endif /* HAVE_READV */
12125
12126
12127
#ifdef HAVE_PREAD
12128
/*[clinic input]
12129
@permit_long_summary
12130
os.pread
12131
12132
    fd: int
12133
    length: Py_ssize_t
12134
    offset: Py_off_t
12135
    /
12136
12137
Read a number of bytes from a file descriptor starting at a particular offset.
12138
12139
Read length bytes from file descriptor fd, starting at offset bytes from
12140
the beginning of the file.  The file offset remains unchanged.
12141
[clinic start generated code]*/
12142
12143
static PyObject *
12144
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12145
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12146
0
{
12147
0
    Py_ssize_t n;
12148
0
    int async_err = 0;
12149
12150
0
    if (length < 0) {
12151
0
        errno = EINVAL;
12152
0
        return posix_error();
12153
0
    }
12154
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12155
0
    if (writer == NULL) {
12156
0
        return NULL;
12157
0
    }
12158
12159
0
    do {
12160
0
        Py_BEGIN_ALLOW_THREADS
12161
0
        _Py_BEGIN_SUPPRESS_IPH
12162
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12163
0
        _Py_END_SUPPRESS_IPH
12164
0
        Py_END_ALLOW_THREADS
12165
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12166
12167
0
    if (n < 0) {
12168
0
        if (!async_err) {
12169
0
            posix_error();
12170
0
        }
12171
0
        PyBytesWriter_Discard(writer);
12172
0
        return NULL;
12173
0
    }
12174
0
    return PyBytesWriter_FinishWithSize(writer, n);
12175
0
}
12176
#endif /* HAVE_PREAD */
12177
12178
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12179
/*[clinic input]
12180
@permit_long_docstring_body
12181
os.preadv -> Py_ssize_t
12182
12183
    fd: int
12184
    buffers: object
12185
    offset: Py_off_t
12186
    flags: int = 0
12187
    /
12188
12189
Reads from a file descriptor into a number of mutable bytes-like objects.
12190
12191
Combines the functionality of readv() and pread(). As readv(), it will
12192
transfer data into each buffer until it is full and then move on to the next
12193
buffer in the sequence to hold the rest of the data. Its fourth argument,
12194
specifies the file offset at which the input operation is to be performed. It
12195
will return the total number of bytes read (which can be less than the total
12196
capacity of all the objects).
12197
12198
The flags argument contains a bitwise OR of zero or more of the following flags:
12199
12200
- RWF_HIPRI
12201
- RWF_NOWAIT
12202
- RWF_DONTCACHE
12203
12204
Using non-zero flags requires Linux 4.6 or newer.
12205
[clinic start generated code]*/
12206
12207
static Py_ssize_t
12208
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12209
               int flags)
12210
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
12211
0
{
12212
0
    Py_ssize_t cnt, n;
12213
0
    int async_err = 0;
12214
0
    struct iovec *iov;
12215
0
    Py_buffer *buf;
12216
12217
0
    if (!PySequence_Check(buffers)) {
12218
0
        PyErr_SetString(PyExc_TypeError,
12219
0
            "preadv2() arg 2 must be a sequence");
12220
0
        return -1;
12221
0
    }
12222
12223
0
    cnt = PySequence_Size(buffers);
12224
0
    if (cnt < 0) {
12225
0
        return -1;
12226
0
    }
12227
12228
#ifndef HAVE_PREADV2
12229
    if(flags != 0) {
12230
        argument_unavailable_error("preadv2", "flags");
12231
        return -1;
12232
    }
12233
#endif
12234
12235
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12236
0
        return -1;
12237
0
    }
12238
0
#ifdef HAVE_PREADV2
12239
0
    do {
12240
0
        Py_BEGIN_ALLOW_THREADS
12241
0
        _Py_BEGIN_SUPPRESS_IPH
12242
0
        n = preadv2(fd, iov, cnt, offset, flags);
12243
0
        _Py_END_SUPPRESS_IPH
12244
0
        Py_END_ALLOW_THREADS
12245
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12246
#else
12247
    do {
12248
#if defined(__APPLE__) && defined(__clang__)
12249
/* This entire function will be removed from the module dict when the API
12250
 * is not available.
12251
 */
12252
#pragma clang diagnostic push
12253
#pragma clang diagnostic ignored "-Wunguarded-availability"
12254
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12255
#endif
12256
        Py_BEGIN_ALLOW_THREADS
12257
        _Py_BEGIN_SUPPRESS_IPH
12258
        n = preadv(fd, iov, cnt, offset);
12259
        _Py_END_SUPPRESS_IPH
12260
        Py_END_ALLOW_THREADS
12261
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12262
12263
#if defined(__APPLE__) && defined(__clang__)
12264
#pragma clang diagnostic pop
12265
#endif
12266
12267
#endif
12268
12269
0
    int saved_errno = errno;
12270
0
    iov_cleanup(iov, buf, cnt);
12271
0
    if (n < 0) {
12272
0
        if (!async_err) {
12273
0
            errno = saved_errno;
12274
0
            posix_error();
12275
0
        }
12276
0
        return -1;
12277
0
    }
12278
12279
0
    return n;
12280
0
}
12281
#endif /* HAVE_PREADV */
12282
12283
12284
/*[clinic input]
12285
os.write -> Py_ssize_t
12286
12287
    fd: int
12288
    data: Py_buffer
12289
    /
12290
12291
Write a bytes object to a file descriptor.
12292
[clinic start generated code]*/
12293
12294
static Py_ssize_t
12295
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12296
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12297
2
{
12298
2
    return _Py_write(fd, data->buf, data->len);
12299
2
}
12300
12301
#ifdef HAVE_SENDFILE
12302
#ifdef __APPLE__
12303
/*[clinic input]
12304
os.sendfile
12305
12306
    out_fd: int
12307
    in_fd: int
12308
    offset: Py_off_t
12309
    count as sbytes: Py_off_t
12310
    headers: object(c_default="NULL") = ()
12311
    trailers: object(c_default="NULL") = ()
12312
    flags: int = 0
12313
12314
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12315
[clinic start generated code]*/
12316
12317
static PyObject *
12318
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12319
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12320
                 int flags)
12321
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12322
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12323
/*[clinic input]
12324
os.sendfile
12325
12326
    out_fd: int
12327
    in_fd: int
12328
    offset: Py_off_t
12329
    count: Py_ssize_t(allow_negative=False)
12330
    headers: object(c_default="NULL") = ()
12331
    trailers: object(c_default="NULL") = ()
12332
    flags: int = 0
12333
12334
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12335
[clinic start generated code]*/
12336
12337
static PyObject *
12338
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12339
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12340
                 int flags)
12341
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12342
#else
12343
/*[clinic input]
12344
os.sendfile
12345
12346
    out_fd: int
12347
    in_fd: int
12348
    offset as offobj: object
12349
    count: Py_ssize_t(allow_negative=False)
12350
12351
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12352
[clinic start generated code]*/
12353
12354
static PyObject *
12355
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12356
                 Py_ssize_t count)
12357
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12358
#endif
12359
0
{
12360
0
    Py_ssize_t ret;
12361
0
    int async_err = 0;
12362
12363
#ifdef __APPLE__
12364
    if(sbytes < 0) {
12365
        PyErr_SetString(PyExc_ValueError,
12366
                        "count cannot be negative");
12367
        return NULL;
12368
    }
12369
#else
12370
0
    assert(count >= 0);
12371
0
#endif
12372
12373
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12374
#ifndef __APPLE__
12375
    off_t sbytes;
12376
#endif
12377
    Py_buffer *hbuf, *tbuf;
12378
    struct sf_hdtr sf;
12379
12380
    sf.headers = NULL;
12381
    sf.trailers = NULL;
12382
12383
    if (headers != NULL) {
12384
        if (!PySequence_Check(headers)) {
12385
            PyErr_SetString(PyExc_TypeError,
12386
                "sendfile() headers must be a sequence");
12387
            return NULL;
12388
        } else {
12389
            Py_ssize_t i = PySequence_Size(headers);
12390
            if (i < 0)
12391
                return NULL;
12392
            if (i > INT_MAX) {
12393
                PyErr_SetString(PyExc_OverflowError,
12394
                    "sendfile() header is too large");
12395
                return NULL;
12396
            }
12397
            if (i > 0) {
12398
                sf.hdr_cnt = (int)i;
12399
                if (iov_setup(&(sf.headers), &hbuf,
12400
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12401
                    return NULL;
12402
#ifdef __APPLE__
12403
                for (i = 0; i < sf.hdr_cnt; i++) {
12404
                    Py_ssize_t blen = sf.headers[i].iov_len;
12405
# define OFF_T_MAX 0x7fffffffffffffff
12406
                    if (sbytes >= OFF_T_MAX - blen) {
12407
                        PyErr_SetString(PyExc_OverflowError,
12408
                            "sendfile() header is too large");
12409
                        return NULL;
12410
                    }
12411
                    sbytes += blen;
12412
                }
12413
#endif
12414
            }
12415
        }
12416
    }
12417
    if (trailers != NULL) {
12418
        if (!PySequence_Check(trailers)) {
12419
            PyErr_SetString(PyExc_TypeError,
12420
                "sendfile() trailers must be a sequence");
12421
            return NULL;
12422
        } else {
12423
            Py_ssize_t i = PySequence_Size(trailers);
12424
            if (i < 0)
12425
                return NULL;
12426
            if (i > INT_MAX) {
12427
                PyErr_SetString(PyExc_OverflowError,
12428
                    "sendfile() trailer is too large");
12429
                return NULL;
12430
            }
12431
            if (i > 0) {
12432
                sf.trl_cnt = (int)i;
12433
                if (iov_setup(&(sf.trailers), &tbuf,
12434
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12435
                    return NULL;
12436
            }
12437
        }
12438
    }
12439
12440
    _Py_BEGIN_SUPPRESS_IPH
12441
    do {
12442
        Py_BEGIN_ALLOW_THREADS
12443
#ifdef __APPLE__
12444
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12445
#else
12446
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12447
#endif
12448
        Py_END_ALLOW_THREADS
12449
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12450
    _Py_END_SUPPRESS_IPH
12451
12452
    int saved_errno = errno;
12453
    if (sf.headers != NULL)
12454
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12455
    if (sf.trailers != NULL)
12456
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12457
12458
    if (ret < 0) {
12459
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12460
            if (sbytes != 0) {
12461
                // some data has been sent
12462
                goto done;
12463
            }
12464
            // no data has been sent; upper application is supposed
12465
            // to retry on EAGAIN or EBUSY
12466
        }
12467
        if (!async_err) {
12468
            errno = saved_errno;
12469
            posix_error();
12470
        }
12471
        return NULL;
12472
    }
12473
    goto done;
12474
12475
done:
12476
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12477
        return PyLong_FromLong(sbytes);
12478
    #else
12479
        return PyLong_FromLongLong(sbytes);
12480
    #endif
12481
12482
#else
12483
0
#ifdef __linux__
12484
0
    if (offobj == Py_None) {
12485
0
        do {
12486
0
            Py_BEGIN_ALLOW_THREADS
12487
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12488
0
            Py_END_ALLOW_THREADS
12489
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12490
0
        if (ret < 0)
12491
0
            return (!async_err) ? posix_error() : NULL;
12492
0
        return PyLong_FromSsize_t(ret);
12493
0
    }
12494
0
#endif
12495
0
    off_t offset;
12496
0
    if (!Py_off_t_converter(offobj, &offset))
12497
0
        return NULL;
12498
12499
#if defined(__sun) && defined(__SVR4)
12500
    // On Solaris, sendfile raises EINVAL rather than returning 0
12501
    // when the offset is equal or bigger than the in_fd size.
12502
    struct stat st;
12503
12504
    do {
12505
        Py_BEGIN_ALLOW_THREADS
12506
        ret = fstat(in_fd, &st);
12507
        Py_END_ALLOW_THREADS
12508
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12509
    if (ret < 0)
12510
        return (!async_err) ? posix_error() : NULL;
12511
12512
    if (offset >= st.st_size) {
12513
        return PyLong_FromLong(0);
12514
    }
12515
12516
    // On illumos specifically sendfile() may perform a partial write but
12517
    // return -1/an error (in one confirmed case the destination socket
12518
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12519
    // code to check if the offset parameter was modified by sendfile().
12520
    //
12521
    // We need this variable to track said change.
12522
    off_t original_offset = offset;
12523
#endif
12524
12525
0
    do {
12526
0
        Py_BEGIN_ALLOW_THREADS
12527
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12528
#if defined(__sun) && defined(__SVR4)
12529
        // This handles illumos-specific sendfile() partial write behavior,
12530
        // see a comment above for more details.
12531
        if (ret < 0 && offset != original_offset) {
12532
            ret = offset - original_offset;
12533
        }
12534
#endif
12535
0
        Py_END_ALLOW_THREADS
12536
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12537
0
    if (ret < 0)
12538
0
        return (!async_err) ? posix_error() : NULL;
12539
0
    return PyLong_FromSsize_t(ret);
12540
0
#endif
12541
0
}
12542
#endif /* HAVE_SENDFILE */
12543
12544
12545
#if defined(__APPLE__)
12546
/*[clinic input]
12547
os._fcopyfile
12548
12549
    in_fd: int
12550
    out_fd: int
12551
    flags: int
12552
    /
12553
12554
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12555
[clinic start generated code]*/
12556
12557
static PyObject *
12558
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12559
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12560
{
12561
    int ret;
12562
12563
    Py_BEGIN_ALLOW_THREADS
12564
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12565
    Py_END_ALLOW_THREADS
12566
    if (ret < 0)
12567
        return posix_error();
12568
    Py_RETURN_NONE;
12569
}
12570
#endif
12571
12572
12573
/*[clinic input]
12574
os.fstat
12575
12576
    fd : int
12577
12578
Perform a stat system call on the given file descriptor.
12579
12580
Like stat(), but for an open file descriptor.
12581
Equivalent to os.stat(fd).
12582
[clinic start generated code]*/
12583
12584
static PyObject *
12585
os_fstat_impl(PyObject *module, int fd)
12586
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12587
138k
{
12588
138k
    STRUCT_STAT st;
12589
138k
    int res;
12590
138k
    int async_err = 0;
12591
12592
138k
    do {
12593
138k
        Py_BEGIN_ALLOW_THREADS
12594
138k
        res = FSTAT(fd, &st);
12595
138k
        Py_END_ALLOW_THREADS
12596
138k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12597
138k
    if (res != 0) {
12598
#ifdef MS_WINDOWS
12599
        return PyErr_SetFromWindowsErr(0);
12600
#else
12601
0
        return (!async_err) ? posix_error() : NULL;
12602
0
#endif
12603
0
    }
12604
12605
138k
    return _pystat_fromstructstat(module, &st);
12606
138k
}
12607
12608
12609
/*[clinic input]
12610
os.isatty -> bool
12611
    fd: int
12612
    /
12613
12614
Return True if the fd is connected to a terminal.
12615
12616
Return True if the file descriptor is an open file descriptor
12617
connected to the slave end of a terminal.
12618
[clinic start generated code]*/
12619
12620
static int
12621
os_isatty_impl(PyObject *module, int fd)
12622
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12623
0
{
12624
0
    int return_value;
12625
0
    Py_BEGIN_ALLOW_THREADS
12626
0
    _Py_BEGIN_SUPPRESS_IPH
12627
0
    return_value = isatty(fd);
12628
0
    _Py_END_SUPPRESS_IPH
12629
0
    Py_END_ALLOW_THREADS
12630
0
    return return_value;
12631
0
}
12632
12633
12634
#ifdef HAVE_PIPE
12635
/*[clinic input]
12636
os.pipe
12637
12638
Create a pipe.
12639
12640
Returns a tuple of two file descriptors:
12641
  (read_fd, write_fd)
12642
[clinic start generated code]*/
12643
12644
static PyObject *
12645
os_pipe_impl(PyObject *module)
12646
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12647
0
{
12648
0
    int fds[2];
12649
#ifdef MS_WINDOWS
12650
    HANDLE read, write;
12651
    SECURITY_ATTRIBUTES attr;
12652
    BOOL ok;
12653
#else
12654
0
    int res;
12655
0
#endif
12656
12657
#ifdef MS_WINDOWS
12658
    attr.nLength = sizeof(attr);
12659
    attr.lpSecurityDescriptor = NULL;
12660
    attr.bInheritHandle = FALSE;
12661
12662
    Py_BEGIN_ALLOW_THREADS
12663
    ok = CreatePipe(&read, &write, &attr, 0);
12664
    if (ok) {
12665
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12666
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12667
        if (fds[0] == -1 || fds[1] == -1) {
12668
            CloseHandle(read);
12669
            CloseHandle(write);
12670
            ok = 0;
12671
        }
12672
    }
12673
    Py_END_ALLOW_THREADS
12674
12675
    if (!ok)
12676
        return PyErr_SetFromWindowsErr(0);
12677
#else
12678
12679
0
#ifdef HAVE_PIPE2
12680
0
    Py_BEGIN_ALLOW_THREADS
12681
0
    res = pipe2(fds, O_CLOEXEC);
12682
0
    Py_END_ALLOW_THREADS
12683
12684
0
    if (res != 0 && errno == ENOSYS)
12685
0
    {
12686
0
#endif
12687
0
        Py_BEGIN_ALLOW_THREADS
12688
0
        res = pipe(fds);
12689
0
        Py_END_ALLOW_THREADS
12690
12691
0
        if (res == 0) {
12692
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12693
0
                close(fds[0]);
12694
0
                close(fds[1]);
12695
0
                return NULL;
12696
0
            }
12697
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12698
0
                close(fds[0]);
12699
0
                close(fds[1]);
12700
0
                return NULL;
12701
0
            }
12702
0
        }
12703
0
#ifdef HAVE_PIPE2
12704
0
    }
12705
0
#endif
12706
12707
0
    if (res != 0)
12708
0
        return PyErr_SetFromErrno(PyExc_OSError);
12709
0
#endif /* !MS_WINDOWS */
12710
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12711
0
}
12712
#endif  /* HAVE_PIPE */
12713
12714
12715
#ifdef HAVE_PIPE2
12716
/*[clinic input]
12717
os.pipe2
12718
12719
    flags: int
12720
    /
12721
12722
Create a pipe with flags set atomically.
12723
12724
Returns a tuple of two file descriptors:
12725
  (read_fd, write_fd)
12726
12727
flags can be constructed by ORing together one or more of these values:
12728
O_NONBLOCK, O_CLOEXEC.
12729
[clinic start generated code]*/
12730
12731
static PyObject *
12732
os_pipe2_impl(PyObject *module, int flags)
12733
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12734
0
{
12735
0
    int fds[2];
12736
0
    int res;
12737
12738
0
    res = pipe2(fds, flags);
12739
0
    if (res != 0)
12740
0
        return posix_error();
12741
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12742
0
}
12743
#endif /* HAVE_PIPE2 */
12744
12745
12746
#ifdef HAVE_WRITEV
12747
/*[clinic input]
12748
os.writev -> Py_ssize_t
12749
    fd: int
12750
    buffers: object
12751
    /
12752
12753
Iterate over buffers, and write the contents of each to a file descriptor.
12754
12755
Returns the total number of bytes written.
12756
buffers must be a sequence of bytes-like objects.
12757
[clinic start generated code]*/
12758
12759
static Py_ssize_t
12760
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12761
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12762
0
{
12763
0
    Py_ssize_t cnt;
12764
0
    Py_ssize_t result;
12765
0
    int async_err = 0;
12766
0
    struct iovec *iov;
12767
0
    Py_buffer *buf;
12768
12769
0
    if (!PySequence_Check(buffers)) {
12770
0
        PyErr_SetString(PyExc_TypeError,
12771
0
            "writev() arg 2 must be a sequence");
12772
0
        return -1;
12773
0
    }
12774
0
    cnt = PySequence_Size(buffers);
12775
0
    if (cnt < 0)
12776
0
        return -1;
12777
12778
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12779
0
        return -1;
12780
0
    }
12781
12782
0
    do {
12783
0
        Py_BEGIN_ALLOW_THREADS
12784
0
        result = writev(fd, iov, cnt);
12785
0
        Py_END_ALLOW_THREADS
12786
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12787
12788
0
    if (result < 0 && !async_err)
12789
0
        posix_error();
12790
12791
0
    iov_cleanup(iov, buf, cnt);
12792
0
    return result;
12793
0
}
12794
#endif /* HAVE_WRITEV */
12795
12796
12797
#ifdef HAVE_PWRITE
12798
/*[clinic input]
12799
os.pwrite -> Py_ssize_t
12800
12801
    fd: int
12802
    buffer: Py_buffer
12803
    offset: Py_off_t
12804
    /
12805
12806
Write bytes to a file descriptor starting at a particular offset.
12807
12808
Write buffer to fd, starting at offset bytes from the beginning of
12809
the file.  Returns the number of bytes written.  Does not change the
12810
current file offset.
12811
[clinic start generated code]*/
12812
12813
static Py_ssize_t
12814
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12815
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12816
0
{
12817
0
    Py_ssize_t size;
12818
0
    int async_err = 0;
12819
12820
0
    do {
12821
0
        Py_BEGIN_ALLOW_THREADS
12822
0
        _Py_BEGIN_SUPPRESS_IPH
12823
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12824
0
        _Py_END_SUPPRESS_IPH
12825
0
        Py_END_ALLOW_THREADS
12826
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12827
12828
0
    if (size < 0 && !async_err)
12829
0
        posix_error();
12830
0
    return size;
12831
0
}
12832
#endif /* HAVE_PWRITE */
12833
12834
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12835
/*[clinic input]
12836
@permit_long_summary
12837
@permit_long_docstring_body
12838
os.pwritev -> Py_ssize_t
12839
12840
    fd: int
12841
    buffers: object
12842
    offset: Py_off_t
12843
    flags: int = 0
12844
    /
12845
12846
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12847
12848
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12849
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12850
buffer is written before proceeding to second, and so on. The operating system may
12851
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12852
This function writes the contents of each object to the file descriptor and returns
12853
the total number of bytes written.
12854
12855
The flags argument contains a bitwise OR of zero or more of the following flags:
12856
12857
- RWF_DSYNC
12858
- RWF_SYNC
12859
- RWF_APPEND
12860
- RWF_DONTCACHE
12861
12862
Using non-zero flags requires Linux 4.7 or newer.
12863
[clinic start generated code]*/
12864
12865
static Py_ssize_t
12866
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12867
                int flags)
12868
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=664a67626d485665]*/
12869
0
{
12870
0
    Py_ssize_t cnt;
12871
0
    Py_ssize_t result;
12872
0
    int async_err = 0;
12873
0
    struct iovec *iov;
12874
0
    Py_buffer *buf;
12875
12876
0
    if (!PySequence_Check(buffers)) {
12877
0
        PyErr_SetString(PyExc_TypeError,
12878
0
            "pwritev() arg 2 must be a sequence");
12879
0
        return -1;
12880
0
    }
12881
12882
0
    cnt = PySequence_Size(buffers);
12883
0
    if (cnt < 0) {
12884
0
        return -1;
12885
0
    }
12886
12887
#ifndef HAVE_PWRITEV2
12888
    if(flags != 0) {
12889
        argument_unavailable_error("pwritev2", "flags");
12890
        return -1;
12891
    }
12892
#endif
12893
12894
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12895
0
        return -1;
12896
0
    }
12897
0
#ifdef HAVE_PWRITEV2
12898
0
    do {
12899
0
        Py_BEGIN_ALLOW_THREADS
12900
0
        _Py_BEGIN_SUPPRESS_IPH
12901
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12902
0
        _Py_END_SUPPRESS_IPH
12903
0
        Py_END_ALLOW_THREADS
12904
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12905
#else
12906
12907
#if defined(__APPLE__) && defined(__clang__)
12908
/* This entire function will be removed from the module dict when the API
12909
 * is not available.
12910
 */
12911
#pragma clang diagnostic push
12912
#pragma clang diagnostic ignored "-Wunguarded-availability"
12913
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12914
#endif
12915
    do {
12916
        Py_BEGIN_ALLOW_THREADS
12917
        _Py_BEGIN_SUPPRESS_IPH
12918
        result = pwritev(fd, iov, cnt, offset);
12919
        _Py_END_SUPPRESS_IPH
12920
        Py_END_ALLOW_THREADS
12921
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12922
12923
#if defined(__APPLE__) && defined(__clang__)
12924
#pragma clang diagnostic pop
12925
#endif
12926
12927
#endif
12928
12929
0
    if (result < 0) {
12930
0
        if (!async_err) {
12931
0
            posix_error();
12932
0
        }
12933
0
        result = -1;
12934
0
    }
12935
0
    iov_cleanup(iov, buf, cnt);
12936
12937
0
    return result;
12938
0
}
12939
#endif /* HAVE_PWRITEV */
12940
12941
#ifdef HAVE_COPY_FILE_RANGE
12942
/*[clinic input]
12943
12944
os.copy_file_range
12945
    src: int
12946
        Source file descriptor.
12947
    dst: int
12948
        Destination file descriptor.
12949
    count: Py_ssize_t(allow_negative=False)
12950
        Number of bytes to copy.
12951
    offset_src: object = None
12952
        Starting offset in src.
12953
    offset_dst: object = None
12954
        Starting offset in dst.
12955
12956
Copy count bytes from one file descriptor to another.
12957
12958
If offset_src is None, then src is read from the current position;
12959
respectively for offset_dst.
12960
[clinic start generated code]*/
12961
12962
static PyObject *
12963
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12964
                        PyObject *offset_src, PyObject *offset_dst)
12965
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12966
0
{
12967
0
    off_t offset_src_val, offset_dst_val;
12968
0
    off_t *p_offset_src = NULL;
12969
0
    off_t *p_offset_dst = NULL;
12970
0
    Py_ssize_t ret;
12971
0
    int async_err = 0;
12972
    /* The flags argument is provided to allow
12973
     * for future extensions and currently must be to 0. */
12974
0
    int flags = 0;
12975
12976
12977
0
    if (offset_src != Py_None) {
12978
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12979
0
            return NULL;
12980
0
        }
12981
0
        p_offset_src = &offset_src_val;
12982
0
    }
12983
12984
0
    if (offset_dst != Py_None) {
12985
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12986
0
            return NULL;
12987
0
        }
12988
0
        p_offset_dst = &offset_dst_val;
12989
0
    }
12990
12991
0
    do {
12992
0
        Py_BEGIN_ALLOW_THREADS
12993
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
12994
0
        Py_END_ALLOW_THREADS
12995
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12996
12997
0
    if (ret < 0) {
12998
0
        return (!async_err) ? posix_error() : NULL;
12999
0
    }
13000
13001
0
    return PyLong_FromSsize_t(ret);
13002
0
}
13003
#endif /* HAVE_COPY_FILE_RANGE*/
13004
13005
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13006
/*[clinic input]
13007
13008
os.splice
13009
    src: int
13010
        Source file descriptor.
13011
    dst: int
13012
        Destination file descriptor.
13013
    count: Py_ssize_t(allow_negative=False)
13014
        Number of bytes to copy.
13015
    offset_src: object = None
13016
        Starting offset in src.
13017
    offset_dst: object = None
13018
        Starting offset in dst.
13019
    flags: unsigned_int = 0
13020
        Flags to modify the semantics of the call.
13021
13022
Transfer count bytes from one pipe to a descriptor or vice versa.
13023
13024
If offset_src is None, then src is read from the current position;
13025
respectively for offset_dst. The offset associated to the file
13026
descriptor that refers to a pipe must be None.
13027
[clinic start generated code]*/
13028
13029
static PyObject *
13030
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13031
               PyObject *offset_src, PyObject *offset_dst,
13032
               unsigned int flags)
13033
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13034
0
{
13035
0
    off_t offset_src_val, offset_dst_val;
13036
0
    off_t *p_offset_src = NULL;
13037
0
    off_t *p_offset_dst = NULL;
13038
0
    Py_ssize_t ret;
13039
0
    int async_err = 0;
13040
13041
13042
0
    if (offset_src != Py_None) {
13043
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
13044
0
            return NULL;
13045
0
        }
13046
0
        p_offset_src = &offset_src_val;
13047
0
    }
13048
13049
0
    if (offset_dst != Py_None) {
13050
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
13051
0
            return NULL;
13052
0
        }
13053
0
        p_offset_dst = &offset_dst_val;
13054
0
    }
13055
13056
0
    do {
13057
0
        Py_BEGIN_ALLOW_THREADS
13058
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13059
0
        Py_END_ALLOW_THREADS
13060
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13061
13062
0
    if (ret < 0) {
13063
0
        return (!async_err) ? posix_error() : NULL;
13064
0
    }
13065
13066
0
    return PyLong_FromSsize_t(ret);
13067
0
}
13068
#endif /* HAVE_SPLICE*/
13069
13070
#ifdef HAVE_MKFIFO
13071
/*[clinic input]
13072
os.mkfifo
13073
13074
    path: path_t
13075
    mode: int=0o666
13076
    *
13077
    dir_fd: dir_fd(requires='mkfifoat')=None
13078
13079
Create a "fifo" (a POSIX named pipe).
13080
13081
If dir_fd is not None, it should be a file descriptor open to a directory,
13082
  and path should be relative; path will then be relative to that directory.
13083
dir_fd may not be implemented on your platform.
13084
  If it is unavailable, using it will raise a NotImplementedError.
13085
[clinic start generated code]*/
13086
13087
static PyObject *
13088
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13089
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
13090
0
{
13091
0
    int result;
13092
0
    int async_err = 0;
13093
0
#ifdef HAVE_MKFIFOAT
13094
0
    int mkfifoat_unavailable = 0;
13095
0
#endif
13096
13097
0
    do {
13098
0
        Py_BEGIN_ALLOW_THREADS
13099
0
#ifdef HAVE_MKFIFOAT
13100
0
        if (dir_fd != DEFAULT_DIR_FD) {
13101
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13102
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13103
13104
0
            } else {
13105
0
                mkfifoat_unavailable = 1;
13106
0
                result = 0;
13107
0
            }
13108
0
        } else
13109
0
#endif
13110
0
            result = mkfifo(path->narrow, mode);
13111
0
        Py_END_ALLOW_THREADS
13112
0
    } while (result != 0 && errno == EINTR &&
13113
0
             !(async_err = PyErr_CheckSignals()));
13114
13115
0
#ifdef HAVE_MKFIFOAT
13116
0
    if (mkfifoat_unavailable) {
13117
0
        argument_unavailable_error(NULL, "dir_fd");
13118
0
        return NULL;
13119
0
    }
13120
0
#endif
13121
13122
0
    if (result != 0)
13123
0
        return (!async_err) ? posix_error() : NULL;
13124
13125
0
    Py_RETURN_NONE;
13126
0
}
13127
#endif /* HAVE_MKFIFO */
13128
13129
13130
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13131
/*[clinic input]
13132
@permit_long_docstring_body
13133
os.mknod
13134
13135
    path: path_t
13136
    mode: int=0o600
13137
    device: dev_t=0
13138
    *
13139
    dir_fd: dir_fd(requires='mknodat')=None
13140
13141
Create a node in the file system.
13142
13143
Create a node in the file system (file, device special file or named pipe)
13144
at path.  mode specifies both the permissions to use and the
13145
type of node to be created, being combined (bitwise OR) with one of
13146
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
13147
device defines the newly created device special file (probably using
13148
os.makedev()).  Otherwise device is ignored.
13149
13150
If dir_fd is not None, it should be a file descriptor open to a directory,
13151
  and path should be relative; path will then be relative to that directory.
13152
dir_fd may not be implemented on your platform.
13153
  If it is unavailable, using it will raise a NotImplementedError.
13154
[clinic start generated code]*/
13155
13156
static PyObject *
13157
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13158
              int dir_fd)
13159
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
13160
0
{
13161
0
    int result;
13162
0
    int async_err = 0;
13163
0
#ifdef HAVE_MKNODAT
13164
0
    int mknodat_unavailable = 0;
13165
0
#endif
13166
13167
0
    do {
13168
0
        Py_BEGIN_ALLOW_THREADS
13169
0
#ifdef HAVE_MKNODAT
13170
0
        if (dir_fd != DEFAULT_DIR_FD) {
13171
0
            if (HAVE_MKNODAT_RUNTIME) {
13172
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13173
13174
0
            } else {
13175
0
                mknodat_unavailable = 1;
13176
0
                result = 0;
13177
0
            }
13178
0
        } else
13179
0
#endif
13180
0
            result = mknod(path->narrow, mode, device);
13181
0
        Py_END_ALLOW_THREADS
13182
0
    } while (result != 0 && errno == EINTR &&
13183
0
             !(async_err = PyErr_CheckSignals()));
13184
0
#ifdef HAVE_MKNODAT
13185
0
    if (mknodat_unavailable) {
13186
0
        argument_unavailable_error(NULL, "dir_fd");
13187
0
        return NULL;
13188
0
    }
13189
0
#endif
13190
0
    if (result != 0)
13191
0
        return (!async_err) ? posix_error() : NULL;
13192
13193
0
    Py_RETURN_NONE;
13194
0
}
13195
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13196
13197
13198
#ifdef HAVE_DEVICE_MACROS
13199
static PyObject *
13200
major_minor_conv(unsigned int value)
13201
0
{
13202
0
#ifdef NODEV
13203
0
    if (value == (unsigned int)NODEV) {
13204
0
        return PyLong_FromLong((int)NODEV);
13205
0
    }
13206
0
#endif
13207
0
    return PyLong_FromUnsignedLong(value);
13208
0
}
13209
13210
static int
13211
major_minor_check(dev_t value)
13212
0
{
13213
0
#ifdef NODEV
13214
0
    if (value == NODEV) {
13215
0
        return 1;
13216
0
    }
13217
0
#endif
13218
0
    return (dev_t)(unsigned int)value == value;
13219
0
}
13220
13221
/*[clinic input]
13222
os.major
13223
13224
    device: dev_t
13225
    /
13226
13227
Extracts a device major number from a raw device number.
13228
[clinic start generated code]*/
13229
13230
static PyObject *
13231
os_major_impl(PyObject *module, dev_t device)
13232
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13233
0
{
13234
0
    return major_minor_conv(major(device));
13235
0
}
13236
13237
13238
/*[clinic input]
13239
os.minor
13240
13241
    device: dev_t
13242
    /
13243
13244
Extracts a device minor number from a raw device number.
13245
[clinic start generated code]*/
13246
13247
static PyObject *
13248
os_minor_impl(PyObject *module, dev_t device)
13249
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13250
0
{
13251
0
    return major_minor_conv(minor(device));
13252
0
}
13253
13254
13255
/*[clinic input]
13256
os.makedev -> dev_t
13257
13258
    major: dev_t
13259
    minor: dev_t
13260
    /
13261
13262
Composes a raw device number from the major and minor device numbers.
13263
[clinic start generated code]*/
13264
13265
static dev_t
13266
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13267
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13268
0
{
13269
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13270
0
        PyErr_SetString(PyExc_OverflowError,
13271
0
                        "Python int too large to convert to C unsigned int");
13272
0
        return (dev_t)-1;
13273
0
    }
13274
0
    return makedev(major, minor);
13275
0
}
13276
#endif /* HAVE_DEVICE_MACROS */
13277
13278
13279
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13280
/*[clinic input]
13281
os.ftruncate
13282
13283
    fd: int
13284
    length: Py_off_t
13285
    /
13286
13287
Truncate a file, specified by file descriptor, to a specific length.
13288
[clinic start generated code]*/
13289
13290
static PyObject *
13291
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13292
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13293
0
{
13294
0
    int result;
13295
0
    int async_err = 0;
13296
13297
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13298
0
        return NULL;
13299
0
    }
13300
13301
0
    do {
13302
0
        Py_BEGIN_ALLOW_THREADS
13303
0
        _Py_BEGIN_SUPPRESS_IPH
13304
#ifdef MS_WINDOWS
13305
        result = _chsize_s(fd, length);
13306
#else
13307
0
        result = ftruncate(fd, length);
13308
0
#endif
13309
0
        _Py_END_SUPPRESS_IPH
13310
0
        Py_END_ALLOW_THREADS
13311
0
    } while (result != 0 && errno == EINTR &&
13312
0
             !(async_err = PyErr_CheckSignals()));
13313
0
    if (result != 0)
13314
0
        return (!async_err) ? posix_error() : NULL;
13315
0
    Py_RETURN_NONE;
13316
0
}
13317
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13318
13319
13320
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13321
/*[clinic input]
13322
os.truncate
13323
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13324
    length: Py_off_t
13325
13326
Truncate a file, specified by path, to a specific length.
13327
13328
On some platforms, path may also be specified as an open file descriptor.
13329
  If this functionality is unavailable, using it raises an exception.
13330
[clinic start generated code]*/
13331
13332
static PyObject *
13333
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13334
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
13335
0
{
13336
0
    int result;
13337
#ifdef MS_WINDOWS
13338
    int fd;
13339
#endif
13340
13341
0
    if (path->fd != -1)
13342
0
        return os_ftruncate_impl(module, path->fd, length);
13343
13344
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13345
0
        return NULL;
13346
0
    }
13347
13348
0
    Py_BEGIN_ALLOW_THREADS
13349
0
    _Py_BEGIN_SUPPRESS_IPH
13350
#ifdef MS_WINDOWS
13351
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13352
    if (fd < 0)
13353
        result = -1;
13354
    else {
13355
        result = _chsize_s(fd, length);
13356
        close(fd);
13357
        if (result < 0)
13358
            errno = result;
13359
    }
13360
#else
13361
0
    result = truncate(path->narrow, length);
13362
0
#endif
13363
0
    _Py_END_SUPPRESS_IPH
13364
0
    Py_END_ALLOW_THREADS
13365
0
    if (result < 0)
13366
0
        return posix_path_error(path);
13367
13368
0
    Py_RETURN_NONE;
13369
0
}
13370
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13371
13372
13373
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
13374
   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
13375
   defined, which is the case in Python on AIX. AIX bug report:
13376
   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
13377
#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
13378
#  define POSIX_FADVISE_AIX_BUG
13379
#endif
13380
13381
13382
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13383
   OSs, support was dropped in WASI preview2. */
13384
#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \
13385
    !defined(__wasi__)
13386
/*[clinic input]
13387
os.posix_fallocate
13388
13389
    fd: int
13390
    offset: Py_off_t
13391
    length: Py_off_t
13392
    /
13393
13394
Ensure a file has allocated at least a particular number of bytes on disk.
13395
13396
Ensure that the file specified by fd encompasses a range of bytes
13397
starting at offset bytes from the beginning and continuing for length bytes.
13398
[clinic start generated code]*/
13399
13400
static PyObject *
13401
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13402
                        Py_off_t length)
13403
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
13404
0
{
13405
0
    int result;
13406
0
    int async_err = 0;
13407
13408
0
    do {
13409
0
        Py_BEGIN_ALLOW_THREADS
13410
0
        result = posix_fallocate(fd, offset, length);
13411
0
        Py_END_ALLOW_THREADS
13412
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13413
13414
0
    if (result == 0)
13415
0
        Py_RETURN_NONE;
13416
13417
0
    if (async_err)
13418
0
        return NULL;
13419
13420
0
    errno = result;
13421
0
    return posix_error();
13422
0
}
13423
#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */
13424
13425
13426
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
13427
/*[clinic input]
13428
os.posix_fadvise
13429
13430
    fd: int
13431
    offset: Py_off_t
13432
    length: Py_off_t
13433
    advice: int
13434
    /
13435
13436
Announce an intention to access data in a specific pattern.
13437
13438
Announce an intention to access data in a specific pattern, thus allowing
13439
the kernel to make optimizations.
13440
The advice applies to the region of the file specified by fd starting at
13441
offset and continuing for length bytes.
13442
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13443
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13444
POSIX_FADV_DONTNEED.
13445
[clinic start generated code]*/
13446
13447
static PyObject *
13448
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13449
                      Py_off_t length, int advice)
13450
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13451
0
{
13452
0
    int result;
13453
0
    int async_err = 0;
13454
13455
0
    do {
13456
0
        Py_BEGIN_ALLOW_THREADS
13457
0
        result = posix_fadvise(fd, offset, length, advice);
13458
0
        Py_END_ALLOW_THREADS
13459
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13460
13461
0
    if (result == 0)
13462
0
        Py_RETURN_NONE;
13463
13464
0
    if (async_err)
13465
0
        return NULL;
13466
13467
0
    errno = result;
13468
0
    return posix_error();
13469
0
}
13470
#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
13471
13472
13473
#ifdef MS_WINDOWS
13474
static PyObject*
13475
win32_putenv(PyObject *name, PyObject *value)
13476
{
13477
    /* Search from index 1 because on Windows starting '=' is allowed for
13478
       defining hidden environment variables. */
13479
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13480
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13481
    {
13482
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13483
        return NULL;
13484
    }
13485
    PyObject *unicode;
13486
    if (value != NULL) {
13487
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13488
    }
13489
    else {
13490
        unicode = PyUnicode_FromFormat("%U=", name);
13491
    }
13492
    if (unicode == NULL) {
13493
        return NULL;
13494
    }
13495
13496
    Py_ssize_t size;
13497
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13498
    Py_DECREF(unicode);
13499
13500
    if (env == NULL) {
13501
        return NULL;
13502
    }
13503
    if (size > _MAX_ENV) {
13504
        PyErr_Format(PyExc_ValueError,
13505
                     "the environment variable is longer than %u characters",
13506
                     _MAX_ENV);
13507
        PyMem_Free(env);
13508
        return NULL;
13509
    }
13510
    if (wcslen(env) != (size_t)size) {
13511
        PyErr_SetString(PyExc_ValueError,
13512
                        "embedded null character");
13513
        PyMem_Free(env);
13514
        return NULL;
13515
    }
13516
13517
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13518
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13519
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13520
13521
       Prefer _wputenv() to be compatible with C libraries using CRT
13522
       variables and CRT functions using these variables (ex: getenv()). */
13523
    int err = _wputenv(env);
13524
13525
    if (err) {
13526
        posix_error();
13527
        PyMem_Free(env);
13528
        return NULL;
13529
    }
13530
    PyMem_Free(env);
13531
13532
    Py_RETURN_NONE;
13533
}
13534
#endif
13535
13536
13537
#ifdef MS_WINDOWS
13538
/*[clinic input]
13539
os.putenv
13540
13541
    name: unicode
13542
    value: unicode
13543
    /
13544
13545
Change or add an environment variable.
13546
[clinic start generated code]*/
13547
13548
static PyObject *
13549
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13550
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13551
{
13552
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13553
        return NULL;
13554
    }
13555
    return win32_putenv(name, value);
13556
}
13557
#else
13558
/*[clinic input]
13559
os.putenv
13560
13561
    name: unicode_fs_encoded
13562
    value: unicode_fs_encoded
13563
    /
13564
13565
Change or add an environment variable.
13566
[clinic start generated code]*/
13567
13568
static PyObject *
13569
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13570
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13571
0
{
13572
0
    const char *name_string = PyBytes_AS_STRING(name);
13573
0
    const char *value_string = PyBytes_AS_STRING(value);
13574
13575
0
    if (strchr(name_string, '=') != NULL) {
13576
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13577
0
        return NULL;
13578
0
    }
13579
13580
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13581
0
        return NULL;
13582
0
    }
13583
13584
0
    if (setenv(name_string, value_string, 1)) {
13585
0
        return posix_error();
13586
0
    }
13587
0
    Py_RETURN_NONE;
13588
0
}
13589
#endif  /* !defined(MS_WINDOWS) */
13590
13591
13592
#ifdef MS_WINDOWS
13593
/*[clinic input]
13594
os.unsetenv
13595
    name: unicode
13596
    /
13597
13598
Delete an environment variable.
13599
[clinic start generated code]*/
13600
13601
static PyObject *
13602
os_unsetenv_impl(PyObject *module, PyObject *name)
13603
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13604
{
13605
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13606
        return NULL;
13607
    }
13608
    return win32_putenv(name, NULL);
13609
}
13610
#else
13611
/*[clinic input]
13612
os.unsetenv
13613
    name: unicode_fs_encoded
13614
    /
13615
13616
Delete an environment variable.
13617
[clinic start generated code]*/
13618
13619
static PyObject *
13620
os_unsetenv_impl(PyObject *module, PyObject *name)
13621
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13622
0
{
13623
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13624
0
        return NULL;
13625
0
    }
13626
#ifdef HAVE_BROKEN_UNSETENV
13627
    unsetenv(PyBytes_AS_STRING(name));
13628
#else
13629
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13630
0
    if (err) {
13631
0
        return posix_error();
13632
0
    }
13633
0
#endif
13634
13635
0
    Py_RETURN_NONE;
13636
0
}
13637
#endif /* !MS_WINDOWS */
13638
13639
13640
#ifdef HAVE_CLEARENV
13641
/*[clinic input]
13642
os._clearenv
13643
[clinic start generated code]*/
13644
13645
static PyObject *
13646
os__clearenv_impl(PyObject *module)
13647
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13648
0
{
13649
0
    errno = 0;
13650
0
    int err = clearenv();
13651
0
    if (err) {
13652
0
        return posix_error();
13653
0
    }
13654
0
    Py_RETURN_NONE;
13655
0
}
13656
#endif
13657
13658
13659
/*[clinic input]
13660
os.strerror
13661
13662
    code: int
13663
    /
13664
13665
Translate an error code to a message string.
13666
[clinic start generated code]*/
13667
13668
static PyObject *
13669
os_strerror_impl(PyObject *module, int code)
13670
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13671
0
{
13672
0
    char *message = strerror(code);
13673
0
    if (message == NULL) {
13674
0
        PyErr_SetString(PyExc_ValueError,
13675
0
                        "strerror() argument out of range");
13676
0
        return NULL;
13677
0
    }
13678
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13679
0
}
13680
13681
13682
#ifdef HAVE_SYS_WAIT_H
13683
#ifdef WCOREDUMP
13684
/*[clinic input]
13685
os.WCOREDUMP -> bool
13686
13687
    status: int
13688
    /
13689
13690
Return True if the process returning status was dumped to a core file.
13691
[clinic start generated code]*/
13692
13693
static int
13694
os_WCOREDUMP_impl(PyObject *module, int status)
13695
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13696
0
{
13697
0
    WAIT_TYPE wait_status;
13698
0
    WAIT_STATUS_INT(wait_status) = status;
13699
0
    return WCOREDUMP(wait_status);
13700
0
}
13701
#endif /* WCOREDUMP */
13702
13703
13704
#ifdef WIFCONTINUED
13705
/*[clinic input]
13706
os.WIFCONTINUED -> bool
13707
13708
    status: int
13709
13710
Return True if a particular process was continued from a job control stop.
13711
13712
Return True if the process returning status was continued from a
13713
job control stop.
13714
[clinic start generated code]*/
13715
13716
static int
13717
os_WIFCONTINUED_impl(PyObject *module, int status)
13718
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13719
0
{
13720
0
    WAIT_TYPE wait_status;
13721
0
    WAIT_STATUS_INT(wait_status) = status;
13722
0
    return WIFCONTINUED(wait_status);
13723
0
}
13724
#endif /* WIFCONTINUED */
13725
13726
13727
#ifdef WIFSTOPPED
13728
/*[clinic input]
13729
os.WIFSTOPPED -> bool
13730
13731
    status: int
13732
13733
Return True if the process returning status was stopped.
13734
[clinic start generated code]*/
13735
13736
static int
13737
os_WIFSTOPPED_impl(PyObject *module, int status)
13738
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13739
0
{
13740
0
    WAIT_TYPE wait_status;
13741
0
    WAIT_STATUS_INT(wait_status) = status;
13742
0
    return WIFSTOPPED(wait_status);
13743
0
}
13744
#endif /* WIFSTOPPED */
13745
13746
13747
#ifdef WIFSIGNALED
13748
/*[clinic input]
13749
os.WIFSIGNALED -> bool
13750
13751
    status: int
13752
13753
Return True if the process returning status was terminated by a signal.
13754
[clinic start generated code]*/
13755
13756
static int
13757
os_WIFSIGNALED_impl(PyObject *module, int status)
13758
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13759
0
{
13760
0
    WAIT_TYPE wait_status;
13761
0
    WAIT_STATUS_INT(wait_status) = status;
13762
0
    return WIFSIGNALED(wait_status);
13763
0
}
13764
#endif /* WIFSIGNALED */
13765
13766
13767
#ifdef WIFEXITED
13768
/*[clinic input]
13769
@permit_long_summary
13770
os.WIFEXITED -> bool
13771
13772
    status: int
13773
13774
Return True if the process returning status exited via the exit() system call.
13775
[clinic start generated code]*/
13776
13777
static int
13778
os_WIFEXITED_impl(PyObject *module, int status)
13779
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13780
0
{
13781
0
    WAIT_TYPE wait_status;
13782
0
    WAIT_STATUS_INT(wait_status) = status;
13783
0
    return WIFEXITED(wait_status);
13784
0
}
13785
#endif /* WIFEXITED */
13786
13787
13788
#ifdef WEXITSTATUS
13789
/*[clinic input]
13790
os.WEXITSTATUS -> int
13791
13792
    status: int
13793
13794
Return the process return code from status.
13795
[clinic start generated code]*/
13796
13797
static int
13798
os_WEXITSTATUS_impl(PyObject *module, int status)
13799
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13800
0
{
13801
0
    WAIT_TYPE wait_status;
13802
0
    WAIT_STATUS_INT(wait_status) = status;
13803
0
    return WEXITSTATUS(wait_status);
13804
0
}
13805
#endif /* WEXITSTATUS */
13806
13807
13808
#ifdef WTERMSIG
13809
/*[clinic input]
13810
@permit_long_summary
13811
os.WTERMSIG -> int
13812
13813
    status: int
13814
13815
Return the signal that terminated the process that provided the status value.
13816
[clinic start generated code]*/
13817
13818
static int
13819
os_WTERMSIG_impl(PyObject *module, int status)
13820
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13821
0
{
13822
0
    WAIT_TYPE wait_status;
13823
0
    WAIT_STATUS_INT(wait_status) = status;
13824
0
    return WTERMSIG(wait_status);
13825
0
}
13826
#endif /* WTERMSIG */
13827
13828
13829
#ifdef WSTOPSIG
13830
/*[clinic input]
13831
os.WSTOPSIG -> int
13832
13833
    status: int
13834
13835
Return the signal that stopped the process that provided the status value.
13836
[clinic start generated code]*/
13837
13838
static int
13839
os_WSTOPSIG_impl(PyObject *module, int status)
13840
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13841
0
{
13842
0
    WAIT_TYPE wait_status;
13843
0
    WAIT_STATUS_INT(wait_status) = status;
13844
0
    return WSTOPSIG(wait_status);
13845
0
}
13846
#endif /* WSTOPSIG */
13847
#endif /* HAVE_SYS_WAIT_H */
13848
13849
13850
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13851
#ifdef _SCO_DS
13852
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13853
   needed definitions in sys/statvfs.h */
13854
#define _SVID3
13855
#endif
13856
#include <sys/statvfs.h>
13857
13858
#ifdef __APPLE__
13859
/* On macOS struct statvfs uses 32-bit integers for block counts,
13860
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13861
 * os.statvfs is implemented in terms of statfs(2).
13862
 */
13863
13864
static PyObject*
13865
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13866
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13867
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13868
    if (v == NULL) {
13869
        return NULL;
13870
    }
13871
13872
    long flags = 0;
13873
    if (st.f_flags & MNT_RDONLY) {
13874
        flags |= ST_RDONLY;
13875
    }
13876
    if (st.f_flags & MNT_NOSUID) {
13877
        flags |= ST_NOSUID;
13878
    }
13879
13880
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13881
13882
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13883
    do {                                                 \
13884
        PyObject *obj = (EXPR);                          \
13885
        if (obj == NULL) {                               \
13886
            Py_DECREF((SEQ));                            \
13887
            return NULL;                                 \
13888
        }                                                \
13889
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13890
    } while (0)
13891
13892
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13893
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13894
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13895
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13896
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13897
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13898
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13899
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13900
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13901
13902
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13903
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13904
13905
#undef SET_ITEM
13906
13907
    return v;
13908
}
13909
13910
#else
13911
13912
13913
13914
static PyObject*
13915
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13916
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13917
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13918
0
    if (v == NULL)
13919
0
        return NULL;
13920
13921
0
    int pos = 0;
13922
13923
0
#define SET_RESULT(CALL)                                     \
13924
0
    do {                                                     \
13925
0
        PyObject *item = (CALL);                             \
13926
0
        if (item == NULL) {                                  \
13927
0
            Py_DECREF(v);                                    \
13928
0
            return NULL;                                     \
13929
0
        }                                                    \
13930
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13931
0
    } while(0)
13932
13933
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13934
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13935
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13936
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13937
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13938
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13939
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13940
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13941
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13942
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13943
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13944
#else
13945
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13946
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13947
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13948
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13949
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13950
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13951
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13952
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13953
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13954
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13955
#endif
13956
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13957
 * (issue #32390). */
13958
#if defined(_AIX) && defined(_ALL_SOURCE)
13959
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13960
#else
13961
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13962
0
#endif
13963
13964
0
#undef SET_RESULT
13965
13966
0
    return v;
13967
0
}
13968
13969
#endif
13970
13971
13972
/*[clinic input]
13973
os.fstatvfs
13974
    fd: int
13975
    /
13976
13977
Perform an fstatvfs system call on the given fd.
13978
13979
Equivalent to statvfs(fd).
13980
[clinic start generated code]*/
13981
13982
static PyObject *
13983
os_fstatvfs_impl(PyObject *module, int fd)
13984
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13985
0
{
13986
0
    int result;
13987
0
    int async_err = 0;
13988
#ifdef __APPLE__
13989
    struct statfs st;
13990
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13991
     * the former uses 32-bit values for block counts.
13992
     */
13993
    do {
13994
        Py_BEGIN_ALLOW_THREADS
13995
        result = fstatfs(fd, &st);
13996
        Py_END_ALLOW_THREADS
13997
    } while (result != 0 && errno == EINTR &&
13998
             !(async_err = PyErr_CheckSignals()));
13999
    if (result != 0)
14000
        return (!async_err) ? posix_error() : NULL;
14001
14002
    return _pystatvfs_fromstructstatfs(module, st);
14003
#else
14004
0
    struct statvfs st;
14005
14006
0
    do {
14007
0
        Py_BEGIN_ALLOW_THREADS
14008
0
        result = fstatvfs(fd, &st);
14009
0
        Py_END_ALLOW_THREADS
14010
0
    } while (result != 0 && errno == EINTR &&
14011
0
             !(async_err = PyErr_CheckSignals()));
14012
0
    if (result != 0)
14013
0
        return (!async_err) ? posix_error() : NULL;
14014
14015
0
    return _pystatvfs_fromstructstatvfs(module, st);
14016
0
#endif
14017
0
}
14018
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14019
14020
14021
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14022
#include <sys/statvfs.h>
14023
/*[clinic input]
14024
os.statvfs
14025
14026
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14027
14028
Perform a statvfs system call on the given path.
14029
14030
path may always be specified as a string.
14031
On some platforms, path may also be specified as an open file descriptor.
14032
  If this functionality is unavailable, using it raises an exception.
14033
[clinic start generated code]*/
14034
14035
static PyObject *
14036
os_statvfs_impl(PyObject *module, path_t *path)
14037
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
14038
0
{
14039
0
    int result;
14040
14041
#ifdef __APPLE__
14042
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14043
     * the former uses 32-bit values for block counts.
14044
     */
14045
    struct statfs st;
14046
14047
    Py_BEGIN_ALLOW_THREADS
14048
    if (path->fd != -1) {
14049
        result = fstatfs(path->fd, &st);
14050
    }
14051
    else
14052
        result = statfs(path->narrow, &st);
14053
    Py_END_ALLOW_THREADS
14054
14055
    if (result) {
14056
        return path_error(path);
14057
    }
14058
14059
    return _pystatvfs_fromstructstatfs(module, st);
14060
14061
#else
14062
0
    struct statvfs st;
14063
14064
0
    Py_BEGIN_ALLOW_THREADS
14065
0
#ifdef HAVE_FSTATVFS
14066
0
    if (path->fd != -1) {
14067
0
        result = fstatvfs(path->fd, &st);
14068
0
    }
14069
0
    else
14070
0
#endif
14071
0
        result = statvfs(path->narrow, &st);
14072
0
    Py_END_ALLOW_THREADS
14073
14074
0
    if (result) {
14075
0
        return path_error(path);
14076
0
    }
14077
14078
0
    return _pystatvfs_fromstructstatvfs(module, st);
14079
0
#endif
14080
0
}
14081
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14082
14083
14084
#ifdef MS_WINDOWS
14085
/*[clinic input]
14086
os._getdiskusage
14087
14088
    path: path_t
14089
14090
Return disk usage statistics about the given path as a (total, free) tuple.
14091
[clinic start generated code]*/
14092
14093
static PyObject *
14094
os__getdiskusage_impl(PyObject *module, path_t *path)
14095
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
14096
{
14097
    BOOL retval;
14098
    ULARGE_INTEGER _, total, free;
14099
    DWORD err = 0;
14100
14101
    Py_BEGIN_ALLOW_THREADS
14102
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14103
    Py_END_ALLOW_THREADS
14104
    if (retval == 0) {
14105
        if (GetLastError() == ERROR_DIRECTORY) {
14106
            wchar_t *dir_path = NULL;
14107
14108
            dir_path = PyMem_New(wchar_t, path->length + 1);
14109
            if (dir_path == NULL) {
14110
                return PyErr_NoMemory();
14111
            }
14112
14113
            wcscpy_s(dir_path, path->length + 1, path->wide);
14114
14115
            if (_dirnameW(dir_path) != -1) {
14116
                Py_BEGIN_ALLOW_THREADS
14117
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14118
                Py_END_ALLOW_THREADS
14119
            }
14120
            /* Record the last error in case it's modified by PyMem_Free. */
14121
            err = GetLastError();
14122
            PyMem_Free(dir_path);
14123
            if (retval) {
14124
                goto success;
14125
            }
14126
        }
14127
        return PyErr_SetFromWindowsErr(err);
14128
    }
14129
14130
success:
14131
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14132
}
14133
#endif /* MS_WINDOWS */
14134
14135
14136
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14137
 * It maps strings representing configuration variable names to
14138
 * integer values, allowing those functions to be called with the
14139
 * magic names instead of polluting the module's namespace with tons of
14140
 * rarely-used constants.  There are three separate tables that use
14141
 * these definitions.
14142
 *
14143
 * This code is always included, even if none of the interfaces that
14144
 * need it are included.  The #if hackery needed to avoid it would be
14145
 * sufficiently pervasive that it's not worth the loss of readability.
14146
 */
14147
struct constdef {
14148
    const char *name;
14149
    int value;
14150
};
14151
14152
static int
14153
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14154
0
{
14155
0
    if (PyUnicode_Check(arg)) {
14156
0
        PyObject *table = PyObject_GetAttrString(module, tablename);
14157
0
        if (table == NULL) {
14158
0
            return 0;
14159
0
        }
14160
14161
0
        arg = PyObject_GetItem(table, arg);
14162
0
        Py_DECREF(table);
14163
0
        if (arg == NULL) {
14164
0
            PyErr_SetString(
14165
0
                PyExc_ValueError, "unrecognized configuration name");
14166
0
            return 0;
14167
0
        }
14168
0
    } else {
14169
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14170
0
    }
14171
14172
0
    int success = 0;
14173
0
    if (!PyIndex_Check(arg)) {
14174
0
        PyErr_SetString(PyExc_TypeError,
14175
0
            "configuration names must be strings or integers");
14176
0
    } else {
14177
0
        int value = PyLong_AsInt(arg);
14178
0
        if (!(value == -1 && PyErr_Occurred())) {
14179
0
            *valuep = value;
14180
0
            success = 1;
14181
0
        }
14182
0
    }
14183
0
    Py_DECREF(arg);
14184
0
    return success;
14185
0
}
14186
14187
14188
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14189
static struct constdef  posix_constants_pathconf[] = {
14190
#ifdef _PC_ABI_AIO_XFER_MAX
14191
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14192
#endif
14193
#ifdef _PC_ABI_ASYNC_IO
14194
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14195
#endif
14196
#ifdef _PC_ASYNC_IO
14197
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14198
#endif
14199
#ifdef _PC_CHOWN_RESTRICTED
14200
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14201
#endif
14202
#ifdef _PC_FILESIZEBITS
14203
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14204
#endif
14205
#ifdef _PC_LAST
14206
    {"PC_LAST", _PC_LAST},
14207
#endif
14208
#ifdef _PC_LINK_MAX
14209
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14210
#endif
14211
#ifdef _PC_MAX_CANON
14212
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14213
#endif
14214
#ifdef _PC_MAX_INPUT
14215
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14216
#endif
14217
#ifdef _PC_NAME_MAX
14218
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14219
#endif
14220
#ifdef _PC_NO_TRUNC
14221
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14222
#endif
14223
#ifdef _PC_PATH_MAX
14224
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14225
#endif
14226
#ifdef _PC_PIPE_BUF
14227
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14228
#endif
14229
#ifdef _PC_PRIO_IO
14230
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14231
#endif
14232
#ifdef _PC_SOCK_MAXBUF
14233
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14234
#endif
14235
#ifdef _PC_SYNC_IO
14236
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14237
#endif
14238
#ifdef _PC_VDISABLE
14239
    {"PC_VDISABLE",     _PC_VDISABLE},
14240
#endif
14241
#ifdef _PC_ACL_ENABLED
14242
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14243
#endif
14244
#ifdef _PC_MIN_HOLE_SIZE
14245
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14246
#endif
14247
#ifdef _PC_ALLOC_SIZE_MIN
14248
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14249
#endif
14250
#ifdef _PC_REC_INCR_XFER_SIZE
14251
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14252
#endif
14253
#ifdef _PC_REC_MAX_XFER_SIZE
14254
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14255
#endif
14256
#ifdef _PC_REC_MIN_XFER_SIZE
14257
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14258
#endif
14259
#ifdef _PC_REC_XFER_ALIGN
14260
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14261
#endif
14262
#ifdef _PC_SYMLINK_MAX
14263
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14264
#endif
14265
#ifdef _PC_XATTR_ENABLED
14266
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14267
#endif
14268
#ifdef _PC_XATTR_EXISTS
14269
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14270
#endif
14271
#ifdef _PC_TIMESTAMP_RESOLUTION
14272
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14273
#endif
14274
};
14275
#endif
14276
14277
14278
#ifdef HAVE_FPATHCONF
14279
/*[clinic input]
14280
os.fpathconf -> long
14281
14282
    fd: fildes
14283
    name: confname(table="pathconf_names")
14284
    /
14285
14286
Return the configuration limit name for the file descriptor fd.
14287
14288
If there is no limit, return -1.
14289
[clinic start generated code]*/
14290
14291
static long
14292
os_fpathconf_impl(PyObject *module, int fd, int name)
14293
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14294
0
{
14295
0
    long limit;
14296
14297
0
    errno = 0;
14298
0
    limit = fpathconf(fd, name);
14299
0
    if (limit == -1 && errno != 0)
14300
0
        posix_error();
14301
14302
0
    return limit;
14303
0
}
14304
#endif /* HAVE_FPATHCONF */
14305
14306
14307
#ifdef HAVE_PATHCONF
14308
/*[clinic input]
14309
os.pathconf -> long
14310
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14311
    name: confname(table="pathconf_names")
14312
14313
Return the configuration limit name for the file or directory path.
14314
14315
If there is no limit, return -1.
14316
On some platforms, path may also be specified as an open file descriptor.
14317
  If this functionality is unavailable, using it raises an exception.
14318
[clinic start generated code]*/
14319
14320
static long
14321
os_pathconf_impl(PyObject *module, path_t *path, int name)
14322
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
14323
0
{
14324
0
    long limit;
14325
14326
0
    errno = 0;
14327
0
#ifdef HAVE_FPATHCONF
14328
0
    if (path->fd != -1)
14329
0
        limit = fpathconf(path->fd, name);
14330
0
    else
14331
0
#endif
14332
0
        limit = pathconf(path->narrow, name);
14333
0
    if (limit == -1 && errno != 0) {
14334
0
        if (errno == EINVAL)
14335
            /* could be a path or name problem */
14336
0
            posix_error();
14337
0
        else
14338
0
            path_error(path);
14339
0
    }
14340
14341
0
    return limit;
14342
0
}
14343
#endif /* HAVE_PATHCONF */
14344
14345
#ifdef HAVE_CONFSTR
14346
static struct constdef posix_constants_confstr[] = {
14347
#ifdef _CS_ARCHITECTURE
14348
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14349
#endif
14350
#ifdef _CS_GNU_LIBC_VERSION
14351
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14352
#endif
14353
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14354
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14355
#endif
14356
#ifdef _CS_HOSTNAME
14357
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14358
#endif
14359
#ifdef _CS_HW_PROVIDER
14360
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14361
#endif
14362
#ifdef _CS_HW_SERIAL
14363
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14364
#endif
14365
#ifdef _CS_INITTAB_NAME
14366
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14367
#endif
14368
#ifdef _CS_LFS64_CFLAGS
14369
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14370
#endif
14371
#ifdef _CS_LFS64_LDFLAGS
14372
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14373
#endif
14374
#ifdef _CS_LFS64_LIBS
14375
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14376
#endif
14377
#ifdef _CS_LFS64_LINTFLAGS
14378
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14379
#endif
14380
#ifdef _CS_LFS_CFLAGS
14381
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14382
#endif
14383
#ifdef _CS_LFS_LDFLAGS
14384
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14385
#endif
14386
#ifdef _CS_LFS_LIBS
14387
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14388
#endif
14389
#ifdef _CS_LFS_LINTFLAGS
14390
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14391
#endif
14392
#ifdef _CS_MACHINE
14393
    {"CS_MACHINE",      _CS_MACHINE},
14394
#endif
14395
#ifdef _CS_PATH
14396
    {"CS_PATH", _CS_PATH},
14397
#endif
14398
#ifdef _CS_RELEASE
14399
    {"CS_RELEASE",      _CS_RELEASE},
14400
#endif
14401
#ifdef _CS_SRPC_DOMAIN
14402
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14403
#endif
14404
#ifdef _CS_SYSNAME
14405
    {"CS_SYSNAME",      _CS_SYSNAME},
14406
#endif
14407
#ifdef _CS_VERSION
14408
    {"CS_VERSION",      _CS_VERSION},
14409
#endif
14410
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14411
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14412
#endif
14413
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14414
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14415
#endif
14416
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14417
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14418
#endif
14419
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14420
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14421
#endif
14422
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14423
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14424
#endif
14425
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14426
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14427
#endif
14428
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14429
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14430
#endif
14431
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14432
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14433
#endif
14434
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14435
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14436
#endif
14437
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14438
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14439
#endif
14440
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14441
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14442
#endif
14443
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14444
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14445
#endif
14446
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14447
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14448
#endif
14449
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14450
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14451
#endif
14452
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14453
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14454
#endif
14455
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14456
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14457
#endif
14458
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14459
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14460
#endif
14461
#ifdef _MIPS_CS_BASE
14462
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14463
#endif
14464
#ifdef _MIPS_CS_HOSTID
14465
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14466
#endif
14467
#ifdef _MIPS_CS_HW_NAME
14468
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14469
#endif
14470
#ifdef _MIPS_CS_NUM_PROCESSORS
14471
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14472
#endif
14473
#ifdef _MIPS_CS_OSREL_MAJ
14474
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14475
#endif
14476
#ifdef _MIPS_CS_OSREL_MIN
14477
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14478
#endif
14479
#ifdef _MIPS_CS_OSREL_PATCH
14480
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14481
#endif
14482
#ifdef _MIPS_CS_OS_NAME
14483
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14484
#endif
14485
#ifdef _MIPS_CS_OS_PROVIDER
14486
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14487
#endif
14488
#ifdef _MIPS_CS_PROCESSORS
14489
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14490
#endif
14491
#ifdef _MIPS_CS_SERIAL
14492
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14493
#endif
14494
#ifdef _MIPS_CS_VENDOR
14495
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14496
#endif
14497
};
14498
14499
14500
/*[clinic input]
14501
os.confstr
14502
14503
    name: confname(table="confstr_names")
14504
    /
14505
14506
Return a string-valued system configuration variable.
14507
[clinic start generated code]*/
14508
14509
static PyObject *
14510
os_confstr_impl(PyObject *module, int name)
14511
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14512
0
{
14513
0
    PyObject *result = NULL;
14514
0
    char buffer[255];
14515
0
    size_t len;
14516
14517
0
    errno = 0;
14518
0
    len = confstr(name, buffer, sizeof(buffer));
14519
0
    if (len == 0) {
14520
0
        if (errno) {
14521
0
            posix_error();
14522
0
            return NULL;
14523
0
        }
14524
0
        else {
14525
0
            Py_RETURN_NONE;
14526
0
        }
14527
0
    }
14528
14529
0
    if (len >= sizeof(buffer)) {
14530
0
        size_t len2;
14531
0
        char *buf = PyMem_Malloc(len);
14532
0
        if (buf == NULL)
14533
0
            return PyErr_NoMemory();
14534
0
        len2 = confstr(name, buf, len);
14535
0
        assert(len == len2);
14536
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14537
0
        PyMem_Free(buf);
14538
0
    }
14539
0
    else
14540
0
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14541
0
    return result;
14542
0
}
14543
#endif /* HAVE_CONFSTR */
14544
14545
14546
#ifdef HAVE_SYSCONF
14547
static struct constdef posix_constants_sysconf[] = {
14548
#ifdef _SC_2_CHAR_TERM
14549
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14550
#endif
14551
#ifdef _SC_2_C_BIND
14552
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14553
#endif
14554
#ifdef _SC_2_C_DEV
14555
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14556
#endif
14557
#ifdef _SC_2_C_VERSION
14558
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14559
#endif
14560
#ifdef _SC_2_FORT_DEV
14561
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14562
#endif
14563
#ifdef _SC_2_FORT_RUN
14564
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14565
#endif
14566
#ifdef _SC_2_LOCALEDEF
14567
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14568
#endif
14569
#ifdef _SC_2_SW_DEV
14570
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14571
#endif
14572
#ifdef _SC_2_UPE
14573
    {"SC_2_UPE",        _SC_2_UPE},
14574
#endif
14575
#ifdef _SC_2_VERSION
14576
    {"SC_2_VERSION",    _SC_2_VERSION},
14577
#endif
14578
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14579
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14580
#endif
14581
#ifdef _SC_ACL
14582
    {"SC_ACL",  _SC_ACL},
14583
#endif
14584
#ifdef _SC_AIO_LISTIO_MAX
14585
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14586
#endif
14587
#ifdef _SC_AIO_MAX
14588
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14589
#endif
14590
#ifdef _SC_AIO_PRIO_DELTA_MAX
14591
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14592
#endif
14593
#ifdef _SC_ARG_MAX
14594
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14595
#endif
14596
#ifdef _SC_ASYNCHRONOUS_IO
14597
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14598
#endif
14599
#ifdef _SC_ATEXIT_MAX
14600
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14601
#endif
14602
#ifdef _SC_AUDIT
14603
    {"SC_AUDIT",        _SC_AUDIT},
14604
#endif
14605
#ifdef _SC_AVPHYS_PAGES
14606
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14607
#endif
14608
#ifdef _SC_BC_BASE_MAX
14609
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14610
#endif
14611
#ifdef _SC_BC_DIM_MAX
14612
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14613
#endif
14614
#ifdef _SC_BC_SCALE_MAX
14615
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14616
#endif
14617
#ifdef _SC_BC_STRING_MAX
14618
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14619
#endif
14620
#ifdef _SC_CAP
14621
    {"SC_CAP",  _SC_CAP},
14622
#endif
14623
#ifdef _SC_CHARCLASS_NAME_MAX
14624
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14625
#endif
14626
#ifdef _SC_CHAR_BIT
14627
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14628
#endif
14629
#ifdef _SC_CHAR_MAX
14630
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14631
#endif
14632
#ifdef _SC_CHAR_MIN
14633
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14634
#endif
14635
#ifdef _SC_CHILD_MAX
14636
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14637
#endif
14638
#ifdef _SC_CLK_TCK
14639
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14640
#endif
14641
#ifdef _SC_COHER_BLKSZ
14642
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14643
#endif
14644
#ifdef _SC_COLL_WEIGHTS_MAX
14645
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14646
#endif
14647
#ifdef _SC_DCACHE_ASSOC
14648
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14649
#endif
14650
#ifdef _SC_DCACHE_BLKSZ
14651
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14652
#endif
14653
#ifdef _SC_DCACHE_LINESZ
14654
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14655
#endif
14656
#ifdef _SC_DCACHE_SZ
14657
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14658
#endif
14659
#ifdef _SC_DCACHE_TBLKSZ
14660
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14661
#endif
14662
#ifdef _SC_DELAYTIMER_MAX
14663
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14664
#endif
14665
#ifdef _SC_EQUIV_CLASS_MAX
14666
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14667
#endif
14668
#ifdef _SC_EXPR_NEST_MAX
14669
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14670
#endif
14671
#ifdef _SC_FSYNC
14672
    {"SC_FSYNC",        _SC_FSYNC},
14673
#endif
14674
#ifdef _SC_GETGR_R_SIZE_MAX
14675
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14676
#endif
14677
#ifdef _SC_GETPW_R_SIZE_MAX
14678
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14679
#endif
14680
#ifdef _SC_ICACHE_ASSOC
14681
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14682
#endif
14683
#ifdef _SC_ICACHE_BLKSZ
14684
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14685
#endif
14686
#ifdef _SC_ICACHE_LINESZ
14687
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14688
#endif
14689
#ifdef _SC_ICACHE_SZ
14690
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14691
#endif
14692
#ifdef _SC_INF
14693
    {"SC_INF",  _SC_INF},
14694
#endif
14695
#ifdef _SC_INT_MAX
14696
    {"SC_INT_MAX",      _SC_INT_MAX},
14697
#endif
14698
#ifdef _SC_INT_MIN
14699
    {"SC_INT_MIN",      _SC_INT_MIN},
14700
#endif
14701
#ifdef _SC_IOV_MAX
14702
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14703
#endif
14704
#ifdef _SC_IP_SECOPTS
14705
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14706
#endif
14707
#ifdef _SC_JOB_CONTROL
14708
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14709
#endif
14710
#ifdef _SC_KERN_POINTERS
14711
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14712
#endif
14713
#ifdef _SC_KERN_SIM
14714
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14715
#endif
14716
#ifdef _SC_LINE_MAX
14717
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14718
#endif
14719
#ifdef _SC_LOGIN_NAME_MAX
14720
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14721
#endif
14722
#ifdef _SC_LOGNAME_MAX
14723
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14724
#endif
14725
#ifdef _SC_LONG_BIT
14726
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14727
#endif
14728
#ifdef _SC_MAC
14729
    {"SC_MAC",  _SC_MAC},
14730
#endif
14731
#ifdef _SC_MAPPED_FILES
14732
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14733
#endif
14734
#ifdef _SC_MAXPID
14735
    {"SC_MAXPID",       _SC_MAXPID},
14736
#endif
14737
#ifdef _SC_MB_LEN_MAX
14738
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14739
#endif
14740
#ifdef _SC_MEMLOCK
14741
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14742
#endif
14743
#ifdef _SC_MEMLOCK_RANGE
14744
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14745
#endif
14746
#ifdef _SC_MEMORY_PROTECTION
14747
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14748
#endif
14749
#ifdef _SC_MESSAGE_PASSING
14750
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14751
#endif
14752
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14753
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14754
#endif
14755
#ifdef _SC_MQ_OPEN_MAX
14756
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14757
#endif
14758
#ifdef _SC_MQ_PRIO_MAX
14759
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14760
#endif
14761
#ifdef _SC_NACLS_MAX
14762
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14763
#endif
14764
#ifdef _SC_NGROUPS_MAX
14765
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14766
#endif
14767
#ifdef _SC_NL_ARGMAX
14768
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14769
#endif
14770
#ifdef _SC_NL_LANGMAX
14771
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14772
#endif
14773
#ifdef _SC_NL_MSGMAX
14774
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14775
#endif
14776
#ifdef _SC_NL_NMAX
14777
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14778
#endif
14779
#ifdef _SC_NL_SETMAX
14780
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14781
#endif
14782
#ifdef _SC_NL_TEXTMAX
14783
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14784
#endif
14785
#ifdef _SC_NPROCESSORS_CONF
14786
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14787
#endif
14788
#ifdef _SC_NPROCESSORS_ONLN
14789
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14790
#endif
14791
#ifdef _SC_NPROC_CONF
14792
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14793
#endif
14794
#ifdef _SC_NPROC_ONLN
14795
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14796
#endif
14797
#ifdef _SC_NZERO
14798
    {"SC_NZERO",        _SC_NZERO},
14799
#endif
14800
#ifdef _SC_OPEN_MAX
14801
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14802
#endif
14803
#ifdef _SC_PAGESIZE
14804
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14805
#endif
14806
#ifdef _SC_PAGE_SIZE
14807
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14808
#endif
14809
#ifdef _SC_AIX_REALMEM
14810
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14811
#endif
14812
#ifdef _SC_PASS_MAX
14813
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14814
#endif
14815
#ifdef _SC_PHYS_PAGES
14816
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14817
#endif
14818
#ifdef _SC_PII
14819
    {"SC_PII",  _SC_PII},
14820
#endif
14821
#ifdef _SC_PII_INTERNET
14822
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14823
#endif
14824
#ifdef _SC_PII_INTERNET_DGRAM
14825
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14826
#endif
14827
#ifdef _SC_PII_INTERNET_STREAM
14828
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14829
#endif
14830
#ifdef _SC_PII_OSI
14831
    {"SC_PII_OSI",      _SC_PII_OSI},
14832
#endif
14833
#ifdef _SC_PII_OSI_CLTS
14834
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14835
#endif
14836
#ifdef _SC_PII_OSI_COTS
14837
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14838
#endif
14839
#ifdef _SC_PII_OSI_M
14840
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14841
#endif
14842
#ifdef _SC_PII_SOCKET
14843
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14844
#endif
14845
#ifdef _SC_PII_XTI
14846
    {"SC_PII_XTI",      _SC_PII_XTI},
14847
#endif
14848
#ifdef _SC_POLL
14849
    {"SC_POLL", _SC_POLL},
14850
#endif
14851
#ifdef _SC_PRIORITIZED_IO
14852
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14853
#endif
14854
#ifdef _SC_PRIORITY_SCHEDULING
14855
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14856
#endif
14857
#ifdef _SC_REALTIME_SIGNALS
14858
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14859
#endif
14860
#ifdef _SC_RE_DUP_MAX
14861
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14862
#endif
14863
#ifdef _SC_RTSIG_MAX
14864
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14865
#endif
14866
#ifdef _SC_SAVED_IDS
14867
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14868
#endif
14869
#ifdef _SC_SCHAR_MAX
14870
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14871
#endif
14872
#ifdef _SC_SCHAR_MIN
14873
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14874
#endif
14875
#ifdef _SC_SELECT
14876
    {"SC_SELECT",       _SC_SELECT},
14877
#endif
14878
#ifdef _SC_SEMAPHORES
14879
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14880
#endif
14881
#ifdef _SC_SEM_NSEMS_MAX
14882
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14883
#endif
14884
#ifdef _SC_SEM_VALUE_MAX
14885
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14886
#endif
14887
#ifdef _SC_SHARED_MEMORY_OBJECTS
14888
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14889
#endif
14890
#ifdef _SC_SHRT_MAX
14891
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14892
#endif
14893
#ifdef _SC_SHRT_MIN
14894
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14895
#endif
14896
#ifdef _SC_SIGQUEUE_MAX
14897
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14898
#endif
14899
#ifdef _SC_SIGRT_MAX
14900
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14901
#endif
14902
#ifdef _SC_SIGRT_MIN
14903
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14904
#endif
14905
#ifdef _SC_SOFTPOWER
14906
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14907
#endif
14908
#ifdef _SC_SPLIT_CACHE
14909
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14910
#endif
14911
#ifdef _SC_SSIZE_MAX
14912
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14913
#endif
14914
#ifdef _SC_STACK_PROT
14915
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14916
#endif
14917
#ifdef _SC_STREAM_MAX
14918
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14919
#endif
14920
#ifdef _SC_SYNCHRONIZED_IO
14921
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14922
#endif
14923
#ifdef _SC_THREADS
14924
    {"SC_THREADS",      _SC_THREADS},
14925
#endif
14926
#ifdef _SC_THREAD_ATTR_STACKADDR
14927
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14928
#endif
14929
#ifdef _SC_THREAD_ATTR_STACKSIZE
14930
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14931
#endif
14932
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14933
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14934
#endif
14935
#ifdef _SC_THREAD_KEYS_MAX
14936
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14937
#endif
14938
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14939
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14940
#endif
14941
#ifdef _SC_THREAD_PRIO_INHERIT
14942
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14943
#endif
14944
#ifdef _SC_THREAD_PRIO_PROTECT
14945
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14946
#endif
14947
#ifdef _SC_THREAD_PROCESS_SHARED
14948
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14949
#endif
14950
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14951
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14952
#endif
14953
#ifdef _SC_THREAD_STACK_MIN
14954
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14955
#endif
14956
#ifdef _SC_THREAD_THREADS_MAX
14957
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14958
#endif
14959
#ifdef _SC_TIMERS
14960
    {"SC_TIMERS",       _SC_TIMERS},
14961
#endif
14962
#ifdef _SC_TIMER_MAX
14963
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14964
#endif
14965
#ifdef _SC_TTY_NAME_MAX
14966
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14967
#endif
14968
#ifdef _SC_TZNAME_MAX
14969
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14970
#endif
14971
#ifdef _SC_T_IOV_MAX
14972
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14973
#endif
14974
#ifdef _SC_UCHAR_MAX
14975
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14976
#endif
14977
#ifdef _SC_UINT_MAX
14978
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14979
#endif
14980
#ifdef _SC_UIO_MAXIOV
14981
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14982
#endif
14983
#ifdef _SC_ULONG_MAX
14984
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14985
#endif
14986
#ifdef _SC_USHRT_MAX
14987
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14988
#endif
14989
#ifdef _SC_VERSION
14990
    {"SC_VERSION",      _SC_VERSION},
14991
#endif
14992
#ifdef _SC_WORD_BIT
14993
    {"SC_WORD_BIT",     _SC_WORD_BIT},
14994
#endif
14995
#ifdef _SC_XBS5_ILP32_OFF32
14996
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
14997
#endif
14998
#ifdef _SC_XBS5_ILP32_OFFBIG
14999
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15000
#endif
15001
#ifdef _SC_XBS5_LP64_OFF64
15002
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15003
#endif
15004
#ifdef _SC_XBS5_LPBIG_OFFBIG
15005
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15006
#endif
15007
#ifdef _SC_XOPEN_CRYPT
15008
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15009
#endif
15010
#ifdef _SC_XOPEN_ENH_I18N
15011
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15012
#endif
15013
#ifdef _SC_XOPEN_LEGACY
15014
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15015
#endif
15016
#ifdef _SC_XOPEN_REALTIME
15017
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15018
#endif
15019
#ifdef _SC_XOPEN_REALTIME_THREADS
15020
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15021
#endif
15022
#ifdef _SC_XOPEN_SHM
15023
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15024
#endif
15025
#ifdef _SC_XOPEN_UNIX
15026
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15027
#endif
15028
#ifdef _SC_XOPEN_VERSION
15029
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15030
#endif
15031
#ifdef _SC_XOPEN_XCU_VERSION
15032
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15033
#endif
15034
#ifdef _SC_XOPEN_XPG2
15035
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15036
#endif
15037
#ifdef _SC_XOPEN_XPG3
15038
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15039
#endif
15040
#ifdef _SC_XOPEN_XPG4
15041
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15042
#endif
15043
#ifdef _SC_MINSIGSTKSZ
15044
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15045
#endif
15046
};
15047
15048
15049
/*[clinic input]
15050
os.sysconf -> long
15051
    name: confname(table="sysconf_names")
15052
    /
15053
15054
Return an integer-valued system configuration variable.
15055
[clinic start generated code]*/
15056
15057
static long
15058
os_sysconf_impl(PyObject *module, int name)
15059
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15060
0
{
15061
0
    long value;
15062
15063
0
    errno = 0;
15064
0
    value = sysconf(name);
15065
0
    if (value == -1 && errno != 0)
15066
0
        posix_error();
15067
0
    return value;
15068
0
}
15069
#endif /* HAVE_SYSCONF */
15070
15071
15072
static int
15073
setup_confname_table(struct constdef *table, size_t tablesize,
15074
                     const char *tablename, PyObject *module)
15075
84
{
15076
84
    PyObject *d = PyDict_New();
15077
84
    if (d == NULL)
15078
0
        return -1;
15079
15080
5.15k
    for (size_t i=0; i < tablesize; ++i) {
15081
5.06k
        PyObject *o = PyLong_FromLong(table[i].value);
15082
5.06k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15083
0
            Py_XDECREF(o);
15084
0
            Py_DECREF(d);
15085
0
            return -1;
15086
0
        }
15087
5.06k
        Py_DECREF(o);
15088
5.06k
    }
15089
84
    return PyModule_Add(module, tablename, d);
15090
84
}
15091
15092
/* Return -1 on failure, 0 on success. */
15093
static int
15094
setup_confname_tables(PyObject *module)
15095
28
{
15096
28
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15097
28
    if (setup_confname_table(posix_constants_pathconf,
15098
28
                             sizeof(posix_constants_pathconf)
15099
28
                               / sizeof(struct constdef),
15100
28
                             "pathconf_names", module))
15101
0
        return -1;
15102
28
#endif
15103
28
#ifdef HAVE_CONFSTR
15104
28
    if (setup_confname_table(posix_constants_confstr,
15105
28
                             sizeof(posix_constants_confstr)
15106
28
                               / sizeof(struct constdef),
15107
28
                             "confstr_names", module))
15108
0
        return -1;
15109
28
#endif
15110
28
#ifdef HAVE_SYSCONF
15111
28
    if (setup_confname_table(posix_constants_sysconf,
15112
28
                             sizeof(posix_constants_sysconf)
15113
28
                               / sizeof(struct constdef),
15114
28
                             "sysconf_names", module))
15115
0
        return -1;
15116
28
#endif
15117
28
    return 0;
15118
28
}
15119
15120
15121
/*[clinic input]
15122
os.abort
15123
15124
Abort the interpreter immediately.
15125
15126
This function 'dumps core' or otherwise fails in the hardest way possible
15127
on the hosting operating system.  This function never returns.
15128
[clinic start generated code]*/
15129
15130
static PyObject *
15131
os_abort_impl(PyObject *module)
15132
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
15133
0
{
15134
0
    abort();
15135
    /*NOTREACHED*/
15136
#ifndef __clang__
15137
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15138
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15139
       is smarter and emits a warning on the return. */
15140
    Py_FatalError("abort() called from Python code didn't abort!");
15141
    return NULL;
15142
#endif
15143
0
}
15144
15145
#ifdef MS_WINDOWS
15146
/* Grab ShellExecute dynamically from shell32 */
15147
static int has_ShellExecute = -1;
15148
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15149
                                              LPCWSTR, INT);
15150
static int
15151
check_ShellExecute(void)
15152
{
15153
    HINSTANCE hShell32;
15154
15155
    /* only recheck */
15156
    if (-1 == has_ShellExecute) {
15157
        Py_BEGIN_ALLOW_THREADS
15158
        /* Security note: this call is not vulnerable to "DLL hijacking".
15159
           SHELL32 is part of "KnownDLLs" and so Windows always load
15160
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15161
           in the DLL search path. */
15162
        hShell32 = LoadLibraryW(L"SHELL32");
15163
        if (hShell32) {
15164
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15165
                                            "ShellExecuteW");
15166
            has_ShellExecute = Py_ShellExecuteW != NULL;
15167
        } else {
15168
            has_ShellExecute = 0;
15169
        }
15170
        Py_END_ALLOW_THREADS
15171
    }
15172
    return has_ShellExecute;
15173
}
15174
15175
15176
/*[clinic input]
15177
os.startfile
15178
    filepath: path_t
15179
    operation: Py_UNICODE = NULL
15180
    arguments: Py_UNICODE = NULL
15181
    cwd: path_t(nullable=True) = None
15182
    show_cmd: int = 1
15183
15184
Start a file with its associated application.
15185
15186
When "operation" is not specified or "open", this acts like
15187
double-clicking the file in Explorer, or giving the file name as an
15188
argument to the DOS "start" command: the file is opened with whatever
15189
application (if any) its extension is associated.
15190
When another "operation" is given, it specifies what should be done with
15191
the file.  A typical operation is "print".
15192
15193
"arguments" is passed to the application, but should be omitted if the
15194
file is a document.
15195
15196
"cwd" is the working directory for the operation. If "filepath" is
15197
relative, it will be resolved against this directory. This argument
15198
should usually be an absolute path.
15199
15200
"show_cmd" can be used to override the recommended visibility option.
15201
See the Windows ShellExecute documentation for values.
15202
15203
startfile returns as soon as the associated application is launched.
15204
There is no option to wait for the application to close, and no way
15205
to retrieve the application's exit status.
15206
15207
The filepath is relative to the current directory.  If you want to use
15208
an absolute path, make sure the first character is not a slash ("/");
15209
the underlying Win32 ShellExecute function doesn't work if it is.
15210
[clinic start generated code]*/
15211
15212
static PyObject *
15213
os_startfile_impl(PyObject *module, path_t *filepath,
15214
                  const wchar_t *operation, const wchar_t *arguments,
15215
                  path_t *cwd, int show_cmd)
15216
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15217
{
15218
    HINSTANCE rc;
15219
15220
    if(!check_ShellExecute()) {
15221
        /* If the OS doesn't have ShellExecute, return a
15222
           NotImplementedError. */
15223
        return PyErr_Format(PyExc_NotImplementedError,
15224
            "startfile not available on this platform");
15225
    }
15226
15227
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15228
        return NULL;
15229
    }
15230
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15231
                    arguments, cwd->object ? cwd->object : Py_None,
15232
                    show_cmd) < 0) {
15233
        return NULL;
15234
    }
15235
15236
    Py_BEGIN_ALLOW_THREADS
15237
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15238
                          arguments, cwd->wide, show_cmd);
15239
    Py_END_ALLOW_THREADS
15240
15241
    if (rc <= (HINSTANCE)32) {
15242
        win32_error_object("startfile", filepath->object);
15243
        return NULL;
15244
    }
15245
    Py_RETURN_NONE;
15246
}
15247
#endif /* MS_WINDOWS */
15248
15249
15250
#ifdef HAVE_GETLOADAVG
15251
/*[clinic input]
15252
os.getloadavg
15253
15254
Return average recent system load information.
15255
15256
Return the number of processes in the system run queue averaged over
15257
the last 1, 5, and 15 minutes as a tuple of three floats.
15258
Raises OSError if the load average was unobtainable.
15259
[clinic start generated code]*/
15260
15261
static PyObject *
15262
os_getloadavg_impl(PyObject *module)
15263
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15264
0
{
15265
0
    double loadavg[3];
15266
0
    if (getloadavg(loadavg, 3)!=3) {
15267
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15268
0
        return NULL;
15269
0
    } else
15270
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15271
0
}
15272
#endif /* HAVE_GETLOADAVG */
15273
15274
15275
/*[clinic input]
15276
os.device_encoding
15277
    fd: int
15278
15279
Return a string describing the encoding of a terminal's file descriptor.
15280
15281
The file descriptor must be attached to a terminal.
15282
If the device is not a terminal, return None.
15283
[clinic start generated code]*/
15284
15285
static PyObject *
15286
os_device_encoding_impl(PyObject *module, int fd)
15287
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15288
0
{
15289
0
    return _Py_device_encoding(fd);
15290
0
}
15291
15292
15293
#ifdef HAVE_SETRESUID
15294
/*[clinic input]
15295
os.setresuid
15296
15297
    ruid: uid_t
15298
    euid: uid_t
15299
    suid: uid_t
15300
    /
15301
15302
Set the current process's real, effective, and saved user ids.
15303
[clinic start generated code]*/
15304
15305
static PyObject *
15306
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15307
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15308
0
{
15309
0
    if (setresuid(ruid, euid, suid) < 0)
15310
0
        return posix_error();
15311
0
    Py_RETURN_NONE;
15312
0
}
15313
#endif /* HAVE_SETRESUID */
15314
15315
15316
#ifdef HAVE_SETRESGID
15317
/*[clinic input]
15318
os.setresgid
15319
15320
    rgid: gid_t
15321
    egid: gid_t
15322
    sgid: gid_t
15323
    /
15324
15325
Set the current process's real, effective, and saved group ids.
15326
[clinic start generated code]*/
15327
15328
static PyObject *
15329
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15330
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15331
0
{
15332
0
    if (setresgid(rgid, egid, sgid) < 0)
15333
0
        return posix_error();
15334
0
    Py_RETURN_NONE;
15335
0
}
15336
#endif /* HAVE_SETRESGID */
15337
15338
15339
#ifdef HAVE_GETRESUID
15340
/*[clinic input]
15341
os.getresuid
15342
15343
Return a tuple of the current process's real, effective, and saved user ids.
15344
[clinic start generated code]*/
15345
15346
static PyObject *
15347
os_getresuid_impl(PyObject *module)
15348
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
15349
0
{
15350
0
    uid_t ruid, euid, suid;
15351
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15352
0
        return posix_error();
15353
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15354
0
                                  _PyLong_FromUid(euid),
15355
0
                                  _PyLong_FromUid(suid));
15356
0
}
15357
#endif /* HAVE_GETRESUID */
15358
15359
15360
#ifdef HAVE_GETRESGID
15361
/*[clinic input]
15362
@permit_long_summary
15363
os.getresgid
15364
15365
Return a tuple of the current process's real, effective, and saved group ids.
15366
[clinic start generated code]*/
15367
15368
static PyObject *
15369
os_getresgid_impl(PyObject *module)
15370
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15371
0
{
15372
0
    gid_t rgid, egid, sgid;
15373
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15374
0
        return posix_error();
15375
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15376
0
                                  _PyLong_FromGid(egid),
15377
0
                                  _PyLong_FromGid(sgid));
15378
0
}
15379
#endif /* HAVE_GETRESGID */
15380
15381
15382
#ifdef USE_XATTRS
15383
/*[clinic input]
15384
os.getxattr
15385
15386
    path: path_t(allow_fd=True)
15387
    attribute: path_t
15388
    *
15389
    follow_symlinks: bool = True
15390
15391
Return the value of extended attribute attribute on path.
15392
15393
path may be either a string, a path-like object, or an open file descriptor.
15394
If follow_symlinks is False, and the last element of the path is a symbolic
15395
  link, getxattr will examine the symbolic link itself instead of the file
15396
  the link points to.
15397
15398
[clinic start generated code]*/
15399
15400
static PyObject *
15401
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15402
                 int follow_symlinks)
15403
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
15404
0
{
15405
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
15406
0
        return NULL;
15407
15408
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15409
0
        return NULL;
15410
0
    }
15411
15412
0
    for (Py_ssize_t i = 0; ; i++) {
15413
0
        ssize_t result;
15414
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15415
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15416
0
        if (!buffer_size) {
15417
0
            path_error(path);
15418
0
            return NULL;
15419
0
        }
15420
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15421
0
        if (writer == NULL) {
15422
0
            return NULL;
15423
0
        }
15424
0
        void *ptr = PyBytesWriter_GetData(writer);
15425
15426
0
        Py_BEGIN_ALLOW_THREADS;
15427
0
        if (path->fd >= 0)
15428
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15429
0
        else if (follow_symlinks)
15430
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15431
0
        else
15432
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15433
0
        Py_END_ALLOW_THREADS;
15434
15435
0
        if (result < 0) {
15436
0
            PyBytesWriter_Discard(writer);
15437
0
            if (errno == ERANGE) {
15438
0
                continue;
15439
0
            }
15440
0
            path_error(path);
15441
0
            return NULL;
15442
0
        }
15443
15444
0
        return PyBytesWriter_FinishWithSize(writer, result);
15445
0
    }
15446
0
}
15447
15448
15449
/*[clinic input]
15450
@permit_long_docstring_body
15451
os.setxattr
15452
15453
    path: path_t(allow_fd=True)
15454
    attribute: path_t
15455
    value: Py_buffer
15456
    flags: int = 0
15457
    *
15458
    follow_symlinks: bool = True
15459
15460
Set extended attribute attribute on path to value.
15461
15462
path may be either a string, a path-like object,  or an open file descriptor.
15463
If follow_symlinks is False, and the last element of the path is a symbolic
15464
  link, setxattr will modify the symbolic link itself instead of the file
15465
  the link points to.
15466
15467
[clinic start generated code]*/
15468
15469
static PyObject *
15470
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15471
                 Py_buffer *value, int flags, int follow_symlinks)
15472
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15473
0
{
15474
0
    ssize_t result;
15475
15476
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
15477
0
        return NULL;
15478
15479
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15480
0
                    value->buf, value->len, flags) < 0) {
15481
0
        return NULL;
15482
0
    }
15483
15484
0
    Py_BEGIN_ALLOW_THREADS;
15485
0
    if (path->fd > -1)
15486
0
        result = fsetxattr(path->fd, attribute->narrow,
15487
0
                           value->buf, value->len, flags);
15488
0
    else if (follow_symlinks)
15489
0
        result = setxattr(path->narrow, attribute->narrow,
15490
0
                           value->buf, value->len, flags);
15491
0
    else
15492
0
        result = lsetxattr(path->narrow, attribute->narrow,
15493
0
                           value->buf, value->len, flags);
15494
0
    Py_END_ALLOW_THREADS;
15495
15496
0
    if (result) {
15497
0
        path_error(path);
15498
0
        return NULL;
15499
0
    }
15500
15501
0
    Py_RETURN_NONE;
15502
0
}
15503
15504
15505
/*[clinic input]
15506
os.removexattr
15507
15508
    path: path_t(allow_fd=True)
15509
    attribute: path_t
15510
    *
15511
    follow_symlinks: bool = True
15512
15513
Remove extended attribute attribute on path.
15514
15515
path may be either a string, a path-like object, or an open file descriptor.
15516
If follow_symlinks is False, and the last element of the path is a symbolic
15517
  link, removexattr will modify the symbolic link itself instead of the file
15518
  the link points to.
15519
15520
[clinic start generated code]*/
15521
15522
static PyObject *
15523
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15524
                    int follow_symlinks)
15525
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15526
0
{
15527
0
    ssize_t result;
15528
15529
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
15530
0
        return NULL;
15531
15532
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15533
0
        return NULL;
15534
0
    }
15535
15536
0
    Py_BEGIN_ALLOW_THREADS;
15537
0
    if (path->fd > -1)
15538
0
        result = fremovexattr(path->fd, attribute->narrow);
15539
0
    else if (follow_symlinks)
15540
0
        result = removexattr(path->narrow, attribute->narrow);
15541
0
    else
15542
0
        result = lremovexattr(path->narrow, attribute->narrow);
15543
0
    Py_END_ALLOW_THREADS;
15544
15545
0
    if (result) {
15546
0
        return path_error(path);
15547
0
    }
15548
15549
0
    Py_RETURN_NONE;
15550
0
}
15551
15552
15553
/*[clinic input]
15554
@permit_long_docstring_body
15555
os.listxattr
15556
15557
    path: path_t(allow_fd=True, nullable=True) = None
15558
    *
15559
    follow_symlinks: bool = True
15560
15561
Return a list of extended attributes on path.
15562
15563
path may be either None, a string, a path-like object, or an open file descriptor.
15564
if path is None, listxattr will examine the current directory.
15565
If follow_symlinks is False, and the last element of the path is a symbolic
15566
  link, listxattr will examine the symbolic link itself instead of the file
15567
  the link points to.
15568
[clinic start generated code]*/
15569
15570
static PyObject *
15571
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15572
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15573
0
{
15574
0
    Py_ssize_t i;
15575
0
    PyObject *result = NULL;
15576
0
    const char *name;
15577
0
    char *buffer = NULL;
15578
15579
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
15580
0
        goto exit;
15581
15582
0
    if (PySys_Audit("os.listxattr", "(O)",
15583
0
                    path->object ? path->object : Py_None) < 0) {
15584
0
        return NULL;
15585
0
    }
15586
15587
0
    name = path->narrow ? path->narrow : ".";
15588
15589
0
    for (i = 0; ; i++) {
15590
0
        const char *start, *trace, *end;
15591
0
        ssize_t length;
15592
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15593
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15594
0
        if (!buffer_size) {
15595
            /* ERANGE */
15596
0
            path_error(path);
15597
0
            break;
15598
0
        }
15599
0
        buffer = PyMem_Malloc(buffer_size);
15600
0
        if (!buffer) {
15601
0
            PyErr_NoMemory();
15602
0
            break;
15603
0
        }
15604
15605
0
        Py_BEGIN_ALLOW_THREADS;
15606
0
        if (path->fd > -1)
15607
0
            length = flistxattr(path->fd, buffer, buffer_size);
15608
0
        else if (follow_symlinks)
15609
0
            length = listxattr(name, buffer, buffer_size);
15610
0
        else
15611
0
            length = llistxattr(name, buffer, buffer_size);
15612
0
        Py_END_ALLOW_THREADS;
15613
15614
0
        if (length < 0) {
15615
0
            if (errno == ERANGE) {
15616
0
                PyMem_Free(buffer);
15617
0
                buffer = NULL;
15618
0
                continue;
15619
0
            }
15620
0
            path_error(path);
15621
0
            break;
15622
0
        }
15623
15624
0
        result = PyList_New(0);
15625
0
        if (!result) {
15626
0
            goto exit;
15627
0
        }
15628
15629
0
        end = buffer + length;
15630
0
        for (trace = start = buffer; trace != end; trace++) {
15631
0
            if (!*trace) {
15632
0
                int error;
15633
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15634
0
                                                                 trace - start);
15635
0
                if (!attribute) {
15636
0
                    Py_SETREF(result, NULL);
15637
0
                    goto exit;
15638
0
                }
15639
0
                error = PyList_Append(result, attribute);
15640
0
                Py_DECREF(attribute);
15641
0
                if (error) {
15642
0
                    Py_SETREF(result, NULL);
15643
0
                    goto exit;
15644
0
                }
15645
0
                start = trace + 1;
15646
0
            }
15647
0
        }
15648
0
    break;
15649
0
    }
15650
0
exit:
15651
0
    if (buffer)
15652
0
        PyMem_Free(buffer);
15653
0
    return result;
15654
0
}
15655
#endif /* USE_XATTRS */
15656
15657
15658
/*[clinic input]
15659
@permit_long_summary
15660
os.urandom
15661
15662
    size: Py_ssize_t(allow_negative=False)
15663
    /
15664
15665
Return a bytes object containing random bytes suitable for cryptographic use.
15666
[clinic start generated code]*/
15667
15668
static PyObject *
15669
os_urandom_impl(PyObject *module, Py_ssize_t size)
15670
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15671
0
{
15672
0
    if (size < 0) {
15673
0
        return PyErr_Format(PyExc_ValueError,
15674
0
                            "negative argument not allowed");
15675
0
    }
15676
15677
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15678
0
    if (writer == NULL) {
15679
0
        return NULL;
15680
0
    }
15681
15682
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15683
0
    if (result == -1) {
15684
0
        PyBytesWriter_Discard(writer);
15685
0
        return NULL;
15686
0
    }
15687
0
    return PyBytesWriter_Finish(writer);
15688
0
}
15689
15690
#ifdef HAVE_MEMFD_CREATE
15691
/*[clinic input]
15692
os.memfd_create
15693
15694
    name: unicode_fs_encoded
15695
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15696
15697
[clinic start generated code]*/
15698
15699
static PyObject *
15700
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15701
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15702
0
{
15703
0
    int fd;
15704
0
    const char *bytes = PyBytes_AS_STRING(name);
15705
0
    Py_BEGIN_ALLOW_THREADS
15706
0
    fd = memfd_create(bytes, flags);
15707
0
    Py_END_ALLOW_THREADS
15708
0
    if (fd == -1) {
15709
0
        return PyErr_SetFromErrno(PyExc_OSError);
15710
0
    }
15711
0
    return PyLong_FromLong(fd);
15712
0
}
15713
#endif
15714
15715
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15716
/*[clinic input]
15717
os.eventfd
15718
15719
    initval: unsigned_int
15720
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15721
15722
Creates and returns an event notification file descriptor.
15723
[clinic start generated code]*/
15724
15725
static PyObject *
15726
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15727
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15728
15729
0
{
15730
    /* initval is limited to uint32_t, internal counter is uint64_t */
15731
0
    int fd;
15732
0
    Py_BEGIN_ALLOW_THREADS
15733
0
    fd = eventfd(initval, flags);
15734
0
    Py_END_ALLOW_THREADS
15735
0
    if (fd == -1) {
15736
0
        return PyErr_SetFromErrno(PyExc_OSError);
15737
0
    }
15738
0
    return PyLong_FromLong(fd);
15739
0
}
15740
15741
/*[clinic input]
15742
os.eventfd_read
15743
15744
    fd: fildes
15745
15746
Read eventfd value
15747
[clinic start generated code]*/
15748
15749
static PyObject *
15750
os_eventfd_read_impl(PyObject *module, int fd)
15751
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15752
0
{
15753
0
    eventfd_t value;
15754
0
    int result;
15755
0
    Py_BEGIN_ALLOW_THREADS
15756
0
    result = eventfd_read(fd, &value);
15757
0
    Py_END_ALLOW_THREADS
15758
0
    if (result == -1) {
15759
0
        return PyErr_SetFromErrno(PyExc_OSError);
15760
0
    }
15761
0
    return PyLong_FromUnsignedLongLong(value);
15762
0
}
15763
15764
/*[clinic input]
15765
os.eventfd_write
15766
15767
    fd: fildes
15768
    value: unsigned_long_long
15769
15770
Write eventfd value.
15771
[clinic start generated code]*/
15772
15773
static PyObject *
15774
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15775
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15776
0
{
15777
0
    int result;
15778
0
    Py_BEGIN_ALLOW_THREADS
15779
0
    result = eventfd_write(fd, value);
15780
0
    Py_END_ALLOW_THREADS
15781
0
    if (result == -1) {
15782
0
        return PyErr_SetFromErrno(PyExc_OSError);
15783
0
    }
15784
0
    Py_RETURN_NONE;
15785
0
}
15786
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15787
15788
/* Terminal size querying */
15789
15790
PyDoc_STRVAR(TerminalSize_docstring,
15791
    "A tuple of (columns, lines) for holding terminal window size");
15792
15793
static PyStructSequence_Field TerminalSize_fields[] = {
15794
    {"columns", "width of the terminal window in characters"},
15795
    {"lines", "height of the terminal window in characters"},
15796
    {NULL, NULL}
15797
};
15798
15799
static PyStructSequence_Desc TerminalSize_desc = {
15800
    "os.terminal_size",
15801
    TerminalSize_docstring,
15802
    TerminalSize_fields,
15803
    2,
15804
};
15805
15806
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15807
/*[clinic input]
15808
os.get_terminal_size
15809
15810
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15811
    /
15812
15813
Return the size of the terminal window as (columns, lines).
15814
15815
The optional argument fd (default standard output) specifies
15816
which file descriptor should be queried.
15817
15818
If the file descriptor is not connected to a terminal, an OSError
15819
is thrown.
15820
15821
This function will only be defined if an implementation is
15822
available for this system.
15823
15824
shutil.get_terminal_size is the high-level function which should
15825
normally be used, os.get_terminal_size is the low-level implementation.
15826
[clinic start generated code]*/
15827
15828
static PyObject *
15829
os_get_terminal_size_impl(PyObject *module, int fd)
15830
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15831
0
{
15832
0
    int columns, lines;
15833
0
    PyObject *termsize;
15834
15835
    /* Under some conditions stdout may not be connected and
15836
     * fileno(stdout) may point to an invalid file descriptor. For example
15837
     * GUI apps don't have valid standard streams by default.
15838
     *
15839
     * If this happens, and the optional fd argument is not present,
15840
     * the ioctl below will fail returning EBADF. This is what we want.
15841
     */
15842
15843
0
#ifdef TERMSIZE_USE_IOCTL
15844
0
    {
15845
0
        struct winsize w;
15846
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15847
0
            return PyErr_SetFromErrno(PyExc_OSError);
15848
0
        columns = w.ws_col;
15849
0
        lines = w.ws_row;
15850
0
    }
15851
0
#endif /* TERMSIZE_USE_IOCTL */
15852
15853
#ifdef TERMSIZE_USE_CONIO
15854
    {
15855
        HANDLE handle;
15856
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15857
        handle = _Py_get_osfhandle(fd);
15858
        if (handle == INVALID_HANDLE_VALUE)
15859
            return NULL;
15860
15861
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15862
            return PyErr_SetFromWindowsErr(0);
15863
15864
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15865
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15866
    }
15867
#endif /* TERMSIZE_USE_CONIO */
15868
15869
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15870
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15871
0
    if (termsize == NULL)
15872
0
        return NULL;
15873
15874
0
    int pos = 0;
15875
15876
0
#define SET_TERMSIZE(CALL)                                   \
15877
0
    do {                                                     \
15878
0
        PyObject *item = (CALL);                             \
15879
0
        if (item == NULL) {                                  \
15880
0
            Py_DECREF(termsize);                             \
15881
0
            return NULL;                                     \
15882
0
        }                                                    \
15883
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15884
0
    } while(0)
15885
15886
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15887
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15888
0
#undef SET_TERMSIZE
15889
15890
0
    return termsize;
15891
0
}
15892
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15893
15894
/*[clinic input]
15895
os.cpu_count
15896
15897
Return the number of logical CPUs in the system.
15898
15899
Return None if indeterminable.
15900
[clinic start generated code]*/
15901
15902
static PyObject *
15903
os_cpu_count_impl(PyObject *module)
15904
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15905
0
{
15906
0
    const PyConfig *config = _Py_GetConfig();
15907
0
    if (config->cpu_count > 0) {
15908
0
        return PyLong_FromLong(config->cpu_count);
15909
0
    }
15910
15911
0
    int ncpu = 0;
15912
#ifdef MS_WINDOWS
15913
# ifdef MS_WINDOWS_DESKTOP
15914
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15915
# else
15916
    ncpu = 0;
15917
# endif
15918
15919
#elif defined(__hpux)
15920
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15921
15922
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15923
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15924
15925
#elif defined(__VXWORKS__)
15926
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15927
15928
#elif defined(__DragonFly__) || \
15929
      defined(__OpenBSD__)   || \
15930
      defined(__FreeBSD__)   || \
15931
      defined(__NetBSD__)    || \
15932
      defined(__APPLE__)
15933
    ncpu = 0;
15934
    size_t len = sizeof(ncpu);
15935
    int mib[2] = {CTL_HW, HW_NCPU};
15936
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15937
        ncpu = 0;
15938
    }
15939
#endif
15940
15941
0
    if (ncpu < 1) {
15942
0
        Py_RETURN_NONE;
15943
0
    }
15944
0
    return PyLong_FromLong(ncpu);
15945
0
}
15946
15947
15948
/*[clinic input]
15949
os.get_inheritable -> bool
15950
15951
    fd: int
15952
    /
15953
15954
Get the close-on-exe flag of the specified file descriptor.
15955
[clinic start generated code]*/
15956
15957
static int
15958
os_get_inheritable_impl(PyObject *module, int fd)
15959
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15960
0
{
15961
0
    int return_value;
15962
0
    _Py_BEGIN_SUPPRESS_IPH
15963
0
    return_value = _Py_get_inheritable(fd);
15964
0
    _Py_END_SUPPRESS_IPH
15965
0
    return return_value;
15966
0
}
15967
15968
15969
/*[clinic input]
15970
os.set_inheritable
15971
    fd: int
15972
    inheritable: int
15973
    /
15974
15975
Set the inheritable flag of the specified file descriptor.
15976
[clinic start generated code]*/
15977
15978
static PyObject *
15979
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15980
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15981
0
{
15982
0
    int result;
15983
15984
0
    _Py_BEGIN_SUPPRESS_IPH
15985
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15986
0
    _Py_END_SUPPRESS_IPH
15987
0
    if (result < 0)
15988
0
        return NULL;
15989
0
    Py_RETURN_NONE;
15990
0
}
15991
15992
15993
#ifdef MS_WINDOWS
15994
#ifndef HANDLE_FLAG_INHERIT
15995
#define HANDLE_FLAG_INHERIT 0x00000001
15996
#endif
15997
15998
/*[clinic input]
15999
os.get_handle_inheritable -> bool
16000
    handle: intptr_t
16001
    /
16002
16003
Get the close-on-exe flag of the specified file descriptor.
16004
[clinic start generated code]*/
16005
16006
static int
16007
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16008
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16009
{
16010
    DWORD flags;
16011
16012
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16013
        PyErr_SetFromWindowsErr(0);
16014
        return -1;
16015
    }
16016
16017
    return flags & HANDLE_FLAG_INHERIT;
16018
}
16019
16020
16021
/*[clinic input]
16022
os.set_handle_inheritable
16023
    handle: intptr_t
16024
    inheritable: bool
16025
    /
16026
16027
Set the inheritable flag of the specified handle.
16028
[clinic start generated code]*/
16029
16030
static PyObject *
16031
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16032
                               int inheritable)
16033
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16034
{
16035
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16036
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16037
        PyErr_SetFromWindowsErr(0);
16038
        return NULL;
16039
    }
16040
    Py_RETURN_NONE;
16041
}
16042
#endif /* MS_WINDOWS */
16043
16044
/*[clinic input]
16045
os.get_blocking -> bool
16046
    fd: int
16047
    /
16048
16049
Get the blocking mode of the file descriptor.
16050
16051
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16052
[clinic start generated code]*/
16053
16054
static int
16055
os_get_blocking_impl(PyObject *module, int fd)
16056
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16057
0
{
16058
0
    int blocking;
16059
16060
0
    _Py_BEGIN_SUPPRESS_IPH
16061
0
    blocking = _Py_get_blocking(fd);
16062
0
    _Py_END_SUPPRESS_IPH
16063
0
    return blocking;
16064
0
}
16065
16066
/*[clinic input]
16067
os.set_blocking
16068
    fd: int
16069
    blocking: bool
16070
    /
16071
16072
Set the blocking mode of the specified file descriptor.
16073
16074
Set the O_NONBLOCK flag if blocking is False,
16075
clear the O_NONBLOCK flag otherwise.
16076
[clinic start generated code]*/
16077
16078
static PyObject *
16079
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16080
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16081
0
{
16082
0
    int result;
16083
16084
0
    _Py_BEGIN_SUPPRESS_IPH
16085
0
    result = _Py_set_blocking(fd, blocking);
16086
0
    _Py_END_SUPPRESS_IPH
16087
0
    if (result < 0)
16088
0
        return NULL;
16089
0
    Py_RETURN_NONE;
16090
0
}
16091
16092
16093
/*[clinic input]
16094
class os.DirEntry "DirEntry *" "DirEntryType"
16095
[clinic start generated code]*/
16096
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
16097
16098
typedef struct {
16099
    PyObject_HEAD
16100
    PyObject *name;
16101
    PyObject *path;
16102
    PyObject *stat;
16103
    PyObject *lstat;
16104
#ifdef MS_WINDOWS
16105
    struct _Py_stat_struct win32_lstat;
16106
    uint64_t win32_file_index;
16107
    uint64_t win32_file_index_high;
16108
    int got_file_index;
16109
#else /* POSIX */
16110
#ifdef HAVE_DIRENT_D_TYPE
16111
    unsigned char d_type;
16112
#endif
16113
    ino_t d_ino;
16114
    int dir_fd;
16115
#endif
16116
} DirEntry;
16117
16118
135k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16119
16120
static void
16121
DirEntry_dealloc(PyObject *op)
16122
135k
{
16123
135k
    DirEntry *entry = DirEntry_CAST(op);
16124
135k
    PyTypeObject *tp = Py_TYPE(entry);
16125
135k
    Py_XDECREF(entry->name);
16126
135k
    Py_XDECREF(entry->path);
16127
135k
    Py_XDECREF(entry->stat);
16128
135k
    Py_XDECREF(entry->lstat);
16129
135k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16130
135k
    free_func(entry);
16131
135k
    Py_DECREF(tp);
16132
135k
}
16133
16134
/* Forward reference */
16135
static int
16136
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16137
                   int follow_symlinks, unsigned short mode_bits);
16138
16139
/*[clinic input]
16140
os.DirEntry.is_symlink -> bool
16141
    defining_class: defining_class
16142
    /
16143
16144
Return True if the entry is a symbolic link; cached per entry.
16145
[clinic start generated code]*/
16146
16147
static int
16148
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16149
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16150
0
{
16151
#ifdef MS_WINDOWS
16152
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16153
#elif defined(HAVE_DIRENT_D_TYPE)
16154
    /* POSIX */
16155
0
    if (self->d_type != DT_UNKNOWN)
16156
0
        return self->d_type == DT_LNK;
16157
0
    else
16158
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16159
#else
16160
    /* POSIX without d_type */
16161
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16162
#endif
16163
0
}
16164
16165
/*[clinic input]
16166
os.DirEntry.is_junction -> bool
16167
16168
Return True if the entry is a junction; cached per entry.
16169
[clinic start generated code]*/
16170
16171
static int
16172
os_DirEntry_is_junction_impl(DirEntry *self)
16173
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16174
0
{
16175
#ifdef MS_WINDOWS
16176
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16177
#else
16178
0
    return 0;
16179
0
#endif
16180
0
}
16181
16182
static PyObject *
16183
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16184
134k
{
16185
134k
    int result;
16186
134k
    STRUCT_STAT st;
16187
134k
    PyObject *ub;
16188
16189
#ifdef MS_WINDOWS
16190
    if (!PyUnicode_FSDecoder(self->path, &ub))
16191
        return NULL;
16192
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16193
    Py_DECREF(ub);
16194
#else /* POSIX */
16195
134k
    if (!PyUnicode_FSConverter(self->path, &ub))
16196
0
        return NULL;
16197
134k
    const char *path = PyBytes_AS_STRING(ub);
16198
134k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16199
134k
#ifdef HAVE_FSTATAT
16200
134k
      if (HAVE_FSTATAT_RUNTIME) {
16201
134k
        Py_BEGIN_ALLOW_THREADS
16202
134k
        result = fstatat(self->dir_fd, path, &st,
16203
134k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16204
134k
        Py_END_ALLOW_THREADS
16205
134k
      } else
16206
16207
0
#endif /* HAVE_FSTATAT */
16208
0
      {
16209
0
        Py_DECREF(ub);
16210
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16211
0
        return NULL;
16212
0
      }
16213
134k
    }
16214
0
    else
16215
0
#endif
16216
0
    {
16217
0
        Py_BEGIN_ALLOW_THREADS
16218
0
        if (follow_symlinks) {
16219
0
            result = STAT(path, &st);
16220
0
        }
16221
0
        else {
16222
0
            result = LSTAT(path, &st);
16223
0
        }
16224
0
        Py_END_ALLOW_THREADS
16225
0
    }
16226
16227
134k
    int saved_errno = errno;
16228
#if defined(MS_WINDOWS)
16229
    PyMem_Free(path);
16230
#else
16231
134k
    Py_DECREF(ub);
16232
134k
#endif
16233
16234
134k
    if (result != 0) {
16235
0
        errno = saved_errno;
16236
0
        path_object_error(self->path);
16237
0
        return NULL;
16238
0
    }
16239
16240
134k
    return _pystat_fromstructstat(module, &st);
16241
134k
}
16242
16243
static PyObject *
16244
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16245
134k
{
16246
134k
    if (!self->lstat) {
16247
134k
        PyObject *module = PyType_GetModule(defining_class);
16248
#ifdef MS_WINDOWS
16249
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16250
#else /* POSIX */
16251
134k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16252
134k
#endif
16253
134k
    }
16254
134k
    return Py_XNewRef(self->lstat);
16255
134k
}
16256
16257
/*[clinic input]
16258
os.DirEntry.stat
16259
    defining_class: defining_class
16260
    /
16261
    *
16262
    follow_symlinks: bool = True
16263
16264
Return stat_result object for the entry; cached per entry.
16265
[clinic start generated code]*/
16266
16267
static PyObject *
16268
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16269
                      int follow_symlinks)
16270
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16271
134k
{
16272
134k
    if (!follow_symlinks) {
16273
134k
        return DirEntry_get_lstat(defining_class, self);
16274
134k
    }
16275
16276
0
    if (!self->stat) {
16277
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16278
0
        if (result == -1) {
16279
0
            return NULL;
16280
0
        }
16281
0
        if (result) {
16282
0
            PyObject *module = PyType_GetModule(defining_class);
16283
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16284
0
        }
16285
0
        else {
16286
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16287
0
        }
16288
0
    }
16289
16290
0
    return Py_XNewRef(self->stat);
16291
0
}
16292
16293
/* Set exception and return -1 on error, 0 for False, 1 for True */
16294
static int
16295
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16296
                   int follow_symlinks, unsigned short mode_bits)
16297
135k
{
16298
135k
    PyObject *stat = NULL;
16299
135k
    PyObject *st_mode = NULL;
16300
135k
    long mode;
16301
135k
    int result;
16302
135k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16303
135k
    int is_symlink;
16304
135k
    int need_stat;
16305
135k
#endif
16306
#ifdef MS_WINDOWS
16307
    unsigned long dir_bits;
16308
#endif
16309
16310
#ifdef MS_WINDOWS
16311
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16312
    need_stat = follow_symlinks && is_symlink;
16313
#elif defined(HAVE_DIRENT_D_TYPE)
16314
135k
    is_symlink = self->d_type == DT_LNK;
16315
135k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16316
135k
#endif
16317
16318
135k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16319
135k
    if (need_stat) {
16320
0
#endif
16321
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16322
0
        if (!stat) {
16323
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16324
                /* If file doesn't exist (anymore), then return False
16325
                   (i.e., say it's not a file/directory) */
16326
0
                PyErr_Clear();
16327
0
                return 0;
16328
0
            }
16329
0
            goto error;
16330
0
        }
16331
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16332
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16333
0
        if (!st_mode)
16334
0
            goto error;
16335
16336
0
        mode = PyLong_AsLong(st_mode);
16337
0
        if (mode == -1 && PyErr_Occurred())
16338
0
            goto error;
16339
0
        Py_CLEAR(st_mode);
16340
0
        Py_CLEAR(stat);
16341
0
        result = (mode & S_IFMT) == mode_bits;
16342
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16343
0
    }
16344
135k
    else if (is_symlink) {
16345
0
        assert(mode_bits != S_IFLNK);
16346
0
        result = 0;
16347
0
    }
16348
135k
    else {
16349
135k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16350
#ifdef MS_WINDOWS
16351
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16352
        if (mode_bits == S_IFDIR)
16353
            result = dir_bits != 0;
16354
        else
16355
            result = dir_bits == 0;
16356
#else /* POSIX */
16357
135k
        if (mode_bits == S_IFDIR)
16358
135k
            result = self->d_type == DT_DIR;
16359
0
        else
16360
0
            result = self->d_type == DT_REG;
16361
135k
#endif
16362
135k
    }
16363
135k
#endif
16364
16365
135k
    return result;
16366
16367
0
error:
16368
0
    Py_XDECREF(st_mode);
16369
0
    Py_XDECREF(stat);
16370
0
    return -1;
16371
135k
}
16372
16373
/*[clinic input]
16374
os.DirEntry.is_dir -> bool
16375
    defining_class: defining_class
16376
    /
16377
    *
16378
    follow_symlinks: bool = True
16379
16380
Return True if the entry is a directory; cached per entry.
16381
[clinic start generated code]*/
16382
16383
static int
16384
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16385
                        int follow_symlinks)
16386
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16387
135k
{
16388
135k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16389
135k
}
16390
16391
/*[clinic input]
16392
os.DirEntry.is_file -> bool
16393
    defining_class: defining_class
16394
    /
16395
    *
16396
    follow_symlinks: bool = True
16397
16398
Return True if the entry is a file; cached per entry.
16399
[clinic start generated code]*/
16400
16401
static int
16402
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16403
                         int follow_symlinks)
16404
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16405
0
{
16406
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16407
0
}
16408
16409
/*[clinic input]
16410
os.DirEntry.inode
16411
16412
Return inode of the entry; cached per entry.
16413
[clinic start generated code]*/
16414
16415
static PyObject *
16416
os_DirEntry_inode_impl(DirEntry *self)
16417
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16418
0
{
16419
#ifdef MS_WINDOWS
16420
    if (!self->got_file_index) {
16421
        PyObject *unicode;
16422
        STRUCT_STAT stat;
16423
        int result;
16424
16425
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16426
            return NULL;
16427
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16428
        Py_DECREF(unicode);
16429
        result = LSTAT(path, &stat);
16430
16431
        int saved_errno = errno;
16432
        PyMem_Free(path);
16433
16434
        if (result != 0) {
16435
            errno = saved_errno;
16436
            return path_object_error(self->path);
16437
        }
16438
16439
        self->win32_file_index = stat.st_ino;
16440
        self->win32_file_index_high = stat.st_ino_high;
16441
        self->got_file_index = 1;
16442
    }
16443
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16444
#else /* POSIX */
16445
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16446
0
                  "DirEntry.d_ino is larger than unsigned long long");
16447
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16448
0
#endif
16449
0
}
16450
16451
static PyObject *
16452
DirEntry_repr(PyObject *op)
16453
0
{
16454
0
    DirEntry *self = DirEntry_CAST(op);
16455
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16456
0
}
16457
16458
/*[clinic input]
16459
os.DirEntry.__fspath__
16460
16461
Returns the path for the entry.
16462
[clinic start generated code]*/
16463
16464
static PyObject *
16465
os_DirEntry___fspath___impl(DirEntry *self)
16466
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16467
0
{
16468
0
    return Py_NewRef(self->path);
16469
0
}
16470
16471
static PyMemberDef DirEntry_members[] = {
16472
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16473
     "the entry's base filename, relative to scandir() \"path\" argument"},
16474
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16475
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16476
    {NULL}
16477
};
16478
16479
#include "clinic/posixmodule.c.h"
16480
16481
static PyMethodDef DirEntry_methods[] = {
16482
    OS_DIRENTRY_IS_DIR_METHODDEF
16483
    OS_DIRENTRY_IS_FILE_METHODDEF
16484
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16485
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16486
    OS_DIRENTRY_STAT_METHODDEF
16487
    OS_DIRENTRY_INODE_METHODDEF
16488
    OS_DIRENTRY___FSPATH___METHODDEF
16489
    {"__class_getitem__",       Py_GenericAlias,
16490
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16491
    {NULL}
16492
};
16493
16494
static PyType_Slot DirEntryType_slots[] = {
16495
    {Py_tp_dealloc, DirEntry_dealloc},
16496
    {Py_tp_repr, DirEntry_repr},
16497
    {Py_tp_methods, DirEntry_methods},
16498
    {Py_tp_members, DirEntry_members},
16499
    {0, 0},
16500
};
16501
16502
static PyType_Spec DirEntryType_spec = {
16503
    .name = MODNAME ".DirEntry",
16504
    .basicsize = sizeof(DirEntry),
16505
    .flags = (
16506
        Py_TPFLAGS_DEFAULT
16507
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16508
        | Py_TPFLAGS_IMMUTABLETYPE
16509
    ),
16510
    .slots = DirEntryType_slots
16511
};
16512
16513
16514
#ifdef MS_WINDOWS
16515
16516
static wchar_t *
16517
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16518
{
16519
    Py_ssize_t path_len;
16520
    Py_ssize_t size;
16521
    wchar_t *result;
16522
    wchar_t ch;
16523
16524
    if (!path_wide) { /* Default arg: "." */
16525
        path_wide = L".";
16526
        path_len = 1;
16527
    }
16528
    else {
16529
        path_len = wcslen(path_wide);
16530
    }
16531
16532
    /* The +1's are for the path separator and the NUL */
16533
    size = path_len + 1 + wcslen(filename) + 1;
16534
    result = PyMem_New(wchar_t, size);
16535
    if (!result) {
16536
        PyErr_NoMemory();
16537
        return NULL;
16538
    }
16539
    wcscpy(result, path_wide);
16540
    if (path_len > 0) {
16541
        ch = result[path_len - 1];
16542
        if (ch != SEP && ch != ALTSEP && ch != L':')
16543
            result[path_len++] = SEP;
16544
        wcscpy(result + path_len, filename);
16545
    }
16546
    return result;
16547
}
16548
16549
static PyObject *
16550
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16551
{
16552
    DirEntry *entry;
16553
    BY_HANDLE_FILE_INFORMATION file_info;
16554
    ULONG reparse_tag;
16555
    wchar_t *joined_path;
16556
16557
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16558
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16559
    if (!entry)
16560
        return NULL;
16561
    entry->name = NULL;
16562
    entry->path = NULL;
16563
    entry->stat = NULL;
16564
    entry->lstat = NULL;
16565
    entry->got_file_index = 0;
16566
16567
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16568
    if (!entry->name)
16569
        goto error;
16570
    int return_bytes = path->wide && PyBytes_Check(path->object);
16571
    if (return_bytes) {
16572
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16573
        if (!entry->name)
16574
            goto error;
16575
    }
16576
16577
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16578
    if (!joined_path)
16579
        goto error;
16580
16581
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16582
    PyMem_Free(joined_path);
16583
    if (!entry->path)
16584
        goto error;
16585
    if (return_bytes) {
16586
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16587
        if (!entry->path)
16588
            goto error;
16589
    }
16590
16591
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16592
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16593
16594
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16595
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16596
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16597
16598
    return (PyObject *)entry;
16599
16600
error:
16601
    Py_DECREF(entry);
16602
    return NULL;
16603
}
16604
16605
#else /* POSIX */
16606
16607
static char *
16608
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16609
0
{
16610
0
    Py_ssize_t path_len;
16611
0
    Py_ssize_t size;
16612
0
    char *result;
16613
16614
0
    if (!path_narrow) { /* Default arg: "." */
16615
0
        path_narrow = ".";
16616
0
        path_len = 1;
16617
0
    }
16618
0
    else {
16619
0
        path_len = strlen(path_narrow);
16620
0
    }
16621
16622
0
    if (filename_len == -1)
16623
0
        filename_len = strlen(filename);
16624
16625
    /* The +1's are for the path separator and the NUL */
16626
0
    size = path_len + 1 + filename_len + 1;
16627
0
    result = PyMem_New(char, size);
16628
0
    if (!result) {
16629
0
        PyErr_NoMemory();
16630
0
        return NULL;
16631
0
    }
16632
0
    strcpy(result, path_narrow);
16633
0
    if (path_len > 0 && result[path_len - 1] != '/')
16634
0
        result[path_len++] = '/';
16635
0
    strcpy(result + path_len, filename);
16636
0
    return result;
16637
0
}
16638
16639
static PyObject *
16640
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16641
                         Py_ssize_t name_len, ino_t d_ino
16642
#ifdef HAVE_DIRENT_D_TYPE
16643
                         , unsigned char d_type
16644
#endif
16645
                         )
16646
135k
{
16647
135k
    DirEntry *entry;
16648
135k
    char *joined_path;
16649
16650
135k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16651
135k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16652
135k
    if (!entry)
16653
0
        return NULL;
16654
135k
    entry->name = NULL;
16655
135k
    entry->path = NULL;
16656
135k
    entry->stat = NULL;
16657
135k
    entry->lstat = NULL;
16658
16659
135k
    if (path->fd != -1) {
16660
135k
        entry->dir_fd = path->fd;
16661
135k
        joined_path = NULL;
16662
135k
    }
16663
0
    else {
16664
0
        entry->dir_fd = DEFAULT_DIR_FD;
16665
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16666
0
        if (!joined_path)
16667
0
            goto error;
16668
0
    }
16669
16670
135k
    if (!path->narrow || !PyBytes_Check(path->object)) {
16671
135k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16672
135k
        if (joined_path)
16673
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16674
135k
    }
16675
0
    else {
16676
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16677
0
        if (joined_path)
16678
0
            entry->path = PyBytes_FromString(joined_path);
16679
0
    }
16680
135k
    PyMem_Free(joined_path);
16681
135k
    if (!entry->name)
16682
0
        goto error;
16683
16684
135k
    if (path->fd != -1) {
16685
135k
        entry->path = Py_NewRef(entry->name);
16686
135k
    }
16687
0
    else if (!entry->path)
16688
0
        goto error;
16689
16690
135k
#ifdef HAVE_DIRENT_D_TYPE
16691
135k
    entry->d_type = d_type;
16692
135k
#endif
16693
135k
    entry->d_ino = d_ino;
16694
16695
135k
    return (PyObject *)entry;
16696
16697
0
error:
16698
0
    Py_XDECREF(entry);
16699
0
    return NULL;
16700
135k
}
16701
16702
#endif
16703
16704
16705
typedef struct {
16706
    PyObject_HEAD
16707
    path_t path;
16708
#ifdef MS_WINDOWS
16709
    HANDLE handle;
16710
    WIN32_FIND_DATAW file_data;
16711
    int first_time;
16712
#else /* POSIX */
16713
    DIR *dirp;
16714
#endif
16715
#ifdef HAVE_FDOPENDIR
16716
    int fd;
16717
#endif
16718
} ScandirIterator;
16719
16720
551k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16721
16722
#ifdef MS_WINDOWS
16723
16724
static int
16725
ScandirIterator_is_closed(ScandirIterator *iterator)
16726
{
16727
    return iterator->handle == INVALID_HANDLE_VALUE;
16728
}
16729
16730
static void
16731
ScandirIterator_closedir(ScandirIterator *iterator)
16732
{
16733
    HANDLE handle = iterator->handle;
16734
16735
    if (handle == INVALID_HANDLE_VALUE)
16736
        return;
16737
16738
    iterator->handle = INVALID_HANDLE_VALUE;
16739
    Py_BEGIN_ALLOW_THREADS
16740
    FindClose(handle);
16741
    Py_END_ALLOW_THREADS
16742
}
16743
16744
static PyObject *
16745
ScandirIterator_iternext(PyObject *op)
16746
{
16747
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16748
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16749
    BOOL success;
16750
    PyObject *entry;
16751
16752
    /* Happens if the iterator is iterated twice, or closed explicitly */
16753
    if (iterator->handle == INVALID_HANDLE_VALUE)
16754
        return NULL;
16755
16756
    while (1) {
16757
        if (!iterator->first_time) {
16758
            Py_BEGIN_ALLOW_THREADS
16759
            success = FindNextFileW(iterator->handle, file_data);
16760
            Py_END_ALLOW_THREADS
16761
            if (!success) {
16762
                /* Error or no more files */
16763
                if (GetLastError() != ERROR_NO_MORE_FILES)
16764
                    path_error(&iterator->path);
16765
                break;
16766
            }
16767
        }
16768
        iterator->first_time = 0;
16769
16770
        /* Skip over . and .. */
16771
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16772
            wcscmp(file_data->cFileName, L"..") != 0)
16773
        {
16774
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16775
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16776
            if (!entry)
16777
                break;
16778
            return entry;
16779
        }
16780
16781
        /* Loop till we get a non-dot directory or finish iterating */
16782
    }
16783
16784
    /* Error or no more files */
16785
    ScandirIterator_closedir(iterator);
16786
    return NULL;
16787
}
16788
16789
#else /* POSIX */
16790
16791
static int
16792
ScandirIterator_is_closed(ScandirIterator *iterator)
16793
138k
{
16794
138k
    return !iterator->dirp;
16795
138k
}
16796
16797
static void
16798
ScandirIterator_closedir(ScandirIterator *iterator)
16799
277k
{
16800
277k
    DIR *dirp = iterator->dirp;
16801
16802
277k
    if (!dirp)
16803
138k
        return;
16804
16805
138k
    iterator->dirp = NULL;
16806
138k
    Py_BEGIN_ALLOW_THREADS
16807
138k
#ifdef HAVE_FDOPENDIR
16808
138k
    if (iterator->path.fd != -1)
16809
138k
        rewinddir(dirp);
16810
138k
#endif
16811
138k
    closedir(dirp);
16812
138k
    Py_END_ALLOW_THREADS
16813
138k
    return;
16814
277k
}
16815
16816
static PyObject *
16817
ScandirIterator_iternext(PyObject *op)
16818
273k
{
16819
273k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16820
273k
    struct dirent *direntp;
16821
273k
    Py_ssize_t name_len;
16822
273k
    int is_dot;
16823
273k
    PyObject *entry;
16824
16825
    /* Happens if the iterator is iterated twice, or closed explicitly */
16826
273k
    if (!iterator->dirp)
16827
0
        return NULL;
16828
16829
551k
    while (1) {
16830
551k
        errno = 0;
16831
551k
        Py_BEGIN_ALLOW_THREADS
16832
551k
        direntp = readdir(iterator->dirp);
16833
551k
        Py_END_ALLOW_THREADS
16834
16835
551k
        if (!direntp) {
16836
            /* Error or no more files */
16837
138k
            if (errno != 0)
16838
0
                path_error(&iterator->path);
16839
138k
            break;
16840
138k
        }
16841
16842
        /* Skip over . and .. */
16843
412k
        name_len = NAMLEN(direntp);
16844
412k
        is_dot = direntp->d_name[0] == '.' &&
16845
277k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16846
412k
        if (!is_dot) {
16847
135k
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16848
135k
            entry = DirEntry_from_posix_info(module,
16849
135k
                                             &iterator->path, direntp->d_name,
16850
135k
                                             name_len, direntp->d_ino
16851
135k
#ifdef HAVE_DIRENT_D_TYPE
16852
135k
                                             , direntp->d_type
16853
135k
#endif
16854
135k
                                            );
16855
135k
            if (!entry)
16856
0
                break;
16857
135k
            return entry;
16858
135k
        }
16859
16860
        /* Loop till we get a non-dot directory or finish iterating */
16861
412k
    }
16862
16863
    /* Error or no more files */
16864
138k
    ScandirIterator_closedir(iterator);
16865
138k
    return NULL;
16866
273k
}
16867
16868
#endif
16869
16870
static PyObject *
16871
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16872
0
{
16873
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16874
0
    ScandirIterator_closedir(self);
16875
0
    Py_RETURN_NONE;
16876
0
}
16877
16878
static PyObject *
16879
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16880
138k
{
16881
138k
    return Py_NewRef(self);
16882
138k
}
16883
16884
static PyObject *
16885
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16886
138k
{
16887
138k
    ScandirIterator *self = ScandirIterator_CAST(op);
16888
138k
    ScandirIterator_closedir(self);
16889
138k
    Py_RETURN_NONE;
16890
138k
}
16891
16892
static void
16893
ScandirIterator_finalize(PyObject *op)
16894
138k
{
16895
138k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16896
    /* Save the current exception, if any. */
16897
138k
    PyObject *exc = PyErr_GetRaisedException();
16898
16899
138k
    if (!ScandirIterator_is_closed(iterator)) {
16900
0
        ScandirIterator_closedir(iterator);
16901
16902
0
        if (PyErr_ResourceWarning(op, 1,
16903
0
                                  "unclosed scandir iterator %R", iterator))
16904
0
        {
16905
            /* Spurious errors can appear at shutdown */
16906
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16907
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16908
0
                                       "scandir iterator %R", iterator);
16909
0
            }
16910
0
        }
16911
0
    }
16912
16913
138k
    path_cleanup(&iterator->path);
16914
16915
    /* Restore the saved exception. */
16916
138k
    PyErr_SetRaisedException(exc);
16917
138k
}
16918
16919
static void
16920
ScandirIterator_dealloc(PyObject *op)
16921
138k
{
16922
138k
    PyTypeObject *tp = Py_TYPE(op);
16923
138k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16924
0
        return;
16925
16926
138k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16927
138k
    free_func(op);
16928
138k
    Py_DECREF(tp);
16929
138k
}
16930
16931
static PyMethodDef ScandirIterator_methods[] = {
16932
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16933
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16934
    {"close", ScandirIterator_close, METH_NOARGS},
16935
    {NULL}
16936
};
16937
16938
static PyType_Slot ScandirIteratorType_slots[] = {
16939
    {Py_tp_dealloc, ScandirIterator_dealloc},
16940
    {Py_tp_finalize, ScandirIterator_finalize},
16941
    {Py_tp_iter, PyObject_SelfIter},
16942
    {Py_tp_iternext, ScandirIterator_iternext},
16943
    {Py_tp_methods, ScandirIterator_methods},
16944
    {0, 0},
16945
};
16946
16947
static PyType_Spec ScandirIteratorType_spec = {
16948
    .name = MODNAME ".ScandirIterator",
16949
    .basicsize = sizeof(ScandirIterator),
16950
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16951
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16952
    .flags = (
16953
        Py_TPFLAGS_DEFAULT
16954
        | Py_TPFLAGS_HAVE_FINALIZE
16955
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16956
        | Py_TPFLAGS_IMMUTABLETYPE
16957
    ),
16958
    .slots = ScandirIteratorType_slots
16959
};
16960
16961
/*[clinic input]
16962
os.scandir
16963
16964
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16965
16966
Return an iterator of DirEntry objects for given path.
16967
16968
path can be specified as either str, bytes, or a path-like object.  If path
16969
is bytes, the names of yielded DirEntry objects will also be bytes; in
16970
all other circumstances they will be str.
16971
16972
If path is None, uses the path='.'.
16973
[clinic start generated code]*/
16974
16975
static PyObject *
16976
os_scandir_impl(PyObject *module, path_t *path)
16977
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16978
138k
{
16979
138k
    ScandirIterator *iterator;
16980
#ifdef MS_WINDOWS
16981
    wchar_t *path_strW;
16982
#else
16983
138k
    const char *path_str;
16984
138k
#ifdef HAVE_FDOPENDIR
16985
138k
    int fd = -1;
16986
138k
#endif
16987
138k
#endif
16988
16989
138k
    if (PySys_Audit("os.scandir", "O",
16990
138k
                    path->object ? path->object : Py_None) < 0) {
16991
0
        return NULL;
16992
0
    }
16993
16994
138k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
16995
138k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
16996
138k
    if (!iterator)
16997
0
        return NULL;
16998
16999
#ifdef MS_WINDOWS
17000
    iterator->handle = INVALID_HANDLE_VALUE;
17001
#else
17002
138k
    iterator->dirp = NULL;
17003
138k
#endif
17004
17005
    /* Move the ownership to iterator->path */
17006
138k
    memcpy(&iterator->path, path, sizeof(path_t));
17007
138k
    memset(path, 0, sizeof(path_t));
17008
17009
#ifdef MS_WINDOWS
17010
    iterator->first_time = 1;
17011
17012
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
17013
    if (!path_strW)
17014
        goto error;
17015
17016
    Py_BEGIN_ALLOW_THREADS
17017
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17018
    Py_END_ALLOW_THREADS
17019
17020
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17021
        path_error(&iterator->path);
17022
        PyMem_Free(path_strW);
17023
        goto error;
17024
    }
17025
    PyMem_Free(path_strW);
17026
#else /* POSIX */
17027
138k
    errno = 0;
17028
138k
#ifdef HAVE_FDOPENDIR
17029
138k
    if (iterator->path.fd != -1) {
17030
138k
      if (HAVE_FDOPENDIR_RUNTIME) {
17031
        /* closedir() closes the FD, so we duplicate it */
17032
138k
        fd = _Py_dup(iterator->path.fd);
17033
138k
        if (fd == -1)
17034
0
            goto error;
17035
17036
138k
        Py_BEGIN_ALLOW_THREADS
17037
138k
        iterator->dirp = fdopendir(fd);
17038
138k
        Py_END_ALLOW_THREADS
17039
138k
      } else {
17040
0
        PyErr_SetString(PyExc_TypeError,
17041
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17042
0
        return NULL;
17043
0
      }
17044
138k
    }
17045
0
    else
17046
0
#endif
17047
0
    {
17048
0
        if (iterator->path.narrow)
17049
0
            path_str = iterator->path.narrow;
17050
0
        else
17051
0
            path_str = ".";
17052
17053
0
        Py_BEGIN_ALLOW_THREADS
17054
0
        iterator->dirp = opendir(path_str);
17055
0
        Py_END_ALLOW_THREADS
17056
0
    }
17057
17058
138k
    if (!iterator->dirp) {
17059
0
        path_error(&iterator->path);
17060
0
#ifdef HAVE_FDOPENDIR
17061
0
        if (fd != -1) {
17062
0
            Py_BEGIN_ALLOW_THREADS
17063
0
            close(fd);
17064
0
            Py_END_ALLOW_THREADS
17065
0
        }
17066
0
#endif
17067
0
        goto error;
17068
0
    }
17069
138k
#endif
17070
17071
138k
    return (PyObject *)iterator;
17072
17073
0
error:
17074
0
    Py_DECREF(iterator);
17075
0
    return NULL;
17076
138k
}
17077
17078
/*
17079
    Return the file system path representation of the object.
17080
17081
    If the object is str or bytes, then allow it to pass through with
17082
    an incremented refcount. If the object defines __fspath__(), then
17083
    return the result of that method. All other types raise a TypeError.
17084
*/
17085
PyObject *
17086
PyOS_FSPath(PyObject *path)
17087
1.01M
{
17088
    /* For error message reasons, this function is manually inlined in
17089
       path_converter(). */
17090
1.01M
    PyObject *func = NULL;
17091
1.01M
    PyObject *path_repr = NULL;
17092
17093
1.01M
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17094
1.01M
        return Py_NewRef(path);
17095
1.01M
    }
17096
17097
0
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17098
0
    if ((NULL == func) || (func == Py_None)) {
17099
0
        return PyErr_Format(PyExc_TypeError,
17100
0
                            "expected str, bytes or os.PathLike object, "
17101
0
                            "not %.200s",
17102
0
                            _PyType_Name(Py_TYPE(path)));
17103
0
    }
17104
17105
0
    path_repr = _PyObject_CallNoArgs(func);
17106
0
    Py_DECREF(func);
17107
0
    if (NULL == path_repr) {
17108
0
        return NULL;
17109
0
    }
17110
17111
0
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17112
0
        PyErr_Format(PyExc_TypeError,
17113
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17114
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17115
0
                     _PyType_Name(Py_TYPE(path_repr)));
17116
0
        Py_DECREF(path_repr);
17117
0
        return NULL;
17118
0
    }
17119
17120
0
    return path_repr;
17121
0
}
17122
17123
/*[clinic input]
17124
@permit_long_docstring_body
17125
os.fspath
17126
17127
    path: object
17128
17129
Return the file system path representation of the object.
17130
17131
If the object is str or bytes, then allow it to pass through as-is. If the
17132
object defines __fspath__(), then return the result of that method. All other
17133
types raise a TypeError.
17134
[clinic start generated code]*/
17135
17136
static PyObject *
17137
os_fspath_impl(PyObject *module, PyObject *path)
17138
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
17139
830k
{
17140
830k
    return PyOS_FSPath(path);
17141
830k
}
17142
17143
#ifdef HAVE_GETRANDOM_SYSCALL
17144
/*[clinic input]
17145
os.getrandom
17146
17147
    size: Py_ssize_t
17148
    flags: int=0
17149
17150
Obtain a series of random bytes.
17151
[clinic start generated code]*/
17152
17153
static PyObject *
17154
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
17155
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
17156
0
{
17157
0
    if (size < 0) {
17158
0
        errno = EINVAL;
17159
0
        return posix_error();
17160
0
    }
17161
17162
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17163
0
    if (writer == NULL) {
17164
0
        return NULL;
17165
0
    }
17166
0
    void *data = PyBytesWriter_GetData(writer);
17167
17168
0
    Py_ssize_t n;
17169
0
    while (1) {
17170
0
        n = syscall(SYS_getrandom, data, size, flags);
17171
0
        if (n < 0 && errno == EINTR) {
17172
0
            if (PyErr_CheckSignals() < 0) {
17173
0
                goto error;
17174
0
            }
17175
17176
            /* getrandom() was interrupted by a signal: retry */
17177
0
            continue;
17178
0
        }
17179
0
        break;
17180
0
    }
17181
17182
0
    if (n < 0) {
17183
0
        PyErr_SetFromErrno(PyExc_OSError);
17184
0
        goto error;
17185
0
    }
17186
17187
0
    return PyBytesWriter_FinishWithSize(writer, n);
17188
17189
0
error:
17190
0
    PyBytesWriter_Discard(writer);
17191
0
    return NULL;
17192
0
}
17193
#endif   /* HAVE_GETRANDOM_SYSCALL */
17194
17195
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17196
17197
/* bpo-36085: Helper functions for managing DLL search directories
17198
 * on win32
17199
 */
17200
17201
/*[clinic input]
17202
os._add_dll_directory
17203
17204
    path: path_t
17205
17206
Add a path to the DLL search path.
17207
17208
This search path is used when resolving dependencies for imported
17209
extension modules (the module itself is resolved through sys.path),
17210
and also by ctypes.
17211
17212
Returns an opaque value that may be passed to os.remove_dll_directory
17213
to remove this directory from the search path.
17214
[clinic start generated code]*/
17215
17216
static PyObject *
17217
os__add_dll_directory_impl(PyObject *module, path_t *path)
17218
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17219
{
17220
    DLL_DIRECTORY_COOKIE cookie = 0;
17221
    DWORD err = 0;
17222
17223
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17224
        return NULL;
17225
    }
17226
17227
    Py_BEGIN_ALLOW_THREADS
17228
    if (!(cookie = AddDllDirectory(path->wide))) {
17229
        err = GetLastError();
17230
    }
17231
    Py_END_ALLOW_THREADS
17232
17233
    if (err) {
17234
        return win32_error_object_err("add_dll_directory",
17235
                                      path->object, err);
17236
    }
17237
17238
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17239
}
17240
17241
/*[clinic input]
17242
os._remove_dll_directory
17243
17244
    cookie: object
17245
17246
Removes a path from the DLL search path.
17247
17248
The parameter is an opaque value that was returned from
17249
os.add_dll_directory. You can only remove directories that you added
17250
yourself.
17251
[clinic start generated code]*/
17252
17253
static PyObject *
17254
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17255
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17256
{
17257
    DLL_DIRECTORY_COOKIE cookieValue;
17258
    DWORD err = 0;
17259
17260
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17261
        PyErr_SetString(PyExc_TypeError,
17262
            "Provided cookie was not returned from os.add_dll_directory");
17263
        return NULL;
17264
    }
17265
17266
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17267
        cookie, "DLL directory cookie");
17268
17269
    Py_BEGIN_ALLOW_THREADS
17270
    if (!RemoveDllDirectory(cookieValue)) {
17271
        err = GetLastError();
17272
    }
17273
    Py_END_ALLOW_THREADS
17274
17275
    if (err) {
17276
        return win32_error_object_err("remove_dll_directory",
17277
                                      NULL, err);
17278
    }
17279
17280
    if (PyCapsule_SetName(cookie, NULL)) {
17281
        return NULL;
17282
    }
17283
17284
    Py_RETURN_NONE;
17285
}
17286
17287
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17288
17289
17290
/* Only check if WIFEXITED is available: expect that it comes
17291
   with WEXITSTATUS, WIFSIGNALED, etc.
17292
17293
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17294
   subprocess can safely call it during late Python finalization without
17295
   risking that used os attributes were set to None by finalize_modules(). */
17296
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17297
/*[clinic input]
17298
os.waitstatus_to_exitcode
17299
17300
    status as status_obj: object
17301
17302
Convert a wait status to an exit code.
17303
17304
On Unix:
17305
17306
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17307
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17308
* Otherwise, raise a ValueError.
17309
17310
On Windows, return status shifted right by 8 bits.
17311
17312
On Unix, if the process is being traced or if waitpid() was called with
17313
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
17314
This function must not be called if WIFSTOPPED(status) is true.
17315
[clinic start generated code]*/
17316
17317
static PyObject *
17318
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17319
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
17320
0
{
17321
0
#ifndef MS_WINDOWS
17322
0
    int status = PyLong_AsInt(status_obj);
17323
0
    if (status == -1 && PyErr_Occurred()) {
17324
0
        return NULL;
17325
0
    }
17326
17327
0
    WAIT_TYPE wait_status;
17328
0
    WAIT_STATUS_INT(wait_status) = status;
17329
0
    int exitcode;
17330
0
    if (WIFEXITED(wait_status)) {
17331
0
        exitcode = WEXITSTATUS(wait_status);
17332
        /* Sanity check to provide warranty on the function behavior.
17333
           It should not occur in practice */
17334
0
        if (exitcode < 0) {
17335
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17336
0
            return NULL;
17337
0
        }
17338
0
    }
17339
0
    else if (WIFSIGNALED(wait_status)) {
17340
0
        int signum = WTERMSIG(wait_status);
17341
        /* Sanity check to provide warranty on the function behavior.
17342
           It should not occurs in practice */
17343
0
        if (signum <= 0) {
17344
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17345
0
            return NULL;
17346
0
        }
17347
0
        exitcode = -signum;
17348
0
    } else if (WIFSTOPPED(wait_status)) {
17349
        /* Status only received if the process is being traced
17350
           or if waitpid() was called with WUNTRACED option. */
17351
0
        int signum = WSTOPSIG(wait_status);
17352
0
        PyErr_Format(PyExc_ValueError,
17353
0
                     "process stopped by delivery of signal %i",
17354
0
                     signum);
17355
0
        return NULL;
17356
0
    }
17357
0
    else {
17358
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17359
0
        return NULL;
17360
0
    }
17361
0
    return PyLong_FromLong(exitcode);
17362
#else
17363
    /* Windows implementation: see os.waitpid() implementation
17364
       which uses _cwait(). */
17365
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17366
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17367
        return NULL;
17368
    }
17369
17370
    unsigned long long exitcode = (status >> 8);
17371
    /* ExitProcess() accepts an UINT type:
17372
       reject exit code which doesn't fit in an UINT */
17373
    if (exitcode > UINT_MAX) {
17374
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17375
        return NULL;
17376
    }
17377
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17378
#endif
17379
0
}
17380
#endif
17381
17382
#if defined(MS_WINDOWS)
17383
/*[clinic input]
17384
os._supports_virtual_terminal
17385
17386
Checks if virtual terminal is supported in windows
17387
[clinic start generated code]*/
17388
17389
static PyObject *
17390
os__supports_virtual_terminal_impl(PyObject *module)
17391
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17392
{
17393
#ifdef HAVE_WINDOWS_CONSOLE_IO
17394
    DWORD mode = 0;
17395
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17396
    if (!GetConsoleMode(handle, &mode)) {
17397
        Py_RETURN_FALSE;
17398
    }
17399
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17400
#else
17401
    Py_RETURN_FALSE;
17402
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17403
}
17404
#endif
17405
17406
/*[clinic input]
17407
os._inputhook
17408
17409
Calls PyOS_InputHook dropping the GIL first
17410
[clinic start generated code]*/
17411
17412
static PyObject *
17413
os__inputhook_impl(PyObject *module)
17414
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17415
0
{
17416
0
     int result = 0;
17417
0
     if (PyOS_InputHook) {
17418
0
         Py_BEGIN_ALLOW_THREADS;
17419
0
         result = PyOS_InputHook();
17420
0
         Py_END_ALLOW_THREADS;
17421
0
     }
17422
0
     return PyLong_FromLong(result);
17423
0
}
17424
17425
/*[clinic input]
17426
os._is_inputhook_installed
17427
17428
Checks if PyOS_InputHook is set
17429
[clinic start generated code]*/
17430
17431
static PyObject *
17432
os__is_inputhook_installed_impl(PyObject *module)
17433
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17434
0
{
17435
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17436
0
}
17437
17438
/*[clinic input]
17439
os._create_environ
17440
17441
Create the environment dictionary.
17442
[clinic start generated code]*/
17443
17444
static PyObject *
17445
os__create_environ_impl(PyObject *module)
17446
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17447
0
{
17448
0
    return convertenviron();
17449
0
}
17450
17451
17452
#ifdef __EMSCRIPTEN__
17453
/*[clinic input]
17454
os._emscripten_debugger
17455
17456
Create a breakpoint for the JavaScript debugger. Emscripten only.
17457
[clinic start generated code]*/
17458
17459
static PyObject *
17460
os__emscripten_debugger_impl(PyObject *module)
17461
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17462
{
17463
    emscripten_debugger();
17464
    Py_RETURN_NONE;
17465
}
17466
17467
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17468
    console.warn(UTF8ToString(arg));
17469
});
17470
17471
/*[clinic input]
17472
os._emscripten_log
17473
   arg: str
17474
17475
Log something to the JS console. Emscripten only.
17476
[clinic start generated code]*/
17477
17478
static PyObject *
17479
os__emscripten_log_impl(PyObject *module, const char *arg)
17480
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17481
{
17482
    emscripten_log_impl_js(arg);
17483
    Py_RETURN_NONE;
17484
}
17485
#endif /* __EMSCRIPTEN__ */
17486
17487
17488
static PyMethodDef posix_methods[] = {
17489
    OS_STAT_METHODDEF
17490
    OS_STATX_METHODDEF
17491
    OS_ACCESS_METHODDEF
17492
    OS_TTYNAME_METHODDEF
17493
    OS_CHDIR_METHODDEF
17494
    OS_CHFLAGS_METHODDEF
17495
    OS_CHMOD_METHODDEF
17496
    OS_FCHMOD_METHODDEF
17497
    OS_LCHMOD_METHODDEF
17498
    OS_CHOWN_METHODDEF
17499
    OS_FCHOWN_METHODDEF
17500
    OS_LCHOWN_METHODDEF
17501
    OS_LCHFLAGS_METHODDEF
17502
    OS_CHROOT_METHODDEF
17503
    OS_CTERMID_METHODDEF
17504
    OS_GETCWD_METHODDEF
17505
    OS_GETCWDB_METHODDEF
17506
    OS_LINK_METHODDEF
17507
    OS_LISTDIR_METHODDEF
17508
    OS_LISTDRIVES_METHODDEF
17509
    OS_LISTMOUNTS_METHODDEF
17510
    OS_LISTVOLUMES_METHODDEF
17511
    OS_LSTAT_METHODDEF
17512
    OS_MKDIR_METHODDEF
17513
    OS_NICE_METHODDEF
17514
    OS_GETPRIORITY_METHODDEF
17515
    OS_SETPRIORITY_METHODDEF
17516
    OS_POSIX_SPAWN_METHODDEF
17517
    OS_POSIX_SPAWNP_METHODDEF
17518
    OS_READLINK_METHODDEF
17519
    OS_COPY_FILE_RANGE_METHODDEF
17520
    OS_SPLICE_METHODDEF
17521
    OS_RENAME_METHODDEF
17522
    OS_REPLACE_METHODDEF
17523
    OS_RMDIR_METHODDEF
17524
    OS_SYMLINK_METHODDEF
17525
    OS_SYSTEM_METHODDEF
17526
    OS_UMASK_METHODDEF
17527
    OS_UNAME_METHODDEF
17528
    OS_UNLINK_METHODDEF
17529
    OS_REMOVE_METHODDEF
17530
    OS_UTIME_METHODDEF
17531
    OS_TIMES_METHODDEF
17532
    OS__EXIT_METHODDEF
17533
    OS__FCOPYFILE_METHODDEF
17534
    OS_EXECV_METHODDEF
17535
    OS_EXECVE_METHODDEF
17536
    OS_SPAWNV_METHODDEF
17537
    OS_SPAWNVE_METHODDEF
17538
    OS_FORK1_METHODDEF
17539
    OS_FORK_METHODDEF
17540
    OS_REGISTER_AT_FORK_METHODDEF
17541
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17542
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17543
    OS_SCHED_GETPARAM_METHODDEF
17544
    OS_SCHED_GETSCHEDULER_METHODDEF
17545
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17546
    OS_SCHED_SETPARAM_METHODDEF
17547
    OS_SCHED_SETSCHEDULER_METHODDEF
17548
    OS_SCHED_YIELD_METHODDEF
17549
    OS_SCHED_SETAFFINITY_METHODDEF
17550
    OS_SCHED_GETAFFINITY_METHODDEF
17551
    OS_POSIX_OPENPT_METHODDEF
17552
    OS_GRANTPT_METHODDEF
17553
    OS_UNLOCKPT_METHODDEF
17554
    OS_PTSNAME_METHODDEF
17555
    OS_OPENPTY_METHODDEF
17556
    OS_LOGIN_TTY_METHODDEF
17557
    OS_FORKPTY_METHODDEF
17558
    OS_GETEGID_METHODDEF
17559
    OS_GETEUID_METHODDEF
17560
    OS_GETGID_METHODDEF
17561
    OS_GETGROUPLIST_METHODDEF
17562
    OS_GETGROUPS_METHODDEF
17563
    OS_GETPID_METHODDEF
17564
    OS_GETPGRP_METHODDEF
17565
    OS_GETPPID_METHODDEF
17566
    OS_GETUID_METHODDEF
17567
    OS_GETLOGIN_METHODDEF
17568
    OS_KILL_METHODDEF
17569
    OS_KILLPG_METHODDEF
17570
    OS_PLOCK_METHODDEF
17571
    OS_STARTFILE_METHODDEF
17572
    OS_SETUID_METHODDEF
17573
    OS_SETEUID_METHODDEF
17574
    OS_SETREUID_METHODDEF
17575
    OS_SETGID_METHODDEF
17576
    OS_SETEGID_METHODDEF
17577
    OS_SETREGID_METHODDEF
17578
    OS_SETGROUPS_METHODDEF
17579
    OS_INITGROUPS_METHODDEF
17580
    OS_GETPGID_METHODDEF
17581
    OS_SETPGRP_METHODDEF
17582
    OS_WAIT_METHODDEF
17583
    OS_WAIT3_METHODDEF
17584
    OS_WAIT4_METHODDEF
17585
    OS_WAITID_METHODDEF
17586
    OS_WAITPID_METHODDEF
17587
    OS_PIDFD_OPEN_METHODDEF
17588
    OS_GETSID_METHODDEF
17589
    OS_SETSID_METHODDEF
17590
    OS_SETPGID_METHODDEF
17591
    OS_TCGETPGRP_METHODDEF
17592
    OS_TCSETPGRP_METHODDEF
17593
    OS_OPEN_METHODDEF
17594
    OS_CLOSE_METHODDEF
17595
    OS_CLOSERANGE_METHODDEF
17596
    OS_DEVICE_ENCODING_METHODDEF
17597
    OS_DUP_METHODDEF
17598
    OS_DUP2_METHODDEF
17599
    OS_LOCKF_METHODDEF
17600
    OS_LSEEK_METHODDEF
17601
    OS_READ_METHODDEF
17602
    OS_READINTO_METHODDEF
17603
    OS_READV_METHODDEF
17604
    OS_PREAD_METHODDEF
17605
    OS_PREADV_METHODDEF
17606
    OS_WRITE_METHODDEF
17607
    OS_WRITEV_METHODDEF
17608
    OS_PWRITE_METHODDEF
17609
    OS_PWRITEV_METHODDEF
17610
    OS_SENDFILE_METHODDEF
17611
    OS_FSTAT_METHODDEF
17612
    OS_ISATTY_METHODDEF
17613
    OS_PIPE_METHODDEF
17614
    OS_PIPE2_METHODDEF
17615
    OS_MKFIFO_METHODDEF
17616
    OS_MKNOD_METHODDEF
17617
    OS_MAJOR_METHODDEF
17618
    OS_MINOR_METHODDEF
17619
    OS_MAKEDEV_METHODDEF
17620
    OS_FTRUNCATE_METHODDEF
17621
    OS_TRUNCATE_METHODDEF
17622
    OS_POSIX_FALLOCATE_METHODDEF
17623
    OS_POSIX_FADVISE_METHODDEF
17624
    OS_PUTENV_METHODDEF
17625
    OS_UNSETENV_METHODDEF
17626
    OS__CLEARENV_METHODDEF
17627
    OS_STRERROR_METHODDEF
17628
    OS_FCHDIR_METHODDEF
17629
    OS_FSYNC_METHODDEF
17630
    OS_SYNC_METHODDEF
17631
    OS_FDATASYNC_METHODDEF
17632
    OS_WCOREDUMP_METHODDEF
17633
    OS_WIFCONTINUED_METHODDEF
17634
    OS_WIFSTOPPED_METHODDEF
17635
    OS_WIFSIGNALED_METHODDEF
17636
    OS_WIFEXITED_METHODDEF
17637
    OS_WEXITSTATUS_METHODDEF
17638
    OS_WTERMSIG_METHODDEF
17639
    OS_WSTOPSIG_METHODDEF
17640
    OS_FSTATVFS_METHODDEF
17641
    OS_STATVFS_METHODDEF
17642
    OS_CONFSTR_METHODDEF
17643
    OS_SYSCONF_METHODDEF
17644
    OS_FPATHCONF_METHODDEF
17645
    OS_PATHCONF_METHODDEF
17646
    OS_ABORT_METHODDEF
17647
    OS__GETFULLPATHNAME_METHODDEF
17648
    OS__GETDISKUSAGE_METHODDEF
17649
    OS__GETFINALPATHNAME_METHODDEF
17650
    OS__FINDFIRSTFILE_METHODDEF
17651
    OS__GETVOLUMEPATHNAME_METHODDEF
17652
    OS__PATH_SPLITROOT_METHODDEF
17653
    OS__PATH_SPLITROOT_EX_METHODDEF
17654
    OS__PATH_NORMPATH_METHODDEF
17655
    OS_GETLOADAVG_METHODDEF
17656
    OS_URANDOM_METHODDEF
17657
    OS_SETRESUID_METHODDEF
17658
    OS_SETRESGID_METHODDEF
17659
    OS_GETRESUID_METHODDEF
17660
    OS_GETRESGID_METHODDEF
17661
17662
    OS_GETXATTR_METHODDEF
17663
    OS_SETXATTR_METHODDEF
17664
    OS_REMOVEXATTR_METHODDEF
17665
    OS_LISTXATTR_METHODDEF
17666
17667
    OS_GET_TERMINAL_SIZE_METHODDEF
17668
    OS_CPU_COUNT_METHODDEF
17669
    OS_GET_INHERITABLE_METHODDEF
17670
    OS_SET_INHERITABLE_METHODDEF
17671
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17672
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17673
    OS_GET_BLOCKING_METHODDEF
17674
    OS_SET_BLOCKING_METHODDEF
17675
    OS_SCANDIR_METHODDEF
17676
    OS_FSPATH_METHODDEF
17677
    OS_GETRANDOM_METHODDEF
17678
    OS_MEMFD_CREATE_METHODDEF
17679
    OS_EVENTFD_METHODDEF
17680
    OS_EVENTFD_READ_METHODDEF
17681
    OS_EVENTFD_WRITE_METHODDEF
17682
    OS__ADD_DLL_DIRECTORY_METHODDEF
17683
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17684
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17685
    OS_SETNS_METHODDEF
17686
    OS_UNSHARE_METHODDEF
17687
    OS_TIMERFD_CREATE_METHODDEF
17688
    OS_TIMERFD_SETTIME_METHODDEF
17689
    OS_TIMERFD_SETTIME_NS_METHODDEF
17690
    OS_TIMERFD_GETTIME_METHODDEF
17691
    OS_TIMERFD_GETTIME_NS_METHODDEF
17692
17693
    OS__PATH_ISDEVDRIVE_METHODDEF
17694
    OS__PATH_ISDIR_METHODDEF
17695
    OS__PATH_ISFILE_METHODDEF
17696
    OS__PATH_ISLINK_METHODDEF
17697
    OS__PATH_ISJUNCTION_METHODDEF
17698
    OS__PATH_EXISTS_METHODDEF
17699
    OS__PATH_LEXISTS_METHODDEF
17700
17701
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17702
    OS__INPUTHOOK_METHODDEF
17703
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17704
    OS__CREATE_ENVIRON_METHODDEF
17705
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17706
    OS__EMSCRIPTEN_LOG_METHODDEF
17707
    {NULL,              NULL}            /* Sentinel */
17708
};
17709
17710
static int
17711
all_ins(PyObject *m)
17712
28
{
17713
28
#ifdef F_OK
17714
28
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17715
28
#endif
17716
28
#ifdef R_OK
17717
28
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17718
28
#endif
17719
28
#ifdef W_OK
17720
28
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17721
28
#endif
17722
28
#ifdef X_OK
17723
28
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17724
28
#endif
17725
28
#ifdef NGROUPS_MAX
17726
28
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17727
28
#endif
17728
28
#ifdef TMP_MAX
17729
28
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17730
28
#endif
17731
28
#ifdef WCONTINUED
17732
28
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17733
28
#endif
17734
28
#ifdef WNOHANG
17735
28
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17736
28
#endif
17737
28
#ifdef WUNTRACED
17738
28
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17739
28
#endif
17740
28
#ifdef O_RDONLY
17741
28
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17742
28
#endif
17743
28
#ifdef O_WRONLY
17744
28
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17745
28
#endif
17746
28
#ifdef O_RDWR
17747
28
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17748
28
#endif
17749
28
#ifdef O_NDELAY
17750
28
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17751
28
#endif
17752
28
#ifdef O_NONBLOCK
17753
28
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17754
28
#endif
17755
28
#ifdef O_APPEND
17756
28
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17757
28
#endif
17758
28
#ifdef O_DSYNC
17759
28
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17760
28
#endif
17761
28
#ifdef O_RSYNC
17762
28
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17763
28
#endif
17764
28
#ifdef O_SYNC
17765
28
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17766
28
#endif
17767
28
#ifdef O_NOCTTY
17768
28
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17769
28
#endif
17770
28
#ifdef O_CREAT
17771
28
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17772
28
#endif
17773
28
#ifdef O_EXCL
17774
28
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17775
28
#endif
17776
28
#ifdef O_TRUNC
17777
28
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17778
28
#endif
17779
#ifdef O_BINARY
17780
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17781
#endif
17782
#ifdef O_TEXT
17783
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17784
#endif
17785
#ifdef O_XATTR
17786
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17787
#endif
17788
28
#ifdef O_LARGEFILE
17789
28
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17790
28
#endif
17791
28
#ifndef __GNU__
17792
#ifdef O_SHLOCK
17793
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17794
#endif
17795
#ifdef O_EXLOCK
17796
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17797
#endif
17798
28
#endif
17799
#ifdef O_EXEC
17800
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17801
#endif
17802
#ifdef O_SEARCH
17803
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17804
#endif
17805
28
#ifdef O_PATH
17806
28
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17807
28
#endif
17808
#ifdef O_TTY_INIT
17809
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17810
#endif
17811
28
#ifdef O_TMPFILE
17812
28
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17813
28
#endif
17814
28
#ifdef PRIO_PROCESS
17815
28
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17816
28
#endif
17817
28
#ifdef PRIO_PGRP
17818
28
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17819
28
#endif
17820
28
#ifdef PRIO_USER
17821
28
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17822
28
#endif
17823
#ifdef PRIO_DARWIN_THREAD
17824
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17825
#endif
17826
#ifdef PRIO_DARWIN_PROCESS
17827
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17828
#endif
17829
#ifdef PRIO_DARWIN_BG
17830
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17831
#endif
17832
#ifdef PRIO_DARWIN_NONUI
17833
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17834
#endif
17835
28
#ifdef O_CLOEXEC
17836
28
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17837
28
#endif
17838
28
#ifdef O_ACCMODE
17839
28
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17840
28
#endif
17841
#ifdef O_EVTONLY
17842
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17843
#endif
17844
28
#ifdef O_FSYNC
17845
28
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17846
28
#endif
17847
#ifdef O_SYMLINK
17848
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17849
#endif
17850
17851
28
#ifdef SEEK_HOLE
17852
28
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17853
28
#endif
17854
28
#ifdef SEEK_DATA
17855
28
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17856
28
#endif
17857
17858
/* MS Windows */
17859
#ifdef O_NOINHERIT
17860
    /* Don't inherit in child processes. */
17861
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17862
#endif
17863
#ifdef _O_SHORT_LIVED
17864
    /* Optimize for short life (keep in memory). */
17865
    /* MS forgot to define this one with a non-underscore form too. */
17866
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17867
#endif
17868
#ifdef O_TEMPORARY
17869
    /* Automatically delete when last handle is closed. */
17870
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17871
#endif
17872
#ifdef O_RANDOM
17873
    /* Optimize for random access. */
17874
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17875
#endif
17876
#ifdef O_SEQUENTIAL
17877
    /* Optimize for sequential access. */
17878
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17879
#endif
17880
17881
/* GNU extensions. */
17882
28
#ifdef O_ASYNC
17883
    /* Send a SIGIO signal whenever input or output
17884
       becomes available on file descriptor */
17885
28
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17886
28
#endif
17887
28
#ifdef O_DIRECT
17888
    /* Direct disk access. */
17889
28
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17890
28
#endif
17891
28
#ifdef O_DIRECTORY
17892
    /* Must be a directory.      */
17893
28
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17894
28
#endif
17895
28
#ifdef O_NOFOLLOW
17896
    /* Do not follow links.      */
17897
28
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17898
28
#endif
17899
#ifdef O_NOFOLLOW_ANY
17900
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17901
#endif
17902
#ifdef O_NOLINKS
17903
    /* Fails if link count of the named file is greater than 1 */
17904
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17905
#endif
17906
28
#ifdef O_NOATIME
17907
    /* Do not update the access time. */
17908
28
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17909
28
#endif
17910
17911
    /* These come from sysexits.h */
17912
28
#ifdef EX_OK
17913
28
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17914
28
#endif /* EX_OK */
17915
28
#ifdef EX_USAGE
17916
28
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17917
28
#endif /* EX_USAGE */
17918
28
#ifdef EX_DATAERR
17919
28
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17920
28
#endif /* EX_DATAERR */
17921
28
#ifdef EX_NOINPUT
17922
28
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17923
28
#endif /* EX_NOINPUT */
17924
28
#ifdef EX_NOUSER
17925
28
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17926
28
#endif /* EX_NOUSER */
17927
28
#ifdef EX_NOHOST
17928
28
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17929
28
#endif /* EX_NOHOST */
17930
28
#ifdef EX_UNAVAILABLE
17931
28
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17932
28
#endif /* EX_UNAVAILABLE */
17933
28
#ifdef EX_SOFTWARE
17934
28
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17935
28
#endif /* EX_SOFTWARE */
17936
28
#ifdef EX_OSERR
17937
28
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17938
28
#endif /* EX_OSERR */
17939
28
#ifdef EX_OSFILE
17940
28
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17941
28
#endif /* EX_OSFILE */
17942
28
#ifdef EX_CANTCREAT
17943
28
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17944
28
#endif /* EX_CANTCREAT */
17945
28
#ifdef EX_IOERR
17946
28
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17947
28
#endif /* EX_IOERR */
17948
28
#ifdef EX_TEMPFAIL
17949
28
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17950
28
#endif /* EX_TEMPFAIL */
17951
28
#ifdef EX_PROTOCOL
17952
28
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17953
28
#endif /* EX_PROTOCOL */
17954
28
#ifdef EX_NOPERM
17955
28
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17956
28
#endif /* EX_NOPERM */
17957
28
#ifdef EX_CONFIG
17958
28
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17959
28
#endif /* EX_CONFIG */
17960
#ifdef EX_NOTFOUND
17961
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17962
#endif /* EX_NOTFOUND */
17963
17964
    /* statvfs */
17965
28
#ifdef ST_RDONLY
17966
28
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17967
28
#endif /* ST_RDONLY */
17968
28
#ifdef ST_NOSUID
17969
28
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17970
28
#endif /* ST_NOSUID */
17971
17972
       /* GNU extensions */
17973
28
#ifdef ST_NODEV
17974
28
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17975
28
#endif /* ST_NODEV */
17976
28
#ifdef ST_NOEXEC
17977
28
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17978
28
#endif /* ST_NOEXEC */
17979
28
#ifdef ST_SYNCHRONOUS
17980
28
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17981
28
#endif /* ST_SYNCHRONOUS */
17982
28
#ifdef ST_MANDLOCK
17983
28
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17984
28
#endif /* ST_MANDLOCK */
17985
28
#ifdef ST_WRITE
17986
28
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17987
28
#endif /* ST_WRITE */
17988
28
#ifdef ST_APPEND
17989
28
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
17990
28
#endif /* ST_APPEND */
17991
28
#ifdef ST_NOATIME
17992
28
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
17993
28
#endif /* ST_NOATIME */
17994
28
#ifdef ST_NODIRATIME
17995
28
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
17996
28
#endif /* ST_NODIRATIME */
17997
28
#ifdef ST_RELATIME
17998
28
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
17999
28
#endif /* ST_RELATIME */
18000
18001
    /* FreeBSD sendfile() constants */
18002
#ifdef SF_NODISKIO
18003
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18004
#endif
18005
    /* is obsolete since the 11.x release */
18006
#ifdef SF_MNOWAIT
18007
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18008
#endif
18009
#ifdef SF_SYNC
18010
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18011
#endif
18012
#ifdef SF_NOCACHE
18013
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18014
#endif
18015
18016
28
#ifdef TFD_NONBLOCK
18017
28
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18018
28
#endif
18019
28
#ifdef TFD_CLOEXEC
18020
28
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18021
28
#endif
18022
28
#ifdef TFD_TIMER_ABSTIME
18023
28
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18024
28
#endif
18025
28
#ifdef TFD_TIMER_CANCEL_ON_SET
18026
28
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18027
28
#endif
18028
18029
    /* constants for posix_fadvise */
18030
28
#ifdef POSIX_FADV_NORMAL
18031
28
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18032
28
#endif
18033
28
#ifdef POSIX_FADV_SEQUENTIAL
18034
28
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18035
28
#endif
18036
28
#ifdef POSIX_FADV_RANDOM
18037
28
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18038
28
#endif
18039
28
#ifdef POSIX_FADV_NOREUSE
18040
28
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18041
28
#endif
18042
28
#ifdef POSIX_FADV_WILLNEED
18043
28
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18044
28
#endif
18045
28
#ifdef POSIX_FADV_DONTNEED
18046
28
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18047
28
#endif
18048
18049
    /* constants for waitid */
18050
28
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18051
28
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18052
28
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18053
28
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18054
28
#ifdef P_PIDFD
18055
28
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18056
28
#endif
18057
#ifdef PIDFD_NONBLOCK
18058
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18059
#endif
18060
28
#endif
18061
28
#ifdef WEXITED
18062
28
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18063
28
#endif
18064
28
#ifdef WNOWAIT
18065
28
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18066
28
#endif
18067
28
#ifdef WSTOPPED
18068
28
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18069
28
#endif
18070
28
#ifdef CLD_EXITED
18071
28
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18072
28
#endif
18073
28
#ifdef CLD_KILLED
18074
28
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18075
28
#endif
18076
28
#ifdef CLD_DUMPED
18077
28
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18078
28
#endif
18079
28
#ifdef CLD_TRAPPED
18080
28
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18081
28
#endif
18082
28
#ifdef CLD_STOPPED
18083
28
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18084
28
#endif
18085
28
#ifdef CLD_CONTINUED
18086
28
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18087
28
#endif
18088
18089
    /* constants for lockf */
18090
28
#ifdef F_LOCK
18091
28
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18092
28
#endif
18093
28
#ifdef F_TLOCK
18094
28
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18095
28
#endif
18096
28
#ifdef F_ULOCK
18097
28
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18098
28
#endif
18099
28
#ifdef F_TEST
18100
28
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18101
28
#endif
18102
18103
28
#ifdef RWF_DSYNC
18104
28
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18105
28
#endif
18106
28
#ifdef RWF_HIPRI
18107
28
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18108
28
#endif
18109
28
#ifdef RWF_SYNC
18110
28
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18111
28
#endif
18112
28
#ifdef RWF_NOWAIT
18113
28
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18114
28
#endif
18115
#ifdef RWF_DONTCACHE
18116
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18117
#endif
18118
28
#ifdef RWF_APPEND
18119
28
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18120
28
#endif
18121
18122
/* constants for splice */
18123
28
#if defined(HAVE_SPLICE) && defined(__linux__)
18124
28
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18125
28
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18126
28
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18127
28
#endif
18128
18129
/* constants for posix_spawn */
18130
28
#ifdef HAVE_POSIX_SPAWN
18131
28
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18132
28
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18133
28
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18134
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18135
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18136
#endif
18137
28
#endif
18138
18139
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18140
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18141
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18142
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18143
#endif
18144
#ifdef HAVE_SPAWNV
18145
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18146
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18147
#endif
18148
18149
28
#ifdef HAVE_SCHED_H
18150
28
#ifdef SCHED_OTHER
18151
28
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18152
28
#endif
18153
28
#ifdef SCHED_DEADLINE
18154
28
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18155
28
#endif
18156
28
#ifdef SCHED_FIFO
18157
28
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18158
28
#endif
18159
28
#ifdef SCHED_NORMAL
18160
28
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18161
28
#endif
18162
28
#ifdef SCHED_RR
18163
28
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18164
28
#endif
18165
#ifdef SCHED_SPORADIC
18166
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18167
#endif
18168
28
#ifdef SCHED_BATCH
18169
28
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18170
28
#endif
18171
28
#ifdef SCHED_IDLE
18172
28
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18173
28
#endif
18174
28
#ifdef SCHED_RESET_ON_FORK
18175
28
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18176
28
#endif
18177
#ifdef SCHED_SYS
18178
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18179
#endif
18180
#ifdef SCHED_IA
18181
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18182
#endif
18183
#ifdef SCHED_FSS
18184
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18185
#endif
18186
#ifdef SCHED_FX
18187
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18188
#endif
18189
18190
/* constants for namespaces */
18191
28
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18192
28
#ifdef CLONE_FS
18193
28
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18194
28
#endif
18195
28
#ifdef CLONE_FILES
18196
28
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18197
28
#endif
18198
28
#ifdef CLONE_NEWNS
18199
28
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18200
28
#endif
18201
28
#ifdef CLONE_NEWCGROUP
18202
28
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18203
28
#endif
18204
28
#ifdef CLONE_NEWUTS
18205
28
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18206
28
#endif
18207
28
#ifdef CLONE_NEWIPC
18208
28
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18209
28
#endif
18210
28
#ifdef CLONE_NEWUSER
18211
28
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18212
28
#endif
18213
28
#ifdef CLONE_NEWPID
18214
28
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18215
28
#endif
18216
28
#ifdef CLONE_NEWNET
18217
28
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18218
28
#endif
18219
#ifdef CLONE_NEWTIME
18220
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18221
#endif
18222
28
#ifdef CLONE_SYSVSEM
18223
28
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18224
28
#endif
18225
28
#ifdef CLONE_THREAD
18226
28
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18227
28
#endif
18228
28
#ifdef CLONE_SIGHAND
18229
28
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18230
28
#endif
18231
28
#ifdef CLONE_VM
18232
28
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18233
28
#endif
18234
28
#endif
18235
18236
28
#endif
18237
18238
28
#ifdef USE_XATTRS
18239
28
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18240
28
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18241
28
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18242
28
#endif
18243
18244
28
#if HAVE_DECL_RTLD_LAZY
18245
28
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18246
28
#endif
18247
28
#if HAVE_DECL_RTLD_NOW
18248
28
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18249
28
#endif
18250
28
#if HAVE_DECL_RTLD_GLOBAL
18251
28
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18252
28
#endif
18253
28
#if HAVE_DECL_RTLD_LOCAL
18254
28
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18255
28
#endif
18256
28
#if HAVE_DECL_RTLD_NODELETE
18257
28
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18258
28
#endif
18259
28
#if HAVE_DECL_RTLD_NOLOAD
18260
28
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18261
28
#endif
18262
28
#if HAVE_DECL_RTLD_DEEPBIND
18263
28
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18264
28
#endif
18265
#if HAVE_DECL_RTLD_MEMBER
18266
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18267
#endif
18268
18269
28
#ifdef HAVE_GETRANDOM_SYSCALL
18270
28
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18271
28
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18272
28
#endif
18273
28
#ifdef HAVE_MEMFD_CREATE
18274
28
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18275
28
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18276
28
#ifdef MFD_HUGETLB
18277
28
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18278
28
#endif
18279
28
#ifdef MFD_HUGE_SHIFT
18280
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18281
28
#endif
18282
28
#ifdef MFD_HUGE_MASK
18283
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18284
28
#endif
18285
28
#ifdef MFD_HUGE_64KB
18286
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18287
28
#endif
18288
28
#ifdef MFD_HUGE_512KB
18289
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18290
28
#endif
18291
28
#ifdef MFD_HUGE_1MB
18292
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18293
28
#endif
18294
28
#ifdef MFD_HUGE_2MB
18295
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18296
28
#endif
18297
28
#ifdef MFD_HUGE_8MB
18298
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18299
28
#endif
18300
28
#ifdef MFD_HUGE_16MB
18301
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18302
28
#endif
18303
28
#ifdef MFD_HUGE_32MB
18304
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18305
28
#endif
18306
28
#ifdef MFD_HUGE_256MB
18307
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18308
28
#endif
18309
28
#ifdef MFD_HUGE_512MB
18310
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18311
28
#endif
18312
28
#ifdef MFD_HUGE_1GB
18313
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18314
28
#endif
18315
28
#ifdef MFD_HUGE_2GB
18316
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18317
28
#endif
18318
28
#ifdef MFD_HUGE_16GB
18319
28
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18320
28
#endif
18321
28
#endif /* HAVE_MEMFD_CREATE */
18322
18323
28
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18324
28
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18325
28
#ifdef EFD_NONBLOCK
18326
28
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18327
28
#endif
18328
28
#ifdef EFD_SEMAPHORE
18329
28
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18330
28
#endif
18331
28
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18332
18333
28
#ifdef NODEV
18334
28
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18335
28
#endif
18336
18337
28
#ifdef AT_NO_AUTOMOUNT
18338
28
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18339
28
#endif
18340
18341
28
#ifdef HAVE_STATX
18342
28
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18343
28
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18344
28
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18345
28
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18346
28
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18347
28
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18348
28
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18349
28
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18350
28
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18351
28
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18352
28
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18353
28
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18354
28
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18355
#ifdef STATX_MNT_ID
18356
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18357
#endif
18358
#ifdef STATX_DIOALIGN
18359
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18360
#endif
18361
#ifdef STATX_MNT_ID_UNIQUE
18362
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18363
#endif
18364
#ifdef STATX_SUBVOL
18365
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18366
#endif
18367
#ifdef STATX_WRITE_ATOMIC
18368
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18369
#endif
18370
#ifdef STATX_DIO_READ_ALIGN
18371
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18372
#endif
18373
    /* STATX_ALL intentionally omitted because it is deprecated */
18374
28
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18375
28
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18376
28
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18377
    /* STATX_ATTR_* constants are in the stat module */
18378
28
#endif /* HAVE_STATX */
18379
18380
#if defined(__APPLE__)
18381
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18382
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18383
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18384
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18385
#endif
18386
18387
#ifdef MS_WINDOWS
18388
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18389
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18390
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18391
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18392
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18393
#endif
18394
18395
28
    return 0;
18396
28
}
18397
18398
18399
18400
#define PROBE(name, test) \
18401
   static int name(void)  \
18402
476
   {                      \
18403
476
      if (test) {        \
18404
476
          return 1;       \
18405
476
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
476
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_futimens
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_linkat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_openat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_renameat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18402
28
   {                      \
18403
28
      if (test) {        \
18404
28
          return 1;       \
18405
28
      } else {            \
18406
0
          return 0;       \
18407
0
      }                   \
18408
28
   }
18409
18410
#ifdef HAVE_FSTATAT
18411
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18412
#endif
18413
18414
#ifdef HAVE_FACCESSAT
18415
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18416
#endif
18417
18418
#ifdef HAVE_FCHMODAT
18419
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18420
#endif
18421
18422
#ifdef HAVE_FCHOWNAT
18423
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18424
#endif
18425
18426
#ifdef HAVE_LINKAT
18427
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18428
#endif
18429
18430
#ifdef HAVE_FDOPENDIR
18431
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18432
#endif
18433
18434
#ifdef HAVE_MKDIRAT
18435
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18436
#endif
18437
18438
#ifdef HAVE_MKFIFOAT
18439
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18440
#endif
18441
18442
#ifdef HAVE_MKNODAT
18443
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18444
#endif
18445
18446
#ifdef HAVE_RENAMEAT
18447
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18448
#endif
18449
18450
#ifdef HAVE_UNLINKAT
18451
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18452
#endif
18453
18454
#ifdef HAVE_OPENAT
18455
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18456
#endif
18457
18458
#ifdef HAVE_READLINKAT
18459
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18460
#endif
18461
18462
#ifdef HAVE_SYMLINKAT
18463
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18464
#endif
18465
18466
#ifdef HAVE_FUTIMENS
18467
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18468
#endif
18469
18470
#ifdef HAVE_UTIMENSAT
18471
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18472
#endif
18473
18474
#ifdef HAVE_PTSNAME_R
18475
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18476
#endif
18477
18478
18479
18480
static const struct have_function {
18481
    const char * const label;
18482
    int (*probe)(void);
18483
} have_functions[] = {
18484
18485
#ifdef HAVE_EVENTFD
18486
    {"HAVE_EVENTFD", NULL},
18487
#endif
18488
18489
#ifdef HAVE_TIMERFD_CREATE
18490
    {"HAVE_TIMERFD_CREATE", NULL},
18491
#endif
18492
18493
#ifdef HAVE_FACCESSAT
18494
    { "HAVE_FACCESSAT", probe_faccessat },
18495
#endif
18496
18497
#ifdef HAVE_FCHDIR
18498
    { "HAVE_FCHDIR", NULL },
18499
#endif
18500
18501
#ifdef HAVE_FCHMOD
18502
    { "HAVE_FCHMOD", NULL },
18503
#endif
18504
18505
#ifdef HAVE_FCHMODAT
18506
    { "HAVE_FCHMODAT", probe_fchmodat },
18507
#endif
18508
18509
#ifdef HAVE_FCHOWN
18510
    { "HAVE_FCHOWN", NULL },
18511
#endif
18512
18513
#ifdef HAVE_FCHOWNAT
18514
    { "HAVE_FCHOWNAT", probe_fchownat },
18515
#endif
18516
18517
#ifdef HAVE_FEXECVE
18518
    { "HAVE_FEXECVE", NULL },
18519
#endif
18520
18521
#ifdef HAVE_FDOPENDIR
18522
    { "HAVE_FDOPENDIR", probe_fdopendir },
18523
#endif
18524
18525
#ifdef HAVE_FPATHCONF
18526
    { "HAVE_FPATHCONF", NULL },
18527
#endif
18528
18529
#ifdef HAVE_FSTATAT
18530
    { "HAVE_FSTATAT", probe_fstatat },
18531
#endif
18532
18533
#ifdef HAVE_FSTATVFS
18534
    { "HAVE_FSTATVFS", NULL },
18535
#endif
18536
18537
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18538
    { "HAVE_FTRUNCATE", NULL },
18539
#endif
18540
18541
#ifdef HAVE_FUTIMENS
18542
    { "HAVE_FUTIMENS", probe_futimens },
18543
#endif
18544
18545
#ifdef HAVE_FUTIMES
18546
    { "HAVE_FUTIMES", NULL },
18547
#endif
18548
18549
#ifdef HAVE_FUTIMESAT
18550
    { "HAVE_FUTIMESAT", NULL },
18551
#endif
18552
18553
#ifdef HAVE_LINKAT
18554
    { "HAVE_LINKAT", probe_linkat },
18555
#endif
18556
18557
#ifdef HAVE_LCHFLAGS
18558
    { "HAVE_LCHFLAGS", NULL },
18559
#endif
18560
18561
#ifdef HAVE_LCHMOD
18562
    { "HAVE_LCHMOD", NULL },
18563
#endif
18564
18565
#ifdef HAVE_LCHOWN
18566
    { "HAVE_LCHOWN", NULL },
18567
#endif
18568
18569
#ifdef HAVE_LSTAT
18570
    { "HAVE_LSTAT", NULL },
18571
#endif
18572
18573
#ifdef HAVE_LUTIMES
18574
    { "HAVE_LUTIMES", NULL },
18575
#endif
18576
18577
#ifdef HAVE_MEMFD_CREATE
18578
    { "HAVE_MEMFD_CREATE", NULL },
18579
#endif
18580
18581
#ifdef HAVE_MKDIRAT
18582
    { "HAVE_MKDIRAT", probe_mkdirat },
18583
#endif
18584
18585
#ifdef HAVE_MKFIFOAT
18586
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18587
#endif
18588
18589
#ifdef HAVE_MKNODAT
18590
    { "HAVE_MKNODAT", probe_mknodat },
18591
#endif
18592
18593
#ifdef HAVE_OPENAT
18594
    { "HAVE_OPENAT", probe_openat },
18595
#endif
18596
18597
#ifdef HAVE_READLINKAT
18598
    { "HAVE_READLINKAT", probe_readlinkat },
18599
#endif
18600
18601
#ifdef HAVE_RENAMEAT
18602
    { "HAVE_RENAMEAT", probe_renameat },
18603
#endif
18604
18605
#ifdef HAVE_SYMLINKAT
18606
    { "HAVE_SYMLINKAT", probe_symlinkat },
18607
#endif
18608
18609
#ifdef HAVE_UNLINKAT
18610
    { "HAVE_UNLINKAT", probe_unlinkat },
18611
#endif
18612
18613
#ifdef HAVE_UTIMENSAT
18614
    { "HAVE_UTIMENSAT", probe_utimensat },
18615
#endif
18616
18617
#ifdef HAVE_PTSNAME_R
18618
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18619
#endif
18620
18621
#ifdef MS_WINDOWS
18622
    { "MS_WINDOWS", NULL },
18623
#endif
18624
18625
    { NULL, NULL }
18626
};
18627
18628
18629
static int
18630
posixmodule_exec(PyObject *m)
18631
28
{
18632
28
    _posixstate *state = get_posix_state(m);
18633
18634
28
#if defined(HAVE_PWRITEV)
18635
28
    if (HAVE_PWRITEV_RUNTIME) {} else {
18636
0
        PyObject* dct = PyModule_GetDict(m);
18637
18638
0
        if (dct == NULL) {
18639
0
            return -1;
18640
0
        }
18641
18642
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18643
0
            return -1;
18644
0
        }
18645
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18646
0
            return -1;
18647
0
        }
18648
0
    }
18649
28
#endif
18650
18651
28
#ifdef HAVE_STATX
18652
28
    if (statx == NULL) {
18653
0
        PyObject* dct = PyModule_GetDict(m);
18654
0
        if (dct == NULL) {
18655
0
            return -1;
18656
0
        }
18657
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
18658
0
            return -1;
18659
0
        }
18660
0
    }
18661
28
    else {
18662
28
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
18663
28
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
18664
0
            return -1;
18665
0
        }
18666
28
    }
18667
28
#endif
18668
18669
    /* Initialize environ dictionary */
18670
28
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18671
0
        return -1;
18672
0
    }
18673
18674
28
    if (all_ins(m))
18675
0
        return -1;
18676
18677
28
    if (setup_confname_tables(m))
18678
0
        return -1;
18679
18680
28
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18681
0
        return -1;
18682
0
    }
18683
18684
28
#if defined(HAVE_WAITID)
18685
28
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18686
28
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18687
0
        return -1;
18688
0
    }
18689
28
#endif
18690
18691
28
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18692
28
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18693
28
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18694
28
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18695
28
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18696
0
        return -1;
18697
0
    }
18698
28
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18699
28
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18700
18701
28
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18702
28
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18703
0
        return -1;
18704
0
    }
18705
18706
28
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18707
28
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18708
28
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18709
0
        return -1;
18710
0
    }
18711
28
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18712
28
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18713
28
                          &os_sched_param_reduce_method) < 0)
18714
0
    {
18715
0
        return -1;
18716
0
    }
18717
28
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18718
28
#endif
18719
18720
    /* initialize TerminalSize_info */
18721
28
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18722
28
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18723
0
        return -1;
18724
0
    }
18725
18726
    /* initialize scandir types */
18727
28
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18728
28
    if (ScandirIteratorType == NULL) {
18729
0
        return -1;
18730
0
    }
18731
28
    state->ScandirIteratorType = ScandirIteratorType;
18732
18733
28
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18734
28
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18735
0
        return -1;
18736
0
    }
18737
18738
28
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18739
28
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18740
0
        return -1;
18741
0
    }
18742
18743
28
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18744
28
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18745
0
        return -1;
18746
0
    }
18747
18748
28
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18749
0
        return -1;
18750
28
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18751
28
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18752
28
    if (state->struct_rusage == NULL)
18753
0
        return -1;
18754
28
#endif
18755
28
    state->st_mode = PyUnicode_InternFromString("st_mode");
18756
28
    if (state->st_mode == NULL)
18757
0
        return -1;
18758
18759
    /* suppress "function not used" warnings */
18760
28
    {
18761
28
    int ignored;
18762
28
    fd_specified("", -1);
18763
28
    follow_symlinks_specified("", 1);
18764
28
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18765
28
    dir_fd_converter(Py_None, &ignored);
18766
28
    dir_fd_unavailable(Py_None, &ignored);
18767
28
    }
18768
18769
    /*
18770
     * provide list of locally available functions
18771
     * so os.py can populate support_* lists
18772
     */
18773
28
    PyObject *list = PyList_New(0);
18774
28
    if (!list) {
18775
0
        return -1;
18776
0
    }
18777
924
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18778
896
        PyObject *unicode;
18779
896
        if (trace->probe && !trace->probe()) continue;
18780
896
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18781
896
        if (!unicode)
18782
0
            return -1;
18783
896
        if (PyList_Append(list, unicode))
18784
0
            return -1;
18785
896
        Py_DECREF(unicode);
18786
896
    }
18787
18788
28
#ifndef MS_WINDOWS
18789
28
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18790
0
        PyErr_SetString(PyExc_RuntimeError,
18791
0
                        "cannot read ticks_per_second");
18792
0
        return -1;
18793
0
    }
18794
28
    assert(state->ticks_per_second >= 1);
18795
28
#endif
18796
18797
28
    return PyModule_Add(m, "_have_functions", list);
18798
28
}
18799
18800
18801
static PyModuleDef_Slot posixmodile_slots[] = {
18802
    {Py_mod_exec, posixmodule_exec},
18803
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18804
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18805
    {0, NULL}
18806
};
18807
18808
static struct PyModuleDef posixmodule = {
18809
    PyModuleDef_HEAD_INIT,
18810
    .m_name = MODNAME,
18811
    .m_doc = posix__doc__,
18812
    .m_size = sizeof(_posixstate),
18813
    .m_methods = posix_methods,
18814
    .m_slots = posixmodile_slots,
18815
    .m_traverse = _posix_traverse,
18816
    .m_clear = _posix_clear,
18817
    .m_free = _posix_free,
18818
};
18819
18820
PyMODINIT_FUNC
18821
INITFUNC(void)
18822
28
{
18823
28
    return PyModuleDef_Init(&posixmodule);
18824
28
}