Coverage Report

Created: 2025-10-12 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/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 <stdio.h>                // ctermid()
44
#include <stdlib.h>               // system()
45
46
#ifdef HAVE_UNISTD_H
47
#  include <unistd.h>             // symlink()
48
#endif
49
50
#ifdef __APPLE__
51
   /* Needed for the implementation of os.statvfs */
52
#  include <sys/param.h>
53
#  include <sys/mount.h>
54
#endif
55
56
#ifdef HAVE_SYS_TIME_H
57
#  include <sys/time.h>           // futimes()
58
#endif
59
60
#ifdef HAVE_SYS_PIDFD_H
61
#  include <sys/pidfd.h>          // PIDFD_NONBLOCK
62
#endif
63
64
#ifdef __EMSCRIPTEN__
65
#  include "emscripten.h"         // emscripten_debugger()
66
#endif
67
68
#ifdef HAVE_SYS_UIO_H
69
#  include <sys/uio.h>
70
#endif
71
72
#ifdef HAVE_SYS_TYPES_H
73
   /* Should be included before <sys/sysmacros.h> on HP-UX v3 */
74
#  include <sys/types.h>
75
#endif
76
#ifdef HAVE_SYS_SYSMACROS_H
77
   /* GNU C Library: major(), minor(), makedev() */
78
#  include <sys/sysmacros.h>
79
#endif
80
81
#ifdef HAVE_SYS_STAT_H
82
#  include <sys/stat.h>
83
#endif
84
85
#ifdef HAVE_SYS_WAIT_H
86
#  include <sys/wait.h>           // WNOHANG
87
#endif
88
89
#ifdef HAVE_LINUX_WAIT_H
90
#  include <linux/wait.h>         // P_PIDFD
91
#endif
92
93
#ifdef HAVE_SIGNAL_H
94
#  include <signal.h>
95
#endif
96
97
#ifdef HAVE_FCNTL_H
98
#  include <fcntl.h>              // fcntl()
99
#endif
100
101
#ifdef HAVE_GRP_H
102
#  include <grp.h>                // setgroups()
103
#endif
104
105
#ifdef HAVE_SYSEXITS_H
106
#  include <sysexits.h>           // EX_OK
107
#endif
108
109
#ifdef HAVE_SYS_LOADAVG_H
110
#  include <sys/loadavg.h>        // getloadavg()
111
#endif
112
113
#ifdef HAVE_SYS_SENDFILE_H
114
#  include <sys/sendfile.h>       // sendfile()
115
#endif
116
117
#if defined(__APPLE__)
118
#  include <copyfile.h>           // fcopyfile()
119
#endif
120
121
#ifdef HAVE_SCHED_H
122
#  include <sched.h>              // sched_setscheduler()
123
#endif
124
#ifdef HAVE_LINUX_SCHED_H
125
#  include <linux/sched.h>        // SCHED_IDLE, SCHED_RR
126
#endif
127
128
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
129
#  ifdef HAVE_SYS_SOCKET_H
130
#    include <sys/socket.h>
131
#  endif
132
#endif
133
134
#ifdef HAVE_DLFCN_H
135
#  include <dlfcn.h>
136
#endif
137
138
#ifdef __hpux
139
#  include <sys/mpctl.h>
140
#endif
141
142
#if defined(__DragonFly__) || \
143
    defined(__OpenBSD__)   || \
144
    defined(__FreeBSD__)   || \
145
    defined(__NetBSD__)    || \
146
    defined(__APPLE__)
147
#  include <sys/sysctl.h>
148
#endif
149
150
#ifdef HAVE_LINUX_RANDOM_H
151
#  include <linux/random.h>       // GRND_RANDOM
152
#endif
153
#ifdef HAVE_GETRANDOM_SYSCALL
154
#  include <sys/syscall.h>        // syscall()
155
#endif
156
157
#ifdef HAVE_POSIX_SPAWN
158
#  include <spawn.h>              // posix_spawn()
159
#endif
160
161
#ifdef HAVE_UTIME_H
162
#  include <utime.h>              // utime()
163
#endif
164
165
#ifdef HAVE_SYS_UTIME_H
166
#  include <sys/utime.h>
167
#  define HAVE_UTIME_H /* pretend we do for the rest of this file */
168
#endif
169
170
#ifdef HAVE_SYS_TIMES_H
171
#  include <sys/times.h>          // times()
172
#endif
173
174
#ifdef HAVE_SYS_PARAM_H
175
#  include <sys/param.h>
176
#endif
177
178
#ifdef HAVE_SYS_UTSNAME_H
179
#  include <sys/utsname.h>        // uname()
180
#endif
181
182
/* memfd_create is either defined in sys/mman.h or sys/memfd.h
183
 * linux/memfd.h defines additional flags
184
 */
185
#ifdef HAVE_SYS_MMAN_H
186
#  include <sys/mman.h>           // memfd_create()
187
#endif
188
#ifdef HAVE_SYS_MEMFD_H
189
#  include <sys/memfd.h>          // memfd_create()
190
#endif
191
#ifdef HAVE_LINUX_MEMFD_H
192
#  include <linux/memfd.h>        // memfd_create(), MFD_CLOEXEC
193
#endif
194
195
#ifdef HAVE_SYS_EVENTFD_H
196
#  include <sys/eventfd.h>        // eventfd()
197
#endif
198
199
#ifdef HAVE_SYS_TIMERFD_H
200
#  include <sys/timerfd.h>        // timerfd_create()
201
#endif
202
203
#ifdef _Py_MEMORY_SANITIZER
204
#  include <sanitizer/msan_interface.h> // __msan_unpoison()
205
#endif
206
207
208
// --- More complex system includes -----------------------------------------
209
210
#ifdef MS_WINDOWS
211
#  include <windows.h>
212
#  if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP)
213
#    include <pathcch.h>          // PathCchSkipRoot()
214
#  endif
215
#  include <aclapi.h>             // SetEntriesInAcl
216
#  include <lmcons.h>             // UNLEN
217
#  include <sddl.h>               // SDDL_REVISION_1
218
#  include <winioctl.h>           // FSCTL_GET_REPARSE_POINT
219
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
220
#    define HAVE_SYMLINK
221
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
222
#endif
223
224
225
#ifdef _MSC_VER
226
#  ifdef HAVE_DIRECT_H
227
#    include <direct.h>
228
#  endif
229
#  ifdef HAVE_IO_H
230
#    include <io.h>
231
#  endif
232
#  ifdef HAVE_PROCESS_H
233
#    include <process.h>          // getpid(), _cwait()
234
#  endif
235
#  include <malloc.h>
236
#endif /* _MSC_VER */
237
238
239
#ifdef HAVE__GETPTY
240
#  include <sys/types.h>          // mode_t
241
   // SGI apparently needs this forward declaration
242
   extern char * _getpty(int *, int, mode_t, int);
243
#endif
244
245
246
#if defined(HAVE_SYS_XATTR_H)
247
#  if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
248
#    define USE_XATTRS
249
#    include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
250
#  endif
251
#  if defined(__CYGWIN__)
252
#    define USE_XATTRS
253
#    include <cygwin/limits.h>  // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX.
254
#  endif
255
#endif
256
#ifdef USE_XATTRS
257
#  include <sys/xattr.h>          // fgetxattr()
258
#endif
259
260
261
#ifdef HAVE_WINDOWS_CONSOLE_IO
262
#  define TERMSIZE_USE_CONIO
263
#elif defined(HAVE_SYS_IOCTL_H)
264
#  include <sys/ioctl.h>          // ioctl(), TIOCGWINSZ
265
#  if defined(HAVE_TERMIOS_H)
266
#    include <termios.h>
267
#  endif
268
#  if defined(TIOCGWINSZ)
269
#    define TERMSIZE_USE_IOCTL
270
#  endif
271
#endif
272
273
274
/* Various compilers have only certain posix functions */
275
/* XXX Gosh I wish these were all moved into pyconfig.h */
276
#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
277
#  define HAVE_OPENDIR    1
278
#  define HAVE_SYSTEM     1
279
#  include <process.h>
280
#elif defined( _MSC_VER)
281
  /* Microsoft compiler */
282
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
283
#    define HAVE_GETPPID    1
284
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */
285
#  if defined(MS_WINDOWS_DESKTOP)
286
#    define HAVE_GETLOGIN   1
287
#  endif /* MS_WINDOWS_DESKTOP */
288
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
289
#    define HAVE_SPAWNV     1
290
#    define HAVE_EXECV      1
291
#    define HAVE_WSPAWNV    1
292
#    define HAVE_WEXECV     1
293
#    define HAVE_SYSTEM     1
294
#    define HAVE_CWAIT      1
295
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
296
#  define HAVE_PIPE       1
297
#  define HAVE_FSYNC      1
298
#  define fsync _commit
299
#endif
300
301
302
#if !defined(_MSC_VER) && defined(__sgi) && _COMPILER_VERSION>=700
303
/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
304
   (default) */
305
extern char *ctermid_r(char *);
306
#endif
307
308
309
#if defined(__VXWORKS__)
310
#  include <vxCpuLib.h>
311
#  include <rtpLib.h>
312
#  include <wait.h>
313
#  include <taskLib.h>
314
#  ifndef _P_WAIT
315
#    define _P_WAIT          0
316
#    define _P_NOWAIT        1
317
#    define _P_NOWAITO       1
318
#  endif
319
#endif /* __VXWORKS__ */
320
321
322
#ifdef HAVE_DIRENT_H
323
#  include <dirent.h>             // opendir()
324
9.17k
#  define NAMLEN(dirent) strlen((dirent)->d_name)
325
#else
326
#  if defined(__WATCOMC__) && !defined(__QNX__)
327
#    include <direct.h>
328
#    define NAMLEN(dirent) strlen((dirent)->d_name)
329
#  else
330
#    define dirent direct
331
#    define NAMLEN(dirent) (dirent)->d_namlen
332
#  endif
333
#  ifdef HAVE_SYS_NDIR_H
334
#    include <sys/ndir.h>
335
#  endif
336
#  ifdef HAVE_SYS_DIR_H
337
#    include <sys/dir.h>
338
#  endif
339
#  ifdef HAVE_NDIR_H
340
#    include <ndir.h>
341
#  endif
342
#endif
343
344
345
#if defined(MAJOR_IN_MKDEV)
346
#  include <sys/mkdev.h>
347
#else
348
#  if defined(MAJOR_IN_SYSMACROS)
349
#    include <sys/sysmacros.h>
350
#  endif
351
#  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
352
#    include <sys/mkdev.h>
353
#  endif
354
#endif
355
356
357
// --- Macros ---------------------------------------------------------------
358
359
#ifndef MAXPATHLEN
360
#  if defined(PATH_MAX) && PATH_MAX > 1024
361
#    define MAXPATHLEN PATH_MAX
362
#  else
363
#    define MAXPATHLEN 1024
364
#  endif
365
#endif /* MAXPATHLEN */
366
367
368
#ifdef UNION_WAIT
369
   /* Emulate some macros on systems that have a union instead of macros */
370
#  ifndef WIFEXITED
371
#    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
372
#  endif
373
#  ifndef WEXITSTATUS
374
#    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
375
#  endif
376
#  ifndef WTERMSIG
377
#    define WTERMSIG(u_wait) ((u_wait).w_termsig)
378
#  endif
379
#  define WAIT_TYPE union wait
380
#  define WAIT_STATUS_INT(s) (s.w_status)
381
#else
382
   /* !UNION_WAIT */
383
0
#  define WAIT_TYPE int
384
0
#  define WAIT_STATUS_INT(s) (s)
385
#endif /* UNION_WAIT */
386
387
388
/* Don't use the "_r" form if we don't need it (also, won't have a
389
   prototype for it, at least on Solaris -- maybe others as well?). */
390
#if defined(HAVE_CTERMID_R)
391
#  define USE_CTERMID_R
392
#endif
393
394
395
/* choose the appropriate stat and fstat functions and return structs */
396
#undef STAT
397
#undef FSTAT
398
#undef STRUCT_STAT
399
#ifdef MS_WINDOWS
400
#  define STAT win32_stat
401
#  define LSTAT win32_lstat
402
#  define FSTAT _Py_fstat_noraise
403
#  define STRUCT_STAT struct _Py_stat_struct
404
#else
405
2.07k
#  define STAT stat
406
0
#  define LSTAT lstat
407
0
#  define FSTAT fstat
408
2.07k
#  define STRUCT_STAT struct stat
409
#endif
410
411
412
#if !defined(EX_OK) && defined(EXIT_SUCCESS)
413
#  define EX_OK EXIT_SUCCESS
414
#endif
415
416
#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
417
#  undef HAVE_SCHED_SETAFFINITY
418
#endif
419
420
/* On android API level 21, 'AT_EACCESS' is not declared although
421
 * HAVE_FACCESSAT is defined. */
422
#ifdef __ANDROID__
423
#  undef HAVE_FACCESSAT
424
#endif
425
426
#if defined(__sun)
427
/* Something to implement in autoconf, not present in autoconf 2.69 */
428
#  define HAVE_STRUCT_STAT_ST_FSTYPE 1
429
#endif
430
431
432
// --- Apple __builtin_available() macros -----------------------------------
433
434
/*
435
 * A number of APIs are available on macOS from a certain macOS version.
436
 * To support building with a new SDK while deploying to older versions
437
 * the availability test is split into two:
438
 *   - HAVE_<FUNCTION>:  The configure check for compile time availability
439
 *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
440
 *
441
 * The latter is always true when not on macOS, or when using a compiler
442
 * that does not support __has_builtin (older versions of Xcode).
443
 *
444
 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
445
 *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
446
 *
447
 * In mixing the test with other tests or using negations will result in compile
448
 * errors.
449
 */
450
#if defined(__APPLE__)
451
452
#include <mach/mach.h>
453
454
#if defined(__has_builtin)
455
#if __has_builtin(__builtin_available)
456
#define HAVE_BUILTIN_AVAILABLE 1
457
#endif
458
#endif
459
460
#ifdef HAVE_BUILTIN_AVAILABLE
461
#  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
462
#  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
463
#  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
464
#  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
465
#  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
466
#  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
467
#  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
468
#  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
469
#  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
470
#  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
471
#  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
472
#  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
473
#  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
474
#  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
475
#  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
476
#  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
477
#  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
478
#  define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
479
480
#  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
481
482
#else /* Xcode 8 or earlier */
483
484
   /* __builtin_available is not present in these compilers, but
485
    * some of the symbols might be weak linked (10.10 SDK or later
486
    * deploying on 10.9.
487
    *
488
    * Fall back to the older style of availability checking for
489
    * symbols introduced in macOS 10.10.
490
    */
491
492
#  ifdef HAVE_FSTATAT
493
#    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
494
#  endif
495
496
#  ifdef HAVE_FACCESSAT
497
#    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
498
#  endif
499
500
#  ifdef HAVE_FCHMODAT
501
#    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
502
#  endif
503
504
#  ifdef HAVE_FCHOWNAT
505
#    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
506
#  endif
507
508
#  ifdef HAVE_LINKAT
509
#    define HAVE_LINKAT_RUNTIME (linkat != NULL)
510
#  endif
511
512
#  ifdef HAVE_FDOPENDIR
513
#    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
514
#  endif
515
516
#  ifdef HAVE_MKDIRAT
517
#    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
518
#  endif
519
520
#  ifdef HAVE_RENAMEAT
521
#    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
522
#  endif
523
524
#  ifdef HAVE_UNLINKAT
525
#    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
526
#  endif
527
528
#  ifdef HAVE_OPENAT
529
#    define HAVE_OPENAT_RUNTIME (openat != NULL)
530
#  endif
531
532
#  ifdef HAVE_READLINKAT
533
#    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
534
#  endif
535
536
#  ifdef HAVE_SYMLINKAT
537
#    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
538
#  endif
539
540
#  ifdef HAVE_UTIMENSAT
541
#    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
542
#  endif
543
544
#  ifdef HAVE_FUTIMENS
545
#    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
546
#  endif
547
548
#  ifdef HAVE_PWRITEV
549
#    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
550
#  endif
551
552
#  ifdef HAVE_MKFIFOAT
553
#    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
554
#  endif
555
556
#  ifdef HAVE_MKNODAT
557
#    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
558
#  endif
559
560
#  ifdef HAVE_PTSNAME_R
561
#    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
562
#  endif
563
564
#endif
565
566
#ifdef HAVE_FUTIMESAT
567
/* Some of the logic for weak linking depends on this assertion */
568
# error "HAVE_FUTIMESAT unexpectedly defined"
569
#endif
570
571
#else
572
0
#  define HAVE_FSTATAT_RUNTIME 1
573
0
#  define HAVE_FACCESSAT_RUNTIME 1
574
0
#  define HAVE_FCHMODAT_RUNTIME 1
575
0
#  define HAVE_FCHOWNAT_RUNTIME 1
576
#ifdef __wasi__
577
#  define HAVE_LINKAT_RUNTIME 0
578
# else
579
0
#  define HAVE_LINKAT_RUNTIME 1
580
# endif
581
0
#  define HAVE_FDOPENDIR_RUNTIME 1
582
0
#  define HAVE_MKDIRAT_RUNTIME 1
583
0
#  define HAVE_RENAMEAT_RUNTIME 1
584
0
#  define HAVE_UNLINKAT_RUNTIME 1
585
0
#  define HAVE_OPENAT_RUNTIME 1
586
0
#  define HAVE_READLINKAT_RUNTIME 1
587
0
#  define HAVE_SYMLINKAT_RUNTIME 1
588
0
#  define HAVE_FUTIMENS_RUNTIME 1
589
0
#  define HAVE_UTIMENSAT_RUNTIME 1
590
22
#  define HAVE_PWRITEV_RUNTIME 1
591
0
#  define HAVE_MKFIFOAT_RUNTIME 1
592
0
#  define HAVE_MKNODAT_RUNTIME 1
593
0
#  define HAVE_PTSNAME_R_RUNTIME 1
594
#endif
595
596
597
// --- os module ------------------------------------------------------------
598
599
#ifdef MS_WINDOWS
600
#  define INITFUNC PyInit_nt
601
#  define MODNAME "nt"
602
#  define MODNAME_OBJ &_Py_ID(nt)
603
#else
604
#  define INITFUNC PyInit_posix
605
66
#  define MODNAME "posix"
606
0
#  define MODNAME_OBJ &_Py_ID(posix)
607
#endif
608
609
/*[clinic input]
610
# one of the few times we lie about this name!
611
module os
612
[clinic start generated code]*/
613
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
614
615
PyDoc_STRVAR(posix__doc__,
616
"This module provides access to operating system functionality that is\n\
617
standardized by the C Standard and the POSIX standard (a thinly\n\
618
disguised Unix interface).  Refer to the library manual and\n\
619
corresponding Unix manual entries for more information on calls.");
620
621
622
// --- Functions ------------------------------------------------------------
623
624
#ifdef HAVE_FORK
625
static void
626
run_at_forkers(PyObject *lst, int reverse)
627
0
{
628
0
    Py_ssize_t i;
629
0
    PyObject *cpy;
630
631
0
    if (lst != NULL) {
632
0
        assert(PyList_CheckExact(lst));
633
634
        /* Use a list copy in case register_at_fork() is called from
635
         * one of the callbacks.
636
         */
637
0
        cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
638
0
        if (cpy == NULL) {
639
0
            PyErr_FormatUnraisable("Exception ignored in atfork callback "
640
0
                                   "while copying list %R", lst);
641
0
        }
642
0
        else {
643
0
            if (reverse)
644
0
                PyList_Reverse(cpy);
645
0
            for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
646
0
                PyObject *func, *res;
647
0
                func = PyList_GET_ITEM(cpy, i);
648
0
                res = _PyObject_CallNoArgs(func);
649
0
                if (res == NULL) {
650
0
                    PyErr_FormatUnraisable("Exception ignored "
651
0
                                           "in atfork callback %R", func);
652
0
                }
653
0
                else {
654
0
                    Py_DECREF(res);
655
0
                }
656
0
            }
657
0
            Py_DECREF(cpy);
658
0
        }
659
0
    }
660
0
}
661
662
void
663
PyOS_BeforeFork(void)
664
0
{
665
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
666
0
    run_at_forkers(interp->before_forkers, 1);
667
668
0
    _PyImport_AcquireLock(interp);
669
0
    _PyEval_StopTheWorldAll(&_PyRuntime);
670
0
    HEAD_LOCK(&_PyRuntime);
671
0
}
672
673
void
674
PyOS_AfterFork_Parent(void)
675
0
{
676
0
    HEAD_UNLOCK(&_PyRuntime);
677
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
678
679
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
680
0
    _PyImport_ReleaseLock(interp);
681
0
    run_at_forkers(interp->after_forkers_parent, 0);
682
0
}
683
684
static void
685
reset_remotedebug_data(PyThreadState *tstate)
686
0
{
687
0
    tstate->remote_debugger_support.debugger_pending_call = 0;
688
0
    memset(tstate->remote_debugger_support.debugger_script_path, 0,
689
0
           _Py_MAX_SCRIPT_PATH_SIZE);
690
0
}
691
692
static void
693
reset_asyncio_state(_PyThreadStateImpl *tstate)
694
0
{
695
0
    llist_init(&tstate->asyncio_tasks_head);
696
0
    tstate->asyncio_running_loop = NULL;
697
0
    tstate->asyncio_running_task = NULL;
698
0
}
699
700
701
void
702
PyOS_AfterFork_Child(void)
703
0
{
704
0
    PyStatus status;
705
0
    _PyRuntimeState *runtime = &_PyRuntime;
706
707
    // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
708
0
    status = _PyRuntimeState_ReInitThreads(runtime);
709
0
    if (_PyStatus_EXCEPTION(status)) {
710
0
        goto fatal_error;
711
0
    }
712
713
0
    PyThreadState *tstate = _PyThreadState_GET();
714
0
    _Py_EnsureTstateNotNULL(tstate);
715
716
0
    assert(tstate->thread_id == PyThread_get_thread_ident());
717
0
#ifdef PY_HAVE_THREAD_NATIVE_ID
718
0
    tstate->native_thread_id = PyThread_get_thread_native_id();
719
0
#endif
720
721
#ifdef Py_GIL_DISABLED
722
    _Py_brc_after_fork(tstate->interp);
723
    _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
724
#endif
725
726
    // Ideally we could guarantee tstate is running main.
727
0
    _PyInterpreterState_ReinitRunningMain(tstate);
728
729
0
    status = _PyEval_ReInitThreads(tstate);
730
0
    if (_PyStatus_EXCEPTION(status)) {
731
0
        goto fatal_error;
732
0
    }
733
734
0
    reset_remotedebug_data(tstate);
735
736
0
    reset_asyncio_state((_PyThreadStateImpl *)tstate);
737
738
    // Remove the dead thread states. We "start the world" once we are the only
739
    // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
740
    // That needs to happen before `_PyThreadState_DeleteList`, because that
741
    // may call destructors.
742
0
    PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
743
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
744
0
    _PyThreadState_DeleteList(list, /*is_after_fork=*/1);
745
746
0
    _PyImport_ReInitLock(tstate->interp);
747
0
    _PyImport_ReleaseLock(tstate->interp);
748
749
0
    _PySignal_AfterFork();
750
751
0
    status = _PyInterpreterState_DeleteExceptMain(runtime);
752
0
    if (_PyStatus_EXCEPTION(status)) {
753
0
        goto fatal_error;
754
0
    }
755
0
    assert(_PyThreadState_GET() == tstate);
756
757
0
    status = _PyPerfTrampoline_AfterFork_Child();
758
0
    if (_PyStatus_EXCEPTION(status)) {
759
0
        goto fatal_error;
760
0
    }
761
762
0
    run_at_forkers(tstate->interp->after_forkers_child, 0);
763
0
    return;
764
765
0
fatal_error:
766
0
    Py_ExitStatusException(status);
767
0
}
768
769
static int
770
register_at_forker(PyObject **lst, PyObject *func)
771
0
{
772
0
    if (func == NULL)  /* nothing to register? do nothing. */
773
0
        return 0;
774
0
    if (*lst == NULL) {
775
0
        *lst = PyList_New(0);
776
0
        if (*lst == NULL)
777
0
            return -1;
778
0
    }
779
0
    return PyList_Append(*lst, func);
780
0
}
781
#endif  /* HAVE_FORK */
782
783
784
/* Legacy wrapper */
785
void
786
PyOS_AfterFork(void)
787
0
{
788
0
#ifdef HAVE_FORK
789
0
    PyOS_AfterFork_Child();
790
0
#endif
791
0
}
792
793
794
#ifdef MS_WINDOWS
795
/* defined in fileutils.c */
796
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
797
void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
798
                                FILE_BASIC_INFO *, FILE_ID_INFO *,
799
                                struct _Py_stat_struct *);
800
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
801
                                 struct _Py_stat_struct *);
802
#endif
803
804
805
#ifndef MS_WINDOWS
806
PyObject *
807
_PyLong_FromUid(uid_t uid)
808
1.89k
{
809
1.89k
    if (uid == (uid_t)-1)
810
0
        return PyLong_FromLong(-1);
811
1.89k
    return PyLong_FromUnsignedLong(uid);
812
1.89k
}
813
814
PyObject *
815
_PyLong_FromGid(gid_t gid)
816
1.89k
{
817
1.89k
    if (gid == (gid_t)-1)
818
0
        return PyLong_FromLong(-1);
819
1.89k
    return PyLong_FromUnsignedLong(gid);
820
1.89k
}
821
822
int
823
_Py_Uid_Converter(PyObject *obj, uid_t *p)
824
0
{
825
0
    uid_t uid;
826
0
    PyObject *index;
827
0
    int overflow;
828
0
    long result;
829
0
    unsigned long uresult;
830
831
0
    index = _PyNumber_Index(obj);
832
0
    if (index == NULL) {
833
0
        PyErr_Format(PyExc_TypeError,
834
0
                     "uid should be integer, not %.200s",
835
0
                     _PyType_Name(Py_TYPE(obj)));
836
0
        return 0;
837
0
    }
838
839
    /*
840
     * Handling uid_t is complicated for two reasons:
841
     *  * Although uid_t is (always?) unsigned, it still
842
     *    accepts -1.
843
     *  * We don't know its size in advance--it may be
844
     *    bigger than an int, or it may be smaller than
845
     *    a long.
846
     *
847
     * So a bit of defensive programming is in order.
848
     * Start with interpreting the value passed
849
     * in as a signed long and see if it works.
850
     */
851
852
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
853
854
0
    if (!overflow) {
855
0
        uid = (uid_t)result;
856
857
0
        if (result == -1) {
858
0
            if (PyErr_Occurred())
859
0
                goto fail;
860
            /* It's a legitimate -1, we're done. */
861
0
            goto success;
862
0
        }
863
864
        /* Any other negative number is disallowed. */
865
0
        if (result < 0)
866
0
            goto underflow;
867
868
        /* Ensure the value wasn't truncated. */
869
0
        if (sizeof(uid_t) < sizeof(long) &&
870
0
            (long)uid != result)
871
0
            goto underflow;
872
0
        goto success;
873
0
    }
874
875
0
    if (overflow < 0)
876
0
        goto underflow;
877
878
    /*
879
     * Okay, the value overflowed a signed long.  If it
880
     * fits in an *unsigned* long, it may still be okay,
881
     * as uid_t may be unsigned long on this platform.
882
     */
883
0
    uresult = PyLong_AsUnsignedLong(index);
884
0
    if (PyErr_Occurred()) {
885
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
886
0
            goto overflow;
887
0
        goto fail;
888
0
    }
889
890
0
    uid = (uid_t)uresult;
891
892
    /*
893
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
894
     * but this value would get interpreted as (uid_t)-1  by chown
895
     * and its siblings.   That's not what the user meant!  So we
896
     * throw an overflow exception instead.   (We already
897
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
898
     */
899
0
    if (uid == (uid_t)-1)
900
0
        goto overflow;
901
902
    /* Ensure the value wasn't truncated. */
903
0
    if (sizeof(uid_t) < sizeof(long) &&
904
0
        (unsigned long)uid != uresult)
905
0
        goto overflow;
906
    /* fallthrough */
907
908
0
success:
909
0
    Py_DECREF(index);
910
0
    *p = uid;
911
0
    return 1;
912
913
0
underflow:
914
0
    PyErr_SetString(PyExc_OverflowError,
915
0
                    "uid is less than minimum");
916
0
    goto fail;
917
918
0
overflow:
919
0
    PyErr_SetString(PyExc_OverflowError,
920
0
                    "uid is greater than maximum");
921
    /* fallthrough */
922
923
0
fail:
924
0
    Py_DECREF(index);
925
0
    return 0;
926
0
}
927
928
int
929
_Py_Gid_Converter(PyObject *obj, gid_t *p)
930
0
{
931
0
    gid_t gid;
932
0
    PyObject *index;
933
0
    int overflow;
934
0
    long result;
935
0
    unsigned long uresult;
936
937
0
    index = _PyNumber_Index(obj);
938
0
    if (index == NULL) {
939
0
        PyErr_Format(PyExc_TypeError,
940
0
                     "gid should be integer, not %.200s",
941
0
                     _PyType_Name(Py_TYPE(obj)));
942
0
        return 0;
943
0
    }
944
945
    /*
946
     * Handling gid_t is complicated for two reasons:
947
     *  * Although gid_t is (always?) unsigned, it still
948
     *    accepts -1.
949
     *  * We don't know its size in advance--it may be
950
     *    bigger than an int, or it may be smaller than
951
     *    a long.
952
     *
953
     * So a bit of defensive programming is in order.
954
     * Start with interpreting the value passed
955
     * in as a signed long and see if it works.
956
     */
957
958
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
959
960
0
    if (!overflow) {
961
0
        gid = (gid_t)result;
962
963
0
        if (result == -1) {
964
0
            if (PyErr_Occurred())
965
0
                goto fail;
966
            /* It's a legitimate -1, we're done. */
967
0
            goto success;
968
0
        }
969
970
        /* Any other negative number is disallowed. */
971
0
        if (result < 0) {
972
0
            goto underflow;
973
0
        }
974
975
        /* Ensure the value wasn't truncated. */
976
0
        if (sizeof(gid_t) < sizeof(long) &&
977
0
            (long)gid != result)
978
0
            goto underflow;
979
0
        goto success;
980
0
    }
981
982
0
    if (overflow < 0)
983
0
        goto underflow;
984
985
    /*
986
     * Okay, the value overflowed a signed long.  If it
987
     * fits in an *unsigned* long, it may still be okay,
988
     * as gid_t may be unsigned long on this platform.
989
     */
990
0
    uresult = PyLong_AsUnsignedLong(index);
991
0
    if (PyErr_Occurred()) {
992
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
993
0
            goto overflow;
994
0
        goto fail;
995
0
    }
996
997
0
    gid = (gid_t)uresult;
998
999
    /*
1000
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
1001
     * but this value would get interpreted as (gid_t)-1  by chown
1002
     * and its siblings.   That's not what the user meant!  So we
1003
     * throw an overflow exception instead.   (We already
1004
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
1005
     */
1006
0
    if (gid == (gid_t)-1)
1007
0
        goto overflow;
1008
1009
    /* Ensure the value wasn't truncated. */
1010
0
    if (sizeof(gid_t) < sizeof(long) &&
1011
0
        (unsigned long)gid != uresult)
1012
0
        goto overflow;
1013
    /* fallthrough */
1014
1015
0
success:
1016
0
    Py_DECREF(index);
1017
0
    *p = gid;
1018
0
    return 1;
1019
1020
0
underflow:
1021
0
    PyErr_SetString(PyExc_OverflowError,
1022
0
                    "gid is less than minimum");
1023
0
    goto fail;
1024
1025
0
overflow:
1026
0
    PyErr_SetString(PyExc_OverflowError,
1027
0
                    "gid is greater than maximum");
1028
    /* fallthrough */
1029
1030
0
fail:
1031
0
    Py_DECREF(index);
1032
0
    return 0;
1033
0
}
1034
#endif /* MS_WINDOWS */
1035
1036
1037
static PyObject *
1038
_PyLong_FromDev(dev_t dev)
1039
3.72k
{
1040
3.72k
#ifdef NODEV
1041
3.72k
    if (dev == NODEV) {
1042
22
        return PyLong_FromLongLong((long long)dev);
1043
22
    }
1044
3.69k
#endif
1045
3.69k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1046
3.72k
}
1047
1048
1049
#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
1050
static int
1051
_Py_Dev_Converter(PyObject *obj, void *p)
1052
0
{
1053
0
    if (!PyLong_Check(obj)) {
1054
0
        obj = _PyNumber_Index(obj);
1055
0
        if (obj == NULL) {
1056
0
            return 0;
1057
0
        }
1058
0
    }
1059
0
    else {
1060
0
        Py_INCREF(obj);
1061
0
    }
1062
0
    assert(PyLong_Check(obj));
1063
0
#ifdef NODEV
1064
0
    if (_PyLong_IsNegative((PyLongObject *)obj)) {
1065
0
        int overflow;
1066
0
        long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
1067
0
        if (result == -1 && PyErr_Occurred()) {
1068
0
            Py_DECREF(obj);
1069
0
            return 0;
1070
0
        }
1071
0
        if (!overflow && result == (long long)NODEV) {
1072
0
            *((dev_t *)p) = NODEV;
1073
0
            Py_DECREF(obj);
1074
0
            return 1;
1075
0
        }
1076
0
    }
1077
0
#endif
1078
1079
0
    unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1080
0
    Py_DECREF(obj);
1081
0
    if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1082
0
        return 0;
1083
0
    }
1084
0
    if ((unsigned long long)(dev_t)result != result) {
1085
0
        PyErr_SetString(PyExc_OverflowError,
1086
0
                        "Python int too large to convert to C dev_t");
1087
0
        return 0;
1088
0
    }
1089
0
    *((dev_t *)p) = (dev_t)result;
1090
0
    return 1;
1091
0
}
1092
#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1093
1094
1095
#ifdef AT_FDCWD
1096
/*
1097
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1098
 * without the int cast, the value gets interpreted as uint (4291925331),
1099
 * which doesn't play nicely with all the initializer lines in this file that
1100
 * look like this:
1101
 *      int dir_fd = DEFAULT_DIR_FD;
1102
 */
1103
8.41k
#define DEFAULT_DIR_FD (int)AT_FDCWD
1104
#else
1105
#define DEFAULT_DIR_FD (-100)
1106
#endif
1107
1108
static int
1109
_fd_converter(PyObject *o, int *p)
1110
0
{
1111
0
    int overflow;
1112
0
    long long_value;
1113
1114
0
    if (PyBool_Check(o)) {
1115
0
        if (PyErr_WarnEx(PyExc_RuntimeWarning,
1116
0
                "bool is used as a file descriptor", 1))
1117
0
        {
1118
0
            return 0;
1119
0
        }
1120
0
    }
1121
0
    PyObject *index = _PyNumber_Index(o);
1122
0
    if (index == NULL) {
1123
0
        return 0;
1124
0
    }
1125
1126
0
    assert(PyLong_Check(index));
1127
0
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1128
0
    Py_DECREF(index);
1129
0
    assert(!PyErr_Occurred());
1130
0
    if (overflow > 0 || long_value > INT_MAX) {
1131
0
        PyErr_SetString(PyExc_OverflowError,
1132
0
                        "fd is greater than maximum");
1133
0
        return 0;
1134
0
    }
1135
0
    if (overflow < 0 || long_value < INT_MIN) {
1136
0
        PyErr_SetString(PyExc_OverflowError,
1137
0
                        "fd is less than minimum");
1138
0
        return 0;
1139
0
    }
1140
1141
0
    *p = (int)long_value;
1142
0
    return 1;
1143
0
}
1144
1145
static int
1146
dir_fd_converter(PyObject *o, void *p)
1147
44
{
1148
44
    if (o == Py_None) {
1149
44
        *(int *)p = DEFAULT_DIR_FD;
1150
44
        return 1;
1151
44
    }
1152
0
    else if (PyIndex_Check(o)) {
1153
0
        return _fd_converter(o, (int *)p);
1154
0
    }
1155
0
    else {
1156
0
        PyErr_Format(PyExc_TypeError,
1157
0
                     "argument should be integer or None, not %.200s",
1158
0
                     _PyType_Name(Py_TYPE(o)));
1159
0
        return 0;
1160
0
    }
1161
44
}
1162
1163
typedef struct {
1164
    PyObject *billion;
1165
    PyObject *DirEntryType;
1166
    PyObject *ScandirIteratorType;
1167
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1168
    PyObject *SchedParamType;
1169
#endif
1170
    newfunc statresult_new_orig;
1171
    PyObject *StatResultType;
1172
    PyObject *StatVFSResultType;
1173
    PyObject *TerminalSizeType;
1174
    PyObject *TimesResultType;
1175
    PyObject *UnameResultType;
1176
#if defined(HAVE_WAITID)
1177
    PyObject *WaitidResultType;
1178
#endif
1179
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1180
    PyObject *struct_rusage;
1181
#endif
1182
    PyObject *st_mode;
1183
#ifndef MS_WINDOWS
1184
    // times() clock frequency in hertz; used by os.times()
1185
    long ticks_per_second;
1186
#endif
1187
} _posixstate;
1188
1189
1190
static inline _posixstate*
1191
get_posix_state(PyObject *module)
1192
7.70k
{
1193
7.70k
    void *state = _PyModule_GetState(module);
1194
7.70k
    assert(state != NULL);
1195
7.70k
    return (_posixstate *)state;
1196
7.70k
}
1197
1198
/*
1199
 * A PyArg_ParseTuple "converter" function
1200
 * that handles filesystem paths in the manner
1201
 * preferred by the os module.
1202
 *
1203
 * path_converter accepts (Unicode) strings and their
1204
 * subclasses, and bytes and their subclasses.  What
1205
 * it does with the argument depends on path.make_wide:
1206
 *
1207
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1208
 *     string we extract the wchar_t * and return it; if we
1209
 *     get bytes we decode to wchar_t * and return that.
1210
 *
1211
 *   * If path.make_wide is zero, if we get bytes we extract
1212
 *     the char_t * and return it; if we get a (Unicode)
1213
 *     string we encode to char_t * and return that.
1214
 *
1215
 * path_converter also optionally accepts signed
1216
 * integers (representing open file descriptors) instead
1217
 * of path strings.
1218
 *
1219
 * Input fields:
1220
 *   path.nullable
1221
 *     If nonzero, the path is permitted to be None.
1222
 *   path.nonstrict
1223
 *     If nonzero, the path is permitted to contain
1224
 *     embedded null characters and have any length.
1225
 *   path.make_wide
1226
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1227
 *     it always uses narrow, encoding if necessary. The default value is
1228
 *     nonzero on Windows, else zero.
1229
 *   path.suppress_value_error
1230
 *     If nonzero, raising ValueError is suppressed.
1231
 *   path.allow_fd
1232
 *     If nonzero, the path is permitted to be a file handle
1233
 *     (a signed int) instead of a string.
1234
 *   path.function_name
1235
 *     If non-NULL, path_converter will use that as the name
1236
 *     of the function in error messages.
1237
 *     (If path.function_name is NULL it omits the function name.)
1238
 *   path.argument_name
1239
 *     If non-NULL, path_converter will use that as the name
1240
 *     of the parameter in error messages.
1241
 *     (If path.argument_name is NULL it uses "path".)
1242
 *
1243
 * Output fields:
1244
 *   path.wide
1245
 *     Points to the path if it was expressed as Unicode
1246
 *     or if it was bytes and decoded to Unicode.
1247
 *   path.narrow
1248
 *     Points to the path if it was expressed as bytes,
1249
 *     or if it was Unicode and encoded to bytes.
1250
 *   path.fd
1251
 *     Contains a file descriptor if path.accept_fd was true
1252
 *     and the caller provided a signed integer instead of any
1253
 *     sort of string.
1254
 *
1255
 *     WARNING: if your "path" parameter is optional, and is
1256
 *     unspecified, path_converter will never get called.
1257
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1258
 *     yourself!
1259
 *   path.value_error
1260
 *     If nonzero, then suppress_value_error was specified and a ValueError
1261
 *     occurred.
1262
 *   path.length
1263
 *     The length of the path in characters, if specified as
1264
 *     a string.
1265
 *   path.object
1266
 *     The original object passed in (if get a PathLike object,
1267
 *     the result of PyOS_FSPath() is treated as the original object).
1268
 *     Own a reference to the object.
1269
 *   path.cleanup
1270
 *     For internal use only.  May point to a temporary object.
1271
 *     (Pay no attention to the man behind the curtain.)
1272
 *
1273
 *   At most one of path.wide or path.narrow will be non-NULL.
1274
 *   If path was None and path.nullable was set,
1275
 *     or if path was an integer and path.allow_fd was set,
1276
 *     both path.wide and path.narrow will be NULL
1277
 *     and path.length will be 0.
1278
 *
1279
 *   path_converter takes care to not write to the path_t
1280
 *   unless it's successful.  However it must reset the
1281
 *   "cleanup" field each time it's called.
1282
 *
1283
 * Use as follows:
1284
 *      path_t path;
1285
 *      memset(&path, 0, sizeof(path));
1286
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1287
 *      // ... use values from path ...
1288
 *      path_cleanup(&path);
1289
 *
1290
 * (Note that if PyArg_Parse fails you don't need to call
1291
 * path_cleanup().  However it is safe to do so.)
1292
 */
1293
typedef struct {
1294
    // Input fields
1295
    const char *function_name;
1296
    const char *argument_name;
1297
    int nullable;
1298
    int nonstrict;
1299
    int make_wide;
1300
    int suppress_value_error;
1301
    int allow_fd;
1302
    // Output fields
1303
    const wchar_t *wide;
1304
    const char *narrow;
1305
    int fd;
1306
    int value_error;
1307
    Py_ssize_t length;
1308
    PyObject *object;
1309
    PyObject *cleanup;
1310
} path_t;
1311
1312
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1313
                          make_wide, suppress_value_error, allow_fd) \
1314
2.30k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1315
2.30k
     suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL}
1316
#ifdef MS_WINDOWS
1317
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1318
                            nonstrict, suppress_value_error, allow_fd) \
1319
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1320
                      suppress_value_error, allow_fd)
1321
#else
1322
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1323
                            nonstrict, suppress_value_error, allow_fd) \
1324
2.19k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1325
2.19k
                      suppress_value_error, allow_fd)
1326
#endif
1327
1328
static void
1329
path_cleanup(path_t *path)
1330
2.30k
{
1331
2.30k
    wchar_t *wide = (wchar_t *)path->wide;
1332
2.30k
    path->wide = NULL;
1333
2.30k
    PyMem_Free(wide);
1334
2.30k
    Py_CLEAR(path->object);
1335
2.30k
    Py_CLEAR(path->cleanup);
1336
2.30k
}
1337
1338
static int
1339
path_converter(PyObject *o, void *p)
1340
2.30k
{
1341
2.30k
    path_t *path = (path_t *)p;
1342
2.30k
    PyObject *bytes = NULL;
1343
2.30k
    Py_ssize_t length = 0;
1344
2.30k
    int is_index, is_bytes, is_unicode;
1345
2.30k
    const char *narrow;
1346
2.30k
    PyObject *wo = NULL;
1347
2.30k
    wchar_t *wide = NULL;
1348
1349
2.30k
#define FORMAT_EXCEPTION(exc, fmt) \
1350
2.30k
    PyErr_Format(exc, "%s%s" fmt, \
1351
0
        path->function_name ? path->function_name : "", \
1352
0
        path->function_name ? ": "                : "", \
1353
0
        path->argument_name ? path->argument_name : "path")
1354
1355
    /* Py_CLEANUP_SUPPORTED support */
1356
2.30k
    if (o == NULL) {
1357
0
        path_cleanup(path);
1358
0
        return 1;
1359
0
    }
1360
1361
    /* Ensure it's always safe to call path_cleanup(). */
1362
2.30k
    path->object = path->cleanup = NULL;
1363
    /* path->object owns a reference to the original object */
1364
2.30k
    Py_INCREF(o);
1365
1366
2.30k
    if ((o == Py_None) && path->nullable) {
1367
0
        path->wide = NULL;
1368
0
        path->narrow = NULL;
1369
0
        path->fd = -1;
1370
0
        goto success_exit;
1371
0
    }
1372
1373
    /* Only call this here so that we don't treat the return value of
1374
       os.fspath() as an fd or buffer. */
1375
2.30k
    is_index = path->allow_fd && PyIndex_Check(o);
1376
2.30k
    is_bytes = PyBytes_Check(o);
1377
2.30k
    is_unicode = PyUnicode_Check(o);
1378
1379
2.30k
    if (!is_index && !is_unicode && !is_bytes) {
1380
        /* Inline PyOS_FSPath() for better error messages. */
1381
0
        PyObject *func, *res;
1382
1383
0
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1384
0
        if ((NULL == func) || (func == Py_None)) {
1385
0
            goto error_format;
1386
0
        }
1387
0
        res = _PyObject_CallNoArgs(func);
1388
0
        Py_DECREF(func);
1389
0
        if (NULL == res) {
1390
0
            goto error_exit;
1391
0
        }
1392
0
        else if (PyUnicode_Check(res)) {
1393
0
            is_unicode = 1;
1394
0
        }
1395
0
        else if (PyBytes_Check(res)) {
1396
0
            is_bytes = 1;
1397
0
        }
1398
0
        else {
1399
0
            PyErr_Format(PyExc_TypeError,
1400
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1401
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1402
0
                 _PyType_Name(Py_TYPE(res)));
1403
0
            Py_DECREF(res);
1404
0
            goto error_exit;
1405
0
        }
1406
1407
        /* still owns a reference to the original object */
1408
0
        Py_SETREF(o, res);
1409
0
    }
1410
1411
2.30k
    if (is_unicode) {
1412
2.30k
        if (path->make_wide) {
1413
110
            wide = PyUnicode_AsWideCharString(o, &length);
1414
110
            if (!wide) {
1415
0
                goto error_exit;
1416
0
            }
1417
#ifdef MS_WINDOWS
1418
            if (!path->nonstrict && length > 32767) {
1419
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1420
                goto error_exit;
1421
            }
1422
#endif
1423
110
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1424
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1425
0
                                 "embedded null character in %s");
1426
0
                goto error_exit;
1427
0
            }
1428
1429
110
            path->wide = wide;
1430
110
            path->narrow = NULL;
1431
110
            path->fd = -1;
1432
110
            wide = NULL;
1433
110
            goto success_exit;
1434
110
        }
1435
2.19k
        bytes = PyUnicode_EncodeFSDefault(o);
1436
2.19k
        if (!bytes) {
1437
0
            goto error_exit;
1438
0
        }
1439
2.19k
    }
1440
0
    else if (is_bytes) {
1441
0
        bytes = Py_NewRef(o);
1442
0
    }
1443
0
    else if (is_index) {
1444
0
        if (!_fd_converter(o, &path->fd)) {
1445
0
            goto error_exit;
1446
0
        }
1447
0
        path->wide = NULL;
1448
0
        path->narrow = NULL;
1449
0
        goto success_exit;
1450
0
    }
1451
0
    else {
1452
0
 error_format:
1453
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1454
0
            path->function_name ? path->function_name : "",
1455
0
            path->function_name ? ": "                : "",
1456
0
            path->argument_name ? path->argument_name : "path",
1457
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1458
0
                                               "integer or None" :
1459
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1460
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1461
0
                             "string, bytes or os.PathLike",
1462
0
            _PyType_Name(Py_TYPE(o)));
1463
0
        goto error_exit;
1464
0
    }
1465
1466
2.19k
    length = PyBytes_GET_SIZE(bytes);
1467
2.19k
    narrow = PyBytes_AS_STRING(bytes);
1468
2.19k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1469
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1470
0
        goto error_exit;
1471
0
    }
1472
1473
2.19k
    if (path->make_wide) {
1474
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1475
0
        if (!wo) {
1476
0
            goto error_exit;
1477
0
        }
1478
1479
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1480
0
        Py_DECREF(wo);
1481
0
        if (!wide) {
1482
0
            goto error_exit;
1483
0
        }
1484
#ifdef MS_WINDOWS
1485
        if (!path->nonstrict && length > 32767) {
1486
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1487
            goto error_exit;
1488
        }
1489
#endif
1490
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1491
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1492
0
                             "embedded null character in %s");
1493
0
            goto error_exit;
1494
0
        }
1495
0
        path->wide = wide;
1496
0
        path->narrow = NULL;
1497
0
        Py_DECREF(bytes);
1498
0
        wide = NULL;
1499
0
    }
1500
2.19k
    else {
1501
2.19k
        path->wide = NULL;
1502
2.19k
        path->narrow = narrow;
1503
2.19k
        if (bytes == o) {
1504
            /* Still a reference owned by path->object, don't have to
1505
            worry about path->narrow is used after free. */
1506
0
            Py_DECREF(bytes);
1507
0
        }
1508
2.19k
        else {
1509
2.19k
            path->cleanup = bytes;
1510
2.19k
        }
1511
2.19k
    }
1512
2.19k
    path->fd = -1;
1513
1514
2.30k
 success_exit:
1515
2.30k
    path->value_error = 0;
1516
2.30k
    path->length = length;
1517
2.30k
    path->object = o;
1518
2.30k
    return Py_CLEANUP_SUPPORTED;
1519
1520
0
 error_exit:
1521
0
    Py_XDECREF(o);
1522
0
    Py_XDECREF(bytes);
1523
0
    PyMem_Free(wide);
1524
0
    if (!path->suppress_value_error ||
1525
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1526
0
    {
1527
0
        return 0;
1528
0
    }
1529
0
    PyErr_Clear();
1530
0
    path->wide = NULL;
1531
0
    path->narrow = NULL;
1532
0
    path->fd = -1;
1533
0
    path->value_error = 1;
1534
0
    path->length = 0;
1535
0
    path->object = NULL;
1536
0
    return Py_CLEANUP_SUPPORTED;
1537
0
}
1538
1539
static void
1540
argument_unavailable_error(const char *function_name, const char *argument_name)
1541
0
{
1542
0
    PyErr_Format(PyExc_NotImplementedError,
1543
0
        "%s%s%s unavailable on this platform",
1544
0
        (function_name != NULL) ? function_name : "",
1545
0
        (function_name != NULL) ? ": ": "",
1546
0
        argument_name);
1547
0
}
1548
1549
static int
1550
dir_fd_unavailable(PyObject *o, void *p)
1551
22
{
1552
22
    int dir_fd;
1553
22
    if (!dir_fd_converter(o, &dir_fd))
1554
0
        return 0;
1555
22
    if (dir_fd != DEFAULT_DIR_FD) {
1556
0
        argument_unavailable_error(NULL, "dir_fd");
1557
0
        return 0;
1558
0
    }
1559
22
    *(int *)p = dir_fd;
1560
22
    return 1;
1561
22
}
1562
1563
static int
1564
fd_specified(const char *function_name, int fd)
1565
22
{
1566
22
    if (fd == -1)
1567
22
        return 0;
1568
1569
0
    argument_unavailable_error(function_name, "fd");
1570
0
    return 1;
1571
22
}
1572
1573
static int
1574
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1575
22
{
1576
22
    if (follow_symlinks)
1577
22
        return 0;
1578
1579
0
    argument_unavailable_error(function_name, "follow_symlinks");
1580
0
    return 1;
1581
22
}
1582
1583
static int
1584
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1585
2.07k
{
1586
2.07k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1587
0
        PyErr_Format(PyExc_ValueError,
1588
0
                     "%s: can't specify dir_fd without matching path",
1589
0
                     function_name);
1590
0
        return 1;
1591
0
    }
1592
2.07k
    return 0;
1593
2.07k
}
1594
1595
static int
1596
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1597
2.07k
{
1598
2.07k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1599
0
        PyErr_Format(PyExc_ValueError,
1600
0
                     "%s: can't specify both dir_fd and fd",
1601
0
                     function_name);
1602
0
        return 1;
1603
0
    }
1604
2.07k
    return 0;
1605
2.07k
}
1606
1607
static int
1608
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1609
                               int follow_symlinks)
1610
2.07k
{
1611
2.07k
    if ((fd > 0) && (!follow_symlinks)) {
1612
0
        PyErr_Format(PyExc_ValueError,
1613
0
                     "%s: cannot use fd and follow_symlinks together",
1614
0
                     function_name);
1615
0
        return 1;
1616
0
    }
1617
2.07k
    return 0;
1618
2.07k
}
1619
1620
static int
1621
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1622
                                   int follow_symlinks)
1623
22
{
1624
22
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1625
0
        PyErr_Format(PyExc_ValueError,
1626
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1627
0
                     function_name);
1628
0
        return 1;
1629
0
    }
1630
22
    return 0;
1631
22
}
1632
1633
#if defined(HAVE_WAITID)
1634
static int
1635
idtype_t_converter(PyObject *arg, void *addr)
1636
0
{
1637
0
    int value = PyLong_AsInt(arg);
1638
0
    if (value == -1 && PyErr_Occurred()) {
1639
0
        return 0;
1640
0
    }
1641
0
    *((idtype_t *)addr) = (idtype_t)(value);
1642
0
    return 1;
1643
0
}
1644
#endif
1645
1646
#ifdef MS_WINDOWS
1647
    typedef long long Py_off_t;
1648
#else
1649
    typedef off_t Py_off_t;
1650
#endif
1651
1652
static int
1653
Py_off_t_converter(PyObject *arg, void *addr)
1654
0
{
1655
#ifdef HAVE_LARGEFILE_SUPPORT
1656
    *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1657
#else
1658
0
    *((Py_off_t *)addr) = PyLong_AsLong(arg);
1659
0
#endif
1660
0
    if (PyErr_Occurred())
1661
0
        return 0;
1662
0
    return 1;
1663
0
}
1664
1665
static PyObject *
1666
PyLong_FromPy_off_t(Py_off_t offset)
1667
0
{
1668
#ifdef HAVE_LARGEFILE_SUPPORT
1669
    return PyLong_FromLongLong(offset);
1670
#else
1671
0
    return PyLong_FromLong(offset);
1672
0
#endif
1673
0
}
1674
1675
#ifdef HAVE_SIGSET_T
1676
/* Convert an iterable of integers to a sigset.
1677
   Return 1 on success, return 0 and raise an exception on error. */
1678
int
1679
_Py_Sigset_Converter(PyObject *obj, void *addr)
1680
0
{
1681
0
    sigset_t *mask = (sigset_t *)addr;
1682
0
    PyObject *iterator, *item;
1683
0
    long signum;
1684
0
    int overflow;
1685
1686
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1687
0
    if (sigemptyset(mask) < (0)) {
1688
        /* Probably only if mask == NULL. */
1689
0
        PyErr_SetFromErrno(PyExc_OSError);
1690
0
        return 0;
1691
0
    }
1692
1693
0
    iterator = PyObject_GetIter(obj);
1694
0
    if (iterator == NULL) {
1695
0
        return 0;
1696
0
    }
1697
1698
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1699
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1700
0
        Py_DECREF(item);
1701
0
        if (signum <= 0 || signum >= Py_NSIG) {
1702
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1703
0
                PyErr_Format(PyExc_ValueError,
1704
0
                             "signal number %ld out of range [1; %i]",
1705
0
                             signum, Py_NSIG - 1);
1706
0
            }
1707
0
            goto error;
1708
0
        }
1709
0
        if (sigaddset(mask, (int)signum)) {
1710
0
            if (errno != EINVAL) {
1711
                /* Probably impossible */
1712
0
                PyErr_SetFromErrno(PyExc_OSError);
1713
0
                goto error;
1714
0
            }
1715
            /* For backwards compatibility, allow idioms such as
1716
             * `range(1, NSIG)` but warn about invalid signal numbers
1717
             */
1718
0
            const char msg[] =
1719
0
                "invalid signal number %ld, please use valid_signals()";
1720
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1721
0
                goto error;
1722
0
            }
1723
0
        }
1724
0
    }
1725
0
    if (!PyErr_Occurred()) {
1726
0
        Py_DECREF(iterator);
1727
0
        return 1;
1728
0
    }
1729
1730
0
error:
1731
0
    Py_DECREF(iterator);
1732
0
    return 0;
1733
0
}
1734
#endif /* HAVE_SIGSET_T */
1735
1736
/* Return a dictionary corresponding to the POSIX environment table */
1737
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1738
/* On Darwin/MacOSX a shared library or framework has no access to
1739
** environ directly, we must obtain it with _NSGetEnviron(). See also
1740
** man environ(7).
1741
*/
1742
#include <crt_externs.h>
1743
#define USE_DARWIN_NS_GET_ENVIRON 1
1744
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1745
extern char **environ;
1746
#endif /* !_MSC_VER */
1747
1748
static PyObject *
1749
convertenviron(void)
1750
22
{
1751
22
    PyObject *d;
1752
#ifdef MS_WINDOWS
1753
    wchar_t **e;
1754
#else
1755
22
    char **e;
1756
22
#endif
1757
1758
22
    d = PyDict_New();
1759
22
    if (d == NULL)
1760
0
        return NULL;
1761
#ifdef MS_WINDOWS
1762
    /* _wenviron must be initialized in this way if the program is started
1763
       through main() instead of wmain(). */
1764
    (void)_wgetenv(L"");
1765
    e = _wenviron;
1766
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1767
    /* environ is not accessible as an extern in a shared object on OSX; use
1768
       _NSGetEnviron to resolve it. The value changes if you add environment
1769
       variables between calls to Py_Initialize, so don't cache the value. */
1770
    e = *_NSGetEnviron();
1771
#else
1772
22
    e = environ;
1773
22
#endif
1774
22
    if (e == NULL)
1775
0
        return d;
1776
814
    for (; *e != NULL; e++) {
1777
792
        PyObject *k;
1778
792
        PyObject *v;
1779
#ifdef MS_WINDOWS
1780
        const wchar_t *p = wcschr(*e, L'=');
1781
#else
1782
792
        const char *p = strchr(*e, '=');
1783
792
#endif
1784
792
        if (p == NULL)
1785
0
            continue;
1786
#ifdef MS_WINDOWS
1787
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1788
#else
1789
792
        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1790
792
#endif
1791
792
        if (k == NULL) {
1792
0
            Py_DECREF(d);
1793
0
            return NULL;
1794
0
        }
1795
#ifdef MS_WINDOWS
1796
        v = PyUnicode_FromWideChar(p+1, -1);
1797
#else
1798
792
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1799
792
#endif
1800
792
        if (v == NULL) {
1801
0
            Py_DECREF(k);
1802
0
            Py_DECREF(d);
1803
0
            return NULL;
1804
0
        }
1805
792
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1806
0
            Py_DECREF(v);
1807
0
            Py_DECREF(k);
1808
0
            Py_DECREF(d);
1809
0
            return NULL;
1810
0
        }
1811
792
        Py_DECREF(k);
1812
792
        Py_DECREF(v);
1813
792
    }
1814
22
    return d;
1815
22
}
1816
1817
/* Set a POSIX-specific error from errno, and return NULL */
1818
1819
static PyObject *
1820
posix_error(void)
1821
0
{
1822
0
    return PyErr_SetFromErrno(PyExc_OSError);
1823
0
}
1824
1825
#ifdef MS_WINDOWS
1826
static PyObject *
1827
win32_error(const char* function, const char* filename)
1828
{
1829
    /* XXX We should pass the function name along in the future.
1830
       (winreg.c also wants to pass the function name.)
1831
       This would however require an additional param to the
1832
       Windows error object, which is non-trivial.
1833
    */
1834
    errno = GetLastError();
1835
    if (filename)
1836
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1837
    else
1838
        return PyErr_SetFromWindowsErr(errno);
1839
}
1840
1841
static PyObject *
1842
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1843
{
1844
    /* XXX - see win32_error for comments on 'function' */
1845
    if (filename)
1846
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1847
                    PyExc_OSError,
1848
                    err,
1849
                    filename);
1850
    else
1851
        return PyErr_SetFromWindowsErr(err);
1852
}
1853
1854
static PyObject *
1855
win32_error_object(const char* function, PyObject* filename)
1856
{
1857
    errno = GetLastError();
1858
    return win32_error_object_err(function, filename, errno);
1859
}
1860
1861
#endif /* MS_WINDOWS */
1862
1863
static PyObject *
1864
posix_path_object_error(PyObject *path)
1865
227
{
1866
227
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1867
227
}
1868
1869
static PyObject *
1870
path_object_error(PyObject *path)
1871
227
{
1872
#ifdef MS_WINDOWS
1873
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1874
                PyExc_OSError, 0, path);
1875
#else
1876
227
    return posix_path_object_error(path);
1877
227
#endif
1878
227
}
1879
1880
static PyObject *
1881
path_object_error2(PyObject *path, PyObject *path2)
1882
0
{
1883
#ifdef MS_WINDOWS
1884
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1885
                PyExc_OSError, 0, path, path2);
1886
#else
1887
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1888
0
#endif
1889
0
}
1890
1891
static PyObject *
1892
path_error(path_t *path)
1893
227
{
1894
227
    return path_object_error(path->object);
1895
227
}
1896
1897
static PyObject *
1898
posix_path_error(path_t *path)
1899
0
{
1900
0
    return posix_path_object_error(path->object);
1901
0
}
1902
1903
static PyObject *
1904
path_error2(path_t *path, path_t *path2)
1905
0
{
1906
0
    return path_object_error2(path->object, path2->object);
1907
0
}
1908
1909
1910
/* POSIX generic methods */
1911
1912
static PyObject *
1913
posix_fildes_fd(int fd, int (*func)(int))
1914
0
{
1915
0
    int res;
1916
0
    int async_err = 0;
1917
1918
0
    do {
1919
0
        Py_BEGIN_ALLOW_THREADS
1920
0
        _Py_BEGIN_SUPPRESS_IPH
1921
0
        res = (*func)(fd);
1922
0
        _Py_END_SUPPRESS_IPH
1923
0
        Py_END_ALLOW_THREADS
1924
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1925
0
    if (res != 0)
1926
0
        return (!async_err) ? posix_error() : NULL;
1927
0
    Py_RETURN_NONE;
1928
0
}
1929
1930
1931
#ifdef MS_WINDOWS
1932
/* This is a reimplementation of the C library's chdir function,
1933
   but one that produces Win32 errors instead of DOS error codes.
1934
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1935
   it also needs to set "magic" environment variables indicating
1936
   the per-drive current directory, which are of the form =<drive>: */
1937
static BOOL __stdcall
1938
win32_wchdir(LPCWSTR path)
1939
{
1940
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1941
    int result;
1942
    wchar_t env[4] = L"=x:";
1943
1944
    if(!SetCurrentDirectoryW(path))
1945
        return FALSE;
1946
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1947
    if (!result)
1948
        return FALSE;
1949
    if (result > Py_ARRAY_LENGTH(path_buf)) {
1950
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1951
        if (!new_path) {
1952
            SetLastError(ERROR_OUTOFMEMORY);
1953
            return FALSE;
1954
        }
1955
        result = GetCurrentDirectoryW(result, new_path);
1956
        if (!result) {
1957
            PyMem_RawFree(new_path);
1958
            return FALSE;
1959
        }
1960
    }
1961
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1962
                            wcsncmp(new_path, L"//", 2) == 0);
1963
    if (!is_unc_like_path) {
1964
        env[1] = new_path[0];
1965
        result = SetEnvironmentVariableW(env, new_path);
1966
    }
1967
    if (new_path != path_buf)
1968
        PyMem_RawFree(new_path);
1969
    return result ? TRUE : FALSE;
1970
}
1971
#endif
1972
1973
#ifdef MS_WINDOWS
1974
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1975
   - time stamps are restricted to second resolution
1976
   - file modification times suffer from forth-and-back conversions between
1977
     UTC and local time
1978
   Therefore, we implement our own stat, based on the Win32 API directly.
1979
*/
1980
#define HAVE_STAT_NSEC 1
1981
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1982
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1983
1984
static void
1985
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1986
                       BY_HANDLE_FILE_INFORMATION *info,
1987
                       ULONG *reparse_tag)
1988
{
1989
    memset(info, 0, sizeof(*info));
1990
    info->dwFileAttributes = pFileData->dwFileAttributes;
1991
    info->ftCreationTime   = pFileData->ftCreationTime;
1992
    info->ftLastAccessTime = pFileData->ftLastAccessTime;
1993
    info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1994
    info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1995
    info->nFileSizeLow     = pFileData->nFileSizeLow;
1996
/*  info->nNumberOfLinks   = 1; */
1997
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1998
        *reparse_tag = pFileData->dwReserved0;
1999
    else
2000
        *reparse_tag = 0;
2001
}
2002
2003
static BOOL
2004
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
2005
{
2006
    HANDLE hFindFile;
2007
    WIN32_FIND_DATAW FileData;
2008
    LPCWSTR filename = pszFile;
2009
    size_t n = wcslen(pszFile);
2010
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2011
        // cannot use PyMem_Malloc here because we do not hold the GIL
2012
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2013
        if(!filename) {
2014
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2015
            return FALSE;
2016
        }
2017
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2018
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2019
            ((LPWSTR)filename)[n] = L'\0';
2020
        }
2021
        if (!n || (n == 1 && filename[1] == L':')) {
2022
            // Nothing left to query
2023
            free((void *)filename);
2024
            return FALSE;
2025
        }
2026
    }
2027
    hFindFile = FindFirstFileW(filename, &FileData);
2028
    if (pszFile != filename) {
2029
        free((void *)filename);
2030
    }
2031
    if (hFindFile == INVALID_HANDLE_VALUE) {
2032
        return FALSE;
2033
    }
2034
    FindClose(hFindFile);
2035
    find_data_to_file_info(&FileData, info, reparse_tag);
2036
    return TRUE;
2037
}
2038
2039
2040
static void
2041
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2042
                         struct _Py_stat_struct *result)
2043
{
2044
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2045
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2046
           the filename has an extension that is commonly used by files
2047
           that CreateProcessW can execute. A real implementation calls
2048
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2049
           AccessCheck to check for generic read, write, and execute
2050
           access. */
2051
        const wchar_t *fileExtension = wcsrchr(path, '.');
2052
        if (fileExtension) {
2053
            if (_wcsicmp(fileExtension, L".exe") == 0 ||
2054
                _wcsicmp(fileExtension, L".bat") == 0 ||
2055
                _wcsicmp(fileExtension, L".cmd") == 0 ||
2056
                _wcsicmp(fileExtension, L".com") == 0) {
2057
                result->st_mode |= 0111;
2058
            }
2059
        }
2060
    }
2061
}
2062
2063
2064
static int
2065
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2066
                      BOOL traverse)
2067
{
2068
    HANDLE hFile;
2069
    BY_HANDLE_FILE_INFORMATION fileInfo;
2070
    FILE_BASIC_INFO basicInfo;
2071
    FILE_BASIC_INFO *pBasicInfo = NULL;
2072
    FILE_ID_INFO idInfo;
2073
    FILE_ID_INFO *pIdInfo = NULL;
2074
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2075
    DWORD fileType, error;
2076
    BOOL isUnhandledTag = FALSE;
2077
    int retval = 0;
2078
2079
    DWORD access = FILE_READ_ATTRIBUTES;
2080
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2081
    if (!traverse) {
2082
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2083
    }
2084
2085
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2086
    if (hFile == INVALID_HANDLE_VALUE) {
2087
        /* Either the path doesn't exist, or the caller lacks access. */
2088
        error = GetLastError();
2089
        switch (error) {
2090
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2091
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2092
            /* Try reading the parent directory. */
2093
            if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2094
                /* Cannot read the parent directory. */
2095
                switch (GetLastError()) {
2096
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2097
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2098
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2099
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2100
                    break;
2101
                /* Restore the error from CreateFileW(). */
2102
                default:
2103
                    SetLastError(error);
2104
                }
2105
2106
                return -1;
2107
            }
2108
            if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2109
                if (traverse ||
2110
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2111
                    /* The stat call has to traverse but cannot, so fail. */
2112
                    SetLastError(error);
2113
                    return -1;
2114
                }
2115
            }
2116
            break;
2117
2118
        case ERROR_INVALID_PARAMETER:
2119
            /* \\.\con requires read or write access. */
2120
            hFile = CreateFileW(path, access | GENERIC_READ,
2121
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2122
                        OPEN_EXISTING, flags, NULL);
2123
            if (hFile == INVALID_HANDLE_VALUE) {
2124
                SetLastError(error);
2125
                return -1;
2126
            }
2127
            break;
2128
2129
        case ERROR_CANT_ACCESS_FILE:
2130
            /* bpo37834: open unhandled reparse points if traverse fails. */
2131
            if (traverse) {
2132
                traverse = FALSE;
2133
                isUnhandledTag = TRUE;
2134
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2135
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2136
            }
2137
            if (hFile == INVALID_HANDLE_VALUE) {
2138
                SetLastError(error);
2139
                return -1;
2140
            }
2141
            break;
2142
2143
        default:
2144
            return -1;
2145
        }
2146
    }
2147
2148
    if (hFile != INVALID_HANDLE_VALUE) {
2149
        /* Handle types other than files on disk. */
2150
        fileType = GetFileType(hFile);
2151
        if (fileType != FILE_TYPE_DISK) {
2152
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2153
                retval = -1;
2154
                goto cleanup;
2155
            }
2156
            DWORD fileAttributes = GetFileAttributesW(path);
2157
            memset(result, 0, sizeof(*result));
2158
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2159
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2160
                /* \\.\pipe\ or \\.\mailslot\ */
2161
                result->st_mode = _S_IFDIR;
2162
            } else if (fileType == FILE_TYPE_CHAR) {
2163
                /* \\.\nul */
2164
                result->st_mode = _S_IFCHR;
2165
            } else if (fileType == FILE_TYPE_PIPE) {
2166
                /* \\.\pipe\spam */
2167
                result->st_mode = _S_IFIFO;
2168
            }
2169
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2170
            goto cleanup;
2171
        }
2172
2173
        /* Query the reparse tag, and traverse a non-link. */
2174
        if (!traverse) {
2175
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2176
                    &tagInfo, sizeof(tagInfo))) {
2177
                /* Allow devices that do not support FileAttributeTagInfo. */
2178
                switch (GetLastError()) {
2179
                case ERROR_INVALID_PARAMETER:
2180
                case ERROR_INVALID_FUNCTION:
2181
                case ERROR_NOT_SUPPORTED:
2182
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2183
                    tagInfo.ReparseTag = 0;
2184
                    break;
2185
                default:
2186
                    retval = -1;
2187
                    goto cleanup;
2188
                }
2189
            } else if (tagInfo.FileAttributes &
2190
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2191
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2192
                    if (isUnhandledTag) {
2193
                        /* Traversing previously failed for either this link
2194
                           or its target. */
2195
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2196
                        retval = -1;
2197
                        goto cleanup;
2198
                    }
2199
                /* Traverse a non-link, but not if traversing already failed
2200
                   for an unhandled tag. */
2201
                } else if (!isUnhandledTag) {
2202
                    CloseHandle(hFile);
2203
                    return win32_xstat_slow_impl(path, result, TRUE);
2204
                }
2205
            }
2206
        }
2207
2208
        if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2209
            !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2210
                                          &basicInfo, sizeof(basicInfo))) {
2211
            switch (GetLastError()) {
2212
            case ERROR_INVALID_PARAMETER:
2213
            case ERROR_INVALID_FUNCTION:
2214
            case ERROR_NOT_SUPPORTED:
2215
                /* Volumes and physical disks are block devices, e.g.
2216
                   \\.\C: and \\.\PhysicalDrive0. */
2217
                memset(result, 0, sizeof(*result));
2218
                result->st_mode = 0x6000; /* S_IFBLK */
2219
                goto cleanup;
2220
            }
2221
            retval = -1;
2222
            goto cleanup;
2223
        }
2224
2225
        /* Successfully got FileBasicInfo, so we'll pass it along */
2226
        pBasicInfo = &basicInfo;
2227
2228
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2229
            /* Successfully got FileIdInfo, so pass it along */
2230
            pIdInfo = &idInfo;
2231
        }
2232
    }
2233
2234
    _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2235
    update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2236
2237
cleanup:
2238
    if (hFile != INVALID_HANDLE_VALUE) {
2239
        /* Preserve last error if we are failing */
2240
        error = retval ? GetLastError() : 0;
2241
        if (!CloseHandle(hFile)) {
2242
            retval = -1;
2243
        } else if (retval) {
2244
            /* Restore last error */
2245
            SetLastError(error);
2246
        }
2247
    }
2248
2249
    return retval;
2250
}
2251
2252
static int
2253
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2254
                 BOOL traverse)
2255
{
2256
    FILE_STAT_BASIC_INFORMATION statInfo;
2257
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2258
                                     &statInfo, sizeof(statInfo))) {
2259
        if (// Cannot use fast path for reparse points ...
2260
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2261
            // ... unless it's a name surrogate (symlink) and we're not following
2262
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2263
        ) {
2264
            _Py_stat_basic_info_to_stat(&statInfo, result);
2265
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2266
            return 0;
2267
        }
2268
    } else {
2269
        switch(GetLastError()) {
2270
        case ERROR_FILE_NOT_FOUND:
2271
        case ERROR_PATH_NOT_FOUND:
2272
        case ERROR_NOT_READY:
2273
        case ERROR_BAD_NET_NAME:
2274
            /* These errors aren't worth retrying with the slow path */
2275
            return -1;
2276
        case ERROR_NOT_SUPPORTED:
2277
            /* indicates the API couldn't be loaded */
2278
            break;
2279
        }
2280
    }
2281
2282
    return win32_xstat_slow_impl(path, result, traverse);
2283
}
2284
2285
static int
2286
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2287
{
2288
    /* Protocol violation: we explicitly clear errno, instead of
2289
       setting it to a POSIX error. Callers should use GetLastError. */
2290
    int code = win32_xstat_impl(path, result, traverse);
2291
    errno = 0;
2292
2293
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2294
    result->st_ctime = result->st_birthtime;
2295
    result->st_ctime_nsec = result->st_birthtime_nsec;
2296
    return code;
2297
}
2298
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2299
2300
   In Posix, stat automatically traverses symlinks and returns the stat
2301
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2302
   default does not traverse symlinks and instead returns attributes for
2303
   the symlink.
2304
2305
   Instead, we will open the file (which *does* traverse symlinks by default)
2306
   and GetFileInformationByHandle(). */
2307
2308
static int
2309
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2310
{
2311
    return win32_xstat(path, result, FALSE);
2312
}
2313
2314
static int
2315
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2316
{
2317
    return win32_xstat(path, result, TRUE);
2318
}
2319
2320
#endif /* MS_WINDOWS */
2321
2322
PyDoc_STRVAR(stat_result__doc__,
2323
"stat_result: Result from stat, fstat, or lstat.\n\n\
2324
This object may be accessed either as a tuple of\n\
2325
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2326
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2327
\n\
2328
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2329
or st_flags, they are available as attributes only.\n\
2330
\n\
2331
See os.stat for more information.");
2332
2333
static PyStructSequence_Field stat_result_fields[] = {
2334
    {"st_mode",    "protection bits"},
2335
    {"st_ino",     "inode"},
2336
    {"st_dev",     "device"},
2337
    {"st_nlink",   "number of hard links"},
2338
    {"st_uid",     "user ID of owner"},
2339
    {"st_gid",     "group ID of owner"},
2340
    {"st_size",    "total size, in bytes"},
2341
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2342
    {NULL,   "integer time of last access"},
2343
    {NULL,   "integer time of last modification"},
2344
    {NULL,   "integer time of last change"},
2345
    {"st_atime",   "time of last access"},
2346
    {"st_mtime",   "time of last modification"},
2347
    {"st_ctime",   "time of last change"},
2348
    {"st_atime_ns",   "time of last access in nanoseconds"},
2349
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2350
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2351
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2352
    {"st_blksize", "blocksize for filesystem I/O"},
2353
#endif
2354
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2355
    {"st_blocks",  "number of blocks allocated"},
2356
#endif
2357
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2358
    {"st_rdev",    "device type (if inode device)"},
2359
#endif
2360
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2361
    {"st_flags",   "user defined flags for file"},
2362
#endif
2363
#ifdef HAVE_STRUCT_STAT_ST_GEN
2364
    {"st_gen",    "generation number"},
2365
#endif
2366
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2367
    {"st_birthtime",   "time of creation"},
2368
#endif
2369
#ifdef MS_WINDOWS
2370
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2371
#endif
2372
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2373
    {"st_file_attributes", "Windows file attribute bits"},
2374
#endif
2375
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2376
    {"st_fstype",  "Type of filesystem"},
2377
#endif
2378
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2379
    {"st_reparse_tag", "Windows reparse tag"},
2380
#endif
2381
    {0}
2382
};
2383
2384
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2385
#define ST_BLKSIZE_IDX 16
2386
#else
2387
#define ST_BLKSIZE_IDX 15
2388
#endif
2389
2390
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2391
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2392
#else
2393
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2394
#endif
2395
2396
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2397
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2398
#else
2399
#define ST_RDEV_IDX ST_BLOCKS_IDX
2400
#endif
2401
2402
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2403
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2404
#else
2405
#define ST_FLAGS_IDX ST_RDEV_IDX
2406
#endif
2407
2408
#ifdef HAVE_STRUCT_STAT_ST_GEN
2409
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2410
#else
2411
#define ST_GEN_IDX ST_FLAGS_IDX
2412
#endif
2413
2414
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2415
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2416
#else
2417
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2418
#endif
2419
2420
#ifdef MS_WINDOWS
2421
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2422
#else
2423
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2424
#endif
2425
2426
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2427
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2428
#else
2429
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2430
#endif
2431
2432
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2433
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2434
#else
2435
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2436
#endif
2437
2438
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2439
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2440
#else
2441
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2442
#endif
2443
2444
static PyStructSequence_Desc stat_result_desc = {
2445
    "stat_result", /* name */
2446
    stat_result__doc__, /* doc */
2447
    stat_result_fields,
2448
    10
2449
};
2450
2451
PyDoc_STRVAR(statvfs_result__doc__,
2452
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2453
This object may be accessed either as a tuple of\n\
2454
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2455
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2456
\n\
2457
See os.statvfs for more information.");
2458
2459
static PyStructSequence_Field statvfs_result_fields[] = {
2460
    {"f_bsize",  },
2461
    {"f_frsize", },
2462
    {"f_blocks", },
2463
    {"f_bfree",  },
2464
    {"f_bavail", },
2465
    {"f_files",  },
2466
    {"f_ffree",  },
2467
    {"f_favail", },
2468
    {"f_flag",   },
2469
    {"f_namemax",},
2470
    {"f_fsid",   },
2471
    {0}
2472
};
2473
2474
static PyStructSequence_Desc statvfs_result_desc = {
2475
    "statvfs_result", /* name */
2476
    statvfs_result__doc__, /* doc */
2477
    statvfs_result_fields,
2478
    10
2479
};
2480
2481
#if defined(HAVE_WAITID)
2482
PyDoc_STRVAR(waitid_result__doc__,
2483
"waitid_result: Result from waitid.\n\n\
2484
This object may be accessed either as a tuple of\n\
2485
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2486
or via the attributes si_pid, si_uid, and so on.\n\
2487
\n\
2488
See os.waitid for more information.");
2489
2490
static PyStructSequence_Field waitid_result_fields[] = {
2491
    {"si_pid",  },
2492
    {"si_uid", },
2493
    {"si_signo", },
2494
    {"si_status",  },
2495
    {"si_code", },
2496
    {0}
2497
};
2498
2499
static PyStructSequence_Desc waitid_result_desc = {
2500
    "waitid_result", /* name */
2501
    waitid_result__doc__, /* doc */
2502
    waitid_result_fields,
2503
    5
2504
};
2505
#endif
2506
2507
static PyObject *
2508
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2509
0
{
2510
0
    PyStructSequence *result;
2511
0
    int i;
2512
2513
    // ht_module doesn't get set in PyStructSequence_NewType(),
2514
    // so we can't use PyType_GetModule().
2515
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2516
0
    if (mod == NULL) {
2517
0
        return NULL;
2518
0
    }
2519
0
    _posixstate *state = get_posix_state(mod);
2520
0
    Py_DECREF(mod);
2521
0
    if (state == NULL) {
2522
0
        return NULL;
2523
0
    }
2524
0
#define structseq_new state->statresult_new_orig
2525
2526
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2527
0
    if (!result)
2528
0
        return NULL;
2529
    /* If we have been initialized from a tuple,
2530
       st_?time might be set to None. Initialize it
2531
       from the int slots.  */
2532
0
    for (i = 7; i <= 9; i++) {
2533
0
        if (result->ob_item[i+3] == Py_None) {
2534
0
            Py_DECREF(Py_None);
2535
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2536
0
        }
2537
0
    }
2538
0
    return (PyObject*)result;
2539
0
}
2540
2541
static int
2542
_posix_clear(PyObject *module)
2543
0
{
2544
0
    _posixstate *state = get_posix_state(module);
2545
0
    Py_CLEAR(state->billion);
2546
0
    Py_CLEAR(state->DirEntryType);
2547
0
    Py_CLEAR(state->ScandirIteratorType);
2548
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2549
0
    Py_CLEAR(state->SchedParamType);
2550
0
#endif
2551
0
    Py_CLEAR(state->StatResultType);
2552
0
    Py_CLEAR(state->StatVFSResultType);
2553
0
    Py_CLEAR(state->TerminalSizeType);
2554
0
    Py_CLEAR(state->TimesResultType);
2555
0
    Py_CLEAR(state->UnameResultType);
2556
0
#if defined(HAVE_WAITID)
2557
0
    Py_CLEAR(state->WaitidResultType);
2558
0
#endif
2559
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2560
0
    Py_CLEAR(state->struct_rusage);
2561
0
#endif
2562
0
    Py_CLEAR(state->st_mode);
2563
0
    return 0;
2564
0
}
2565
2566
static int
2567
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2568
5.83k
{
2569
5.83k
    _posixstate *state = get_posix_state(module);
2570
5.83k
    Py_VISIT(state->billion);
2571
5.83k
    Py_VISIT(state->DirEntryType);
2572
5.83k
    Py_VISIT(state->ScandirIteratorType);
2573
5.83k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2574
5.83k
    Py_VISIT(state->SchedParamType);
2575
5.83k
#endif
2576
5.83k
    Py_VISIT(state->StatResultType);
2577
5.83k
    Py_VISIT(state->StatVFSResultType);
2578
5.83k
    Py_VISIT(state->TerminalSizeType);
2579
5.83k
    Py_VISIT(state->TimesResultType);
2580
5.83k
    Py_VISIT(state->UnameResultType);
2581
5.83k
#if defined(HAVE_WAITID)
2582
5.83k
    Py_VISIT(state->WaitidResultType);
2583
5.83k
#endif
2584
5.83k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2585
5.83k
    Py_VISIT(state->struct_rusage);
2586
5.83k
#endif
2587
5.83k
    Py_VISIT(state->st_mode);
2588
5.83k
    return 0;
2589
5.83k
}
2590
2591
static void
2592
_posix_free(void *module)
2593
0
{
2594
0
   _posix_clear((PyObject *)module);
2595
0
}
2596
2597
static int
2598
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2599
          int ns_index, time_t sec, unsigned long nsec)
2600
5.54k
{
2601
5.54k
    assert(!PyErr_Occurred());
2602
16.6k
#define SEC_TO_NS (1000000000LL)
2603
5.54k
    assert(nsec < SEC_TO_NS);
2604
2605
5.54k
    if (s_index >= 0) {
2606
5.54k
        PyObject *s = _PyLong_FromTime_t(sec);
2607
5.54k
        if (s == NULL) {
2608
0
            return -1;
2609
0
        }
2610
5.54k
        PyStructSequence_SET_ITEM(v, s_index, s);
2611
5.54k
    }
2612
2613
5.54k
    if (f_index >= 0) {
2614
5.54k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2615
5.54k
        if (float_s == NULL) {
2616
0
            return -1;
2617
0
        }
2618
5.54k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2619
5.54k
    }
2620
2621
5.54k
    int res = -1;
2622
5.54k
    if (ns_index >= 0) {
2623
        /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2624
5.54k
        if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2625
5.54k
            PyObject *ns_total = PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2626
5.54k
            if (ns_total == NULL) {
2627
0
                return -1;
2628
0
            }
2629
5.54k
            PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2630
5.54k
            assert(!PyErr_Occurred());
2631
5.54k
            res = 0;
2632
5.54k
        }
2633
0
        else {
2634
0
            PyObject *s_in_ns = NULL;
2635
0
            PyObject *ns_total = NULL;
2636
0
            PyObject *s = _PyLong_FromTime_t(sec);
2637
0
            PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2638
0
            if (s == NULL || ns_fractional == NULL) {
2639
0
                goto exit;
2640
0
            }
2641
2642
0
            s_in_ns = PyNumber_Multiply(s, state->billion);
2643
0
            if (s_in_ns == NULL) {
2644
0
                goto exit;
2645
0
            }
2646
2647
0
            ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2648
0
            if (ns_total == NULL) {
2649
0
                goto exit;
2650
0
            }
2651
0
            PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2652
0
            assert(!PyErr_Occurred());
2653
0
            res = 0;
2654
2655
0
        exit:
2656
0
            Py_XDECREF(s);
2657
0
            Py_XDECREF(ns_fractional);
2658
0
            Py_XDECREF(s_in_ns);
2659
0
        }
2660
5.54k
    }
2661
2662
5.54k
    return res;
2663
5.54k
    #undef SEC_TO_NS
2664
5.54k
}
2665
2666
#ifdef MS_WINDOWS
2667
static PyObject*
2668
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2669
{
2670
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2671
    if (!o_low || !high) {
2672
        return o_low;
2673
    }
2674
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2675
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2676
    if (!l64) {
2677
        Py_XDECREF(o_high);
2678
        Py_DECREF(o_low);
2679
        return NULL;
2680
    }
2681
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2682
    Py_DECREF(l64);
2683
    if (!o_high) {
2684
        Py_DECREF(o_low);
2685
        return NULL;
2686
    }
2687
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2688
    Py_DECREF(o_high);
2689
    return o_low;
2690
}
2691
#endif
2692
2693
/* pack a system stat C structure into the Python stat tuple
2694
   (used by posix_stat() and posix_fstat()) */
2695
static PyObject*
2696
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2697
1.84k
{
2698
1.84k
    assert(!PyErr_Occurred());
2699
2700
1.84k
    _posixstate *state = get_posix_state(module);
2701
1.84k
    PyObject *StatResultType = state->StatResultType;
2702
1.84k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2703
1.84k
    if (v == NULL) {
2704
0
        return NULL;
2705
0
    }
2706
2707
1.84k
#define SET_ITEM(pos, expr) \
2708
18.4k
    do { \
2709
18.4k
        PyObject *obj = (expr); \
2710
18.4k
        if (obj == NULL) { \
2711
0
            goto error; \
2712
0
        } \
2713
18.4k
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2714
18.4k
    } while (0)
2715
2716
1.84k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2717
#ifdef MS_WINDOWS
2718
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2719
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2720
#else
2721
1.84k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2722
1.84k
                  "stat.st_ino is larger than unsigned long long");
2723
1.84k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2724
1.84k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2725
1.84k
#endif
2726
1.84k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2727
#if defined(MS_WINDOWS)
2728
    SET_ITEM(4, PyLong_FromLong(0));
2729
    SET_ITEM(5, PyLong_FromLong(0));
2730
#else
2731
1.84k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2732
1.84k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2733
1.84k
#endif
2734
1.84k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2735
1.84k
                  "stat.st_size is larger than long long");
2736
1.84k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2737
2738
    // Set st_atime, st_mtime and st_ctime
2739
1.84k
    unsigned long ansec, mnsec, cnsec;
2740
1.84k
#if defined(HAVE_STAT_TV_NSEC)
2741
1.84k
    ansec = st->st_atim.tv_nsec;
2742
1.84k
    mnsec = st->st_mtim.tv_nsec;
2743
1.84k
    cnsec = st->st_ctim.tv_nsec;
2744
#elif defined(HAVE_STAT_TV_NSEC2)
2745
    ansec = st->st_atimespec.tv_nsec;
2746
    mnsec = st->st_mtimespec.tv_nsec;
2747
    cnsec = st->st_ctimespec.tv_nsec;
2748
#elif defined(HAVE_STAT_NSEC)
2749
    ansec = st->st_atime_nsec;
2750
    mnsec = st->st_mtime_nsec;
2751
    cnsec = st->st_ctime_nsec;
2752
#else
2753
    ansec = mnsec = cnsec = 0;
2754
#endif
2755
1.84k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2756
0
        goto error;
2757
0
    }
2758
1.84k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2759
0
        goto error;
2760
0
    }
2761
1.84k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2762
0
        goto error;
2763
0
    }
2764
2765
1.84k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2766
1.84k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2767
1.84k
#endif
2768
1.84k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2769
1.84k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2770
1.84k
#endif
2771
1.84k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2772
1.84k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2773
1.84k
#endif
2774
#ifdef HAVE_STRUCT_STAT_ST_GEN
2775
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2776
#endif
2777
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2778
    {
2779
      unsigned long bsec, bnsec;
2780
      bsec = (long)st->st_birthtime;
2781
#ifdef HAVE_STAT_TV_NSEC2
2782
      bnsec = st->st_birthtimespec.tv_nsec;
2783
#else
2784
      bnsec = 0;
2785
#endif
2786
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2787
    }
2788
#elif defined(MS_WINDOWS)
2789
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2790
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2791
        goto error;
2792
    }
2793
#endif
2794
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2795
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2796
#endif
2797
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2798
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2799
             PyLong_FromUnsignedLong(st->st_file_attributes));
2800
#endif
2801
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2802
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2803
#endif
2804
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2805
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2806
#endif
2807
2808
1.84k
    assert(!PyErr_Occurred());
2809
1.84k
    return v;
2810
2811
0
error:
2812
0
    Py_DECREF(v);
2813
0
    return NULL;
2814
2815
1.84k
#undef SET_ITEM
2816
1.84k
}
2817
2818
/* POSIX methods */
2819
2820
2821
static PyObject *
2822
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2823
              int dir_fd, int follow_symlinks)
2824
2.07k
{
2825
2.07k
    STRUCT_STAT st;
2826
2.07k
    int result;
2827
2828
2.07k
#ifdef HAVE_FSTATAT
2829
2.07k
    int fstatat_unavailable = 0;
2830
2.07k
#endif
2831
2832
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2833
    if (follow_symlinks_specified(function_name, follow_symlinks))
2834
        return NULL;
2835
#endif
2836
2837
2.07k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2838
2.07k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2839
2.07k
        fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2840
0
        return NULL;
2841
2842
2.07k
    Py_BEGIN_ALLOW_THREADS
2843
2.07k
    if (path->fd != -1)
2844
0
        result = FSTAT(path->fd, &st);
2845
#ifdef MS_WINDOWS
2846
    else if (follow_symlinks)
2847
        result = win32_stat(path->wide, &st);
2848
    else
2849
        result = win32_lstat(path->wide, &st);
2850
#else
2851
2.07k
    else
2852
2.07k
#if defined(HAVE_LSTAT)
2853
2.07k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2854
0
        result = LSTAT(path->narrow, &st);
2855
2.07k
    else
2856
2.07k
#endif /* HAVE_LSTAT */
2857
2.07k
#ifdef HAVE_FSTATAT
2858
2.07k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2859
0
        if (HAVE_FSTATAT_RUNTIME) {
2860
0
            result = fstatat(dir_fd, path->narrow, &st,
2861
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2862
2863
0
        } else {
2864
0
            fstatat_unavailable = 1;
2865
0
        }
2866
0
    } else
2867
2.07k
#endif /* HAVE_FSTATAT */
2868
2.07k
        result = STAT(path->narrow, &st);
2869
2.07k
#endif /* MS_WINDOWS */
2870
2.07k
    Py_END_ALLOW_THREADS
2871
2872
2.07k
#ifdef HAVE_FSTATAT
2873
2.07k
    if (fstatat_unavailable) {
2874
0
        argument_unavailable_error("stat", "dir_fd");
2875
0
        return NULL;
2876
0
    }
2877
2.07k
#endif
2878
2879
2.07k
    if (result != 0) {
2880
227
        return path_error(path);
2881
227
    }
2882
2883
1.84k
    return _pystat_fromstructstat(module, &st);
2884
2.07k
}
2885
2886
/*[python input]
2887
2888
for s in """
2889
2890
FACCESSAT
2891
FCHMODAT
2892
FCHOWNAT
2893
FSTATAT
2894
LINKAT
2895
MKDIRAT
2896
MKFIFOAT
2897
MKNODAT
2898
OPENAT
2899
READLINKAT
2900
SYMLINKAT
2901
UNLINKAT
2902
2903
""".strip().split():
2904
    s = s.strip()
2905
    print("""
2906
#ifdef HAVE_{s}
2907
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2908
#else
2909
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2910
#endif
2911
""".rstrip().format(s=s))
2912
2913
for s in """
2914
2915
FCHDIR
2916
FCHMOD
2917
FCHOWN
2918
FDOPENDIR
2919
FEXECVE
2920
FPATHCONF
2921
FSTATVFS
2922
FTRUNCATE
2923
2924
""".strip().split():
2925
    s = s.strip()
2926
    print("""
2927
#ifdef HAVE_{s}
2928
    #define PATH_HAVE_{s} 1
2929
#else
2930
    #define PATH_HAVE_{s} 0
2931
#endif
2932
2933
""".rstrip().format(s=s))
2934
[python start generated code]*/
2935
2936
#ifdef HAVE_FACCESSAT
2937
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2938
#else
2939
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2940
#endif
2941
2942
#ifdef HAVE_FCHMODAT
2943
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2944
#else
2945
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2946
#endif
2947
2948
#ifdef HAVE_FCHOWNAT
2949
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2950
#else
2951
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2952
#endif
2953
2954
#ifdef HAVE_FSTATAT
2955
0
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2956
#else
2957
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2958
#endif
2959
2960
#ifdef HAVE_LINKAT
2961
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2962
#else
2963
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2964
#endif
2965
2966
#ifdef HAVE_MKDIRAT
2967
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2968
#else
2969
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2970
#endif
2971
2972
#ifdef HAVE_MKFIFOAT
2973
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2974
#else
2975
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2976
#endif
2977
2978
#ifdef HAVE_MKNODAT
2979
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2980
#else
2981
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2982
#endif
2983
2984
#ifdef HAVE_OPENAT
2985
0
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2986
#else
2987
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2988
#endif
2989
2990
#ifdef HAVE_READLINKAT
2991
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2992
#else
2993
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2994
#endif
2995
2996
#ifdef HAVE_SYMLINKAT
2997
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2998
#else
2999
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3000
#endif
3001
3002
#ifdef HAVE_UNLINKAT
3003
0
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3004
#else
3005
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3006
#endif
3007
3008
#ifdef HAVE_FCHDIR
3009
    #define PATH_HAVE_FCHDIR 1
3010
#else
3011
    #define PATH_HAVE_FCHDIR 0
3012
#endif
3013
3014
#ifdef HAVE_FCHMOD
3015
    #define PATH_HAVE_FCHMOD 1
3016
#else
3017
    #define PATH_HAVE_FCHMOD 0
3018
#endif
3019
3020
#ifdef HAVE_FCHOWN
3021
    #define PATH_HAVE_FCHOWN 1
3022
#else
3023
    #define PATH_HAVE_FCHOWN 0
3024
#endif
3025
3026
#ifdef HAVE_FDOPENDIR
3027
    #define PATH_HAVE_FDOPENDIR 1
3028
#else
3029
    #define PATH_HAVE_FDOPENDIR 0
3030
#endif
3031
3032
#ifdef HAVE_FEXECVE
3033
    #define PATH_HAVE_FEXECVE 1
3034
#else
3035
    #define PATH_HAVE_FEXECVE 0
3036
#endif
3037
3038
#ifdef HAVE_FPATHCONF
3039
    #define PATH_HAVE_FPATHCONF 1
3040
#else
3041
    #define PATH_HAVE_FPATHCONF 0
3042
#endif
3043
3044
#ifdef HAVE_FSTATVFS
3045
    #define PATH_HAVE_FSTATVFS 1
3046
#else
3047
    #define PATH_HAVE_FSTATVFS 0
3048
#endif
3049
3050
#ifdef HAVE_FTRUNCATE
3051
    #define PATH_HAVE_FTRUNCATE 1
3052
#else
3053
    #define PATH_HAVE_FTRUNCATE 0
3054
#endif
3055
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3056
3057
#ifdef MS_WINDOWS
3058
    #undef PATH_HAVE_FTRUNCATE
3059
    #define PATH_HAVE_FTRUNCATE 1
3060
    #undef PATH_HAVE_FCHMOD
3061
    #define PATH_HAVE_FCHMOD 1
3062
#endif
3063
3064
/*[python input]
3065
3066
class path_t_converter(CConverter):
3067
3068
    type = "path_t"
3069
    impl_by_reference = True
3070
    parse_by_reference = True
3071
3072
    converter = 'path_converter'
3073
3074
    def converter_init(self, *, allow_fd=False, make_wide=None,
3075
                       nonstrict=False, nullable=False,
3076
                       suppress_value_error=False):
3077
        # right now path_t doesn't support default values.
3078
        # to support a default value, you'll need to override initialize().
3079
        if self.default not in (unspecified, None):
3080
            fail("Can't specify a default to the path_t converter!")
3081
3082
        if self.c_default not in (None, 'Py_None'):
3083
            raise RuntimeError("Can't specify a c_default to the path_t converter!")
3084
3085
        self.nullable = nullable
3086
        self.nonstrict = nonstrict
3087
        self.make_wide = make_wide
3088
        self.suppress_value_error = suppress_value_error
3089
        self.allow_fd = allow_fd
3090
3091
    def pre_render(self):
3092
        def strify(value):
3093
            if isinstance(value, str):
3094
                return value
3095
            return str(int(bool(value)))
3096
3097
        # add self.py_name here when merging with posixmodule conversion
3098
        if self.make_wide is None:
3099
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3100
                self.function.name,
3101
                self.name,
3102
                strify(self.nullable),
3103
                strify(self.nonstrict),
3104
                strify(self.suppress_value_error),
3105
                strify(self.allow_fd),
3106
            )
3107
        else:
3108
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3109
                self.function.name,
3110
                self.name,
3111
                strify(self.nullable),
3112
                strify(self.nonstrict),
3113
                strify(self.make_wide),
3114
                strify(self.suppress_value_error),
3115
                strify(self.allow_fd),
3116
            )
3117
3118
    def cleanup(self):
3119
        return "path_cleanup(&" + self.name + ");\n"
3120
3121
3122
class dir_fd_converter(CConverter):
3123
    type = 'int'
3124
3125
    def converter_init(self, requires=None):
3126
        if self.default in (unspecified, None):
3127
            self.c_default = 'DEFAULT_DIR_FD'
3128
        if isinstance(requires, str):
3129
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3130
        else:
3131
            self.converter = 'dir_fd_converter'
3132
3133
class uid_t_converter(CConverter):
3134
    type = "uid_t"
3135
    converter = '_Py_Uid_Converter'
3136
3137
class gid_t_converter(CConverter):
3138
    type = "gid_t"
3139
    converter = '_Py_Gid_Converter'
3140
3141
class dev_t_converter(CConverter):
3142
    type = 'dev_t'
3143
    converter = '_Py_Dev_Converter'
3144
3145
class dev_t_return_converter(unsigned_long_return_converter):
3146
    type = 'dev_t'
3147
    conversion_fn = '_PyLong_FromDev'
3148
    unsigned_cast = '(dev_t)'
3149
3150
class pid_t_converter(CConverter):
3151
    type = 'pid_t'
3152
    format_unit = '" _Py_PARSE_PID "'
3153
3154
    def parse_arg(self, argname, displayname, *, limited_capi):
3155
        return self.format_code("""
3156
            {paramname} = PyLong_AsPid({argname});
3157
            if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{
3158
                goto exit;
3159
            }}}}
3160
            """, argname=argname)
3161
3162
class idtype_t_converter(CConverter):
3163
    type = 'idtype_t'
3164
    converter = 'idtype_t_converter'
3165
3166
class id_t_converter(CConverter):
3167
    type = 'id_t'
3168
    format_unit = '" _Py_PARSE_PID "'
3169
3170
    def parse_arg(self, argname, displayname, *, limited_capi):
3171
        return self.format_code("""
3172
            {paramname} = (id_t)PyLong_AsPid({argname});
3173
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3174
                goto exit;
3175
            }}}}
3176
            """, argname=argname)
3177
3178
class intptr_t_converter(CConverter):
3179
    type = 'intptr_t'
3180
    format_unit = '" _Py_PARSE_INTPTR "'
3181
3182
    def parse_arg(self, argname, displayname, *, limited_capi):
3183
        return self.format_code("""
3184
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3185
            if (!{paramname} && PyErr_Occurred()) {{{{
3186
                goto exit;
3187
            }}}}
3188
            """, argname=argname)
3189
3190
class Py_off_t_converter(CConverter):
3191
    type = 'Py_off_t'
3192
    converter = 'Py_off_t_converter'
3193
3194
class Py_off_t_return_converter(long_return_converter):
3195
    type = 'Py_off_t'
3196
    conversion_fn = 'PyLong_FromPy_off_t'
3197
3198
class confname_converter(CConverter):
3199
    type="int"
3200
    converter="conv_confname"
3201
3202
    def converter_init(self, *, table):
3203
        self.table = table
3204
3205
    def parse_arg(self, argname, displayname, *, limited_capi):
3206
        return self.format_code("""
3207
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3208
                goto exit;
3209
            }}}}
3210
        """, argname=argname, converter=self.converter, table=self.table)
3211
3212
[python start generated code]*/
3213
/*[python end generated code: output=da39a3ee5e6b4b0d input=d2759f2332cd39b3]*/
3214
3215
/*[clinic input]
3216
3217
os.stat
3218
3219
    path : path_t(allow_fd=True)
3220
        Path to be examined; can be string, bytes, a path-like object or
3221
        open-file-descriptor int.
3222
3223
    *
3224
3225
    dir_fd : dir_fd(requires='fstatat') = None
3226
        If not None, it should be a file descriptor open to a directory,
3227
        and path should be a relative string; path will then be relative to
3228
        that directory.
3229
3230
    follow_symlinks: bool = True
3231
        If False, and the last element of the path is a symbolic link,
3232
        stat will examine the symbolic link itself instead of the file
3233
        the link points to.
3234
3235
Perform a stat system call on the given path.
3236
3237
dir_fd and follow_symlinks may not be implemented
3238
  on your platform.  If they are unavailable, using them will raise a
3239
  NotImplementedError.
3240
3241
It's an error to use dir_fd or follow_symlinks when specifying path as
3242
  an open file descriptor.
3243
3244
[clinic start generated code]*/
3245
3246
static PyObject *
3247
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3248
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3249
2.07k
{
3250
2.07k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3251
2.07k
}
3252
3253
3254
/*[clinic input]
3255
@permit_long_summary
3256
os.lstat
3257
3258
    path : path_t
3259
3260
    *
3261
3262
    dir_fd : dir_fd(requires='fstatat') = None
3263
3264
Perform a stat system call on the given path, without following symbolic links.
3265
3266
Like stat(), but do not follow symbolic links.
3267
Equivalent to stat(path, follow_symlinks=False).
3268
[clinic start generated code]*/
3269
3270
static PyObject *
3271
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3272
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3273
0
{
3274
0
    int follow_symlinks = 0;
3275
0
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3276
0
}
3277
3278
3279
/*[clinic input]
3280
os.access -> bool
3281
3282
    path: path_t
3283
        Path to be tested; can be string, bytes, or a path-like object.
3284
3285
    mode: int
3286
        Operating-system mode bitfield.  Can be F_OK to test existence,
3287
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3288
3289
    *
3290
3291
    dir_fd : dir_fd(requires='faccessat') = None
3292
        If not None, it should be a file descriptor open to a directory,
3293
        and path should be relative; path will then be relative to that
3294
        directory.
3295
3296
    effective_ids: bool = False
3297
        If True, access will use the effective uid/gid instead of
3298
        the real uid/gid.
3299
3300
    follow_symlinks: bool = True
3301
        If False, and the last element of the path is a symbolic link,
3302
        access will examine the symbolic link itself instead of the file
3303
        the link points to.
3304
3305
Use the real uid/gid to test for access to a path.
3306
3307
{parameters}
3308
dir_fd, effective_ids, and follow_symlinks may not be implemented
3309
  on your platform.  If they are unavailable, using them will raise a
3310
  NotImplementedError.
3311
3312
Note that most operations will use the effective uid/gid, therefore this
3313
  routine can be used in a suid/sgid environment to test if the invoking
3314
  user has the specified access to the path.
3315
3316
[clinic start generated code]*/
3317
3318
static int
3319
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3320
               int effective_ids, int follow_symlinks)
3321
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3322
0
{
3323
0
    int return_value;
3324
3325
#ifdef MS_WINDOWS
3326
    DWORD attr;
3327
#else
3328
0
    int result;
3329
0
#endif
3330
3331
0
#ifdef HAVE_FACCESSAT
3332
0
    int faccessat_unavailable = 0;
3333
0
#endif
3334
3335
#ifndef HAVE_FACCESSAT
3336
    if (follow_symlinks_specified("access", follow_symlinks))
3337
        return -1;
3338
3339
    if (effective_ids) {
3340
        argument_unavailable_error("access", "effective_ids");
3341
        return -1;
3342
    }
3343
#endif
3344
3345
#ifdef MS_WINDOWS
3346
    Py_BEGIN_ALLOW_THREADS
3347
    attr = GetFileAttributesW(path->wide);
3348
    Py_END_ALLOW_THREADS
3349
3350
    /*
3351
     * Access is possible if
3352
     *   * we didn't get a -1, and
3353
     *     * write access wasn't requested,
3354
     *     * or the file isn't read-only,
3355
     *     * or it's a directory.
3356
     * (Directories cannot be read-only on Windows.)
3357
    */
3358
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3359
            (!(mode & 2) ||
3360
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3361
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3362
#else
3363
3364
0
    Py_BEGIN_ALLOW_THREADS
3365
0
#ifdef HAVE_FACCESSAT
3366
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3367
0
        effective_ids ||
3368
0
        !follow_symlinks) {
3369
3370
0
        if (HAVE_FACCESSAT_RUNTIME) {
3371
0
            int flags = 0;
3372
0
            if (!follow_symlinks)
3373
0
                flags |= AT_SYMLINK_NOFOLLOW;
3374
0
            if (effective_ids)
3375
0
                flags |= AT_EACCESS;
3376
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3377
0
        } else {
3378
0
            faccessat_unavailable = 1;
3379
0
        }
3380
0
    }
3381
0
    else
3382
0
#endif
3383
0
        result = access(path->narrow, mode);
3384
0
    Py_END_ALLOW_THREADS
3385
3386
0
#ifdef HAVE_FACCESSAT
3387
0
    if (faccessat_unavailable) {
3388
0
        if (dir_fd != DEFAULT_DIR_FD) {
3389
0
            argument_unavailable_error("access", "dir_fd");
3390
0
            return -1;
3391
0
        }
3392
0
        if (follow_symlinks_specified("access", follow_symlinks))
3393
0
            return -1;
3394
3395
0
        if (effective_ids) {
3396
0
            argument_unavailable_error("access", "effective_ids");
3397
0
            return -1;
3398
0
        }
3399
        /* should be unreachable */
3400
0
        return -1;
3401
0
    }
3402
0
#endif
3403
0
    return_value = !result;
3404
0
#endif
3405
3406
0
    return return_value;
3407
0
}
3408
3409
#ifndef F_OK
3410
#define F_OK 0
3411
#endif
3412
#ifndef R_OK
3413
#define R_OK 4
3414
#endif
3415
#ifndef W_OK
3416
#define W_OK 2
3417
#endif
3418
#ifndef X_OK
3419
#define X_OK 1
3420
#endif
3421
3422
3423
#ifdef HAVE_TTYNAME_R
3424
/*[clinic input]
3425
os.ttyname
3426
3427
    fd: int
3428
        Integer file descriptor handle.
3429
3430
    /
3431
3432
Return the name of the terminal device connected to 'fd'.
3433
[clinic start generated code]*/
3434
3435
static PyObject *
3436
os_ttyname_impl(PyObject *module, int fd)
3437
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3438
0
{
3439
3440
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3441
0
    if (size == -1) {
3442
0
        return posix_error();
3443
0
    }
3444
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3445
0
    if (buffer == NULL) {
3446
0
        return PyErr_NoMemory();
3447
0
    }
3448
0
    int ret = ttyname_r(fd, buffer, size);
3449
0
    if (ret != 0) {
3450
0
        PyMem_RawFree(buffer);
3451
0
        errno = ret;
3452
0
        return posix_error();
3453
0
    }
3454
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3455
0
    PyMem_RawFree(buffer);
3456
0
    return res;
3457
0
}
3458
#endif
3459
3460
#ifdef HAVE_CTERMID
3461
/*[clinic input]
3462
os.ctermid
3463
3464
Return the name of the controlling terminal for this process.
3465
[clinic start generated code]*/
3466
3467
static PyObject *
3468
os_ctermid_impl(PyObject *module)
3469
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3470
0
{
3471
0
    char *ret;
3472
0
    char buffer[L_ctermid];
3473
3474
#ifdef USE_CTERMID_R
3475
    ret = ctermid_r(buffer);
3476
#else
3477
0
    ret = ctermid(buffer);
3478
0
#endif
3479
0
    if (ret == NULL)
3480
0
        return posix_error();
3481
0
    return PyUnicode_DecodeFSDefault(buffer);
3482
0
}
3483
#endif /* HAVE_CTERMID */
3484
3485
3486
/*[clinic input]
3487
os.chdir
3488
3489
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3490
3491
Change the current working directory to the specified path.
3492
3493
path may always be specified as a string.
3494
On some platforms, path may also be specified as an open file descriptor.
3495
If this functionality is unavailable, using it raises an exception.
3496
[clinic start generated code]*/
3497
3498
static PyObject *
3499
os_chdir_impl(PyObject *module, path_t *path)
3500
/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/
3501
0
{
3502
0
    int result;
3503
3504
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3505
0
        return NULL;
3506
0
    }
3507
3508
0
    Py_BEGIN_ALLOW_THREADS
3509
#ifdef MS_WINDOWS
3510
    /* on unix, success = 0, on windows, success = !0 */
3511
    result = !win32_wchdir(path->wide);
3512
#else
3513
0
#ifdef HAVE_FCHDIR
3514
0
    if (path->fd != -1)
3515
0
        result = fchdir(path->fd);
3516
0
    else
3517
0
#endif
3518
0
        result = chdir(path->narrow);
3519
0
#endif
3520
0
    Py_END_ALLOW_THREADS
3521
3522
0
    if (result) {
3523
0
        return path_error(path);
3524
0
    }
3525
3526
0
    Py_RETURN_NONE;
3527
0
}
3528
3529
3530
#ifdef HAVE_FCHDIR
3531
/*[clinic input]
3532
os.fchdir
3533
3534
    fd: fildes
3535
3536
Change to the directory of the given file descriptor.
3537
3538
fd must be opened on a directory, not a file.
3539
Equivalent to os.chdir(fd).
3540
3541
[clinic start generated code]*/
3542
3543
static PyObject *
3544
os_fchdir_impl(PyObject *module, int fd)
3545
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3546
0
{
3547
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3548
0
        return NULL;
3549
0
    }
3550
0
    return posix_fildes_fd(fd, fchdir);
3551
0
}
3552
#endif /* HAVE_FCHDIR */
3553
3554
#ifdef MS_WINDOWS
3555
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3556
#else
3557
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3558
#endif
3559
3560
#ifdef MS_WINDOWS
3561
static int
3562
win32_lchmod(LPCWSTR path, int mode)
3563
{
3564
    DWORD attr = GetFileAttributesW(path);
3565
    if (attr == INVALID_FILE_ATTRIBUTES) {
3566
        return 0;
3567
    }
3568
    if (mode & _S_IWRITE) {
3569
        attr &= ~FILE_ATTRIBUTE_READONLY;
3570
    }
3571
    else {
3572
        attr |= FILE_ATTRIBUTE_READONLY;
3573
    }
3574
    return SetFileAttributesW(path, attr);
3575
}
3576
3577
static int
3578
win32_hchmod(HANDLE hfile, int mode)
3579
{
3580
    FILE_BASIC_INFO info;
3581
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
3582
                                      &info, sizeof(info)))
3583
    {
3584
        return 0;
3585
    }
3586
    if (mode & _S_IWRITE) {
3587
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
3588
    }
3589
    else {
3590
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
3591
    }
3592
    return SetFileInformationByHandle(hfile, FileBasicInfo,
3593
                                      &info, sizeof(info));
3594
}
3595
3596
static int
3597
win32_fchmod(int fd, int mode)
3598
{
3599
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
3600
    if (hfile == INVALID_HANDLE_VALUE) {
3601
        SetLastError(ERROR_INVALID_HANDLE);
3602
        return 0;
3603
    }
3604
    return win32_hchmod(hfile, mode);
3605
}
3606
3607
#endif /* MS_WINDOWS */
3608
3609
/*[clinic input]
3610
os.chmod
3611
3612
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3613
        Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3614
        On some platforms, path may also be specified as an open file descriptor.
3615
        If this functionality is unavailable, using it raises an exception.
3616
3617
    mode: int
3618
        Operating-system mode bitfield.
3619
        Be careful when using number literals for *mode*. The conventional UNIX notation for
3620
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3621
        Python.
3622
3623
    *
3624
3625
    dir_fd : dir_fd(requires='fchmodat') = None
3626
        If not None, it should be a file descriptor open to a directory,
3627
        and path should be relative; path will then be relative to that
3628
        directory.
3629
3630
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
3631
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
3632
        If False, and the last element of the path is a symbolic link,
3633
        chmod will modify the symbolic link itself instead of the file
3634
        the link points to.
3635
3636
Change the access permissions of a file.
3637
3638
It is an error to use dir_fd or follow_symlinks when specifying path as
3639
  an open file descriptor.
3640
dir_fd and follow_symlinks may not be implemented on your platform.
3641
  If they are unavailable, using them will raise a NotImplementedError.
3642
3643
[clinic start generated code]*/
3644
3645
static PyObject *
3646
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3647
              int follow_symlinks)
3648
/*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
3649
0
{
3650
0
    int result;
3651
3652
0
#ifdef HAVE_FCHMODAT
3653
0
    int fchmodat_nofollow_unsupported = 0;
3654
0
    int fchmodat_unsupported = 0;
3655
0
#endif
3656
3657
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
3658
    if (follow_symlinks_specified("chmod", follow_symlinks))
3659
        return NULL;
3660
#endif
3661
3662
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3663
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3664
0
        return NULL;
3665
0
    }
3666
3667
#ifdef MS_WINDOWS
3668
    result = 0;
3669
    Py_BEGIN_ALLOW_THREADS
3670
    if (path->fd != -1) {
3671
        result = win32_fchmod(path->fd, mode);
3672
    }
3673
    else if (follow_symlinks) {
3674
        HANDLE hfile = CreateFileW(path->wide,
3675
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
3676
                                   0, NULL,
3677
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
3678
        if (hfile != INVALID_HANDLE_VALUE) {
3679
            result = win32_hchmod(hfile, mode);
3680
            (void)CloseHandle(hfile);
3681
        }
3682
    }
3683
    else {
3684
        result = win32_lchmod(path->wide, mode);
3685
    }
3686
    Py_END_ALLOW_THREADS
3687
    if (!result) {
3688
        return path_error(path);
3689
    }
3690
#else /* MS_WINDOWS */
3691
0
    Py_BEGIN_ALLOW_THREADS
3692
0
#ifdef HAVE_FCHMOD
3693
0
    if (path->fd != -1)
3694
0
        result = fchmod(path->fd, mode);
3695
0
    else
3696
0
#endif /* HAVE_CHMOD */
3697
#ifdef HAVE_LCHMOD
3698
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3699
        result = lchmod(path->narrow, mode);
3700
    else
3701
#endif /* HAVE_LCHMOD */
3702
0
#ifdef HAVE_FCHMODAT
3703
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3704
0
        if (HAVE_FCHMODAT_RUNTIME) {
3705
            /*
3706
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3707
             * The documentation specifically shows how to use it,
3708
             * and then says it isn't implemented yet.
3709
             * (true on linux with glibc 2.15, and openindiana 3.x)
3710
             *
3711
             * Once it is supported, os.chmod will automatically
3712
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
3713
             * Until then, we need to be careful what exception we raise.
3714
             */
3715
0
            result = fchmodat(dir_fd, path->narrow, mode,
3716
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3717
            /*
3718
             * But wait!  We can't throw the exception without allowing threads,
3719
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3720
             */
3721
0
            fchmodat_nofollow_unsupported =
3722
0
                             result &&
3723
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3724
0
                             !follow_symlinks;
3725
0
        } else {
3726
0
            fchmodat_unsupported = 1;
3727
0
            fchmodat_nofollow_unsupported = 1;
3728
3729
0
            result = -1;
3730
0
        }
3731
0
    }
3732
0
    else
3733
0
#endif /* HAVE_FHCMODAT */
3734
0
    {
3735
0
#ifdef HAVE_CHMOD
3736
0
        result = chmod(path->narrow, mode);
3737
#elif defined(__wasi__)
3738
        // WASI SDK 15.0 does not support chmod.
3739
        // Ignore missing syscall for now.
3740
        result = 0;
3741
#else
3742
        result = -1;
3743
        errno = ENOSYS;
3744
#endif
3745
0
    }
3746
0
    Py_END_ALLOW_THREADS
3747
3748
0
    if (result) {
3749
0
#ifdef HAVE_FCHMODAT
3750
0
        if (fchmodat_unsupported) {
3751
0
            if (dir_fd != DEFAULT_DIR_FD) {
3752
0
                argument_unavailable_error("chmod", "dir_fd");
3753
0
                return NULL;
3754
0
            }
3755
0
        }
3756
3757
0
        if (fchmodat_nofollow_unsupported) {
3758
0
            if (dir_fd != DEFAULT_DIR_FD)
3759
0
                dir_fd_and_follow_symlinks_invalid("chmod",
3760
0
                                                   dir_fd, follow_symlinks);
3761
0
            else
3762
0
                follow_symlinks_specified("chmod", follow_symlinks);
3763
0
            return NULL;
3764
0
        }
3765
0
        else
3766
0
#endif /* HAVE_FCHMODAT */
3767
0
        return path_error(path);
3768
0
    }
3769
0
#endif /* MS_WINDOWS */
3770
3771
0
    Py_RETURN_NONE;
3772
0
}
3773
3774
3775
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
3776
/*[clinic input]
3777
os.fchmod
3778
3779
    fd: int
3780
        The file descriptor of the file to be modified.
3781
    mode: int
3782
        Operating-system mode bitfield.
3783
        Be careful when using number literals for *mode*. The conventional UNIX notation for
3784
        numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3785
        Python.
3786
3787
Change the access permissions of the file given by file descriptor fd.
3788
3789
Equivalent to os.chmod(fd, mode).
3790
[clinic start generated code]*/
3791
3792
static PyObject *
3793
os_fchmod_impl(PyObject *module, int fd, int mode)
3794
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
3795
0
{
3796
0
    int res;
3797
3798
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3799
0
        return NULL;
3800
0
    }
3801
3802
#ifdef MS_WINDOWS
3803
    res = 0;
3804
    Py_BEGIN_ALLOW_THREADS
3805
    res = win32_fchmod(fd, mode);
3806
    Py_END_ALLOW_THREADS
3807
    if (!res) {
3808
        return PyErr_SetFromWindowsErr(0);
3809
    }
3810
#else /* MS_WINDOWS */
3811
0
    int async_err = 0;
3812
0
    do {
3813
0
        Py_BEGIN_ALLOW_THREADS
3814
0
        res = fchmod(fd, mode);
3815
0
        Py_END_ALLOW_THREADS
3816
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3817
0
    if (res != 0)
3818
0
        return (!async_err) ? posix_error() : NULL;
3819
0
#endif /* MS_WINDOWS */
3820
3821
0
    Py_RETURN_NONE;
3822
0
}
3823
#endif /* HAVE_FCHMOD || MS_WINDOWS */
3824
3825
3826
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
3827
/*[clinic input]
3828
os.lchmod
3829
3830
    path: path_t
3831
    mode: int
3832
3833
Change the access permissions of a file, without following symbolic links.
3834
3835
If path is a symlink, this affects the link itself rather than the target.
3836
Equivalent to chmod(path, mode, follow_symlinks=False)."
3837
[clinic start generated code]*/
3838
3839
static PyObject *
3840
os_lchmod_impl(PyObject *module, path_t *path, int mode)
3841
/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3842
{
3843
    int res;
3844
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3845
        return NULL;
3846
    }
3847
#ifdef MS_WINDOWS
3848
    Py_BEGIN_ALLOW_THREADS
3849
    res = win32_lchmod(path->wide, mode);
3850
    Py_END_ALLOW_THREADS
3851
    if (!res) {
3852
        path_error(path);
3853
        return NULL;
3854
    }
3855
#else /* MS_WINDOWS */
3856
    Py_BEGIN_ALLOW_THREADS
3857
    res = lchmod(path->narrow, mode);
3858
    Py_END_ALLOW_THREADS
3859
    if (res < 0) {
3860
        path_error(path);
3861
        return NULL;
3862
    }
3863
#endif /* MS_WINDOWS */
3864
    Py_RETURN_NONE;
3865
}
3866
#endif /* HAVE_LCHMOD || MS_WINDOWS */
3867
3868
3869
#ifdef HAVE_CHFLAGS
3870
/*[clinic input]
3871
os.chflags
3872
3873
    path: path_t
3874
    flags: unsigned_long(bitwise=True)
3875
    follow_symlinks: bool=True
3876
3877
Set file flags.
3878
3879
If follow_symlinks is False, and the last element of the path is a symbolic
3880
  link, chflags will change flags on the symbolic link itself instead of the
3881
  file the link points to.
3882
follow_symlinks may not be implemented on your platform.  If it is
3883
unavailable, using it will raise a NotImplementedError.
3884
3885
[clinic start generated code]*/
3886
3887
static PyObject *
3888
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3889
                int follow_symlinks)
3890
/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3891
{
3892
    int result;
3893
3894
#ifndef HAVE_LCHFLAGS
3895
    if (follow_symlinks_specified("chflags", follow_symlinks))
3896
        return NULL;
3897
#endif
3898
3899
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3900
        return NULL;
3901
    }
3902
3903
    Py_BEGIN_ALLOW_THREADS
3904
#ifdef HAVE_LCHFLAGS
3905
    if (!follow_symlinks)
3906
        result = lchflags(path->narrow, flags);
3907
    else
3908
#endif
3909
        result = chflags(path->narrow, flags);
3910
    Py_END_ALLOW_THREADS
3911
3912
    if (result)
3913
        return path_error(path);
3914
3915
    Py_RETURN_NONE;
3916
}
3917
#endif /* HAVE_CHFLAGS */
3918
3919
3920
#ifdef HAVE_LCHFLAGS
3921
/*[clinic input]
3922
os.lchflags
3923
3924
    path: path_t
3925
    flags: unsigned_long(bitwise=True)
3926
3927
Set file flags.
3928
3929
This function will not follow symbolic links.
3930
Equivalent to chflags(path, flags, follow_symlinks=False).
3931
[clinic start generated code]*/
3932
3933
static PyObject *
3934
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3935
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3936
{
3937
    int res;
3938
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3939
        return NULL;
3940
    }
3941
    Py_BEGIN_ALLOW_THREADS
3942
    res = lchflags(path->narrow, flags);
3943
    Py_END_ALLOW_THREADS
3944
    if (res < 0) {
3945
        return path_error(path);
3946
    }
3947
    Py_RETURN_NONE;
3948
}
3949
#endif /* HAVE_LCHFLAGS */
3950
3951
3952
#ifdef HAVE_CHROOT
3953
/*[clinic input]
3954
os.chroot
3955
    path: path_t
3956
3957
Change root directory to path.
3958
3959
[clinic start generated code]*/
3960
3961
static PyObject *
3962
os_chroot_impl(PyObject *module, path_t *path)
3963
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3964
0
{
3965
0
    int res;
3966
0
    Py_BEGIN_ALLOW_THREADS
3967
0
    res = chroot(path->narrow);
3968
0
    Py_END_ALLOW_THREADS
3969
0
    if (res < 0)
3970
0
        return path_error(path);
3971
0
    Py_RETURN_NONE;
3972
0
}
3973
#endif /* HAVE_CHROOT */
3974
3975
3976
#ifdef HAVE_FSYNC
3977
/*[clinic input]
3978
os.fsync
3979
3980
    fd: fildes
3981
3982
Force write of fd to disk.
3983
[clinic start generated code]*/
3984
3985
static PyObject *
3986
os_fsync_impl(PyObject *module, int fd)
3987
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3988
0
{
3989
0
    return posix_fildes_fd(fd, fsync);
3990
0
}
3991
#endif /* HAVE_FSYNC */
3992
3993
3994
#ifdef HAVE_SYNC
3995
/*[clinic input]
3996
os.sync
3997
3998
Force write of everything to disk.
3999
[clinic start generated code]*/
4000
4001
static PyObject *
4002
os_sync_impl(PyObject *module)
4003
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4004
0
{
4005
0
    Py_BEGIN_ALLOW_THREADS
4006
0
    sync();
4007
0
    Py_END_ALLOW_THREADS
4008
0
    Py_RETURN_NONE;
4009
0
}
4010
#endif /* HAVE_SYNC */
4011
4012
4013
#ifdef HAVE_FDATASYNC
4014
#ifdef __hpux
4015
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4016
#endif
4017
4018
/*[clinic input]
4019
os.fdatasync
4020
4021
    fd: fildes
4022
4023
Force write of fd to disk without forcing update of metadata.
4024
[clinic start generated code]*/
4025
4026
static PyObject *
4027
os_fdatasync_impl(PyObject *module, int fd)
4028
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4029
0
{
4030
0
    return posix_fildes_fd(fd, fdatasync);
4031
0
}
4032
#endif /* HAVE_FDATASYNC */
4033
4034
4035
#ifdef HAVE_CHOWN
4036
/*[clinic input]
4037
os.chown
4038
4039
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4040
        Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
4041
4042
    uid: uid_t
4043
4044
    gid: gid_t
4045
4046
    *
4047
4048
    dir_fd : dir_fd(requires='fchownat') = None
4049
        If not None, it should be a file descriptor open to a directory,
4050
        and path should be relative; path will then be relative to that
4051
        directory.
4052
4053
    follow_symlinks: bool = True
4054
        If False, and the last element of the path is a symbolic link,
4055
        stat will examine the symbolic link itself instead of the file
4056
        the link points to.
4057
4058
Change the owner and group id of path to the numeric uid and gid.\
4059
4060
path may always be specified as a string.
4061
On some platforms, path may also be specified as an open file descriptor.
4062
  If this functionality is unavailable, using it raises an exception.
4063
If dir_fd is not None, it should be a file descriptor open to a directory,
4064
  and path should be relative; path will then be relative to that directory.
4065
If follow_symlinks is False, and the last element of the path is a symbolic
4066
  link, chown will modify the symbolic link itself instead of the file the
4067
  link points to.
4068
It is an error to use dir_fd or follow_symlinks when specifying path as
4069
  an open file descriptor.
4070
dir_fd and follow_symlinks may not be implemented on your platform.
4071
  If they are unavailable, using them will raise a NotImplementedError.
4072
4073
[clinic start generated code]*/
4074
4075
static PyObject *
4076
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4077
              int dir_fd, int follow_symlinks)
4078
/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
4079
0
{
4080
0
    int result;
4081
4082
0
#if defined(HAVE_FCHOWNAT)
4083
0
    int fchownat_unsupported = 0;
4084
0
#endif
4085
4086
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4087
    if (follow_symlinks_specified("chown", follow_symlinks))
4088
        return NULL;
4089
#endif
4090
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4091
0
        fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
4092
0
        return NULL;
4093
4094
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4095
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4096
0
        return NULL;
4097
0
    }
4098
4099
0
    Py_BEGIN_ALLOW_THREADS
4100
0
#ifdef HAVE_FCHOWN
4101
0
    if (path->fd != -1)
4102
0
        result = fchown(path->fd, uid, gid);
4103
0
    else
4104
0
#endif
4105
0
#ifdef HAVE_LCHOWN
4106
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4107
0
        result = lchown(path->narrow, uid, gid);
4108
0
    else
4109
0
#endif
4110
0
#ifdef HAVE_FCHOWNAT
4111
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4112
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4113
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4114
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4115
0
      } else {
4116
0
         fchownat_unsupported = 1;
4117
0
      }
4118
0
    } else
4119
0
#endif
4120
0
        result = chown(path->narrow, uid, gid);
4121
0
    Py_END_ALLOW_THREADS
4122
4123
0
#ifdef HAVE_FCHOWNAT
4124
0
    if (fchownat_unsupported) {
4125
        /* This would be incorrect if the current platform
4126
         * doesn't support lchown.
4127
         */
4128
0
        argument_unavailable_error(NULL, "dir_fd");
4129
0
        return NULL;
4130
0
    }
4131
0
#endif
4132
4133
0
    if (result)
4134
0
        return path_error(path);
4135
4136
0
    Py_RETURN_NONE;
4137
0
}
4138
#endif /* HAVE_CHOWN */
4139
4140
4141
#ifdef HAVE_FCHOWN
4142
/*[clinic input]
4143
os.fchown
4144
4145
    fd: int
4146
    uid: uid_t
4147
    gid: gid_t
4148
4149
Change the owner and group id of the file specified by file descriptor.
4150
4151
Equivalent to os.chown(fd, uid, gid).
4152
4153
[clinic start generated code]*/
4154
4155
static PyObject *
4156
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4157
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4158
0
{
4159
0
    int res;
4160
0
    int async_err = 0;
4161
4162
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4163
0
        return NULL;
4164
0
    }
4165
4166
0
    do {
4167
0
        Py_BEGIN_ALLOW_THREADS
4168
0
        res = fchown(fd, uid, gid);
4169
0
        Py_END_ALLOW_THREADS
4170
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4171
0
    if (res != 0)
4172
0
        return (!async_err) ? posix_error() : NULL;
4173
4174
0
    Py_RETURN_NONE;
4175
0
}
4176
#endif /* HAVE_FCHOWN */
4177
4178
4179
#ifdef HAVE_LCHOWN
4180
/*[clinic input]
4181
os.lchown
4182
4183
    path : path_t
4184
    uid: uid_t
4185
    gid: gid_t
4186
4187
Change the owner and group id of path to the numeric uid and gid.
4188
4189
This function will not follow symbolic links.
4190
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4191
[clinic start generated code]*/
4192
4193
static PyObject *
4194
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4195
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4196
0
{
4197
0
    int res;
4198
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4199
0
        return NULL;
4200
0
    }
4201
0
    Py_BEGIN_ALLOW_THREADS
4202
0
    res = lchown(path->narrow, uid, gid);
4203
0
    Py_END_ALLOW_THREADS
4204
0
    if (res < 0) {
4205
0
        return path_error(path);
4206
0
    }
4207
0
    Py_RETURN_NONE;
4208
0
}
4209
#endif /* HAVE_LCHOWN */
4210
4211
4212
static PyObject *
4213
posix_getcwd(int use_bytes)
4214
0
{
4215
#ifdef MS_WINDOWS
4216
    wchar_t wbuf[MAXPATHLEN];
4217
    wchar_t *wbuf2 = wbuf;
4218
    DWORD len;
4219
4220
    Py_BEGIN_ALLOW_THREADS
4221
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4222
    /* If the buffer is large enough, len does not include the
4223
       terminating \0. If the buffer is too small, len includes
4224
       the space needed for the terminator. */
4225
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4226
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4227
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4228
        }
4229
        else {
4230
            wbuf2 = NULL;
4231
        }
4232
        if (wbuf2) {
4233
            len = GetCurrentDirectoryW(len, wbuf2);
4234
        }
4235
    }
4236
    Py_END_ALLOW_THREADS
4237
4238
    if (!wbuf2) {
4239
        PyErr_NoMemory();
4240
        return NULL;
4241
    }
4242
    if (!len) {
4243
        PyErr_SetFromWindowsErr(0);
4244
        if (wbuf2 != wbuf)
4245
            PyMem_RawFree(wbuf2);
4246
        return NULL;
4247
    }
4248
4249
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4250
    if (wbuf2 != wbuf) {
4251
        PyMem_RawFree(wbuf2);
4252
    }
4253
4254
    if (use_bytes) {
4255
        if (resobj == NULL) {
4256
            return NULL;
4257
        }
4258
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4259
    }
4260
4261
    return resobj;
4262
#else
4263
0
    const size_t chunk = 1024;
4264
4265
0
    char *buf = NULL;
4266
0
    char *cwd = NULL;
4267
0
    size_t buflen = 0;
4268
4269
0
    Py_BEGIN_ALLOW_THREADS
4270
0
    do {
4271
0
        char *newbuf;
4272
0
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4273
0
            buflen += chunk;
4274
0
            newbuf = PyMem_RawRealloc(buf, buflen);
4275
0
        }
4276
0
        else {
4277
0
            newbuf = NULL;
4278
0
        }
4279
0
        if (newbuf == NULL) {
4280
0
            PyMem_RawFree(buf);
4281
0
            buf = NULL;
4282
0
            break;
4283
0
        }
4284
0
        buf = newbuf;
4285
4286
0
        cwd = getcwd(buf, buflen);
4287
0
    } while (cwd == NULL && errno == ERANGE);
4288
0
    Py_END_ALLOW_THREADS
4289
4290
0
    if (buf == NULL) {
4291
0
        return PyErr_NoMemory();
4292
0
    }
4293
0
    if (cwd == NULL) {
4294
0
        posix_error();
4295
0
        PyMem_RawFree(buf);
4296
0
        return NULL;
4297
0
    }
4298
4299
0
    PyObject *obj;
4300
0
    if (use_bytes) {
4301
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4302
0
    }
4303
0
    else {
4304
0
        obj = PyUnicode_DecodeFSDefault(buf);
4305
0
    }
4306
0
#ifdef __linux__
4307
0
    if (buf[0] != '/') {
4308
        /*
4309
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4310
         * relative pathname starting with '(unreachable)'. We detect this
4311
         * and fail with ENOENT, matching newer glibc behaviour.
4312
         */
4313
0
        errno = ENOENT;
4314
0
        path_object_error(obj);
4315
0
        PyMem_RawFree(buf);
4316
0
        return NULL;
4317
0
    }
4318
0
#endif
4319
0
    assert(buf[0] == '/');
4320
0
    PyMem_RawFree(buf);
4321
4322
0
    return obj;
4323
0
#endif   /* !MS_WINDOWS */
4324
0
}
4325
4326
4327
/*[clinic input]
4328
os.getcwd
4329
4330
Return a unicode string representing the current working directory.
4331
[clinic start generated code]*/
4332
4333
static PyObject *
4334
os_getcwd_impl(PyObject *module)
4335
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4336
0
{
4337
0
    return posix_getcwd(0);
4338
0
}
4339
4340
4341
/*[clinic input]
4342
os.getcwdb
4343
4344
Return a bytes string representing the current working directory.
4345
[clinic start generated code]*/
4346
4347
static PyObject *
4348
os_getcwdb_impl(PyObject *module)
4349
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4350
0
{
4351
0
    return posix_getcwd(1);
4352
0
}
4353
4354
4355
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4356
#define HAVE_LINK 1
4357
#endif
4358
4359
#ifdef HAVE_LINK
4360
/*[clinic input]
4361
4362
@permit_long_docstring_body
4363
os.link
4364
4365
    src : path_t
4366
    dst : path_t
4367
    *
4368
    src_dir_fd : dir_fd = None
4369
    dst_dir_fd : dir_fd = None
4370
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4371
4372
Create a hard link to a file.
4373
4374
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4375
  descriptor open to a directory, and the respective path string (src or dst)
4376
  should be relative; the path will then be relative to that directory.
4377
If follow_symlinks is False, and the last element of src is a symbolic
4378
  link, link will create a link to the symbolic link itself instead of the
4379
  file the link points to.
4380
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4381
  platform.  If they are unavailable, using them will raise a
4382
  NotImplementedError.
4383
[clinic start generated code]*/
4384
4385
static PyObject *
4386
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4387
             int dst_dir_fd, int follow_symlinks)
4388
/*[clinic end generated code: output=7f00f6007fd5269a input=e2a50a6497050e44]*/
4389
0
{
4390
#ifdef MS_WINDOWS
4391
    BOOL result = FALSE;
4392
#else
4393
0
    int result;
4394
0
#endif
4395
4396
0
#ifdef HAVE_LINKAT
4397
0
    if (HAVE_LINKAT_RUNTIME) {
4398
0
        if (follow_symlinks < 0) {
4399
0
            follow_symlinks = 1;
4400
0
        }
4401
0
    }
4402
0
    else
4403
0
#endif
4404
0
    {
4405
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4406
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4407
0
            return NULL;
4408
0
        }
4409
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4410
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4411
0
#if defined(MS_WINDOWS) || defined(__linux__)
4412
0
        if (follow_symlinks == 1) {
4413
0
            argument_unavailable_error("link", "follow_symlinks=True");
4414
0
            return NULL;
4415
0
        }
4416
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4417
        if (follow_symlinks == 0) {
4418
            argument_unavailable_error("link", "follow_symlinks=False");
4419
            return NULL;
4420
        }
4421
#else
4422
        if (follow_symlinks >= 0) {
4423
            argument_unavailable_error("link", "follow_symlinks");
4424
            return NULL;
4425
        }
4426
#endif
4427
0
    }
4428
4429
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4430
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4431
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4432
0
        return NULL;
4433
0
    }
4434
4435
#ifdef MS_WINDOWS
4436
    Py_BEGIN_ALLOW_THREADS
4437
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4438
    Py_END_ALLOW_THREADS
4439
4440
    if (!result)
4441
        return path_error2(src, dst);
4442
#else
4443
0
    Py_BEGIN_ALLOW_THREADS
4444
0
#ifdef HAVE_LINKAT
4445
0
    if (HAVE_LINKAT_RUNTIME) {
4446
0
        result = linkat(src_dir_fd, src->narrow,
4447
0
            dst_dir_fd, dst->narrow,
4448
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4449
0
    }
4450
0
    else
4451
0
#endif
4452
0
    {
4453
        /* linkat not available */
4454
0
        result = link(src->narrow, dst->narrow);
4455
0
    }
4456
0
    Py_END_ALLOW_THREADS
4457
4458
0
    if (result)
4459
0
        return path_error2(src, dst);
4460
0
#endif /* MS_WINDOWS */
4461
4462
0
    Py_RETURN_NONE;
4463
0
}
4464
#endif
4465
4466
4467
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4468
static PyObject *
4469
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4470
{
4471
    PyObject *v;
4472
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4473
    BOOL result, return_bytes;
4474
    wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4475
    /* only claim to have space for MAX_PATH */
4476
    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4477
    wchar_t *wnamebuf = NULL;
4478
4479
    WIN32_FIND_DATAW wFileData;
4480
    const wchar_t *po_wchars;
4481
4482
    if (!path->wide) { /* Default arg: "." */
4483
        po_wchars = L".";
4484
        len = 1;
4485
        return_bytes = 0;
4486
    } else {
4487
        po_wchars = path->wide;
4488
        len = wcslen(path->wide);
4489
        return_bytes = PyBytes_Check(path->object);
4490
    }
4491
    /* The +5 is so we can append "\\*.*\0" */
4492
    wnamebuf = PyMem_New(wchar_t, len + 5);
4493
    if (!wnamebuf) {
4494
        PyErr_NoMemory();
4495
        goto exit;
4496
    }
4497
    wcscpy(wnamebuf, po_wchars);
4498
    if (len > 0) {
4499
        wchar_t wch = wnamebuf[len-1];
4500
        if (wch != SEP && wch != ALTSEP && wch != L':')
4501
            wnamebuf[len++] = SEP;
4502
        wcscpy(wnamebuf + len, L"*.*");
4503
    }
4504
    if ((list = PyList_New(0)) == NULL) {
4505
        goto exit;
4506
    }
4507
    Py_BEGIN_ALLOW_THREADS
4508
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4509
    Py_END_ALLOW_THREADS
4510
    if (hFindFile == INVALID_HANDLE_VALUE) {
4511
        int error = GetLastError();
4512
        if (error == ERROR_FILE_NOT_FOUND)
4513
            goto exit;
4514
        path_error(path);
4515
        Py_CLEAR(list);
4516
        goto exit;
4517
    }
4518
    do {
4519
        /* Skip over . and .. */
4520
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4521
            wcscmp(wFileData.cFileName, L"..") != 0) {
4522
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4523
                                       wcslen(wFileData.cFileName));
4524
            if (return_bytes && v) {
4525
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4526
            }
4527
            if (v == NULL) {
4528
                Py_CLEAR(list);
4529
                break;
4530
            }
4531
            if (PyList_Append(list, v) != 0) {
4532
                Py_DECREF(v);
4533
                Py_CLEAR(list);
4534
                break;
4535
            }
4536
            Py_DECREF(v);
4537
        }
4538
        Py_BEGIN_ALLOW_THREADS
4539
        result = FindNextFileW(hFindFile, &wFileData);
4540
        Py_END_ALLOW_THREADS
4541
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4542
           it got to the end of the directory. */
4543
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4544
            path_error(path);
4545
            Py_CLEAR(list);
4546
            goto exit;
4547
        }
4548
    } while (result == TRUE);
4549
4550
exit:
4551
    if (hFindFile != INVALID_HANDLE_VALUE) {
4552
        if (FindClose(hFindFile) == FALSE) {
4553
            if (list != NULL) {
4554
                path_error(path);
4555
                Py_CLEAR(list);
4556
            }
4557
        }
4558
    }
4559
    PyMem_Free(wnamebuf);
4560
4561
    return list;
4562
}  /* end of _listdir_windows_no_opendir */
4563
4564
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4565
4566
static PyObject *
4567
_posix_listdir(path_t *path, PyObject *list)
4568
120
{
4569
120
    PyObject *v;
4570
120
    DIR *dirp = NULL;
4571
120
    struct dirent *ep;
4572
120
    int return_str; /* if false, return bytes */
4573
120
#ifdef HAVE_FDOPENDIR
4574
120
    int fd = -1;
4575
120
#endif
4576
4577
120
    errno = 0;
4578
120
#ifdef HAVE_FDOPENDIR
4579
120
    if (path->fd != -1) {
4580
0
      if (HAVE_FDOPENDIR_RUNTIME) {
4581
        /* closedir() closes the FD, so we duplicate it */
4582
0
        fd = _Py_dup(path->fd);
4583
0
        if (fd == -1)
4584
0
            return NULL;
4585
4586
0
        return_str = 1;
4587
4588
0
        Py_BEGIN_ALLOW_THREADS
4589
0
        dirp = fdopendir(fd);
4590
0
        Py_END_ALLOW_THREADS
4591
0
      } else {
4592
0
        PyErr_SetString(PyExc_TypeError,
4593
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
4594
0
        return NULL;
4595
0
      }
4596
0
    }
4597
120
    else
4598
120
#endif
4599
120
    {
4600
120
        const char *name;
4601
120
        if (path->narrow) {
4602
120
            name = path->narrow;
4603
            /* only return bytes if they specified a bytes object */
4604
120
            return_str = !PyBytes_Check(path->object);
4605
120
        }
4606
0
        else {
4607
0
            name = ".";
4608
0
            return_str = 1;
4609
0
        }
4610
4611
120
        Py_BEGIN_ALLOW_THREADS
4612
120
        dirp = opendir(name);
4613
120
        Py_END_ALLOW_THREADS
4614
120
    }
4615
4616
120
    if (dirp == NULL) {
4617
0
        path_error(path);
4618
0
        list = NULL;
4619
0
#ifdef HAVE_FDOPENDIR
4620
0
        if (fd != -1) {
4621
0
            Py_BEGIN_ALLOW_THREADS
4622
0
            close(fd);
4623
0
            Py_END_ALLOW_THREADS
4624
0
        }
4625
0
#endif
4626
0
        goto exit;
4627
0
    }
4628
120
    if ((list = PyList_New(0)) == NULL) {
4629
0
        goto exit;
4630
0
    }
4631
9.17k
    for (;;) {
4632
9.17k
        errno = 0;
4633
9.17k
        Py_BEGIN_ALLOW_THREADS
4634
9.17k
        ep = readdir(dirp);
4635
9.17k
        Py_END_ALLOW_THREADS
4636
9.17k
        if (ep == NULL) {
4637
120
            if (errno == 0) {
4638
120
                break;
4639
120
            } else {
4640
0
                path_error(path);
4641
0
                Py_CLEAR(list);
4642
0
                goto exit;
4643
0
            }
4644
120
        }
4645
9.05k
        if (ep->d_name[0] == '.' &&
4646
240
            (NAMLEN(ep) == 1 ||
4647
120
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4648
240
            continue;
4649
8.81k
        if (return_str)
4650
8.81k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4651
0
        else
4652
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4653
8.81k
        if (v == NULL) {
4654
0
            Py_CLEAR(list);
4655
0
            break;
4656
0
        }
4657
8.81k
        if (PyList_Append(list, v) != 0) {
4658
0
            Py_DECREF(v);
4659
0
            Py_CLEAR(list);
4660
0
            break;
4661
0
        }
4662
8.81k
        Py_DECREF(v);
4663
8.81k
    }
4664
4665
120
exit:
4666
120
    if (dirp != NULL) {
4667
120
        Py_BEGIN_ALLOW_THREADS
4668
120
#ifdef HAVE_FDOPENDIR
4669
120
        if (fd > -1)
4670
0
            rewinddir(dirp);
4671
120
#endif
4672
120
        closedir(dirp);
4673
120
        Py_END_ALLOW_THREADS
4674
120
    }
4675
4676
120
    return list;
4677
120
}  /* end of _posix_listdir */
4678
#endif  /* which OS */
4679
4680
4681
/*[clinic input]
4682
@permit_long_docstring_body
4683
os.listdir
4684
4685
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4686
4687
Return a list containing the names of the files in the directory.
4688
4689
path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4690
  the filenames returned will also be bytes; in all other circumstances
4691
  the filenames returned will be str.
4692
If path is None, uses the path='.'.
4693
On some platforms, path may also be specified as an open file descriptor;\
4694
  the file descriptor must refer to a directory.
4695
  If this functionality is unavailable, using it raises NotImplementedError.
4696
4697
The list is in arbitrary order.  It does not include the special
4698
entries '.' and '..' even if they are present in the directory.
4699
4700
4701
[clinic start generated code]*/
4702
4703
static PyObject *
4704
os_listdir_impl(PyObject *module, path_t *path)
4705
/*[clinic end generated code: output=293045673fcd1a75 input=0bd1728387391b9a]*/
4706
120
{
4707
120
    if (PySys_Audit("os.listdir", "O",
4708
120
                    path->object ? path->object : Py_None) < 0) {
4709
0
        return NULL;
4710
0
    }
4711
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4712
    return _listdir_windows_no_opendir(path, NULL);
4713
#else
4714
120
    return _posix_listdir(path, NULL);
4715
120
#endif
4716
120
}
4717
4718
4719
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
4720
4721
/*[clinic input]
4722
os.listdrives
4723
4724
Return a list containing the names of drives in the system.
4725
4726
A drive name typically looks like 'C:\\'.
4727
4728
[clinic start generated code]*/
4729
4730
static PyObject *
4731
os_listdrives_impl(PyObject *module)
4732
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
4733
{
4734
    /* Number of possible drives is limited, so 256 should always be enough.
4735
       On the day when it is not, listmounts() will have to be used. */
4736
    wchar_t buffer[256];
4737
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
4738
    PyObject *result = NULL;
4739
    if (PySys_Audit("os.listdrives", NULL) < 0) {
4740
        return NULL;
4741
    }
4742
4743
    Py_BEGIN_ALLOW_THREADS;
4744
    buflen = GetLogicalDriveStringsW(buflen, buffer);
4745
    Py_END_ALLOW_THREADS;
4746
4747
    if (!buflen) {
4748
        PyErr_SetFromWindowsErr(0);
4749
        return NULL;
4750
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
4751
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
4752
        return NULL;
4753
    }
4754
4755
    /* buflen includes a null terminator, so remove it */
4756
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
4757
    if (str) {
4758
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
4759
        if (nullchar) {
4760
            result = PyUnicode_Split(str, nullchar, -1);
4761
            Py_DECREF(nullchar);
4762
        }
4763
        Py_DECREF(str);
4764
    }
4765
    return result;
4766
}
4767
4768
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
4769
4770
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
4771
4772
/*[clinic input]
4773
os.listvolumes
4774
4775
Return a list containing the volumes in the system.
4776
4777
Volumes are typically represented as a GUID path.
4778
4779
[clinic start generated code]*/
4780
4781
static PyObject *
4782
os_listvolumes_impl(PyObject *module)
4783
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
4784
{
4785
    PyObject *result = PyList_New(0);
4786
    HANDLE find = INVALID_HANDLE_VALUE;
4787
    wchar_t buffer[MAX_PATH + 1];
4788
    if (!result) {
4789
        return NULL;
4790
    }
4791
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
4792
        Py_DECREF(result);
4793
        return NULL;
4794
    }
4795
4796
    int err = 0;
4797
    Py_BEGIN_ALLOW_THREADS;
4798
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
4799
    if (find == INVALID_HANDLE_VALUE) {
4800
        err = GetLastError();
4801
    }
4802
    Py_END_ALLOW_THREADS;
4803
4804
    while (!err) {
4805
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
4806
        if (!s || PyList_Append(result, s) < 0) {
4807
            Py_XDECREF(s);
4808
            Py_CLEAR(result);
4809
            break;
4810
        }
4811
        Py_DECREF(s);
4812
4813
        Py_BEGIN_ALLOW_THREADS;
4814
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
4815
            err = GetLastError();
4816
        }
4817
        Py_END_ALLOW_THREADS;
4818
    }
4819
4820
    if (find != INVALID_HANDLE_VALUE) {
4821
        Py_BEGIN_ALLOW_THREADS;
4822
        FindVolumeClose(find);
4823
        Py_END_ALLOW_THREADS;
4824
    }
4825
    if (err && err != ERROR_NO_MORE_FILES) {
4826
        PyErr_SetFromWindowsErr(err);
4827
        Py_XDECREF(result);
4828
        result = NULL;
4829
    }
4830
    return result;
4831
}
4832
4833
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
4834
4835
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
4836
4837
/*[clinic input]
4838
os.listmounts
4839
4840
    volume: path_t
4841
4842
Return a list containing mount points for a particular volume.
4843
4844
'volume' should be a GUID path as returned from os.listvolumes.
4845
4846
[clinic start generated code]*/
4847
4848
static PyObject *
4849
os_listmounts_impl(PyObject *module, path_t *volume)
4850
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
4851
{
4852
    wchar_t default_buffer[MAX_PATH + 1];
4853
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
4854
    LPWSTR buffer = default_buffer;
4855
    DWORD attributes;
4856
    PyObject *str = NULL;
4857
    PyObject *nullchar = NULL;
4858
    PyObject *result = NULL;
4859
4860
    /* Ensure we have a valid volume path before continuing */
4861
    Py_BEGIN_ALLOW_THREADS
4862
    attributes = GetFileAttributesW(volume->wide);
4863
    Py_END_ALLOW_THREADS
4864
    if (attributes == INVALID_FILE_ATTRIBUTES &&
4865
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
4866
    {
4867
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
4868
    }
4869
4870
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
4871
        return NULL;
4872
    }
4873
4874
    while (1) {
4875
        BOOL success;
4876
        Py_BEGIN_ALLOW_THREADS
4877
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
4878
                                                   buflen, &buflen);
4879
        Py_END_ALLOW_THREADS
4880
        if (success) {
4881
            break;
4882
        }
4883
        if (GetLastError() != ERROR_MORE_DATA) {
4884
            PyErr_SetFromWindowsErr(0);
4885
            goto exit;
4886
        }
4887
        if (buffer != default_buffer) {
4888
            PyMem_Free((void *)buffer);
4889
        }
4890
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
4891
        if (!buffer) {
4892
            PyErr_NoMemory();
4893
            goto exit;
4894
        }
4895
    }
4896
    if (buflen < 2) {
4897
        result = PyList_New(0);
4898
        goto exit;
4899
    }
4900
    // buflen includes two null terminators, one for the last string
4901
    // and one for the array of strings.
4902
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
4903
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
4904
    if (str && nullchar) {
4905
        result = PyUnicode_Split(str, nullchar, -1);
4906
    }
4907
exit:
4908
    if (buffer != default_buffer) {
4909
        PyMem_Free(buffer);
4910
    }
4911
    Py_XDECREF(nullchar);
4912
    Py_XDECREF(str);
4913
    return result;
4914
}
4915
4916
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
4917
4918
#ifdef MS_WINDOWS
4919
4920
/*[clinic input]
4921
os._path_isdevdrive
4922
4923
    path: path_t
4924
4925
Determines whether the specified path is on a Windows Dev Drive.
4926
4927
[clinic start generated code]*/
4928
4929
static PyObject *
4930
os__path_isdevdrive_impl(PyObject *module, path_t *path)
4931
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
4932
{
4933
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
4934
    /* This flag will be documented at
4935
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
4936
       after release, and will be available in the latest WinSDK.
4937
       We include the flag to avoid a specific version dependency
4938
       on the latest WinSDK. */
4939
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
4940
#endif
4941
    int err = 0;
4942
    PyObject *r = NULL;
4943
    wchar_t volume[MAX_PATH];
4944
4945
    Py_BEGIN_ALLOW_THREADS
4946
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
4947
        /* invalid path of some kind */
4948
        /* Note that this also includes the case where a volume is mounted
4949
           in a path longer than 260 characters. This is likely to be rare
4950
           and problematic for other reasons, so a (soft) failure in this
4951
           check seems okay. */
4952
        err = GetLastError();
4953
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
4954
        /* only care about local dev drives */
4955
        r = Py_False;
4956
    } else {
4957
        HANDLE hVolume = CreateFileW(
4958
            volume,
4959
            FILE_READ_ATTRIBUTES,
4960
            FILE_SHARE_READ | FILE_SHARE_WRITE,
4961
            NULL,
4962
            OPEN_EXISTING,
4963
            FILE_FLAG_BACKUP_SEMANTICS,
4964
            NULL
4965
        );
4966
        if (hVolume == INVALID_HANDLE_VALUE) {
4967
            err = GetLastError();
4968
        } else {
4969
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
4970
            volumeState.Version = 1;
4971
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
4972
            if (!DeviceIoControl(
4973
                hVolume,
4974
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
4975
                &volumeState,
4976
                sizeof(volumeState),
4977
                &volumeState,
4978
                sizeof(volumeState),
4979
                NULL,
4980
                NULL
4981
            )) {
4982
                err = GetLastError();
4983
            }
4984
            CloseHandle(hVolume);
4985
            if (err == ERROR_INVALID_PARAMETER) {
4986
                /* not supported on this platform */
4987
                r = Py_False;
4988
            } else if (!err) {
4989
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
4990
                    ? Py_True : Py_False;
4991
            }
4992
        }
4993
    }
4994
    Py_END_ALLOW_THREADS
4995
4996
    if (err) {
4997
        PyErr_SetFromWindowsErr(err);
4998
        return NULL;
4999
    }
5000
5001
    if (r) {
5002
        return Py_NewRef(r);
5003
    }
5004
5005
    return NULL;
5006
}
5007
5008
5009
int
5010
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5011
{
5012
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5013
    DWORD result;
5014
5015
    result = GetFullPathNameW(path,
5016
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5017
                              NULL);
5018
    if (!result) {
5019
        return -1;
5020
    }
5021
5022
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5023
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5024
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5025
        }
5026
        else {
5027
            woutbufp = NULL;
5028
        }
5029
        if (!woutbufp) {
5030
            *abspath_p = NULL;
5031
            return 0;
5032
        }
5033
5034
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5035
        if (!result) {
5036
            PyMem_RawFree(woutbufp);
5037
            return -1;
5038
        }
5039
    }
5040
5041
    if (woutbufp != woutbuf) {
5042
        *abspath_p = woutbufp;
5043
        return 0;
5044
    }
5045
5046
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5047
    return 0;
5048
}
5049
5050
5051
/* A helper function for abspath on win32 */
5052
/*[clinic input]
5053
os._getfullpathname
5054
5055
    path: path_t
5056
    /
5057
5058
[clinic start generated code]*/
5059
5060
static PyObject *
5061
os__getfullpathname_impl(PyObject *module, path_t *path)
5062
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5063
{
5064
    wchar_t *abspath;
5065
5066
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5067
        return win32_error_object("GetFullPathNameW", path->object);
5068
    }
5069
    if (abspath == NULL) {
5070
        return PyErr_NoMemory();
5071
    }
5072
5073
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5074
    PyMem_RawFree(abspath);
5075
    if (str == NULL) {
5076
        return NULL;
5077
    }
5078
    if (PyBytes_Check(path->object)) {
5079
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5080
    }
5081
    return str;
5082
}
5083
5084
5085
/*[clinic input]
5086
os._getfinalpathname
5087
5088
    path: path_t
5089
    /
5090
5091
A helper function for samepath on windows.
5092
[clinic start generated code]*/
5093
5094
static PyObject *
5095
os__getfinalpathname_impl(PyObject *module, path_t *path)
5096
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5097
{
5098
    HANDLE hFile;
5099
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5100
    int buf_size = Py_ARRAY_LENGTH(buf);
5101
    int result_length;
5102
    PyObject *result;
5103
5104
    Py_BEGIN_ALLOW_THREADS
5105
    hFile = CreateFileW(
5106
        path->wide,
5107
        0, /* desired access */
5108
        0, /* share mode */
5109
        NULL, /* security attributes */
5110
        OPEN_EXISTING,
5111
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5112
        FILE_FLAG_BACKUP_SEMANTICS,
5113
        NULL);
5114
    Py_END_ALLOW_THREADS
5115
5116
    if (hFile == INVALID_HANDLE_VALUE) {
5117
        return win32_error_object("CreateFileW", path->object);
5118
    }
5119
5120
    /* We have a good handle to the target, use it to determine the
5121
       target path name. */
5122
    while (1) {
5123
        Py_BEGIN_ALLOW_THREADS
5124
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5125
                                                  buf_size, VOLUME_NAME_DOS);
5126
        Py_END_ALLOW_THREADS
5127
5128
        if (!result_length) {
5129
            result = win32_error_object("GetFinalPathNameByHandleW",
5130
                                         path->object);
5131
            goto cleanup;
5132
        }
5133
5134
        if (result_length < buf_size) {
5135
            break;
5136
        }
5137
5138
        wchar_t *tmp;
5139
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5140
                            result_length * sizeof(*tmp));
5141
        if (!tmp) {
5142
            result = PyErr_NoMemory();
5143
            goto cleanup;
5144
        }
5145
5146
        buf_size = result_length;
5147
        target_path = tmp;
5148
    }
5149
5150
    result = PyUnicode_FromWideChar(target_path, result_length);
5151
    if (result && PyBytes_Check(path->object)) {
5152
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5153
    }
5154
5155
cleanup:
5156
    if (target_path != buf) {
5157
        PyMem_Free(target_path);
5158
    }
5159
    CloseHandle(hFile);
5160
    return result;
5161
}
5162
5163
/*[clinic input]
5164
os._findfirstfile
5165
    path: path_t
5166
    /
5167
A function to get the real file name without accessing the file in Windows.
5168
[clinic start generated code]*/
5169
5170
static PyObject *
5171
os__findfirstfile_impl(PyObject *module, path_t *path)
5172
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5173
{
5174
    PyObject *result;
5175
    HANDLE hFindFile;
5176
    WIN32_FIND_DATAW wFileData;
5177
    WCHAR *wRealFileName;
5178
5179
    Py_BEGIN_ALLOW_THREADS
5180
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5181
    Py_END_ALLOW_THREADS
5182
5183
    if (hFindFile == INVALID_HANDLE_VALUE) {
5184
        path_error(path);
5185
        return NULL;
5186
    }
5187
5188
    wRealFileName = wFileData.cFileName;
5189
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5190
    FindClose(hFindFile);
5191
    return result;
5192
}
5193
5194
5195
/*[clinic input]
5196
os._getvolumepathname
5197
5198
    path: path_t
5199
5200
A helper function for ismount on Win32.
5201
[clinic start generated code]*/
5202
5203
static PyObject *
5204
os__getvolumepathname_impl(PyObject *module, path_t *path)
5205
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5206
{
5207
    PyObject *result;
5208
    wchar_t *mountpath=NULL;
5209
    size_t buflen;
5210
    BOOL ret;
5211
5212
    /* Volume path should be shorter than entire path */
5213
    buflen = Py_MAX(path->length, MAX_PATH);
5214
5215
    if (buflen > PY_DWORD_MAX) {
5216
        PyErr_SetString(PyExc_OverflowError, "path too long");
5217
        return NULL;
5218
    }
5219
5220
    mountpath = PyMem_New(wchar_t, buflen);
5221
    if (mountpath == NULL)
5222
        return PyErr_NoMemory();
5223
5224
    Py_BEGIN_ALLOW_THREADS
5225
    ret = GetVolumePathNameW(path->wide, mountpath,
5226
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5227
    Py_END_ALLOW_THREADS
5228
5229
    if (!ret) {
5230
        result = win32_error_object("_getvolumepathname", path->object);
5231
        goto exit;
5232
    }
5233
    result = PyUnicode_FromWideChar(mountpath, -1);
5234
    if (PyBytes_Check(path->object))
5235
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5236
5237
exit:
5238
    PyMem_Free(mountpath);
5239
    return result;
5240
}
5241
5242
5243
/*[clinic input]
5244
os._path_splitroot
5245
5246
    path: path_t,
5247
    /
5248
5249
Removes everything after the root on Win32.
5250
[clinic start generated code]*/
5251
5252
static PyObject *
5253
os__path_splitroot_impl(PyObject *module, path_t *path)
5254
/*[clinic end generated code: output=ab7f1a88b654581c input=42831e41f8458f6d]*/
5255
{
5256
    wchar_t *buffer;
5257
    wchar_t *end;
5258
    PyObject *result = NULL;
5259
    HRESULT ret;
5260
5261
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5262
    if (!buffer) {
5263
        return NULL;
5264
    }
5265
    wcscpy(buffer, path->wide);
5266
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5267
        *p = L'\\';
5268
    }
5269
5270
    Py_BEGIN_ALLOW_THREADS
5271
    ret = PathCchSkipRoot(buffer, &end);
5272
    Py_END_ALLOW_THREADS
5273
    if (FAILED(ret)) {
5274
        result = Py_BuildValue("sO", "", path->object);
5275
    } else if (end != buffer) {
5276
        size_t rootLen = (size_t)(end - buffer);
5277
        result = Py_BuildValue("NN",
5278
            PyUnicode_FromWideChar(path->wide, rootLen),
5279
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5280
        );
5281
    } else {
5282
        result = Py_BuildValue("Os", path->object, "");
5283
    }
5284
    PyMem_Free(buffer);
5285
5286
    return result;
5287
}
5288
5289
5290
#define PY_IFREG  1 // Regular file
5291
#define PY_IFDIR  2 // Directory
5292
#define PY_IFLNK  4 // Symlink
5293
#define PY_IFMNT  8 // Mount Point (junction)
5294
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5295
#define PY_IFRRP 32 // Regular Reparse Point
5296
5297
static inline BOOL
5298
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5299
{
5300
    switch (testedType) {
5301
    case PY_IFREG:
5302
        return diskDevice && attributes &&
5303
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5304
    case PY_IFDIR:
5305
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5306
    case PY_IFLNK:
5307
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5308
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5309
    case PY_IFMNT:
5310
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5311
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5312
    case PY_IFLRP:
5313
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5314
               IsReparseTagNameSurrogate(reparseTag);
5315
    case PY_IFRRP:
5316
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5317
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5318
    }
5319
5320
    return FALSE;
5321
}
5322
5323
static BOOL
5324
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5325
{
5326
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5327
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5328
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5329
5330
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5331
    if (diskOnly && !diskDevice) {
5332
        return FALSE;
5333
    }
5334
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5335
        FILE_ATTRIBUTE_TAG_INFO info;
5336
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5337
                                            sizeof(info)) &&
5338
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5339
                         testedType);
5340
    }
5341
    FILE_BASIC_INFO info;
5342
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5343
                                        sizeof(info)) &&
5344
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5345
}
5346
5347
static BOOL
5348
_testFileTypeByName(LPCWSTR path, int testedType)
5349
{
5350
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5351
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5352
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5353
5354
    FILE_STAT_BASIC_INFORMATION info;
5355
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5356
                                     sizeof(info)))
5357
    {
5358
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5359
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5360
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5361
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5362
                                diskDevice, testedType);
5363
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5364
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5365
        {
5366
            return result;
5367
        }
5368
    }
5369
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5370
                GetLastError()))
5371
    {
5372
        return FALSE;
5373
    }
5374
5375
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5376
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5377
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5378
    }
5379
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5380
                               OPEN_EXISTING, flags, NULL);
5381
    if (hfile != INVALID_HANDLE_VALUE) {
5382
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5383
        CloseHandle(hfile);
5384
        return result;
5385
    }
5386
5387
    switch (GetLastError()) {
5388
    case ERROR_ACCESS_DENIED:
5389
    case ERROR_SHARING_VIOLATION:
5390
    case ERROR_CANT_ACCESS_FILE:
5391
    case ERROR_INVALID_PARAMETER:
5392
        int rc;
5393
        STRUCT_STAT st;
5394
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5395
            rc = STAT(path, &st);
5396
        }
5397
        else {
5398
            // PY_IFRRP is not generally supported in this case, except for
5399
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5400
            rc = LSTAT(path, &st);
5401
        }
5402
        if (!rc) {
5403
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5404
                             st.st_mode & S_IFREG, testedType);
5405
        }
5406
    }
5407
5408
    return FALSE;
5409
}
5410
5411
5412
static BOOL
5413
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5414
{
5415
    FILE_STAT_BASIC_INFORMATION info;
5416
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5417
                                     sizeof(info)))
5418
    {
5419
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5420
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5421
        {
5422
            return TRUE;
5423
        }
5424
    }
5425
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5426
                    GetLastError()))
5427
    {
5428
        return FALSE;
5429
    }
5430
5431
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5432
    if (!followLinks) {
5433
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5434
    }
5435
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5436
                               OPEN_EXISTING, flags, NULL);
5437
    if (hfile != INVALID_HANDLE_VALUE) {
5438
        if (followLinks) {
5439
            CloseHandle(hfile);
5440
            return TRUE;
5441
        }
5442
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5443
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5444
        CloseHandle(hfile);
5445
        if (!result) {
5446
            return TRUE;
5447
        }
5448
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5449
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5450
        if (hfile != INVALID_HANDLE_VALUE) {
5451
            CloseHandle(hfile);
5452
            return TRUE;
5453
        }
5454
    }
5455
5456
    switch (GetLastError()) {
5457
    case ERROR_ACCESS_DENIED:
5458
    case ERROR_SHARING_VIOLATION:
5459
    case ERROR_CANT_ACCESS_FILE:
5460
    case ERROR_INVALID_PARAMETER:
5461
        STRUCT_STAT _st;
5462
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5463
    }
5464
5465
    return FALSE;
5466
}
5467
5468
5469
static BOOL
5470
_testFileExists(path_t *path, BOOL followLinks)
5471
{
5472
    BOOL result = FALSE;
5473
    if (path->value_error) {
5474
        return FALSE;
5475
    }
5476
5477
    Py_BEGIN_ALLOW_THREADS
5478
    if (path->fd != -1) {
5479
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5480
        if (hfile != INVALID_HANDLE_VALUE) {
5481
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5482
                result = TRUE;
5483
            }
5484
        }
5485
    }
5486
    else if (path->wide) {
5487
        result = _testFileExistsByName(path->wide, followLinks);
5488
    }
5489
    Py_END_ALLOW_THREADS
5490
5491
    return result;
5492
}
5493
5494
5495
static BOOL
5496
_testFileType(path_t *path, int testedType)
5497
{
5498
    BOOL result = FALSE;
5499
    if (path->value_error) {
5500
        return FALSE;
5501
    }
5502
5503
    Py_BEGIN_ALLOW_THREADS
5504
    if (path->fd != -1) {
5505
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5506
        if (hfile != INVALID_HANDLE_VALUE) {
5507
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5508
        }
5509
    }
5510
    else if (path->wide) {
5511
        result = _testFileTypeByName(path->wide, testedType);
5512
    }
5513
    Py_END_ALLOW_THREADS
5514
5515
    return result;
5516
}
5517
5518
5519
/*[clinic input]
5520
os._path_exists -> bool
5521
5522
    path: path_t(allow_fd=True, suppress_value_error=True)
5523
5524
Test whether a path exists.  Returns False for broken symbolic links.
5525
5526
[clinic start generated code]*/
5527
5528
static int
5529
os__path_exists_impl(PyObject *module, path_t *path)
5530
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5531
{
5532
    return _testFileExists(path, TRUE);
5533
}
5534
5535
5536
/*[clinic input]
5537
os._path_lexists -> bool
5538
5539
    path: path_t(allow_fd=True, suppress_value_error=True)
5540
5541
Test whether a path exists.  Returns True for broken symbolic links.
5542
5543
[clinic start generated code]*/
5544
5545
static int
5546
os__path_lexists_impl(PyObject *module, path_t *path)
5547
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5548
{
5549
    return _testFileExists(path, FALSE);
5550
}
5551
5552
5553
/*[clinic input]
5554
os._path_isdir -> bool
5555
5556
    path: path_t(allow_fd=True, suppress_value_error=True),
5557
    /
5558
5559
Return true if the pathname refers to an existing directory.
5560
5561
[clinic start generated code]*/
5562
5563
static int
5564
os__path_isdir_impl(PyObject *module, path_t *path)
5565
/*[clinic end generated code: output=d5786196f9e2fa7a input=0d3fd790564d244b]*/
5566
{
5567
    return _testFileType(path, PY_IFDIR);
5568
}
5569
5570
5571
/*[clinic input]
5572
os._path_isfile -> bool
5573
5574
    path: path_t(allow_fd=True, suppress_value_error=True)
5575
5576
Test whether a path is a regular file
5577
5578
[clinic start generated code]*/
5579
5580
static int
5581
os__path_isfile_impl(PyObject *module, path_t *path)
5582
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
5583
{
5584
    return _testFileType(path, PY_IFREG);
5585
}
5586
5587
5588
/*[clinic input]
5589
os._path_islink -> bool
5590
5591
    path: path_t(allow_fd=True, suppress_value_error=True)
5592
5593
Test whether a path is a symbolic link
5594
5595
[clinic start generated code]*/
5596
5597
static int
5598
os__path_islink_impl(PyObject *module, path_t *path)
5599
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
5600
{
5601
    return _testFileType(path, PY_IFLNK);
5602
}
5603
5604
5605
/*[clinic input]
5606
os._path_isjunction -> bool
5607
5608
    path: path_t(allow_fd=True, suppress_value_error=True)
5609
5610
Test whether a path is a junction
5611
5612
[clinic start generated code]*/
5613
5614
static int
5615
os__path_isjunction_impl(PyObject *module, path_t *path)
5616
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
5617
{
5618
    return _testFileType(path, PY_IFMNT);
5619
}
5620
5621
#undef PY_IFREG
5622
#undef PY_IFDIR
5623
#undef PY_IFLNK
5624
#undef PY_IFMNT
5625
#undef PY_IFLRP
5626
#undef PY_IFRRP
5627
5628
#endif /* MS_WINDOWS */
5629
5630
5631
/*[clinic input]
5632
os._path_splitroot_ex
5633
5634
    path: path_t(make_wide=True, nonstrict=True),
5635
    /
5636
5637
Split a pathname into drive, root and tail.
5638
5639
The tail contains anything after the root.
5640
[clinic start generated code]*/
5641
5642
static PyObject *
5643
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
5644
/*[clinic end generated code: output=4b0072b6cdf4b611 input=4ac47b394d68bd21]*/
5645
0
{
5646
0
    Py_ssize_t drvsize, rootsize;
5647
0
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
5648
5649
0
    const wchar_t *buffer = path->wide;
5650
0
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
5651
0
    drv = PyUnicode_FromWideChar(buffer, drvsize);
5652
0
    if (drv == NULL) {
5653
0
        goto exit;
5654
0
    }
5655
0
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
5656
0
    if (root == NULL) {
5657
0
        goto exit;
5658
0
    }
5659
0
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
5660
0
                                  path->length - drvsize - rootsize);
5661
0
    if (tail == NULL) {
5662
0
        goto exit;
5663
0
    }
5664
0
    if (PyBytes_Check(path->object)) {
5665
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
5666
0
        if (drv == NULL) {
5667
0
            goto exit;
5668
0
        }
5669
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
5670
0
        if (root == NULL) {
5671
0
            goto exit;
5672
0
        }
5673
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
5674
0
        if (tail == NULL) {
5675
0
            goto exit;
5676
0
        }
5677
0
    }
5678
0
    result = PyTuple_Pack(3, drv, root, tail);
5679
0
exit:
5680
0
    Py_XDECREF(drv);
5681
0
    Py_XDECREF(root);
5682
0
    Py_XDECREF(tail);
5683
0
    return result;
5684
0
}
5685
5686
5687
/*[clinic input]
5688
os._path_normpath
5689
5690
    path: path_t(make_wide=True, nonstrict=True)
5691
5692
Normalize path, eliminating double slashes, etc.
5693
[clinic start generated code]*/
5694
5695
static PyObject *
5696
os__path_normpath_impl(PyObject *module, path_t *path)
5697
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
5698
110
{
5699
110
    PyObject *result;
5700
110
    Py_ssize_t norm_len;
5701
110
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
5702
110
                                               path->length, &norm_len);
5703
110
    if (!norm_len) {
5704
0
        result = PyUnicode_FromOrdinal('.');
5705
0
    }
5706
110
    else {
5707
110
        result = PyUnicode_FromWideChar(norm_path, norm_len);
5708
110
    }
5709
110
    if (PyBytes_Check(path->object)) {
5710
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5711
0
    }
5712
110
    return result;
5713
110
}
5714
5715
/*[clinic input]
5716
os.mkdir
5717
5718
    path : path_t
5719
5720
    mode: int = 0o777
5721
5722
    *
5723
5724
    dir_fd : dir_fd(requires='mkdirat') = None
5725
5726
# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
5727
5728
Create a directory.
5729
5730
If dir_fd is not None, it should be a file descriptor open to a directory,
5731
  and path should be relative; path will then be relative to that directory.
5732
dir_fd may not be implemented on your platform.
5733
  If it is unavailable, using it will raise a NotImplementedError.
5734
5735
The mode argument is ignored on Windows. Where it is used, the current umask
5736
value is first masked out.
5737
[clinic start generated code]*/
5738
5739
static PyObject *
5740
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
5741
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
5742
0
{
5743
0
    int result;
5744
#ifdef MS_WINDOWS
5745
    int error = 0;
5746
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
5747
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
5748
#endif
5749
0
#ifdef HAVE_MKDIRAT
5750
0
    int mkdirat_unavailable = 0;
5751
0
#endif
5752
5753
0
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
5754
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5755
0
        return NULL;
5756
0
    }
5757
5758
#ifdef MS_WINDOWS
5759
    Py_BEGIN_ALLOW_THREADS
5760
    // For API sets that don't support these APIs, we have no choice
5761
    // but to silently create a directory with default ACL.
5762
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
5763
    if (mode == 0700 /* 0o700 */) {
5764
        ULONG sdSize;
5765
        pSecAttr = &secAttr;
5766
        // Set a discretionary ACL (D) that is protected (P) and includes
5767
        // inheritable (OICI) entries that allow (A) full control (FA) to
5768
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
5769
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
5770
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
5771
            SDDL_REVISION_1,
5772
            &secAttr.lpSecurityDescriptor,
5773
            &sdSize
5774
        )) {
5775
            error = GetLastError();
5776
        }
5777
    }
5778
#endif
5779
    if (!error) {
5780
        result = CreateDirectoryW(path->wide, pSecAttr);
5781
        if (secAttr.lpSecurityDescriptor &&
5782
            // uncommonly, LocalFree returns non-zero on error, but still uses
5783
            // GetLastError() to see what the error code is
5784
            LocalFree(secAttr.lpSecurityDescriptor)) {
5785
            error = GetLastError();
5786
        }
5787
    }
5788
    Py_END_ALLOW_THREADS
5789
5790
    if (error) {
5791
        return PyErr_SetFromWindowsErr(error);
5792
    }
5793
    if (!result) {
5794
        return path_error(path);
5795
    }
5796
#else
5797
0
    Py_BEGIN_ALLOW_THREADS
5798
0
#if HAVE_MKDIRAT
5799
0
    if (dir_fd != DEFAULT_DIR_FD) {
5800
0
      if (HAVE_MKDIRAT_RUNTIME) {
5801
0
        result = mkdirat(dir_fd, path->narrow, mode);
5802
5803
0
      } else {
5804
0
        mkdirat_unavailable = 1;
5805
0
      }
5806
0
    } else
5807
0
#endif
5808
#if defined(__WATCOMC__) && !defined(__QNX__)
5809
        result = mkdir(path->narrow);
5810
#else
5811
0
        result = mkdir(path->narrow, mode);
5812
0
#endif
5813
0
    Py_END_ALLOW_THREADS
5814
5815
0
#if HAVE_MKDIRAT
5816
0
    if (mkdirat_unavailable) {
5817
0
        argument_unavailable_error(NULL, "dir_fd");
5818
0
        return NULL;
5819
0
    }
5820
0
#endif
5821
5822
0
    if (result < 0)
5823
0
        return path_error(path);
5824
0
#endif /* MS_WINDOWS */
5825
0
    Py_RETURN_NONE;
5826
0
}
5827
5828
5829
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
5830
#if defined(HAVE_SYS_RESOURCE_H)
5831
#include <sys/resource.h>
5832
#endif
5833
5834
5835
#ifdef HAVE_NICE
5836
/*[clinic input]
5837
os.nice
5838
5839
    increment: int
5840
    /
5841
5842
Add increment to the priority of process and return the new priority.
5843
[clinic start generated code]*/
5844
5845
static PyObject *
5846
os_nice_impl(PyObject *module, int increment)
5847
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
5848
0
{
5849
0
    int value;
5850
5851
    /* There are two flavours of 'nice': one that returns the new
5852
       priority (as required by almost all standards out there) and the
5853
       Linux/FreeBSD one, which returns '0' on success and advices
5854
       the use of getpriority() to get the new priority.
5855
5856
       If we are of the nice family that returns the new priority, we
5857
       need to clear errno before the call, and check if errno is filled
5858
       before calling posix_error() on a returnvalue of -1, because the
5859
       -1 may be the actual new priority! */
5860
5861
0
    errno = 0;
5862
0
    value = nice(increment);
5863
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
5864
    if (value == 0)
5865
        value = getpriority(PRIO_PROCESS, 0);
5866
#endif
5867
0
    if (value == -1 && errno != 0)
5868
        /* either nice() or getpriority() returned an error */
5869
0
        return posix_error();
5870
0
    return PyLong_FromLong((long) value);
5871
0
}
5872
#endif /* HAVE_NICE */
5873
5874
5875
#ifdef HAVE_GETPRIORITY
5876
/*[clinic input]
5877
os.getpriority
5878
5879
    which: int
5880
    who: int
5881
5882
Return program scheduling priority.
5883
[clinic start generated code]*/
5884
5885
static PyObject *
5886
os_getpriority_impl(PyObject *module, int which, int who)
5887
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
5888
0
{
5889
0
    int retval;
5890
5891
0
    errno = 0;
5892
0
    retval = getpriority(which, who);
5893
0
    if (errno != 0)
5894
0
        return posix_error();
5895
0
    return PyLong_FromLong((long)retval);
5896
0
}
5897
#endif /* HAVE_GETPRIORITY */
5898
5899
5900
#ifdef HAVE_SETPRIORITY
5901
/*[clinic input]
5902
os.setpriority
5903
5904
    which: int
5905
    who: int
5906
    priority: int
5907
5908
Set program scheduling priority.
5909
[clinic start generated code]*/
5910
5911
static PyObject *
5912
os_setpriority_impl(PyObject *module, int which, int who, int priority)
5913
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
5914
0
{
5915
0
    int retval;
5916
5917
0
    retval = setpriority(which, who, priority);
5918
0
    if (retval == -1)
5919
0
        return posix_error();
5920
0
    Py_RETURN_NONE;
5921
0
}
5922
#endif /* HAVE_SETPRIORITY */
5923
5924
5925
static PyObject *
5926
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
5927
0
{
5928
0
    const char *function_name = is_replace ? "replace" : "rename";
5929
0
    int dir_fd_specified;
5930
5931
0
#ifdef HAVE_RENAMEAT
5932
0
    int renameat_unavailable = 0;
5933
0
#endif
5934
5935
#ifdef MS_WINDOWS
5936
    BOOL result;
5937
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
5938
#else
5939
0
    int result;
5940
0
#endif
5941
5942
0
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
5943
0
                       (dst_dir_fd != DEFAULT_DIR_FD);
5944
#ifndef HAVE_RENAMEAT
5945
    if (dir_fd_specified) {
5946
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5947
        return NULL;
5948
    }
5949
#endif
5950
5951
0
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
5952
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
5953
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
5954
0
        return NULL;
5955
0
    }
5956
5957
#ifdef MS_WINDOWS
5958
    Py_BEGIN_ALLOW_THREADS
5959
    result = MoveFileExW(src->wide, dst->wide, flags);
5960
    Py_END_ALLOW_THREADS
5961
5962
    if (!result)
5963
        return path_error2(src, dst);
5964
5965
#else
5966
0
    Py_BEGIN_ALLOW_THREADS
5967
0
#ifdef HAVE_RENAMEAT
5968
0
    if (dir_fd_specified) {
5969
0
        if (HAVE_RENAMEAT_RUNTIME) {
5970
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
5971
0
        } else {
5972
0
            renameat_unavailable = 1;
5973
0
        }
5974
0
    } else
5975
0
#endif
5976
0
    result = rename(src->narrow, dst->narrow);
5977
0
    Py_END_ALLOW_THREADS
5978
5979
5980
0
#ifdef HAVE_RENAMEAT
5981
0
    if (renameat_unavailable) {
5982
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5983
0
        return NULL;
5984
0
    }
5985
0
#endif
5986
5987
0
    if (result)
5988
0
        return path_error2(src, dst);
5989
0
#endif
5990
0
    Py_RETURN_NONE;
5991
0
}
5992
5993
5994
/*[clinic input]
5995
@permit_long_docstring_body
5996
os.rename
5997
5998
    src : path_t
5999
    dst : path_t
6000
    *
6001
    src_dir_fd : dir_fd = None
6002
    dst_dir_fd : dir_fd = None
6003
6004
Rename a file or directory.
6005
6006
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6007
  descriptor open to a directory, and the respective path string (src or dst)
6008
  should be relative; the path will then be relative to that directory.
6009
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6010
  If they are unavailable, using them will raise a NotImplementedError.
6011
[clinic start generated code]*/
6012
6013
static PyObject *
6014
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6015
               int dst_dir_fd)
6016
/*[clinic end generated code: output=59e803072cf41230 input=11aae8c091162766]*/
6017
0
{
6018
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6019
0
}
6020
6021
6022
/*[clinic input]
6023
@permit_long_docstring_body
6024
os.replace = os.rename
6025
6026
Rename a file or directory, overwriting the destination.
6027
6028
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6029
  descriptor open to a directory, and the respective path string (src or dst)
6030
  should be relative; the path will then be relative to that directory.
6031
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6032
  If they are unavailable, using them will raise a NotImplementedError.
6033
[clinic start generated code]*/
6034
6035
static PyObject *
6036
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6037
                int dst_dir_fd)
6038
/*[clinic end generated code: output=1968c02e7857422b input=78d6c8087e90994c]*/
6039
0
{
6040
0
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6041
0
}
6042
6043
6044
/*[clinic input]
6045
os.rmdir
6046
6047
    path: path_t
6048
    *
6049
    dir_fd: dir_fd(requires='unlinkat') = None
6050
6051
Remove a directory.
6052
6053
If dir_fd is not None, it should be a file descriptor open to a directory,
6054
  and path should be relative; path will then be relative to that directory.
6055
dir_fd may not be implemented on your platform.
6056
  If it is unavailable, using it will raise a NotImplementedError.
6057
[clinic start generated code]*/
6058
6059
static PyObject *
6060
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6061
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
6062
0
{
6063
0
    int result;
6064
0
#ifdef HAVE_UNLINKAT
6065
0
    int unlinkat_unavailable = 0;
6066
0
#endif
6067
6068
0
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6069
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6070
0
        return NULL;
6071
0
    }
6072
6073
0
    Py_BEGIN_ALLOW_THREADS
6074
#ifdef MS_WINDOWS
6075
    /* Windows, success=1, UNIX, success=0 */
6076
    result = !RemoveDirectoryW(path->wide);
6077
#else
6078
0
#ifdef HAVE_UNLINKAT
6079
0
    if (dir_fd != DEFAULT_DIR_FD) {
6080
0
      if (HAVE_UNLINKAT_RUNTIME) {
6081
0
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6082
0
      } else {
6083
0
        unlinkat_unavailable = 1;
6084
0
        result = -1;
6085
0
      }
6086
0
    } else
6087
0
#endif
6088
0
        result = rmdir(path->narrow);
6089
0
#endif
6090
0
    Py_END_ALLOW_THREADS
6091
6092
0
#ifdef HAVE_UNLINKAT
6093
0
    if (unlinkat_unavailable) {
6094
0
        argument_unavailable_error("rmdir", "dir_fd");
6095
0
        return NULL;
6096
0
    }
6097
0
#endif
6098
6099
0
    if (result)
6100
0
        return path_error(path);
6101
6102
0
    Py_RETURN_NONE;
6103
0
}
6104
6105
6106
#ifdef HAVE_SYSTEM
6107
#ifdef MS_WINDOWS
6108
/*[clinic input]
6109
os.system -> long
6110
6111
    command: Py_UNICODE
6112
6113
Execute the command in a subshell.
6114
[clinic start generated code]*/
6115
6116
static long
6117
os_system_impl(PyObject *module, const wchar_t *command)
6118
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6119
{
6120
    long result;
6121
6122
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6123
        return -1;
6124
    }
6125
6126
    Py_BEGIN_ALLOW_THREADS
6127
    _Py_BEGIN_SUPPRESS_IPH
6128
    result = _wsystem(command);
6129
    _Py_END_SUPPRESS_IPH
6130
    Py_END_ALLOW_THREADS
6131
    return result;
6132
}
6133
#else /* MS_WINDOWS */
6134
/*[clinic input]
6135
os.system -> long
6136
6137
    command: unicode_fs_encoded
6138
6139
Execute the command in a subshell.
6140
[clinic start generated code]*/
6141
6142
static long
6143
os_system_impl(PyObject *module, PyObject *command)
6144
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6145
0
{
6146
0
    long result;
6147
0
    const char *bytes = PyBytes_AsString(command);
6148
6149
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6150
0
        return -1;
6151
0
    }
6152
6153
0
    Py_BEGIN_ALLOW_THREADS
6154
0
    result = system(bytes);
6155
0
    Py_END_ALLOW_THREADS
6156
0
    return result;
6157
0
}
6158
#endif
6159
#endif /* HAVE_SYSTEM */
6160
6161
6162
#ifdef HAVE_UMASK
6163
/*[clinic input]
6164
os.umask
6165
6166
    mask: int
6167
    /
6168
6169
Set the current numeric umask and return the previous umask.
6170
[clinic start generated code]*/
6171
6172
static PyObject *
6173
os_umask_impl(PyObject *module, int mask)
6174
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6175
0
{
6176
0
    int i = (int)umask(mask);
6177
0
    if (i < 0)
6178
0
        return posix_error();
6179
0
    return PyLong_FromLong((long)i);
6180
0
}
6181
#endif
6182
6183
#ifdef MS_WINDOWS
6184
6185
/* override the default DeleteFileW behavior so that directory
6186
symlinks can be removed with this function, the same as with
6187
Unix symlinks */
6188
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6189
{
6190
    WIN32_FILE_ATTRIBUTE_DATA info;
6191
    WIN32_FIND_DATAW find_data;
6192
    HANDLE find_data_handle;
6193
    int is_directory = 0;
6194
    int is_link = 0;
6195
6196
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6197
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6198
6199
        /* Get WIN32_FIND_DATA structure for the path to determine if
6200
           it is a symlink */
6201
        if(is_directory &&
6202
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6203
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6204
6205
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6206
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6207
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6208
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6209
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6210
                FindClose(find_data_handle);
6211
            }
6212
        }
6213
    }
6214
6215
    if (is_directory && is_link)
6216
        return RemoveDirectoryW(lpFileName);
6217
6218
    return DeleteFileW(lpFileName);
6219
}
6220
#endif /* MS_WINDOWS */
6221
6222
6223
/*[clinic input]
6224
os.unlink
6225
6226
    path: path_t
6227
    *
6228
    dir_fd: dir_fd(requires='unlinkat')=None
6229
6230
Remove a file (same as remove()).
6231
6232
If dir_fd is not None, it should be a file descriptor open to a directory,
6233
  and path should be relative; path will then be relative to that directory.
6234
dir_fd may not be implemented on your platform.
6235
  If it is unavailable, using it will raise a NotImplementedError.
6236
6237
[clinic start generated code]*/
6238
6239
static PyObject *
6240
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6241
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6242
0
{
6243
0
    int result;
6244
0
#ifdef HAVE_UNLINKAT
6245
0
    int unlinkat_unavailable = 0;
6246
0
#endif
6247
6248
0
    if (PySys_Audit("os.remove", "Oi", path->object,
6249
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6250
0
        return NULL;
6251
0
    }
6252
6253
0
    Py_BEGIN_ALLOW_THREADS
6254
0
    _Py_BEGIN_SUPPRESS_IPH
6255
#ifdef MS_WINDOWS
6256
    /* Windows, success=1, UNIX, success=0 */
6257
    result = !Py_DeleteFileW(path->wide);
6258
#else
6259
0
#ifdef HAVE_UNLINKAT
6260
0
    if (dir_fd != DEFAULT_DIR_FD) {
6261
0
      if (HAVE_UNLINKAT_RUNTIME) {
6262
6263
0
        result = unlinkat(dir_fd, path->narrow, 0);
6264
0
      } else {
6265
0
        unlinkat_unavailable = 1;
6266
0
      }
6267
0
    } else
6268
0
#endif /* HAVE_UNLINKAT */
6269
0
        result = unlink(path->narrow);
6270
0
#endif
6271
0
    _Py_END_SUPPRESS_IPH
6272
0
    Py_END_ALLOW_THREADS
6273
6274
0
#ifdef HAVE_UNLINKAT
6275
0
    if (unlinkat_unavailable) {
6276
0
        argument_unavailable_error(NULL, "dir_fd");
6277
0
        return NULL;
6278
0
    }
6279
0
#endif
6280
6281
0
    if (result)
6282
0
        return path_error(path);
6283
6284
0
    Py_RETURN_NONE;
6285
0
}
6286
6287
6288
/*[clinic input]
6289
os.remove = os.unlink
6290
6291
Remove a file (same as unlink()).
6292
6293
If dir_fd is not None, it should be a file descriptor open to a directory,
6294
  and path should be relative; path will then be relative to that directory.
6295
dir_fd may not be implemented on your platform.
6296
  If it is unavailable, using it will raise a NotImplementedError.
6297
[clinic start generated code]*/
6298
6299
static PyObject *
6300
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6301
/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6302
0
{
6303
0
    return os_unlink_impl(module, path, dir_fd);
6304
0
}
6305
6306
6307
static PyStructSequence_Field uname_result_fields[] = {
6308
    {"sysname",    "operating system name"},
6309
    {"nodename",   "name of machine on network (implementation-defined)"},
6310
    {"release",    "operating system release"},
6311
    {"version",    "operating system version"},
6312
    {"machine",    "hardware identifier"},
6313
    {NULL}
6314
};
6315
6316
PyDoc_STRVAR(uname_result__doc__,
6317
"uname_result: Result from os.uname().\n\n\
6318
This object may be accessed either as a tuple of\n\
6319
  (sysname, nodename, release, version, machine),\n\
6320
or via the attributes sysname, nodename, release, version, and machine.\n\
6321
\n\
6322
See os.uname for more information.");
6323
6324
static PyStructSequence_Desc uname_result_desc = {
6325
    MODNAME ".uname_result", /* name */
6326
    uname_result__doc__, /* doc */
6327
    uname_result_fields,
6328
    5
6329
};
6330
6331
#ifdef HAVE_UNAME
6332
/*[clinic input]
6333
os.uname
6334
6335
Return an object identifying the current operating system.
6336
6337
The object behaves like a named tuple with the following fields:
6338
  (sysname, nodename, release, version, machine)
6339
6340
[clinic start generated code]*/
6341
6342
static PyObject *
6343
os_uname_impl(PyObject *module)
6344
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6345
0
{
6346
0
    struct utsname u;
6347
0
    int res;
6348
0
    PyObject *value;
6349
6350
0
    Py_BEGIN_ALLOW_THREADS
6351
0
    res = uname(&u);
6352
0
    Py_END_ALLOW_THREADS
6353
0
    if (res < 0)
6354
0
        return posix_error();
6355
6356
0
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6357
0
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6358
0
    if (value == NULL)
6359
0
        return NULL;
6360
6361
0
#define SET(i, field) \
6362
0
    { \
6363
0
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6364
0
    if (!o) { \
6365
0
        Py_DECREF(value); \
6366
0
        return NULL; \
6367
0
    } \
6368
0
    PyStructSequence_SET_ITEM(value, i, o); \
6369
0
    } \
6370
0
6371
0
    SET(0, u.sysname);
6372
0
    SET(1, u.nodename);
6373
0
    SET(2, u.release);
6374
0
    SET(3, u.version);
6375
0
    SET(4, u.machine);
6376
6377
0
#undef SET
6378
6379
0
    return value;
6380
0
}
6381
#endif /* HAVE_UNAME */
6382
6383
6384
6385
typedef struct {
6386
    int    now;
6387
    time_t atime_s;
6388
    long   atime_ns;
6389
    time_t mtime_s;
6390
    long   mtime_ns;
6391
} utime_t;
6392
6393
/*
6394
 * these macros assume that "ut" is a pointer to a utime_t
6395
 * they also intentionally leak the declaration of a pointer named "time"
6396
 */
6397
#define UTIME_TO_TIMESPEC \
6398
0
    struct timespec ts[2]; \
6399
0
    struct timespec *time; \
6400
0
    if (ut->now) \
6401
0
        time = NULL; \
6402
0
    else { \
6403
0
        ts[0].tv_sec = ut->atime_s; \
6404
0
        ts[0].tv_nsec = ut->atime_ns; \
6405
0
        ts[1].tv_sec = ut->mtime_s; \
6406
0
        ts[1].tv_nsec = ut->mtime_ns; \
6407
0
        time = ts; \
6408
0
    } \
6409
6410
#define UTIME_TO_TIMEVAL \
6411
0
    struct timeval tv[2]; \
6412
0
    struct timeval *time; \
6413
0
    if (ut->now) \
6414
0
        time = NULL; \
6415
0
    else { \
6416
0
        tv[0].tv_sec = ut->atime_s; \
6417
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6418
0
        tv[1].tv_sec = ut->mtime_s; \
6419
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6420
0
        time = tv; \
6421
0
    } \
6422
6423
#define UTIME_TO_UTIMBUF \
6424
    struct utimbuf u; \
6425
    struct utimbuf *time; \
6426
    if (ut->now) \
6427
        time = NULL; \
6428
    else { \
6429
        u.actime = ut->atime_s; \
6430
        u.modtime = ut->mtime_s; \
6431
        time = &u; \
6432
    }
6433
6434
#define UTIME_TO_TIME_T \
6435
    time_t timet[2]; \
6436
    time_t *time; \
6437
    if (ut->now) \
6438
        time = NULL; \
6439
    else { \
6440
        timet[0] = ut->atime_s; \
6441
        timet[1] = ut->mtime_s; \
6442
        time = timet; \
6443
    } \
6444
6445
6446
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6447
6448
static int
6449
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6450
0
{
6451
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6452
    if (HAVE_UTIMENSAT_RUNTIME) {
6453
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6454
        UTIME_TO_TIMESPEC;
6455
        return utimensat(dir_fd, path, time, flags);
6456
    }  else {
6457
        errno = ENOSYS;
6458
        return -1;
6459
    }
6460
#elif defined(HAVE_UTIMENSAT)
6461
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6462
0
    UTIME_TO_TIMESPEC;
6463
0
    return utimensat(dir_fd, path, time, flags);
6464
#elif defined(HAVE_FUTIMESAT)
6465
    UTIME_TO_TIMEVAL;
6466
    /*
6467
     * follow_symlinks will never be false here;
6468
     * we only allow !follow_symlinks and dir_fd together
6469
     * if we have utimensat()
6470
     */
6471
    assert(follow_symlinks);
6472
    return futimesat(dir_fd, path, time);
6473
#endif
6474
0
}
6475
6476
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6477
#else
6478
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6479
#endif
6480
6481
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6482
6483
static int
6484
utime_fd(utime_t *ut, int fd)
6485
0
{
6486
0
#ifdef HAVE_FUTIMENS
6487
6488
0
    if (HAVE_FUTIMENS_RUNTIME) {
6489
6490
0
    UTIME_TO_TIMESPEC;
6491
0
    return futimens(fd, time);
6492
6493
0
    } else
6494
#ifndef HAVE_FUTIMES
6495
    {
6496
        /* Not sure if this can happen */
6497
        PyErr_SetString(
6498
            PyExc_RuntimeError,
6499
            "neither futimens nor futimes are supported"
6500
            " on this system");
6501
        return -1;
6502
    }
6503
#endif
6504
6505
0
#endif
6506
0
#ifdef HAVE_FUTIMES
6507
0
    {
6508
0
    UTIME_TO_TIMEVAL;
6509
0
    return futimes(fd, time);
6510
0
    }
6511
0
#endif
6512
0
}
6513
6514
    #define PATH_UTIME_HAVE_FD 1
6515
#else
6516
    #define PATH_UTIME_HAVE_FD 0
6517
#endif
6518
6519
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6520
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6521
#endif
6522
6523
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6524
6525
static int
6526
utime_nofollow_symlinks(utime_t *ut, const char *path)
6527
0
{
6528
0
#ifdef HAVE_UTIMENSAT
6529
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6530
0
        UTIME_TO_TIMESPEC;
6531
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6532
0
    } else
6533
#ifndef HAVE_LUTIMES
6534
    {
6535
        /* Not sure if this can happen */
6536
        PyErr_SetString(
6537
            PyExc_RuntimeError,
6538
            "neither utimensat nor lutimes are supported"
6539
            " on this system");
6540
        return -1;
6541
    }
6542
#endif
6543
0
#endif
6544
6545
0
#ifdef HAVE_LUTIMES
6546
0
    {
6547
0
    UTIME_TO_TIMEVAL;
6548
0
    return lutimes(path, time);
6549
0
    }
6550
0
#endif
6551
0
}
6552
6553
#endif
6554
6555
#ifndef MS_WINDOWS
6556
6557
static int
6558
utime_default(utime_t *ut, const char *path)
6559
0
{
6560
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6561
    if (HAVE_UTIMENSAT_RUNTIME) {
6562
        UTIME_TO_TIMESPEC;
6563
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
6564
    } else {
6565
        UTIME_TO_TIMEVAL;
6566
        return utimes(path, time);
6567
    }
6568
#elif defined(HAVE_UTIMENSAT)
6569
0
    UTIME_TO_TIMESPEC;
6570
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
6571
#elif defined(HAVE_UTIMES)
6572
    UTIME_TO_TIMEVAL;
6573
    return utimes(path, time);
6574
#elif defined(HAVE_UTIME_H)
6575
    UTIME_TO_UTIMBUF;
6576
    return utime(path, time);
6577
#else
6578
    UTIME_TO_TIME_T;
6579
    return utime(path, time);
6580
#endif
6581
0
}
6582
6583
#endif
6584
6585
static int
6586
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
6587
0
{
6588
0
    int result = 0;
6589
0
    PyObject *divmod;
6590
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
6591
0
    if (!divmod)
6592
0
        goto exit;
6593
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
6594
0
        PyErr_Format(PyExc_TypeError,
6595
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
6596
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
6597
0
        goto exit;
6598
0
    }
6599
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
6600
0
    if ((*s == -1) && PyErr_Occurred())
6601
0
        goto exit;
6602
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
6603
0
    if ((*ns == -1) && PyErr_Occurred())
6604
0
        goto exit;
6605
6606
0
    result = 1;
6607
0
exit:
6608
0
    Py_XDECREF(divmod);
6609
0
    return result;
6610
0
}
6611
6612
6613
/*[clinic input]
6614
os.utime
6615
6616
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
6617
    times: object = None
6618
    *
6619
    ns: object = NULL
6620
    dir_fd: dir_fd(requires='futimensat') = None
6621
    follow_symlinks: bool=True
6622
6623
# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
6624
6625
Set the access and modified time of path.
6626
6627
path may always be specified as a string.
6628
On some platforms, path may also be specified as an open file descriptor.
6629
  If this functionality is unavailable, using it raises an exception.
6630
6631
If times is not None, it must be a tuple (atime, mtime);
6632
    atime and mtime should be expressed as float seconds since the epoch.
6633
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
6634
    atime_ns and mtime_ns should be expressed as integer nanoseconds
6635
    since the epoch.
6636
If times is None and ns is unspecified, utime uses the current time.
6637
Specifying tuples for both times and ns is an error.
6638
6639
If dir_fd is not None, it should be a file descriptor open to a directory,
6640
  and path should be relative; path will then be relative to that directory.
6641
If follow_symlinks is False, and the last element of the path is a symbolic
6642
  link, utime will modify the symbolic link itself instead of the file the
6643
  link points to.
6644
It is an error to use dir_fd or follow_symlinks when specifying path
6645
  as an open file descriptor.
6646
dir_fd and follow_symlinks may not be available on your platform.
6647
  If they are unavailable, using them will raise a NotImplementedError.
6648
6649
[clinic start generated code]*/
6650
6651
static PyObject *
6652
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
6653
              int dir_fd, int follow_symlinks)
6654
/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
6655
0
{
6656
#ifdef MS_WINDOWS
6657
    HANDLE hFile;
6658
    FILETIME atime, mtime;
6659
#else
6660
0
    int result;
6661
0
#endif
6662
6663
0
    utime_t utime;
6664
6665
0
    memset(&utime, 0, sizeof(utime_t));
6666
6667
0
    if (times != Py_None && ns) {
6668
0
        PyErr_SetString(PyExc_ValueError,
6669
0
                     "utime: you may specify either 'times'"
6670
0
                     " or 'ns' but not both");
6671
0
        return NULL;
6672
0
    }
6673
6674
0
    if (times != Py_None) {
6675
0
        time_t a_sec, m_sec;
6676
0
        long a_nsec, m_nsec;
6677
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
6678
0
            PyErr_SetString(PyExc_TypeError,
6679
0
                         "utime: 'times' must be either"
6680
0
                         " a tuple of two numbers or None");
6681
0
            return NULL;
6682
0
        }
6683
0
        utime.now = 0;
6684
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
6685
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
6686
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
6687
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
6688
0
            return NULL;
6689
0
        }
6690
0
        utime.atime_s = a_sec;
6691
0
        utime.atime_ns = a_nsec;
6692
0
        utime.mtime_s = m_sec;
6693
0
        utime.mtime_ns = m_nsec;
6694
0
    }
6695
0
    else if (ns) {
6696
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
6697
0
            PyErr_SetString(PyExc_TypeError,
6698
0
                         "utime: 'ns' must be a tuple of two ints");
6699
0
            return NULL;
6700
0
        }
6701
0
        utime.now = 0;
6702
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
6703
0
                                      &utime.atime_s, &utime.atime_ns) ||
6704
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
6705
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
6706
0
            return NULL;
6707
0
        }
6708
0
    }
6709
0
    else {
6710
        /* times and ns are both None/unspecified. use "now". */
6711
0
        utime.now = 1;
6712
0
    }
6713
6714
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
6715
    if (follow_symlinks_specified("utime", follow_symlinks))
6716
        return NULL;
6717
#endif
6718
6719
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
6720
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
6721
0
        fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
6722
0
        return NULL;
6723
6724
#if !defined(HAVE_UTIMENSAT)
6725
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
6726
        PyErr_SetString(PyExc_ValueError,
6727
                     "utime: cannot use dir_fd and follow_symlinks "
6728
                     "together on this platform");
6729
        return NULL;
6730
    }
6731
#endif
6732
6733
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
6734
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6735
0
        return NULL;
6736
0
    }
6737
6738
#ifdef MS_WINDOWS
6739
    Py_BEGIN_ALLOW_THREADS
6740
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
6741
                        NULL, OPEN_EXISTING,
6742
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
6743
    Py_END_ALLOW_THREADS
6744
    if (hFile == INVALID_HANDLE_VALUE) {
6745
        path_error(path);
6746
        return NULL;
6747
    }
6748
6749
    if (utime.now) {
6750
        GetSystemTimeAsFileTime(&mtime);
6751
        atime = mtime;
6752
    }
6753
    else {
6754
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
6755
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
6756
    }
6757
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
6758
        path_error(path);
6759
        CloseHandle(hFile);
6760
        return NULL;
6761
    }
6762
    CloseHandle(hFile);
6763
#else /* MS_WINDOWS */
6764
0
    Py_BEGIN_ALLOW_THREADS
6765
6766
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6767
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
6768
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
6769
0
    else
6770
0
#endif
6771
6772
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6773
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
6774
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
6775
6776
0
    } else
6777
0
#endif
6778
6779
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6780
0
    if (path->fd != -1)
6781
0
        result = utime_fd(&utime, path->fd);
6782
0
    else
6783
0
#endif
6784
6785
0
    result = utime_default(&utime, path->narrow);
6786
6787
0
    Py_END_ALLOW_THREADS
6788
6789
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6790
    /* See utime_dir_fd implementation */
6791
    if (result == -1 && errno == ENOSYS) {
6792
        argument_unavailable_error(NULL, "dir_fd");
6793
        return NULL;
6794
    }
6795
#endif
6796
6797
0
    if (result < 0) {
6798
0
        path_error(path);
6799
0
        return NULL;
6800
0
    }
6801
6802
0
#endif /* MS_WINDOWS */
6803
6804
0
    Py_RETURN_NONE;
6805
0
}
6806
6807
/* Process operations */
6808
6809
6810
/*[clinic input]
6811
os._exit
6812
6813
    status: int
6814
6815
Exit to the system with specified status, without normal exit processing.
6816
[clinic start generated code]*/
6817
6818
static PyObject *
6819
os__exit_impl(PyObject *module, int status)
6820
/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
6821
0
{
6822
0
    _exit(status);
6823
0
    return NULL; /* Make gcc -Wall happy */
6824
0
}
6825
6826
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6827
#define EXECV_CHAR wchar_t
6828
#else
6829
0
#define EXECV_CHAR char
6830
#endif
6831
6832
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
6833
static void
6834
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
6835
0
{
6836
0
    Py_ssize_t i;
6837
0
    for (i = 0; i < count; i++)
6838
0
        PyMem_Free(array[i]);
6839
0
    PyMem_Free(array);
6840
0
}
6841
6842
static int
6843
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
6844
0
{
6845
0
    Py_ssize_t size;
6846
0
    PyObject *ub;
6847
0
    int result = 0;
6848
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6849
    if (!PyUnicode_FSDecoder(o, &ub))
6850
        return 0;
6851
    *out = PyUnicode_AsWideCharString(ub, &size);
6852
    if (*out)
6853
        result = 1;
6854
#else
6855
0
    if (!PyUnicode_FSConverter(o, &ub))
6856
0
        return 0;
6857
0
    size = PyBytes_GET_SIZE(ub);
6858
0
    *out = PyMem_Malloc(size + 1);
6859
0
    if (*out) {
6860
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
6861
0
        result = 1;
6862
0
    } else
6863
0
        PyErr_NoMemory();
6864
0
#endif
6865
0
    Py_DECREF(ub);
6866
0
    return result;
6867
0
}
6868
#endif
6869
6870
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
6871
static EXECV_CHAR**
6872
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
6873
0
{
6874
0
    Py_ssize_t i, pos, envc;
6875
0
    PyObject *keys=NULL, *vals=NULL;
6876
0
    PyObject *key2, *val2, *keyval;
6877
0
    EXECV_CHAR **envlist;
6878
6879
0
    i = PyMapping_Size(env);
6880
0
    if (i < 0)
6881
0
        return NULL;
6882
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
6883
0
    if (envlist == NULL) {
6884
0
        PyErr_NoMemory();
6885
0
        return NULL;
6886
0
    }
6887
0
    envc = 0;
6888
0
    keys = PyMapping_Keys(env);
6889
0
    if (!keys)
6890
0
        goto error;
6891
0
    vals = PyMapping_Values(env);
6892
0
    if (!vals)
6893
0
        goto error;
6894
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
6895
0
        PyErr_Format(PyExc_TypeError,
6896
0
                     "env.keys() or env.values() is not a list");
6897
0
        goto error;
6898
0
    }
6899
6900
0
    for (pos = 0; pos < i; pos++) {
6901
0
        PyObject *key = PyList_GetItem(keys, pos);  // Borrowed ref.
6902
0
        if (key == NULL) {
6903
0
            goto error;
6904
0
        }
6905
0
        PyObject *val = PyList_GetItem(vals, pos);  // Borrowed ref.
6906
0
        if (val == NULL) {
6907
0
            goto error;
6908
0
        }
6909
6910
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6911
        if (!PyUnicode_FSDecoder(key, &key2))
6912
            goto error;
6913
        if (!PyUnicode_FSDecoder(val, &val2)) {
6914
            Py_DECREF(key2);
6915
            goto error;
6916
        }
6917
        /* Search from index 1 because on Windows starting '=' is allowed for
6918
           defining hidden environment variables. */
6919
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
6920
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
6921
        {
6922
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6923
            Py_DECREF(key2);
6924
            Py_DECREF(val2);
6925
            goto error;
6926
        }
6927
        keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
6928
#else
6929
0
        if (!PyUnicode_FSConverter(key, &key2))
6930
0
            goto error;
6931
0
        if (!PyUnicode_FSConverter(val, &val2)) {
6932
0
            Py_DECREF(key2);
6933
0
            goto error;
6934
0
        }
6935
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
6936
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
6937
0
        {
6938
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6939
0
            Py_DECREF(key2);
6940
0
            Py_DECREF(val2);
6941
0
            goto error;
6942
0
        }
6943
0
        keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
6944
0
                                             PyBytes_AS_STRING(val2));
6945
0
#endif
6946
0
        Py_DECREF(key2);
6947
0
        Py_DECREF(val2);
6948
0
        if (!keyval)
6949
0
            goto error;
6950
6951
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
6952
0
            Py_DECREF(keyval);
6953
0
            goto error;
6954
0
        }
6955
6956
0
        Py_DECREF(keyval);
6957
0
    }
6958
0
    Py_DECREF(vals);
6959
0
    Py_DECREF(keys);
6960
6961
0
    envlist[envc] = 0;
6962
0
    *envc_ptr = envc;
6963
0
    return envlist;
6964
6965
0
error:
6966
0
    Py_XDECREF(keys);
6967
0
    Py_XDECREF(vals);
6968
0
    free_string_array(envlist, envc);
6969
0
    return NULL;
6970
0
}
6971
6972
static EXECV_CHAR**
6973
parse_arglist(PyObject* argv, Py_ssize_t *argc)
6974
0
{
6975
0
    int i;
6976
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
6977
0
    if (argvlist == NULL) {
6978
0
        PyErr_NoMemory();
6979
0
        return NULL;
6980
0
    }
6981
0
    for (i = 0; i < *argc; i++) {
6982
0
        PyObject* item = PySequence_ITEM(argv, i);
6983
0
        if (item == NULL)
6984
0
            goto fail;
6985
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
6986
0
            Py_DECREF(item);
6987
0
            goto fail;
6988
0
        }
6989
0
        Py_DECREF(item);
6990
0
    }
6991
0
    argvlist[*argc] = NULL;
6992
0
    return argvlist;
6993
0
fail:
6994
0
    *argc = i;
6995
0
    free_string_array(argvlist, *argc);
6996
0
    return NULL;
6997
0
}
6998
6999
#endif
7000
7001
7002
#ifdef HAVE_EXECV
7003
/*[clinic input]
7004
os.execv
7005
7006
    path: path_t
7007
        Path of executable file.
7008
    argv: object
7009
        Tuple or list of strings.
7010
    /
7011
7012
Execute an executable path with arguments, replacing current process.
7013
[clinic start generated code]*/
7014
7015
static PyObject *
7016
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7017
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7018
0
{
7019
0
    EXECV_CHAR **argvlist;
7020
0
    Py_ssize_t argc;
7021
7022
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7023
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7024
0
        PyErr_SetString(PyExc_RuntimeError,
7025
0
                        "exec not supported for isolated subinterpreters");
7026
0
        return NULL;
7027
0
    }
7028
7029
    /* execv has two arguments: (path, argv), where
7030
       argv is a list or tuple of strings. */
7031
7032
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7033
0
        PyErr_SetString(PyExc_TypeError,
7034
0
                        "execv() arg 2 must be a tuple or list");
7035
0
        return NULL;
7036
0
    }
7037
0
    argc = PySequence_Size(argv);
7038
0
    if (argc < 1) {
7039
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7040
0
        return NULL;
7041
0
    }
7042
7043
0
    argvlist = parse_arglist(argv, &argc);
7044
0
    if (argvlist == NULL) {
7045
0
        return NULL;
7046
0
    }
7047
0
    if (!argvlist[0][0]) {
7048
0
        PyErr_SetString(PyExc_ValueError,
7049
0
            "execv() arg 2 first element cannot be empty");
7050
0
        free_string_array(argvlist, argc);
7051
0
        return NULL;
7052
0
    }
7053
7054
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7055
0
        free_string_array(argvlist, argc);
7056
0
        return NULL;
7057
0
    }
7058
7059
0
    _Py_BEGIN_SUPPRESS_IPH
7060
#ifdef HAVE_WEXECV
7061
    _wexecv(path->wide, argvlist);
7062
#else
7063
0
    execv(path->narrow, argvlist);
7064
0
#endif
7065
0
    _Py_END_SUPPRESS_IPH
7066
7067
    /* If we get here it's definitely an error */
7068
7069
0
    posix_error();
7070
0
    free_string_array(argvlist, argc);
7071
0
    return NULL;
7072
0
}
7073
7074
7075
/*[clinic input]
7076
os.execve
7077
7078
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7079
        Path of executable file.
7080
    argv: object
7081
        Tuple or list of strings.
7082
    env: object
7083
        Dictionary of strings mapping to strings.
7084
7085
Execute an executable path with arguments, replacing current process.
7086
[clinic start generated code]*/
7087
7088
static PyObject *
7089
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7090
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7091
0
{
7092
0
    EXECV_CHAR **argvlist = NULL;
7093
0
    EXECV_CHAR **envlist;
7094
0
    Py_ssize_t argc, envc;
7095
7096
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7097
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7098
0
        PyErr_SetString(PyExc_RuntimeError,
7099
0
                        "exec not supported for isolated subinterpreters");
7100
0
        return NULL;
7101
0
    }
7102
7103
    /* execve has three arguments: (path, argv, env), where
7104
       argv is a list or tuple of strings and env is a dictionary
7105
       like posix.environ. */
7106
7107
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7108
0
        PyErr_SetString(PyExc_TypeError,
7109
0
                        "execve: argv must be a tuple or list");
7110
0
        goto fail_0;
7111
0
    }
7112
0
    argc = PySequence_Size(argv);
7113
0
    if (argc < 1) {
7114
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7115
0
        return NULL;
7116
0
    }
7117
7118
0
    if (!PyMapping_Check(env)) {
7119
0
        PyErr_SetString(PyExc_TypeError,
7120
0
                        "execve: environment must be a mapping object");
7121
0
        goto fail_0;
7122
0
    }
7123
7124
0
    argvlist = parse_arglist(argv, &argc);
7125
0
    if (argvlist == NULL) {
7126
0
        goto fail_0;
7127
0
    }
7128
0
    if (!argvlist[0][0]) {
7129
0
        PyErr_SetString(PyExc_ValueError,
7130
0
            "execve: argv first element cannot be empty");
7131
0
        goto fail_0;
7132
0
    }
7133
7134
0
    envlist = parse_envlist(env, &envc);
7135
0
    if (envlist == NULL)
7136
0
        goto fail_0;
7137
7138
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7139
0
        goto fail_1;
7140
0
    }
7141
7142
0
    _Py_BEGIN_SUPPRESS_IPH
7143
0
#ifdef HAVE_FEXECVE
7144
0
    if (path->fd > -1)
7145
0
        fexecve(path->fd, argvlist, envlist);
7146
0
    else
7147
0
#endif
7148
#ifdef HAVE_WEXECV
7149
        _wexecve(path->wide, argvlist, envlist);
7150
#else
7151
0
        execve(path->narrow, argvlist, envlist);
7152
0
#endif
7153
0
    _Py_END_SUPPRESS_IPH
7154
7155
    /* If we get here it's definitely an error */
7156
7157
0
    posix_path_error(path);
7158
0
  fail_1:
7159
0
    free_string_array(envlist, envc);
7160
0
  fail_0:
7161
0
    if (argvlist)
7162
0
        free_string_array(argvlist, argc);
7163
0
    return NULL;
7164
0
}
7165
7166
#endif /* HAVE_EXECV */
7167
7168
#ifdef HAVE_POSIX_SPAWN
7169
7170
enum posix_spawn_file_actions_identifier {
7171
    POSIX_SPAWN_OPEN,
7172
    POSIX_SPAWN_CLOSE,
7173
    POSIX_SPAWN_DUP2
7174
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7175
    ,POSIX_SPAWN_CLOSEFROM
7176
#endif
7177
};
7178
7179
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7180
static int
7181
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7182
#endif
7183
7184
static int
7185
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7186
                        int resetids, int setsid, PyObject *setsigmask,
7187
                        PyObject *setsigdef, PyObject *scheduler,
7188
                        posix_spawnattr_t *attrp)
7189
0
{
7190
0
    long all_flags = 0;
7191
7192
0
    errno = posix_spawnattr_init(attrp);
7193
0
    if (errno) {
7194
0
        posix_error();
7195
0
        return -1;
7196
0
    }
7197
7198
0
    if (setpgroup) {
7199
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7200
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7201
0
            goto fail;
7202
0
        }
7203
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7204
0
        if (errno) {
7205
0
            posix_error();
7206
0
            goto fail;
7207
0
        }
7208
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7209
0
    }
7210
7211
0
    if (resetids) {
7212
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7213
0
    }
7214
7215
0
    if (setsid) {
7216
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7217
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7218
#endif
7219
0
#ifdef POSIX_SPAWN_SETSID
7220
0
        all_flags |= POSIX_SPAWN_SETSID;
7221
#elif defined(POSIX_SPAWN_SETSID_NP)
7222
        all_flags |= POSIX_SPAWN_SETSID_NP;
7223
#else
7224
        argument_unavailable_error(func_name, "setsid");
7225
        return -1;
7226
#endif
7227
7228
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7229
        } else {
7230
            argument_unavailable_error(func_name, "setsid");
7231
            return -1;
7232
        }
7233
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7234
7235
0
    }
7236
7237
0
#ifdef HAVE_SIGSET_T
7238
0
   if (setsigmask) {
7239
0
        sigset_t set;
7240
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7241
0
            goto fail;
7242
0
        }
7243
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7244
0
        if (errno) {
7245
0
            posix_error();
7246
0
            goto fail;
7247
0
        }
7248
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7249
0
    }
7250
7251
0
    if (setsigdef) {
7252
0
        sigset_t set;
7253
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7254
0
            goto fail;
7255
0
        }
7256
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7257
0
        if (errno) {
7258
0
            posix_error();
7259
0
            goto fail;
7260
0
        }
7261
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7262
0
    }
7263
#else
7264
    if (setsigmask || setsigdef) {
7265
        PyErr_SetString(PyExc_NotImplementedError,
7266
                        "sigset is not supported on this platform");
7267
        goto fail;
7268
    }
7269
#endif
7270
7271
0
    if (scheduler) {
7272
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7273
0
        PyObject *py_schedpolicy;
7274
0
        PyObject *schedparam_obj;
7275
0
        struct sched_param schedparam;
7276
7277
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7278
0
                        ";A scheduler tuple must have two elements",
7279
0
                        &py_schedpolicy, &schedparam_obj)) {
7280
0
            goto fail;
7281
0
        }
7282
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7283
0
            goto fail;
7284
0
        }
7285
0
        if (py_schedpolicy != Py_None) {
7286
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7287
7288
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7289
0
                goto fail;
7290
0
            }
7291
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7292
0
            if (errno) {
7293
0
                posix_error();
7294
0
                goto fail;
7295
0
            }
7296
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7297
0
        }
7298
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7299
0
        if (errno) {
7300
0
            posix_error();
7301
0
            goto fail;
7302
0
        }
7303
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7304
#else
7305
        PyErr_SetString(PyExc_NotImplementedError,
7306
                "The scheduler option is not supported in this system.");
7307
        goto fail;
7308
#endif
7309
0
    }
7310
7311
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7312
0
    if (errno) {
7313
0
        posix_error();
7314
0
        goto fail;
7315
0
    }
7316
7317
0
    return 0;
7318
7319
0
fail:
7320
0
    (void)posix_spawnattr_destroy(attrp);
7321
0
    return -1;
7322
0
}
7323
7324
static int
7325
parse_file_actions(PyObject *file_actions,
7326
                   posix_spawn_file_actions_t *file_actionsp,
7327
                   PyObject *temp_buffer)
7328
0
{
7329
0
    PyObject *seq;
7330
0
    PyObject *file_action = NULL;
7331
0
    PyObject *tag_obj;
7332
7333
0
    seq = PySequence_Fast(file_actions,
7334
0
                          "file_actions must be a sequence or None");
7335
0
    if (seq == NULL) {
7336
0
        return -1;
7337
0
    }
7338
7339
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7340
0
    if (errno) {
7341
0
        posix_error();
7342
0
        Py_DECREF(seq);
7343
0
        return -1;
7344
0
    }
7345
7346
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7347
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7348
0
        Py_INCREF(file_action);
7349
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7350
0
            PyErr_SetString(PyExc_TypeError,
7351
0
                "Each file_actions element must be a non-empty tuple");
7352
0
            goto fail;
7353
0
        }
7354
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7355
0
        if (tag == -1 && PyErr_Occurred()) {
7356
0
            goto fail;
7357
0
        }
7358
7359
        /* Populate the file_actions object */
7360
0
        switch (tag) {
7361
0
            case POSIX_SPAWN_OPEN: {
7362
0
                int fd, oflag;
7363
0
                PyObject *path;
7364
0
                unsigned long mode;
7365
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7366
0
                        ";A open file_action tuple must have 5 elements",
7367
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7368
0
                        &oflag, &mode))
7369
0
                {
7370
0
                    goto fail;
7371
0
                }
7372
0
                if (PyList_Append(temp_buffer, path)) {
7373
0
                    Py_DECREF(path);
7374
0
                    goto fail;
7375
0
                }
7376
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7377
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7378
0
                if (errno) {
7379
0
                    posix_error();
7380
0
                    Py_DECREF(path);
7381
0
                    goto fail;
7382
0
                }
7383
0
                Py_DECREF(path);
7384
0
                break;
7385
0
            }
7386
0
            case POSIX_SPAWN_CLOSE: {
7387
0
                int fd;
7388
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7389
0
                        ";A close file_action tuple must have 2 elements",
7390
0
                        &tag_obj, &fd))
7391
0
                {
7392
0
                    goto fail;
7393
0
                }
7394
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7395
0
                if (errno) {
7396
0
                    posix_error();
7397
0
                    goto fail;
7398
0
                }
7399
0
                break;
7400
0
            }
7401
0
            case POSIX_SPAWN_DUP2: {
7402
0
                int fd1, fd2;
7403
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7404
0
                        ";A dup2 file_action tuple must have 3 elements",
7405
0
                        &tag_obj, &fd1, &fd2))
7406
0
                {
7407
0
                    goto fail;
7408
0
                }
7409
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7410
0
                                                         fd1, fd2);
7411
0
                if (errno) {
7412
0
                    posix_error();
7413
0
                    goto fail;
7414
0
                }
7415
0
                break;
7416
0
            }
7417
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7418
            case POSIX_SPAWN_CLOSEFROM: {
7419
                int fd;
7420
                if (!PyArg_ParseTuple(file_action, "Oi"
7421
                        ";A closefrom file_action tuple must have 2 elements",
7422
                        &tag_obj, &fd))
7423
                {
7424
                    goto fail;
7425
                }
7426
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7427
                                                                 fd);
7428
                if (errno) {
7429
                    posix_error();
7430
                    goto fail;
7431
                }
7432
                break;
7433
            }
7434
#endif
7435
0
            default: {
7436
0
                PyErr_SetString(PyExc_TypeError,
7437
0
                                "Unknown file_actions identifier");
7438
0
                goto fail;
7439
0
            }
7440
0
        }
7441
0
        Py_DECREF(file_action);
7442
0
    }
7443
7444
0
    Py_DECREF(seq);
7445
0
    return 0;
7446
7447
0
fail:
7448
0
    Py_DECREF(seq);
7449
0
    Py_DECREF(file_action);
7450
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7451
0
    return -1;
7452
0
}
7453
7454
7455
static PyObject *
7456
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7457
               PyObject *env, PyObject *file_actions,
7458
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7459
               PyObject *setsigdef, PyObject *scheduler)
7460
0
{
7461
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7462
0
    EXECV_CHAR **argvlist = NULL;
7463
0
    EXECV_CHAR **envlist = NULL;
7464
0
    posix_spawn_file_actions_t file_actions_buf;
7465
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7466
0
    posix_spawnattr_t attr;
7467
0
    posix_spawnattr_t *attrp = NULL;
7468
0
    Py_ssize_t argc, envc;
7469
0
    PyObject *result = NULL;
7470
0
    PyObject *temp_buffer = NULL;
7471
0
    pid_t pid;
7472
0
    int err_code;
7473
7474
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7475
       argv is a list or tuple of strings and env is a dictionary
7476
       like posix.environ. */
7477
7478
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7479
0
        PyErr_Format(PyExc_TypeError,
7480
0
                     "%s: argv must be a tuple or list", func_name);
7481
0
        goto exit;
7482
0
    }
7483
0
    argc = PySequence_Size(argv);
7484
0
    if (argc < 1) {
7485
0
        PyErr_Format(PyExc_ValueError,
7486
0
                     "%s: argv must not be empty", func_name);
7487
0
        return NULL;
7488
0
    }
7489
7490
0
    if (!PyMapping_Check(env) && env != Py_None) {
7491
0
        PyErr_Format(PyExc_TypeError,
7492
0
                     "%s: environment must be a mapping object or None", func_name);
7493
0
        goto exit;
7494
0
    }
7495
7496
0
    argvlist = parse_arglist(argv, &argc);
7497
0
    if (argvlist == NULL) {
7498
0
        goto exit;
7499
0
    }
7500
0
    if (!argvlist[0][0]) {
7501
0
        PyErr_Format(PyExc_ValueError,
7502
0
                     "%s: argv first element cannot be empty", func_name);
7503
0
        goto exit;
7504
0
    }
7505
7506
#ifdef USE_DARWIN_NS_GET_ENVIRON
7507
    // There is no environ global in this situation.
7508
    char **environ = NULL;
7509
#endif
7510
7511
0
    if (env == Py_None) {
7512
#ifdef USE_DARWIN_NS_GET_ENVIRON
7513
        environ = *_NSGetEnviron();
7514
#endif
7515
0
        envlist = environ;
7516
0
    } else {
7517
0
        envlist = parse_envlist(env, &envc);
7518
0
        if (envlist == NULL) {
7519
0
            goto exit;
7520
0
        }
7521
0
    }
7522
7523
0
    if (file_actions != NULL && file_actions != Py_None) {
7524
        /* There is a bug in old versions of glibc that makes some of the
7525
         * helper functions for manipulating file actions not copy the provided
7526
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7527
         * copy the value of path for some old versions of glibc (<2.20).
7528
         * The use of temp_buffer here is a workaround that keeps the
7529
         * python objects that own the buffers alive until posix_spawn gets called.
7530
         * Check https://bugs.python.org/issue33630 and
7531
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7532
0
        temp_buffer = PyList_New(0);
7533
0
        if (!temp_buffer) {
7534
0
            goto exit;
7535
0
        }
7536
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7537
0
            goto exit;
7538
0
        }
7539
0
        file_actionsp = &file_actions_buf;
7540
0
    }
7541
7542
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7543
0
                                setsigmask, setsigdef, scheduler, &attr)) {
7544
0
        goto exit;
7545
0
    }
7546
0
    attrp = &attr;
7547
7548
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7549
0
        goto exit;
7550
0
    }
7551
7552
0
    _Py_BEGIN_SUPPRESS_IPH
7553
0
#ifdef HAVE_POSIX_SPAWNP
7554
0
    if (use_posix_spawnp) {
7555
0
        err_code = posix_spawnp(&pid, path->narrow,
7556
0
                                file_actionsp, attrp, argvlist, envlist);
7557
0
    }
7558
0
    else
7559
0
#endif /* HAVE_POSIX_SPAWNP */
7560
0
    {
7561
0
        err_code = posix_spawn(&pid, path->narrow,
7562
0
                               file_actionsp, attrp, argvlist, envlist);
7563
0
    }
7564
0
    _Py_END_SUPPRESS_IPH
7565
7566
0
    if (err_code) {
7567
0
        errno = err_code;
7568
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
7569
0
        goto exit;
7570
0
    }
7571
#ifdef _Py_MEMORY_SANITIZER
7572
    __msan_unpoison(&pid, sizeof(pid));
7573
#endif
7574
0
    result = PyLong_FromPid(pid);
7575
7576
0
exit:
7577
0
    if (file_actionsp) {
7578
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
7579
0
    }
7580
0
    if (attrp) {
7581
0
        (void)posix_spawnattr_destroy(attrp);
7582
0
    }
7583
0
    if (envlist && envlist != environ) {
7584
0
        free_string_array(envlist, envc);
7585
0
    }
7586
0
    if (argvlist) {
7587
0
        free_string_array(argvlist, argc);
7588
0
    }
7589
0
    Py_XDECREF(temp_buffer);
7590
0
    return result;
7591
0
}
7592
7593
7594
/*[clinic input]
7595
7596
os.posix_spawn
7597
    path: path_t
7598
        Path of executable file.
7599
    argv: object
7600
        Tuple or list of strings.
7601
    env: object
7602
        Dictionary of strings mapping to strings.
7603
    /
7604
    *
7605
    file_actions: object(c_default='NULL') = ()
7606
        A sequence of file action tuples.
7607
    setpgroup: object = NULL
7608
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
7609
    resetids: bool = False
7610
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
7611
    setsid: bool = False
7612
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
7613
    setsigmask: object(c_default='NULL') = ()
7614
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
7615
    setsigdef: object(c_default='NULL') = ()
7616
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7617
    scheduler: object = NULL
7618
        A tuple with the scheduler policy (optional) and parameters.
7619
7620
Execute the program specified by path in a new process.
7621
[clinic start generated code]*/
7622
7623
static PyObject *
7624
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
7625
                    PyObject *env, PyObject *file_actions,
7626
                    PyObject *setpgroup, int resetids, int setsid,
7627
                    PyObject *setsigmask, PyObject *setsigdef,
7628
                    PyObject *scheduler)
7629
/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
7630
0
{
7631
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
7632
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
7633
0
                          scheduler);
7634
0
}
7635
 #endif /* HAVE_POSIX_SPAWN */
7636
7637
7638
7639
#ifdef HAVE_POSIX_SPAWNP
7640
/*[clinic input]
7641
7642
os.posix_spawnp
7643
    path: path_t
7644
        Path of executable file.
7645
    argv: object
7646
        Tuple or list of strings.
7647
    env: object
7648
        Dictionary of strings mapping to strings.
7649
    /
7650
    *
7651
    file_actions: object(c_default='NULL') = ()
7652
        A sequence of file action tuples.
7653
    setpgroup: object = NULL
7654
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
7655
    resetids: bool = False
7656
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
7657
    setsid: bool = False
7658
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
7659
    setsigmask: object(c_default='NULL') = ()
7660
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
7661
    setsigdef: object(c_default='NULL') = ()
7662
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7663
    scheduler: object = NULL
7664
        A tuple with the scheduler policy (optional) and parameters.
7665
7666
Execute the program specified by path in a new process.
7667
[clinic start generated code]*/
7668
7669
static PyObject *
7670
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
7671
                     PyObject *env, PyObject *file_actions,
7672
                     PyObject *setpgroup, int resetids, int setsid,
7673
                     PyObject *setsigmask, PyObject *setsigdef,
7674
                     PyObject *scheduler)
7675
/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
7676
0
{
7677
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
7678
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
7679
0
                          scheduler);
7680
0
}
7681
#endif /* HAVE_POSIX_SPAWNP */
7682
7683
#ifdef HAVE_RTPSPAWN
7684
static intptr_t
7685
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
7686
               const char  *envp[])
7687
{
7688
     RTP_ID rtpid;
7689
     int status;
7690
     pid_t res;
7691
     int async_err = 0;
7692
7693
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
7694
        uStackSize=0 cannot be used, the default stack size is too small for
7695
        Python. */
7696
     if (envp) {
7697
         rtpid = rtpSpawn(rtpFileName, argv, envp,
7698
                          100, 0x1000000, 0, VX_FP_TASK);
7699
     }
7700
     else {
7701
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
7702
                          100, 0x1000000, 0, VX_FP_TASK);
7703
     }
7704
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
7705
         do {
7706
             res = waitpid((pid_t)rtpid, &status, 0);
7707
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7708
7709
         if (res < 0)
7710
             return RTP_ID_ERROR;
7711
         return ((intptr_t)status);
7712
     }
7713
     return ((intptr_t)rtpid);
7714
}
7715
#endif
7716
7717
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
7718
/*[clinic input]
7719
os.spawnv
7720
7721
    mode: int
7722
        Mode of process creation.
7723
    path: path_t
7724
        Path of executable file.
7725
    argv: object
7726
        Tuple or list of strings.
7727
    /
7728
7729
Execute the program specified by path in a new process.
7730
[clinic start generated code]*/
7731
7732
static PyObject *
7733
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
7734
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
7735
{
7736
    EXECV_CHAR **argvlist;
7737
    int i;
7738
    Py_ssize_t argc;
7739
    intptr_t spawnval;
7740
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
7741
7742
    /* spawnv has three arguments: (mode, path, argv), where
7743
       argv is a list or tuple of strings. */
7744
7745
    if (PyList_Check(argv)) {
7746
        argc = PyList_Size(argv);
7747
        getitem = PyList_GetItem;
7748
    }
7749
    else if (PyTuple_Check(argv)) {
7750
        argc = PyTuple_Size(argv);
7751
        getitem = PyTuple_GetItem;
7752
    }
7753
    else {
7754
        PyErr_SetString(PyExc_TypeError,
7755
                        "spawnv() arg 2 must be a tuple or list");
7756
        return NULL;
7757
    }
7758
    if (argc == 0) {
7759
        PyErr_SetString(PyExc_ValueError,
7760
            "spawnv() arg 2 cannot be empty");
7761
        return NULL;
7762
    }
7763
7764
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7765
    if (argvlist == NULL) {
7766
        return PyErr_NoMemory();
7767
    }
7768
    for (i = 0; i < argc; i++) {
7769
        if (!fsconvert_strdup((*getitem)(argv, i),
7770
                              &argvlist[i])) {
7771
            free_string_array(argvlist, i);
7772
            PyErr_SetString(
7773
                PyExc_TypeError,
7774
                "spawnv() arg 2 must contain only strings");
7775
            return NULL;
7776
        }
7777
        if (i == 0 && !argvlist[0][0]) {
7778
            free_string_array(argvlist, i + 1);
7779
            PyErr_SetString(
7780
                PyExc_ValueError,
7781
                "spawnv() arg 2 first element cannot be empty");
7782
            return NULL;
7783
        }
7784
    }
7785
    argvlist[argc] = NULL;
7786
7787
#if !defined(HAVE_RTPSPAWN)
7788
    if (mode == _OLD_P_OVERLAY)
7789
        mode = _P_OVERLAY;
7790
#endif
7791
7792
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
7793
                    Py_None) < 0) {
7794
        free_string_array(argvlist, argc);
7795
        return NULL;
7796
    }
7797
7798
    Py_BEGIN_ALLOW_THREADS
7799
    _Py_BEGIN_SUPPRESS_IPH
7800
#ifdef HAVE_WSPAWNV
7801
    spawnval = _wspawnv(mode, path->wide, argvlist);
7802
#elif defined(HAVE_RTPSPAWN)
7803
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
7804
#else
7805
    spawnval = _spawnv(mode, path->narrow, argvlist);
7806
#endif
7807
    _Py_END_SUPPRESS_IPH
7808
    Py_END_ALLOW_THREADS
7809
7810
    int saved_errno = errno;
7811
    free_string_array(argvlist, argc);
7812
7813
    if (spawnval == -1) {
7814
        errno = saved_errno;
7815
        posix_error();
7816
        return NULL;
7817
    }
7818
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7819
}
7820
7821
/*[clinic input]
7822
os.spawnve
7823
7824
    mode: int
7825
        Mode of process creation.
7826
    path: path_t
7827
        Path of executable file.
7828
    argv: object
7829
        Tuple or list of strings.
7830
    env: object
7831
        Dictionary of strings mapping to strings.
7832
    /
7833
7834
Execute the program specified by path in a new process.
7835
[clinic start generated code]*/
7836
7837
static PyObject *
7838
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
7839
                PyObject *env)
7840
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
7841
{
7842
    EXECV_CHAR **argvlist;
7843
    EXECV_CHAR **envlist;
7844
    PyObject *res = NULL;
7845
    Py_ssize_t argc, i, envc;
7846
    intptr_t spawnval;
7847
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
7848
    Py_ssize_t lastarg = 0;
7849
7850
    /* spawnve has four arguments: (mode, path, argv, env), where
7851
       argv is a list or tuple of strings and env is a dictionary
7852
       like posix.environ. */
7853
7854
    if (PyList_Check(argv)) {
7855
        argc = PyList_Size(argv);
7856
        getitem = PyList_GetItem;
7857
    }
7858
    else if (PyTuple_Check(argv)) {
7859
        argc = PyTuple_Size(argv);
7860
        getitem = PyTuple_GetItem;
7861
    }
7862
    else {
7863
        PyErr_SetString(PyExc_TypeError,
7864
                        "spawnve() arg 2 must be a tuple or list");
7865
        goto fail_0;
7866
    }
7867
    if (argc == 0) {
7868
        PyErr_SetString(PyExc_ValueError,
7869
            "spawnve() arg 2 cannot be empty");
7870
        goto fail_0;
7871
    }
7872
    if (!PyMapping_Check(env)) {
7873
        PyErr_SetString(PyExc_TypeError,
7874
                        "spawnve() arg 3 must be a mapping object");
7875
        goto fail_0;
7876
    }
7877
7878
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7879
    if (argvlist == NULL) {
7880
        PyErr_NoMemory();
7881
        goto fail_0;
7882
    }
7883
    for (i = 0; i < argc; i++) {
7884
        if (!fsconvert_strdup((*getitem)(argv, i),
7885
                              &argvlist[i]))
7886
        {
7887
            lastarg = i;
7888
            goto fail_1;
7889
        }
7890
        if (i == 0 && !argvlist[0][0]) {
7891
            lastarg = i + 1;
7892
            PyErr_SetString(
7893
                PyExc_ValueError,
7894
                "spawnv() arg 2 first element cannot be empty");
7895
            goto fail_1;
7896
        }
7897
    }
7898
    lastarg = argc;
7899
    argvlist[argc] = NULL;
7900
7901
    envlist = parse_envlist(env, &envc);
7902
    if (envlist == NULL)
7903
        goto fail_1;
7904
7905
#if !defined(HAVE_RTPSPAWN)
7906
    if (mode == _OLD_P_OVERLAY)
7907
        mode = _P_OVERLAY;
7908
#endif
7909
7910
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
7911
        goto fail_2;
7912
    }
7913
7914
    Py_BEGIN_ALLOW_THREADS
7915
    _Py_BEGIN_SUPPRESS_IPH
7916
#ifdef HAVE_WSPAWNV
7917
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
7918
#elif defined(HAVE_RTPSPAWN)
7919
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
7920
                           (const char **)envlist);
7921
#else
7922
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
7923
#endif
7924
    _Py_END_SUPPRESS_IPH
7925
    Py_END_ALLOW_THREADS
7926
7927
    if (spawnval == -1)
7928
        (void) posix_error();
7929
    else
7930
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7931
7932
  fail_2:
7933
    while (--envc >= 0) {
7934
        PyMem_Free(envlist[envc]);
7935
    }
7936
    PyMem_Free(envlist);
7937
  fail_1:
7938
    free_string_array(argvlist, lastarg);
7939
  fail_0:
7940
    return res;
7941
}
7942
7943
#endif /* HAVE_SPAWNV */
7944
7945
#ifdef HAVE_FORK
7946
7947
/* Helper function to validate arguments.
7948
   Returns 0 on success.  non-zero on failure with a TypeError raised.
7949
   If obj is non-NULL it must be callable.  */
7950
static int
7951
check_null_or_callable(PyObject *obj, const char* obj_name)
7952
0
{
7953
0
    if (obj && !PyCallable_Check(obj)) {
7954
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
7955
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
7956
0
        return -1;
7957
0
    }
7958
0
    return 0;
7959
0
}
7960
7961
/*[clinic input]
7962
os.register_at_fork
7963
7964
    *
7965
    before: object=NULL
7966
        A callable to be called in the parent before the fork() syscall.
7967
    after_in_child: object=NULL
7968
        A callable to be called in the child after fork().
7969
    after_in_parent: object=NULL
7970
        A callable to be called in the parent after fork().
7971
7972
Register callables to be called when forking a new process.
7973
7974
'before' callbacks are called in reverse order.
7975
'after_in_child' and 'after_in_parent' callbacks are called in order.
7976
7977
[clinic start generated code]*/
7978
7979
static PyObject *
7980
os_register_at_fork_impl(PyObject *module, PyObject *before,
7981
                         PyObject *after_in_child, PyObject *after_in_parent)
7982
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
7983
0
{
7984
0
    PyInterpreterState *interp;
7985
7986
0
    if (!before && !after_in_child && !after_in_parent) {
7987
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
7988
0
        return NULL;
7989
0
    }
7990
0
    if (check_null_or_callable(before, "before") ||
7991
0
        check_null_or_callable(after_in_child, "after_in_child") ||
7992
0
        check_null_or_callable(after_in_parent, "after_in_parent")) {
7993
0
        return NULL;
7994
0
    }
7995
0
    interp = _PyInterpreterState_GET();
7996
7997
0
    if (register_at_forker(&interp->before_forkers, before)) {
7998
0
        return NULL;
7999
0
    }
8000
0
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8001
0
        return NULL;
8002
0
    }
8003
0
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8004
0
        return NULL;
8005
0
    }
8006
0
    Py_RETURN_NONE;
8007
0
}
8008
#endif /* HAVE_FORK */
8009
8010
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8011
// Common code to raise a warning if we detect there is more than one thread
8012
// running in the process. Best effort, silent if unable to count threads.
8013
// Constraint: Quick. Never overcounts. Never leaves an error set.
8014
//
8015
// This should only be called from the parent process after
8016
// PyOS_AfterFork_Parent().
8017
static int
8018
warn_about_fork_with_threads(const char* name)
8019
0
{
8020
    // It's not safe to issue the warning while the world is stopped, because
8021
    // other threads might be holding locks that we need, which would deadlock.
8022
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8023
8024
    // TODO: Consider making an `os` module API to return the current number
8025
    // of threads in the process. That'd presumably use this platform code but
8026
    // raise an error rather than using the inaccurate fallback.
8027
0
    Py_ssize_t num_python_threads = 0;
8028
#if defined(__APPLE__) && defined(HAVE_GETPID)
8029
    mach_port_t macos_self = mach_task_self();
8030
    mach_port_t macos_task;
8031
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8032
        thread_array_t macos_threads;
8033
        mach_msg_type_number_t macos_n_threads;
8034
        if (task_threads(macos_task, &macos_threads,
8035
                         &macos_n_threads) == KERN_SUCCESS) {
8036
            num_python_threads = macos_n_threads;
8037
        }
8038
    }
8039
#elif defined(__linux__)
8040
    // Linux /proc/self/stat 20th field is the number of threads.
8041
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8042
0
    if (proc_stat) {
8043
0
        size_t n;
8044
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8045
        // observed on the author's workstation.
8046
0
        char stat_line[160];
8047
0
        n = fread(&stat_line, 1, 159, proc_stat);
8048
0
        stat_line[n] = '\0';
8049
0
        fclose(proc_stat);
8050
8051
0
        char *saveptr = NULL;
8052
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8053
0
        unsigned int idx;
8054
0
        for (idx = 19; idx && field; --idx) {
8055
0
            field = strtok_r(NULL, " ", &saveptr);
8056
0
        }
8057
0
        if (idx == 0 && field) {  // found the 20th field
8058
0
            num_python_threads = atoi(field);  // 0 on error
8059
0
        }
8060
0
    }
8061
0
#endif
8062
0
    if (num_python_threads <= 0) {
8063
        // Fall back to just the number our threading module knows about.
8064
        // An incomplete view of the world, but better than nothing.
8065
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8066
0
        if (!threading) {
8067
0
            PyErr_Clear();
8068
0
            return 0;
8069
0
        }
8070
0
        PyObject *threading_active =
8071
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8072
0
        if (!threading_active) {
8073
0
            PyErr_Clear();
8074
0
            Py_DECREF(threading);
8075
0
            return 0;
8076
0
        }
8077
0
        PyObject *threading_limbo =
8078
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8079
0
        if (!threading_limbo) {
8080
0
            PyErr_Clear();
8081
0
            Py_DECREF(threading);
8082
0
            Py_DECREF(threading_active);
8083
0
            return 0;
8084
0
        }
8085
0
        Py_DECREF(threading);
8086
        // Duplicating what threading.active_count() does but without holding
8087
        // threading._active_limbo_lock so our count could be inaccurate if
8088
        // these dicts are mid-update from another thread.  Not a big deal.
8089
        // Worst case if someone replaced threading._active or threading._limbo
8090
        // with non-dicts, we get -1 from *Length() below and undercount.
8091
        // Nobody should, but we're best effort so we clear errors and move on.
8092
0
        num_python_threads = (PyMapping_Length(threading_active)
8093
0
                              + PyMapping_Length(threading_limbo));
8094
0
        PyErr_Clear();
8095
0
        Py_DECREF(threading_active);
8096
0
        Py_DECREF(threading_limbo);
8097
0
    }
8098
0
    if (num_python_threads > 1) {
8099
0
        return PyErr_WarnFormat(
8100
0
                PyExc_DeprecationWarning, 1,
8101
0
#ifdef HAVE_GETPID
8102
0
                "This process (pid=%d) is multi-threaded, "
8103
#else
8104
                "This process is multi-threaded, "
8105
#endif
8106
0
                "use of %s() may lead to deadlocks in the child.",
8107
0
#ifdef HAVE_GETPID
8108
0
                getpid(),
8109
0
#endif
8110
0
                name);
8111
0
    }
8112
0
    return 0;
8113
0
}
8114
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8115
8116
#ifdef HAVE_FORK1
8117
/*[clinic input]
8118
os.fork1
8119
8120
Fork a child process with a single multiplexed (i.e., not bound) thread.
8121
8122
Return 0 to child process and PID of child to parent process.
8123
[clinic start generated code]*/
8124
8125
static PyObject *
8126
os_fork1_impl(PyObject *module)
8127
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8128
{
8129
    pid_t pid;
8130
8131
    PyInterpreterState *interp = _PyInterpreterState_GET();
8132
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8133
        PyErr_SetString(PyExc_PythonFinalizationError,
8134
                        "can't fork at interpreter shutdown");
8135
        return NULL;
8136
    }
8137
    if (!_Py_IsMainInterpreter(interp)) {
8138
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8139
        return NULL;
8140
    }
8141
    PyOS_BeforeFork();
8142
    pid = fork1();
8143
    int saved_errno = errno;
8144
    if (pid == 0) {
8145
        /* child: this clobbers and resets the import lock. */
8146
        PyOS_AfterFork_Child();
8147
    } else {
8148
        /* parent: release the import lock. */
8149
        PyOS_AfterFork_Parent();
8150
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8151
        if (warn_about_fork_with_threads("fork1") < 0) {
8152
            return NULL;
8153
        }
8154
    }
8155
    if (pid == -1) {
8156
        errno = saved_errno;
8157
        return posix_error();
8158
    }
8159
    return PyLong_FromPid(pid);
8160
}
8161
#endif /* HAVE_FORK1 */
8162
8163
8164
#ifdef HAVE_FORK
8165
/*[clinic input]
8166
os.fork
8167
8168
Fork a child process.
8169
8170
Return 0 to child process and PID of child to parent process.
8171
[clinic start generated code]*/
8172
8173
static PyObject *
8174
os_fork_impl(PyObject *module)
8175
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8176
0
{
8177
0
    pid_t pid;
8178
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8179
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8180
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8181
0
                        "can't fork at interpreter shutdown");
8182
0
        return NULL;
8183
0
    }
8184
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8185
0
        PyErr_SetString(PyExc_RuntimeError,
8186
0
                        "fork not supported for isolated subinterpreters");
8187
0
        return NULL;
8188
0
    }
8189
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8190
0
        return NULL;
8191
0
    }
8192
0
    PyOS_BeforeFork();
8193
0
    pid = fork();
8194
0
    int saved_errno = errno;
8195
0
    if (pid == 0) {
8196
        /* child: this clobbers and resets the import lock. */
8197
0
        PyOS_AfterFork_Child();
8198
0
    } else {
8199
        /* parent: release the import lock. */
8200
0
        PyOS_AfterFork_Parent();
8201
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8202
0
        if (warn_about_fork_with_threads("fork") < 0)
8203
0
            return NULL;
8204
0
    }
8205
0
    if (pid == -1) {
8206
0
        errno = saved_errno;
8207
0
        return posix_error();
8208
0
    }
8209
0
    return PyLong_FromPid(pid);
8210
0
}
8211
#endif /* HAVE_FORK */
8212
8213
8214
#ifdef HAVE_SCHED_H
8215
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8216
/*[clinic input]
8217
os.sched_get_priority_max
8218
8219
    policy: int
8220
8221
Get the maximum scheduling priority for policy.
8222
[clinic start generated code]*/
8223
8224
static PyObject *
8225
os_sched_get_priority_max_impl(PyObject *module, int policy)
8226
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8227
0
{
8228
    /* make sure that errno is cleared before the call */
8229
0
    errno = 0;
8230
0
    int max = sched_get_priority_max(policy);
8231
0
    if (max == -1 && errno)
8232
0
        return posix_error();
8233
0
    return PyLong_FromLong(max);
8234
0
}
8235
8236
8237
/*[clinic input]
8238
os.sched_get_priority_min
8239
8240
    policy: int
8241
8242
Get the minimum scheduling priority for policy.
8243
[clinic start generated code]*/
8244
8245
static PyObject *
8246
os_sched_get_priority_min_impl(PyObject *module, int policy)
8247
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8248
0
{
8249
    /* make sure that errno is cleared before the call */
8250
0
    errno = 0;
8251
0
    int min = sched_get_priority_min(policy);
8252
0
    if (min == -1 && errno)
8253
0
        return posix_error();
8254
0
    return PyLong_FromLong(min);
8255
0
}
8256
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8257
8258
8259
#ifdef HAVE_SCHED_SETSCHEDULER
8260
/*[clinic input]
8261
os.sched_getscheduler
8262
    pid: pid_t
8263
    /
8264
8265
Get the scheduling policy for the process identified by pid.
8266
8267
Passing 0 for pid returns the scheduling policy for the calling process.
8268
[clinic start generated code]*/
8269
8270
static PyObject *
8271
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8272
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8273
0
{
8274
0
    int policy;
8275
8276
0
    policy = sched_getscheduler(pid);
8277
0
    if (policy < 0)
8278
0
        return posix_error();
8279
0
    return PyLong_FromLong(policy);
8280
0
}
8281
#endif /* HAVE_SCHED_SETSCHEDULER */
8282
8283
8284
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8285
/*[clinic input]
8286
class os.sched_param "PyObject *" "SchedParamType"
8287
8288
@classmethod
8289
os.sched_param.__new__
8290
8291
    sched_priority: object
8292
        A scheduling parameter.
8293
8294
Currently has only one field: sched_priority
8295
[clinic start generated code]*/
8296
8297
static PyObject *
8298
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8299
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8300
0
{
8301
0
    PyObject *res;
8302
8303
0
    res = PyStructSequence_New(type);
8304
0
    if (!res)
8305
0
        return NULL;
8306
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8307
0
    return res;
8308
0
}
8309
8310
static PyObject *
8311
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8312
0
{
8313
0
    return Py_BuildValue("(O(N))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8314
0
}
8315
8316
static PyMethodDef os_sched_param_reduce_method = {
8317
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8318
};
8319
8320
PyDoc_VAR(os_sched_param__doc__);
8321
8322
static PyStructSequence_Field sched_param_fields[] = {
8323
    {"sched_priority", "the scheduling priority"},
8324
    {0}
8325
};
8326
8327
static PyStructSequence_Desc sched_param_desc = {
8328
    "sched_param", /* name */
8329
    os_sched_param__doc__, /* doc */
8330
    sched_param_fields,
8331
    1
8332
};
8333
8334
static int
8335
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8336
0
{
8337
0
    long priority;
8338
8339
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8340
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8341
0
        return 0;
8342
0
    }
8343
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8344
0
    if (priority == -1 && PyErr_Occurred())
8345
0
        return 0;
8346
0
    if (priority > INT_MAX || priority < INT_MIN) {
8347
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8348
0
        return 0;
8349
0
    }
8350
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8351
0
    return 1;
8352
0
}
8353
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8354
8355
8356
#ifdef HAVE_SCHED_SETSCHEDULER
8357
/*[clinic input]
8358
os.sched_setscheduler
8359
8360
    pid: pid_t
8361
    policy: int
8362
    param as param_obj: object
8363
    /
8364
8365
Set the scheduling policy for the process identified by pid.
8366
8367
If pid is 0, the calling process is changed.
8368
param is an instance of sched_param.
8369
[clinic start generated code]*/
8370
8371
static PyObject *
8372
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8373
                           PyObject *param_obj)
8374
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8375
0
{
8376
0
    struct sched_param param;
8377
0
    if (!convert_sched_param(module, param_obj, &param)) {
8378
0
        return NULL;
8379
0
    }
8380
8381
    /*
8382
    ** sched_setscheduler() returns 0 in Linux, but the previous
8383
    ** scheduling policy under Solaris/Illumos, and others.
8384
    ** On error, -1 is returned in all Operating Systems.
8385
    */
8386
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8387
0
        return posix_error();
8388
0
    Py_RETURN_NONE;
8389
0
}
8390
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8391
8392
8393
#ifdef HAVE_SCHED_SETPARAM
8394
/*[clinic input]
8395
os.sched_getparam
8396
    pid: pid_t
8397
    /
8398
8399
Returns scheduling parameters for the process identified by pid.
8400
8401
If pid is 0, returns parameters for the calling process.
8402
Return value is an instance of sched_param.
8403
[clinic start generated code]*/
8404
8405
static PyObject *
8406
os_sched_getparam_impl(PyObject *module, pid_t pid)
8407
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8408
0
{
8409
0
    struct sched_param param;
8410
0
    PyObject *result;
8411
0
    PyObject *priority;
8412
8413
0
    if (sched_getparam(pid, &param))
8414
0
        return posix_error();
8415
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8416
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8417
0
    if (!result)
8418
0
        return NULL;
8419
0
    priority = PyLong_FromLong(param.sched_priority);
8420
0
    if (!priority) {
8421
0
        Py_DECREF(result);
8422
0
        return NULL;
8423
0
    }
8424
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8425
0
    return result;
8426
0
}
8427
8428
8429
/*[clinic input]
8430
os.sched_setparam
8431
    pid: pid_t
8432
    param as param_obj: object
8433
    /
8434
8435
Set scheduling parameters for the process identified by pid.
8436
8437
If pid is 0, sets parameters for the calling process.
8438
param should be an instance of sched_param.
8439
[clinic start generated code]*/
8440
8441
static PyObject *
8442
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8443
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8444
0
{
8445
0
    struct sched_param param;
8446
0
    if (!convert_sched_param(module, param_obj, &param)) {
8447
0
        return NULL;
8448
0
    }
8449
8450
0
    if (sched_setparam(pid, &param))
8451
0
        return posix_error();
8452
0
    Py_RETURN_NONE;
8453
0
}
8454
#endif /* HAVE_SCHED_SETPARAM */
8455
8456
8457
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8458
/*[clinic input]
8459
@permit_long_summary
8460
os.sched_rr_get_interval -> double
8461
    pid: pid_t
8462
    /
8463
8464
Return the round-robin quantum for the process identified by pid, in seconds.
8465
8466
Value returned is a float.
8467
[clinic start generated code]*/
8468
8469
static double
8470
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8471
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8472
0
{
8473
0
    struct timespec interval;
8474
0
    if (sched_rr_get_interval(pid, &interval)) {
8475
0
        posix_error();
8476
0
        return -1.0;
8477
0
    }
8478
#ifdef _Py_MEMORY_SANITIZER
8479
    __msan_unpoison(&interval, sizeof(interval));
8480
#endif
8481
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8482
0
}
8483
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8484
8485
8486
/*[clinic input]
8487
os.sched_yield
8488
8489
Voluntarily relinquish the CPU.
8490
[clinic start generated code]*/
8491
8492
static PyObject *
8493
os_sched_yield_impl(PyObject *module)
8494
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8495
0
{
8496
0
    int result;
8497
0
    Py_BEGIN_ALLOW_THREADS
8498
0
    result = sched_yield();
8499
0
    Py_END_ALLOW_THREADS
8500
0
    if (result < 0) {
8501
0
        return posix_error();
8502
0
    }
8503
0
    Py_RETURN_NONE;
8504
0
}
8505
8506
#ifdef HAVE_SCHED_SETAFFINITY
8507
/* The minimum number of CPUs allocated in a cpu_set_t */
8508
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8509
8510
/*[clinic input]
8511
os.sched_setaffinity
8512
    pid: pid_t
8513
    mask : object
8514
    /
8515
8516
Set the CPU affinity of the process identified by pid to mask.
8517
8518
mask should be an iterable of integers identifying CPUs.
8519
[clinic start generated code]*/
8520
8521
static PyObject *
8522
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8523
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8524
0
{
8525
0
    int ncpus;
8526
0
    size_t setsize;
8527
0
    cpu_set_t *cpu_set = NULL;
8528
0
    PyObject *iterator = NULL, *item;
8529
8530
0
    iterator = PyObject_GetIter(mask);
8531
0
    if (iterator == NULL)
8532
0
        return NULL;
8533
8534
0
    ncpus = NCPUS_START;
8535
0
    setsize = CPU_ALLOC_SIZE(ncpus);
8536
0
    cpu_set = CPU_ALLOC(ncpus);
8537
0
    if (cpu_set == NULL) {
8538
0
        PyErr_NoMemory();
8539
0
        goto error;
8540
0
    }
8541
0
    CPU_ZERO_S(setsize, cpu_set);
8542
8543
0
    while ((item = PyIter_Next(iterator))) {
8544
0
        long cpu;
8545
0
        if (!PyIndex_Check(item)) {
8546
0
            PyErr_Format(PyExc_TypeError,
8547
0
                        "expected an iterator of ints, "
8548
0
                        "but iterator yielded %R",
8549
0
                        Py_TYPE(item));
8550
0
            Py_DECREF(item);
8551
0
            goto error;
8552
0
        }
8553
0
        cpu = PyLong_AsLong(item);
8554
0
        Py_DECREF(item);
8555
0
        if (cpu < 0) {
8556
0
            if (!PyErr_Occurred())
8557
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
8558
0
            goto error;
8559
0
        }
8560
0
        if (cpu > INT_MAX - 1) {
8561
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
8562
0
            goto error;
8563
0
        }
8564
0
        if (cpu >= ncpus) {
8565
            /* Grow CPU mask to fit the CPU number */
8566
0
            int newncpus = ncpus;
8567
0
            cpu_set_t *newmask;
8568
0
            size_t newsetsize;
8569
0
            while (newncpus <= cpu) {
8570
0
                if (newncpus > INT_MAX / 2)
8571
0
                    newncpus = cpu + 1;
8572
0
                else
8573
0
                    newncpus = newncpus * 2;
8574
0
            }
8575
0
            newmask = CPU_ALLOC(newncpus);
8576
0
            if (newmask == NULL) {
8577
0
                PyErr_NoMemory();
8578
0
                goto error;
8579
0
            }
8580
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
8581
0
            CPU_ZERO_S(newsetsize, newmask);
8582
0
            memcpy(newmask, cpu_set, setsize);
8583
0
            CPU_FREE(cpu_set);
8584
0
            setsize = newsetsize;
8585
0
            cpu_set = newmask;
8586
0
            ncpus = newncpus;
8587
0
        }
8588
0
        CPU_SET_S(cpu, setsize, cpu_set);
8589
0
    }
8590
0
    if (PyErr_Occurred()) {
8591
0
        goto error;
8592
0
    }
8593
0
    Py_CLEAR(iterator);
8594
8595
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
8596
0
        posix_error();
8597
0
        goto error;
8598
0
    }
8599
0
    CPU_FREE(cpu_set);
8600
0
    Py_RETURN_NONE;
8601
8602
0
error:
8603
0
    if (cpu_set)
8604
0
        CPU_FREE(cpu_set);
8605
0
    Py_XDECREF(iterator);
8606
0
    return NULL;
8607
0
}
8608
8609
8610
/*[clinic input]
8611
@permit_long_summary
8612
os.sched_getaffinity
8613
    pid: pid_t
8614
    /
8615
8616
Return the affinity of the process identified by pid (or the current process if zero).
8617
8618
The affinity is returned as a set of CPU identifiers.
8619
[clinic start generated code]*/
8620
8621
static PyObject *
8622
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
8623
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
8624
0
{
8625
0
    int ncpus = NCPUS_START;
8626
0
    size_t setsize;
8627
0
    cpu_set_t *mask;
8628
8629
0
    while (1) {
8630
0
        setsize = CPU_ALLOC_SIZE(ncpus);
8631
0
        mask = CPU_ALLOC(ncpus);
8632
0
        if (mask == NULL) {
8633
0
            return PyErr_NoMemory();
8634
0
        }
8635
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
8636
0
            break;
8637
0
        }
8638
0
        CPU_FREE(mask);
8639
0
        if (errno != EINVAL) {
8640
0
            return posix_error();
8641
0
        }
8642
0
        if (ncpus > INT_MAX / 2) {
8643
0
            PyErr_SetString(PyExc_OverflowError,
8644
0
                            "could not allocate a large enough CPU set");
8645
0
            return NULL;
8646
0
        }
8647
0
        ncpus *= 2;
8648
0
    }
8649
8650
0
    PyObject *res = PySet_New(NULL);
8651
0
    if (res == NULL) {
8652
0
        goto error;
8653
0
    }
8654
8655
0
    int cpu = 0;
8656
0
    int count = CPU_COUNT_S(setsize, mask);
8657
0
    for (; count; cpu++) {
8658
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
8659
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
8660
0
            --count;
8661
0
            if (cpu_num == NULL) {
8662
0
                goto error;
8663
0
            }
8664
0
            if (PySet_Add(res, cpu_num)) {
8665
0
                Py_DECREF(cpu_num);
8666
0
                goto error;
8667
0
            }
8668
0
            Py_DECREF(cpu_num);
8669
0
        }
8670
0
    }
8671
0
    CPU_FREE(mask);
8672
0
    return res;
8673
8674
0
error:
8675
0
    if (mask) {
8676
0
        CPU_FREE(mask);
8677
0
    }
8678
0
    Py_XDECREF(res);
8679
0
    return NULL;
8680
0
}
8681
#endif /* HAVE_SCHED_SETAFFINITY */
8682
8683
#endif /* HAVE_SCHED_H */
8684
8685
8686
#ifdef HAVE_POSIX_OPENPT
8687
/*[clinic input]
8688
os.posix_openpt -> int
8689
8690
    oflag: int
8691
    /
8692
8693
Open and return a file descriptor for a master pseudo-terminal device.
8694
8695
Performs a posix_openpt() C function call. The oflag argument is used to
8696
set file status flags and file access modes as specified in the manual page
8697
of posix_openpt() of your system.
8698
[clinic start generated code]*/
8699
8700
static int
8701
os_posix_openpt_impl(PyObject *module, int oflag)
8702
/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
8703
0
{
8704
0
    int fd;
8705
8706
0
#if defined(O_CLOEXEC)
8707
0
    oflag |= O_CLOEXEC;
8708
0
#endif
8709
8710
0
    fd = posix_openpt(oflag);
8711
0
    if (fd == -1) {
8712
0
        posix_error();
8713
0
        return -1;
8714
0
    }
8715
8716
    // Just in case, likely a no-op given O_CLOEXEC above.
8717
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
8718
0
        close(fd);
8719
0
        return -1;
8720
0
    }
8721
8722
0
    return fd;
8723
0
}
8724
#endif /* HAVE_POSIX_OPENPT */
8725
8726
#ifdef HAVE_GRANTPT
8727
/*[clinic input]
8728
os.grantpt
8729
8730
    fd: fildes
8731
        File descriptor of a master pseudo-terminal device.
8732
    /
8733
8734
Grant access to the slave pseudo-terminal device.
8735
8736
Performs a grantpt() C function call.
8737
[clinic start generated code]*/
8738
8739
static PyObject *
8740
os_grantpt_impl(PyObject *module, int fd)
8741
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
8742
0
{
8743
0
    int ret;
8744
0
    int saved_errno;
8745
0
    PyOS_sighandler_t sig_saved;
8746
8747
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8748
8749
0
    ret = grantpt(fd);
8750
0
    if (ret == -1)
8751
0
        saved_errno = errno;
8752
8753
0
    PyOS_setsig(SIGCHLD, sig_saved);
8754
8755
0
    if (ret == -1) {
8756
0
        errno = saved_errno;
8757
0
        return posix_error();
8758
0
    }
8759
8760
0
    Py_RETURN_NONE;
8761
0
}
8762
#endif /* HAVE_GRANTPT */
8763
8764
#ifdef HAVE_UNLOCKPT
8765
/*[clinic input]
8766
os.unlockpt
8767
8768
    fd: fildes
8769
        File descriptor of a master pseudo-terminal device.
8770
    /
8771
8772
Unlock a pseudo-terminal master/slave pair.
8773
8774
Performs an unlockpt() C function call.
8775
[clinic start generated code]*/
8776
8777
static PyObject *
8778
os_unlockpt_impl(PyObject *module, int fd)
8779
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
8780
0
{
8781
0
    if (unlockpt(fd) == -1)
8782
0
        return posix_error();
8783
8784
0
    Py_RETURN_NONE;
8785
0
}
8786
#endif /* HAVE_UNLOCKPT */
8787
8788
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
8789
static PyObject *
8790
py_ptsname(int fd)
8791
0
{
8792
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
8793
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
8794
0
    errno = 0;
8795
0
    char *name = ptsname(fd);
8796
0
    if (name == NULL) {
8797
0
        return posix_error();
8798
0
    }
8799
0
    return PyUnicode_DecodeFSDefault(name);
8800
0
}
8801
8802
/*[clinic input]
8803
os.ptsname
8804
8805
    fd: fildes
8806
        File descriptor of a master pseudo-terminal device.
8807
    /
8808
8809
Return the name of the slave pseudo-terminal device.
8810
8811
If the ptsname_r() C function is available, it is called;
8812
otherwise, performs a ptsname() C function call.
8813
[clinic start generated code]*/
8814
8815
static PyObject *
8816
os_ptsname_impl(PyObject *module, int fd)
8817
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
8818
0
{
8819
0
#ifdef HAVE_PTSNAME_R
8820
0
    int ret;
8821
0
    char name[MAXPATHLEN+1];
8822
8823
0
    if (HAVE_PTSNAME_R_RUNTIME) {
8824
0
        ret = ptsname_r(fd, name, sizeof(name));
8825
0
    }
8826
0
    else {
8827
        // fallback to ptsname() if ptsname_r() is not available in runtime.
8828
0
        return py_ptsname(fd);
8829
0
    }
8830
0
    if (ret != 0) {
8831
0
        errno = ret;
8832
0
        return posix_error();
8833
0
    }
8834
8835
0
    return PyUnicode_DecodeFSDefault(name);
8836
#else
8837
    return py_ptsname(fd);
8838
#endif /* HAVE_PTSNAME_R */
8839
0
}
8840
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
8841
8842
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
8843
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
8844
#  define DEV_PTY_FILE "/dev/ptc"
8845
#  define HAVE_DEV_PTMX
8846
#else
8847
#  define DEV_PTY_FILE "/dev/ptmx"
8848
#endif
8849
8850
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
8851
#ifdef HAVE_PTY_H
8852
#include <pty.h>
8853
#elif defined(HAVE_LIBUTIL_H)
8854
#include <libutil.h>
8855
#elif defined(HAVE_UTIL_H)
8856
#include <util.h>
8857
#endif /* HAVE_PTY_H */
8858
#ifdef HAVE_UTMP_H
8859
#include <utmp.h>
8860
#endif /* HAVE_UTMP_H */
8861
#ifdef HAVE_STROPTS_H
8862
#include <stropts.h>
8863
#endif
8864
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
8865
8866
8867
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
8868
/*[clinic input]
8869
os.openpty
8870
8871
Open a pseudo-terminal.
8872
8873
Return a tuple of (master_fd, slave_fd) containing open file descriptors
8874
for both the master and slave ends.
8875
[clinic start generated code]*/
8876
8877
static PyObject *
8878
os_openpty_impl(PyObject *module)
8879
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
8880
0
{
8881
0
    int master_fd = -1, slave_fd = -1;
8882
#ifndef HAVE_OPENPTY
8883
    char * slave_name;
8884
#endif
8885
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
8886
    PyOS_sighandler_t sig_saved;
8887
#if defined(__sun) && defined(__SVR4)
8888
    extern char *ptsname(int fildes);
8889
#endif
8890
#endif
8891
8892
0
#ifdef HAVE_OPENPTY
8893
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
8894
0
        goto posix_error;
8895
8896
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8897
0
        goto error;
8898
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
8899
0
        goto error;
8900
8901
#elif defined(HAVE__GETPTY)
8902
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
8903
    if (slave_name == NULL)
8904
        goto posix_error;
8905
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8906
        goto error;
8907
8908
    slave_fd = _Py_open(slave_name, O_RDWR);
8909
    if (slave_fd < 0)
8910
        goto error;
8911
8912
#else
8913
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
8914
    if (master_fd < 0)
8915
        goto posix_error;
8916
8917
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8918
8919
    /* change permission of slave */
8920
    if (grantpt(master_fd) < 0) {
8921
        int saved_errno = errno;
8922
        PyOS_setsig(SIGCHLD, sig_saved);
8923
        errno = saved_errno;
8924
        goto posix_error;
8925
    }
8926
8927
    /* unlock slave */
8928
    if (unlockpt(master_fd) < 0) {
8929
        int saved_errno = errno;
8930
        PyOS_setsig(SIGCHLD, sig_saved);
8931
        errno = saved_errno;
8932
        goto posix_error;
8933
    }
8934
8935
    PyOS_setsig(SIGCHLD, sig_saved);
8936
8937
    slave_name = ptsname(master_fd); /* get name of slave */
8938
    if (slave_name == NULL)
8939
        goto posix_error;
8940
8941
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
8942
    if (slave_fd == -1)
8943
        goto error;
8944
8945
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8946
        goto posix_error;
8947
8948
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
8949
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
8950
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
8951
#ifndef __hpux
8952
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
8953
#endif /* __hpux */
8954
#endif /* HAVE_CYGWIN */
8955
#endif /* HAVE_OPENPTY */
8956
8957
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
8958
8959
0
posix_error:
8960
0
    posix_error();
8961
0
error:
8962
0
    if (master_fd != -1)
8963
0
        close(master_fd);
8964
0
    if (slave_fd != -1)
8965
0
        close(slave_fd);
8966
0
    return NULL;
8967
0
}
8968
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
8969
8970
8971
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
8972
#define HAVE_FALLBACK_LOGIN_TTY 1
8973
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
8974
8975
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
8976
/*[clinic input]
8977
os.login_tty
8978
8979
    fd: fildes
8980
    /
8981
8982
Prepare the tty of which fd is a file descriptor for a new login session.
8983
8984
Make the calling process a session leader; make the tty the
8985
controlling tty, the stdin, the stdout, and the stderr of the
8986
calling process; close fd.
8987
[clinic start generated code]*/
8988
8989
static PyObject *
8990
os_login_tty_impl(PyObject *module, int fd)
8991
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
8992
0
{
8993
0
#ifdef HAVE_LOGIN_TTY
8994
0
    if (login_tty(fd) == -1) {
8995
0
        return posix_error();
8996
0
    }
8997
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
8998
    /* Establish a new session. */
8999
    if (setsid() == -1) {
9000
        return posix_error();
9001
    }
9002
9003
    /* The tty becomes the controlling terminal. */
9004
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9005
        return posix_error();
9006
    }
9007
9008
    /* The tty becomes stdin/stdout/stderr */
9009
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9010
        return posix_error();
9011
    }
9012
    if (fd > 2) {
9013
        close(fd);
9014
    }
9015
#endif /* HAVE_LOGIN_TTY */
9016
0
    Py_RETURN_NONE;
9017
0
}
9018
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9019
9020
9021
#ifdef HAVE_FORKPTY
9022
/*[clinic input]
9023
os.forkpty
9024
9025
Fork a new process with a new pseudo-terminal as controlling tty.
9026
9027
Returns a tuple of (pid, master_fd).
9028
Like fork(), return pid of 0 to the child process,
9029
and pid of child to the parent process.
9030
To both, return fd of newly opened pseudo-terminal.
9031
The master_fd is non-inheritable.
9032
[clinic start generated code]*/
9033
9034
static PyObject *
9035
os_forkpty_impl(PyObject *module)
9036
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9037
0
{
9038
0
    int master_fd = -1;
9039
0
    pid_t pid;
9040
9041
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9042
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9043
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9044
0
                        "can't fork at interpreter shutdown");
9045
0
        return NULL;
9046
0
    }
9047
0
    if (!_Py_IsMainInterpreter(interp)) {
9048
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9049
0
        return NULL;
9050
0
    }
9051
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9052
0
        return NULL;
9053
0
    }
9054
0
    PyOS_BeforeFork();
9055
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9056
0
    if (pid == 0) {
9057
        /* child: this clobbers and resets the import lock. */
9058
0
        PyOS_AfterFork_Child();
9059
0
    } else {
9060
        /* parent: release the import lock. */
9061
0
        PyOS_AfterFork_Parent();
9062
        /* set O_CLOEXEC on master_fd */
9063
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9064
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9065
0
                                   "non-inheritable in forkpty()");
9066
0
        }
9067
9068
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9069
0
        if (warn_about_fork_with_threads("forkpty") < 0)
9070
0
            return NULL;
9071
0
    }
9072
0
    if (pid == -1) {
9073
0
        return posix_error();
9074
0
    }
9075
9076
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9077
0
}
9078
#endif /* HAVE_FORKPTY */
9079
9080
9081
#ifdef HAVE_GETEGID
9082
/*[clinic input]
9083
os.getegid
9084
9085
Return the current process's effective group id.
9086
[clinic start generated code]*/
9087
9088
static PyObject *
9089
os_getegid_impl(PyObject *module)
9090
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9091
22
{
9092
22
    return _PyLong_FromGid(getegid());
9093
22
}
9094
#endif /* HAVE_GETEGID */
9095
9096
9097
#ifdef HAVE_GETEUID
9098
/*[clinic input]
9099
os.geteuid
9100
9101
Return the current process's effective user id.
9102
[clinic start generated code]*/
9103
9104
static PyObject *
9105
os_geteuid_impl(PyObject *module)
9106
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9107
22
{
9108
22
    return _PyLong_FromUid(geteuid());
9109
22
}
9110
#endif /* HAVE_GETEUID */
9111
9112
9113
#ifdef HAVE_GETGID
9114
/*[clinic input]
9115
os.getgid
9116
9117
Return the current process's group id.
9118
[clinic start generated code]*/
9119
9120
static PyObject *
9121
os_getgid_impl(PyObject *module)
9122
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9123
22
{
9124
22
    return _PyLong_FromGid(getgid());
9125
22
}
9126
#endif /* HAVE_GETGID */
9127
9128
9129
#if defined(HAVE_GETPID)
9130
/*[clinic input]
9131
os.getpid
9132
9133
Return the current process id.
9134
[clinic start generated code]*/
9135
9136
static PyObject *
9137
os_getpid_impl(PyObject *module)
9138
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9139
0
{
9140
0
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9141
0
    return PyLong_FromPid(getpid());
9142
#else
9143
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9144
#endif
9145
0
}
9146
#endif /* defined(HAVE_GETPID) */
9147
9148
#ifdef NGROUPS_MAX
9149
0
#define MAX_GROUPS NGROUPS_MAX
9150
#else
9151
    /* defined to be 16 on Solaris7, so this should be a small number */
9152
#define MAX_GROUPS 64
9153
#endif
9154
9155
#ifdef HAVE_GETGROUPLIST
9156
9157
#ifdef __APPLE__
9158
/*[clinic input]
9159
os.getgrouplist
9160
9161
    user: str
9162
        username to lookup
9163
    group as basegid: int
9164
        base group id of the user
9165
    /
9166
9167
Returns a list of groups to which a user belongs.
9168
[clinic start generated code]*/
9169
9170
static PyObject *
9171
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9172
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9173
#else
9174
/*[clinic input]
9175
os.getgrouplist
9176
9177
    user: str
9178
        username to lookup
9179
    group as basegid: gid_t
9180
        base group id of the user
9181
    /
9182
9183
Returns a list of groups to which a user belongs.
9184
[clinic start generated code]*/
9185
9186
static PyObject *
9187
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9188
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9189
#endif
9190
0
{
9191
0
    int i, ngroups;
9192
0
    PyObject *list;
9193
#ifdef __APPLE__
9194
    int *groups;
9195
#else
9196
0
    gid_t *groups;
9197
0
#endif
9198
9199
    /*
9200
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9201
     * number of supplemental groups a users can belong to.
9202
     * We have to increment it by one because
9203
     * getgrouplist() returns both the supplemental groups
9204
     * and the primary group, i.e. all of the groups the
9205
     * user belongs to.
9206
     */
9207
0
    ngroups = 1 + MAX_GROUPS;
9208
9209
0
    while (1) {
9210
#ifdef __APPLE__
9211
        groups = PyMem_New(int, ngroups);
9212
#else
9213
0
        groups = PyMem_New(gid_t, ngroups);
9214
0
#endif
9215
0
        if (groups == NULL) {
9216
0
            return PyErr_NoMemory();
9217
0
        }
9218
9219
0
        int old_ngroups = ngroups;
9220
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9221
            /* Success */
9222
0
            break;
9223
0
        }
9224
9225
        /* getgrouplist() fails if the group list is too small */
9226
0
        PyMem_Free(groups);
9227
9228
0
        if (ngroups > old_ngroups) {
9229
            /* If the group list is too small, the glibc implementation of
9230
               getgrouplist() sets ngroups to the total number of groups and
9231
               returns -1. */
9232
0
        }
9233
0
        else {
9234
            /* Double the group list size */
9235
0
            if (ngroups > INT_MAX / 2) {
9236
0
                return PyErr_NoMemory();
9237
0
            }
9238
0
            ngroups *= 2;
9239
0
        }
9240
9241
        /* Retry getgrouplist() with a larger group list */
9242
0
    }
9243
9244
#ifdef _Py_MEMORY_SANITIZER
9245
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9246
    __msan_unpoison(&ngroups, sizeof(ngroups));
9247
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9248
#endif
9249
9250
0
    list = PyList_New(ngroups);
9251
0
    if (list == NULL) {
9252
0
        PyMem_Free(groups);
9253
0
        return NULL;
9254
0
    }
9255
9256
0
    for (i = 0; i < ngroups; i++) {
9257
#ifdef __APPLE__
9258
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9259
#else
9260
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9261
0
#endif
9262
0
        if (o == NULL) {
9263
0
            Py_DECREF(list);
9264
0
            PyMem_Free(groups);
9265
0
            return NULL;
9266
0
        }
9267
0
        PyList_SET_ITEM(list, i, o);
9268
0
    }
9269
9270
0
    PyMem_Free(groups);
9271
9272
0
    return list;
9273
0
}
9274
#endif /* HAVE_GETGROUPLIST */
9275
9276
9277
#ifdef HAVE_GETGROUPS
9278
/*[clinic input]
9279
os.getgroups
9280
9281
Return list of supplemental group IDs for the process.
9282
[clinic start generated code]*/
9283
9284
static PyObject *
9285
os_getgroups_impl(PyObject *module)
9286
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9287
0
{
9288
    // Call getgroups with length 0 to get the actual number of groups
9289
0
    int n = getgroups(0, NULL);
9290
0
    if (n < 0) {
9291
0
        return posix_error();
9292
0
    }
9293
9294
0
    if (n == 0) {
9295
0
        return PyList_New(0);
9296
0
    }
9297
9298
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9299
0
    if (grouplist == NULL) {
9300
0
        return PyErr_NoMemory();
9301
0
    }
9302
9303
0
    n = getgroups(n, grouplist);
9304
0
    if (n == -1) {
9305
0
        posix_error();
9306
0
        PyMem_Free(grouplist);
9307
0
        return NULL;
9308
0
    }
9309
9310
0
    PyObject *result = PyList_New(n);
9311
0
    if (result == NULL) {
9312
0
        goto error;
9313
0
    }
9314
9315
0
    for (int i = 0; i < n; ++i) {
9316
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9317
0
        if (group == NULL) {
9318
0
            goto error;
9319
0
        }
9320
0
        PyList_SET_ITEM(result, i, group);
9321
0
    }
9322
0
    PyMem_Free(grouplist);
9323
9324
0
    return result;
9325
9326
0
error:
9327
0
    PyMem_Free(grouplist);
9328
0
    Py_XDECREF(result);
9329
0
    return NULL;
9330
0
}
9331
#endif /* HAVE_GETGROUPS */
9332
9333
#ifdef HAVE_INITGROUPS
9334
#ifdef __APPLE__
9335
/*[clinic input]
9336
os.initgroups
9337
9338
    username as oname: unicode_fs_encoded
9339
    gid: int
9340
    /
9341
9342
Initialize the group access list.
9343
9344
Call the system initgroups() to initialize the group access list with all of
9345
the groups of which the specified username is a member, plus the specified
9346
group id.
9347
[clinic start generated code]*/
9348
9349
static PyObject *
9350
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9351
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
9352
#else
9353
/*[clinic input]
9354
os.initgroups
9355
9356
    username as oname: unicode_fs_encoded
9357
    gid: gid_t
9358
    /
9359
9360
Initialize the group access list.
9361
9362
Call the system initgroups() to initialize the group access list with all of
9363
the groups of which the specified username is a member, plus the specified
9364
group id.
9365
[clinic start generated code]*/
9366
9367
static PyObject *
9368
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9369
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
9370
#endif
9371
0
{
9372
0
    const char *username = PyBytes_AS_STRING(oname);
9373
9374
0
    if (initgroups(username, gid) == -1)
9375
0
        return PyErr_SetFromErrno(PyExc_OSError);
9376
9377
0
    Py_RETURN_NONE;
9378
0
}
9379
#endif /* HAVE_INITGROUPS */
9380
9381
9382
#ifdef HAVE_GETPGID
9383
/*[clinic input]
9384
os.getpgid
9385
9386
    pid: pid_t
9387
9388
Call the system call getpgid(), and return the result.
9389
[clinic start generated code]*/
9390
9391
static PyObject *
9392
os_getpgid_impl(PyObject *module, pid_t pid)
9393
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9394
0
{
9395
0
    pid_t pgid = getpgid(pid);
9396
0
    if (pgid < 0)
9397
0
        return posix_error();
9398
0
    return PyLong_FromPid(pgid);
9399
0
}
9400
#endif /* HAVE_GETPGID */
9401
9402
9403
#ifdef HAVE_GETPGRP
9404
/*[clinic input]
9405
os.getpgrp
9406
9407
Return the current process group id.
9408
[clinic start generated code]*/
9409
9410
static PyObject *
9411
os_getpgrp_impl(PyObject *module)
9412
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9413
0
{
9414
#ifdef GETPGRP_HAVE_ARG
9415
    return PyLong_FromPid(getpgrp(0));
9416
#else /* GETPGRP_HAVE_ARG */
9417
0
    return PyLong_FromPid(getpgrp());
9418
0
#endif /* GETPGRP_HAVE_ARG */
9419
0
}
9420
#endif /* HAVE_GETPGRP */
9421
9422
9423
#ifdef HAVE_SETPGRP
9424
/*[clinic input]
9425
os.setpgrp
9426
9427
Make the current process the leader of its process group.
9428
[clinic start generated code]*/
9429
9430
static PyObject *
9431
os_setpgrp_impl(PyObject *module)
9432
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9433
0
{
9434
#ifdef SETPGRP_HAVE_ARG
9435
    if (setpgrp(0, 0) < 0)
9436
#else /* SETPGRP_HAVE_ARG */
9437
0
    if (setpgrp() < 0)
9438
0
#endif /* SETPGRP_HAVE_ARG */
9439
0
        return posix_error();
9440
0
    Py_RETURN_NONE;
9441
0
}
9442
#endif /* HAVE_SETPGRP */
9443
9444
#ifdef HAVE_GETPPID
9445
9446
#ifdef MS_WINDOWS
9447
#include <winternl.h>
9448
#include <ProcessSnapshot.h>
9449
9450
// The structure definition in winternl.h may be incomplete.
9451
// This structure is the full version from the MSDN documentation.
9452
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9453
    NTSTATUS ExitStatus;
9454
    PVOID PebBaseAddress;
9455
    ULONG_PTR AffinityMask;
9456
    LONG BasePriority;
9457
    ULONG_PTR UniqueProcessId;
9458
    ULONG_PTR InheritedFromUniqueProcessId;
9459
} PROCESS_BASIC_INFORMATION_FULL;
9460
9461
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9462
    IN    HANDLE           ProcessHandle,
9463
    IN    PROCESSINFOCLASS ProcessInformationClass,
9464
    OUT   PVOID            ProcessInformation,
9465
    IN    ULONG            ProcessInformationLength,
9466
    OUT   PULONG           ReturnLength OPTIONAL);
9467
9468
// This function returns the process ID of the parent process.
9469
// Returns 0 on failure.
9470
static ULONG
9471
win32_getppid_fast(void)
9472
{
9473
    NTSTATUS status;
9474
    HMODULE ntdll;
9475
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9476
    PROCESS_BASIC_INFORMATION_FULL basic_information;
9477
    static ULONG cached_ppid = 0;
9478
9479
    if (cached_ppid) {
9480
        // No need to query the kernel again.
9481
        return cached_ppid;
9482
    }
9483
9484
    ntdll = GetModuleHandleW(L"ntdll.dll");
9485
    if (!ntdll) {
9486
        return 0;
9487
    }
9488
9489
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9490
    if (!pNtQueryInformationProcess) {
9491
        return 0;
9492
    }
9493
9494
    status = pNtQueryInformationProcess(GetCurrentProcess(),
9495
                                        ProcessBasicInformation,
9496
                                        &basic_information,
9497
                                        sizeof(basic_information),
9498
                                        NULL);
9499
9500
    if (!NT_SUCCESS(status)) {
9501
        return 0;
9502
    }
9503
9504
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9505
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
9506
    // zero and (ULONG) -1.
9507
9508
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
9509
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9510
    {
9511
        return 0;
9512
    }
9513
9514
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9515
    // structure member contains a ULONG_PTR which represents the process ID of our parent
9516
    // process. This process ID will be correctly returned even if the parent process has
9517
    // exited or been terminated.
9518
9519
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9520
    return cached_ppid;
9521
}
9522
9523
static PyObject*
9524
win32_getppid(void)
9525
{
9526
    DWORD error;
9527
    PyObject* result = NULL;
9528
    HANDLE process = GetCurrentProcess();
9529
    HPSS snapshot = NULL;
9530
    ULONG pid;
9531
9532
    pid = win32_getppid_fast();
9533
    if (pid != 0) {
9534
        return PyLong_FromUnsignedLong(pid);
9535
    }
9536
9537
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9538
9539
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9540
    if (error != ERROR_SUCCESS) {
9541
        return PyErr_SetFromWindowsErr(error);
9542
    }
9543
9544
    PSS_PROCESS_INFORMATION info;
9545
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
9546
                             sizeof(info));
9547
    if (error == ERROR_SUCCESS) {
9548
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
9549
    }
9550
    else {
9551
        result = PyErr_SetFromWindowsErr(error);
9552
    }
9553
9554
    PssFreeSnapshot(process, snapshot);
9555
    return result;
9556
}
9557
#endif /*MS_WINDOWS*/
9558
9559
9560
/*[clinic input]
9561
os.getppid
9562
9563
Return the parent's process id.
9564
9565
If the parent process has already exited, Windows machines will still
9566
return its id; others systems will return the id of the 'init' process (1).
9567
[clinic start generated code]*/
9568
9569
static PyObject *
9570
os_getppid_impl(PyObject *module)
9571
/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
9572
0
{
9573
#ifdef MS_WINDOWS
9574
    return win32_getppid();
9575
#else
9576
0
    return PyLong_FromPid(getppid());
9577
0
#endif
9578
0
}
9579
#endif /* HAVE_GETPPID */
9580
9581
9582
#ifdef HAVE_GETLOGIN
9583
/*[clinic input]
9584
os.getlogin
9585
9586
Return the actual login name.
9587
[clinic start generated code]*/
9588
9589
static PyObject *
9590
os_getlogin_impl(PyObject *module)
9591
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
9592
0
{
9593
0
    PyObject *result = NULL;
9594
#ifdef MS_WINDOWS
9595
    wchar_t user_name[UNLEN + 1];
9596
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
9597
9598
    if (GetUserNameW(user_name, &num_chars)) {
9599
        /* num_chars is the number of unicode chars plus null terminator */
9600
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
9601
    }
9602
    else
9603
        result = PyErr_SetFromWindowsErr(GetLastError());
9604
#elif defined (HAVE_GETLOGIN_R)
9605
# if defined (HAVE_MAXLOGNAME)
9606
    char name[MAXLOGNAME + 1];
9607
# elif defined (HAVE_UT_NAMESIZE)
9608
    char name[UT_NAMESIZE + 1];
9609
# else
9610
    char name[256];
9611
# endif
9612
0
    int err = getlogin_r(name, sizeof(name));
9613
0
    if (err) {
9614
0
        int old_errno = errno;
9615
0
        errno = err;
9616
0
        posix_error();
9617
0
        errno = old_errno;
9618
0
    }
9619
0
    else {
9620
0
        result = PyUnicode_DecodeFSDefault(name);
9621
0
    }
9622
#else
9623
    char *name;
9624
    int old_errno = errno;
9625
9626
    errno = 0;
9627
    name = getlogin();
9628
    if (name == NULL) {
9629
        if (errno)
9630
            posix_error();
9631
        else
9632
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
9633
    }
9634
    else
9635
        result = PyUnicode_DecodeFSDefault(name);
9636
    errno = old_errno;
9637
#endif
9638
0
    return result;
9639
0
}
9640
#endif /* HAVE_GETLOGIN */
9641
9642
9643
#ifdef HAVE_GETUID
9644
/*[clinic input]
9645
os.getuid
9646
9647
Return the current process's user id.
9648
[clinic start generated code]*/
9649
9650
static PyObject *
9651
os_getuid_impl(PyObject *module)
9652
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
9653
22
{
9654
22
    return _PyLong_FromUid(getuid());
9655
22
}
9656
#endif /* HAVE_GETUID */
9657
9658
9659
#ifdef MS_WINDOWS
9660
#define HAVE_KILL
9661
#endif /* MS_WINDOWS */
9662
9663
#ifdef HAVE_KILL
9664
/*[clinic input]
9665
os.kill
9666
9667
    pid: pid_t
9668
    signal: Py_ssize_t
9669
    /
9670
9671
Kill a process with a signal.
9672
[clinic start generated code]*/
9673
9674
static PyObject *
9675
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
9676
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
9677
0
{
9678
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
9679
0
        return NULL;
9680
0
    }
9681
0
#ifndef MS_WINDOWS
9682
0
    if (kill(pid, (int)signal) == -1) {
9683
0
        return posix_error();
9684
0
    }
9685
9686
    // Check immediately if the signal was sent to the current process.
9687
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
9688
    // is cheap.
9689
0
    if (PyErr_CheckSignals()) {
9690
0
        return NULL;
9691
0
    }
9692
9693
0
    Py_RETURN_NONE;
9694
#else /* !MS_WINDOWS */
9695
    DWORD sig = (DWORD)signal;
9696
9697
#ifdef HAVE_WINDOWS_CONSOLE_IO
9698
    /* Console processes which share a common console can be sent CTRL+C or
9699
       CTRL+BREAK events, provided they handle said events. */
9700
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
9701
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
9702
            return PyErr_SetFromWindowsErr(0);
9703
        }
9704
        Py_RETURN_NONE;
9705
    }
9706
#endif /* HAVE_WINDOWS_CONSOLE_IO */
9707
9708
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
9709
       attempt to open and terminate the process. */
9710
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
9711
    if (handle == NULL) {
9712
        return PyErr_SetFromWindowsErr(0);
9713
    }
9714
9715
    BOOL res = TerminateProcess(handle, sig);
9716
    CloseHandle(handle);
9717
    if (res == 0) {
9718
        return PyErr_SetFromWindowsErr(0);
9719
    }
9720
9721
    Py_RETURN_NONE;
9722
#endif /* !MS_WINDOWS */
9723
0
}
9724
#endif /* HAVE_KILL */
9725
9726
9727
#ifdef HAVE_KILLPG
9728
/*[clinic input]
9729
os.killpg
9730
9731
    pgid: pid_t
9732
    signal: int
9733
    /
9734
9735
Kill a process group with a signal.
9736
[clinic start generated code]*/
9737
9738
static PyObject *
9739
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
9740
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
9741
0
{
9742
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
9743
0
        return NULL;
9744
0
    }
9745
    /* XXX some man pages make the `pgid` parameter an int, others
9746
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
9747
       take the same type. Moreover, pid_t is always at least as wide as
9748
       int (else compilation of this module fails), which is safe. */
9749
0
    if (killpg(pgid, signal) == -1)
9750
0
        return posix_error();
9751
0
    Py_RETURN_NONE;
9752
0
}
9753
#endif /* HAVE_KILLPG */
9754
9755
9756
#ifdef HAVE_PLOCK
9757
#ifdef HAVE_SYS_LOCK_H
9758
#include <sys/lock.h>
9759
#endif
9760
9761
/*[clinic input]
9762
os.plock
9763
    op: int
9764
    /
9765
9766
Lock program segments into memory.");
9767
[clinic start generated code]*/
9768
9769
static PyObject *
9770
os_plock_impl(PyObject *module, int op)
9771
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
9772
{
9773
    if (plock(op) == -1)
9774
        return posix_error();
9775
    Py_RETURN_NONE;
9776
}
9777
#endif /* HAVE_PLOCK */
9778
9779
9780
#ifdef HAVE_SETUID
9781
/*[clinic input]
9782
os.setuid
9783
9784
    uid: uid_t
9785
    /
9786
9787
Set the current process's user id.
9788
[clinic start generated code]*/
9789
9790
static PyObject *
9791
os_setuid_impl(PyObject *module, uid_t uid)
9792
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
9793
0
{
9794
0
    if (setuid(uid) < 0)
9795
0
        return posix_error();
9796
0
    Py_RETURN_NONE;
9797
0
}
9798
#endif /* HAVE_SETUID */
9799
9800
9801
#ifdef HAVE_SETEUID
9802
/*[clinic input]
9803
os.seteuid
9804
9805
    euid: uid_t
9806
    /
9807
9808
Set the current process's effective user id.
9809
[clinic start generated code]*/
9810
9811
static PyObject *
9812
os_seteuid_impl(PyObject *module, uid_t euid)
9813
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
9814
0
{
9815
0
    if (seteuid(euid) < 0)
9816
0
        return posix_error();
9817
0
    Py_RETURN_NONE;
9818
0
}
9819
#endif /* HAVE_SETEUID */
9820
9821
9822
#ifdef HAVE_SETEGID
9823
/*[clinic input]
9824
os.setegid
9825
9826
    egid: gid_t
9827
    /
9828
9829
Set the current process's effective group id.
9830
[clinic start generated code]*/
9831
9832
static PyObject *
9833
os_setegid_impl(PyObject *module, gid_t egid)
9834
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
9835
0
{
9836
0
    if (setegid(egid) < 0)
9837
0
        return posix_error();
9838
0
    Py_RETURN_NONE;
9839
0
}
9840
#endif /* HAVE_SETEGID */
9841
9842
9843
#ifdef HAVE_SETREUID
9844
/*[clinic input]
9845
os.setreuid
9846
9847
    ruid: uid_t
9848
    euid: uid_t
9849
    /
9850
9851
Set the current process's real and effective user ids.
9852
[clinic start generated code]*/
9853
9854
static PyObject *
9855
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
9856
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
9857
0
{
9858
0
    if (setreuid(ruid, euid) < 0) {
9859
0
        return posix_error();
9860
0
    } else {
9861
0
        Py_RETURN_NONE;
9862
0
    }
9863
0
}
9864
#endif /* HAVE_SETREUID */
9865
9866
9867
#ifdef HAVE_SETREGID
9868
/*[clinic input]
9869
os.setregid
9870
9871
    rgid: gid_t
9872
    egid: gid_t
9873
    /
9874
9875
Set the current process's real and effective group ids.
9876
[clinic start generated code]*/
9877
9878
static PyObject *
9879
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
9880
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
9881
0
{
9882
0
    if (setregid(rgid, egid) < 0)
9883
0
        return posix_error();
9884
0
    Py_RETURN_NONE;
9885
0
}
9886
#endif /* HAVE_SETREGID */
9887
9888
9889
#ifdef HAVE_SETGID
9890
/*[clinic input]
9891
os.setgid
9892
    gid: gid_t
9893
    /
9894
9895
Set the current process's group id.
9896
[clinic start generated code]*/
9897
9898
static PyObject *
9899
os_setgid_impl(PyObject *module, gid_t gid)
9900
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
9901
0
{
9902
0
    if (setgid(gid) < 0)
9903
0
        return posix_error();
9904
0
    Py_RETURN_NONE;
9905
0
}
9906
#endif /* HAVE_SETGID */
9907
9908
9909
#ifdef HAVE_SETGROUPS
9910
/*[clinic input]
9911
os.setgroups
9912
9913
    groups: object
9914
    /
9915
9916
Set the groups of the current process to list.
9917
[clinic start generated code]*/
9918
9919
static PyObject *
9920
os_setgroups(PyObject *module, PyObject *groups)
9921
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
9922
0
{
9923
0
    if (!PySequence_Check(groups)) {
9924
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
9925
0
        return NULL;
9926
0
    }
9927
0
    Py_ssize_t len = PySequence_Size(groups);
9928
0
    if (len < 0) {
9929
0
        return NULL;
9930
0
    }
9931
0
    if (len > MAX_GROUPS) {
9932
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
9933
0
        return NULL;
9934
0
    }
9935
9936
0
    gid_t *grouplist = PyMem_New(gid_t, len);
9937
0
    if (grouplist == NULL) {
9938
0
        PyErr_NoMemory();
9939
0
        return NULL;
9940
0
    }
9941
0
    for (Py_ssize_t i = 0; i < len; i++) {
9942
0
        PyObject *elem;
9943
0
        elem = PySequence_GetItem(groups, i);
9944
0
        if (!elem) {
9945
0
            PyMem_Free(grouplist);
9946
0
            return NULL;
9947
0
        }
9948
0
        if (!PyIndex_Check(elem)) {
9949
0
            PyErr_SetString(PyExc_TypeError,
9950
0
                            "groups must be integers");
9951
0
            Py_DECREF(elem);
9952
0
            PyMem_Free(grouplist);
9953
0
            return NULL;
9954
0
        } else {
9955
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
9956
0
                Py_DECREF(elem);
9957
0
                PyMem_Free(grouplist);
9958
0
                return NULL;
9959
0
            }
9960
0
        }
9961
0
        Py_DECREF(elem);
9962
0
    }
9963
9964
0
    if (setgroups(len, grouplist) < 0) {
9965
0
        posix_error();
9966
0
        PyMem_Free(grouplist);
9967
0
        return NULL;
9968
0
    }
9969
0
    PyMem_Free(grouplist);
9970
0
    Py_RETURN_NONE;
9971
0
}
9972
#endif /* HAVE_SETGROUPS */
9973
9974
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
9975
static PyObject *
9976
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
9977
0
{
9978
0
    PyObject *result;
9979
0
    PyObject *struct_rusage;
9980
9981
0
    if (pid == -1)
9982
0
        return posix_error();
9983
9984
    // If wait succeeded but no child was ready to report status, ru will not
9985
    // have been populated.
9986
0
    if (pid == 0) {
9987
0
        memset(ru, 0, sizeof(*ru));
9988
0
    }
9989
9990
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
9991
0
    if (struct_rusage == NULL)
9992
0
        return NULL;
9993
9994
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
9995
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
9996
0
    Py_DECREF(struct_rusage);
9997
0
    if (!result)
9998
0
        return NULL;
9999
10000
0
    int pos = 0;
10001
10002
0
#ifndef doubletime
10003
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10004
0
#endif
10005
10006
0
#define SET_RESULT(CALL)                                     \
10007
0
    do {                                                     \
10008
0
        PyObject *item = (CALL);                             \
10009
0
        if (item == NULL) {                                  \
10010
0
            Py_DECREF(result);                               \
10011
0
            return NULL;                                     \
10012
0
        }                                                    \
10013
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10014
0
    } while(0)
10015
10016
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10017
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10018
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10019
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10020
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10021
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10022
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10023
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10024
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10025
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10026
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10027
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10028
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10029
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10030
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10031
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10032
0
#undef SET_RESULT
10033
10034
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10035
0
}
10036
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10037
10038
10039
#ifdef HAVE_WAIT3
10040
/*[clinic input]
10041
os.wait3
10042
10043
    options: int
10044
Wait for completion of a child process.
10045
10046
Returns a tuple of information about the child process:
10047
  (pid, status, rusage)
10048
[clinic start generated code]*/
10049
10050
static PyObject *
10051
os_wait3_impl(PyObject *module, int options)
10052
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10053
0
{
10054
0
    pid_t pid;
10055
0
    struct rusage ru;
10056
0
    int async_err = 0;
10057
0
    WAIT_TYPE status;
10058
0
    WAIT_STATUS_INT(status) = 0;
10059
10060
0
    do {
10061
0
        Py_BEGIN_ALLOW_THREADS
10062
0
        pid = wait3(&status, options, &ru);
10063
0
        Py_END_ALLOW_THREADS
10064
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10065
0
    if (pid < 0)
10066
0
        return (!async_err) ? posix_error() : NULL;
10067
10068
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10069
0
}
10070
#endif /* HAVE_WAIT3 */
10071
10072
10073
#ifdef HAVE_WAIT4
10074
/*[clinic input]
10075
10076
os.wait4
10077
10078
    pid: pid_t
10079
    options: int
10080
10081
Wait for completion of a specific child process.
10082
10083
Returns a tuple of information about the child process:
10084
  (pid, status, rusage)
10085
[clinic start generated code]*/
10086
10087
static PyObject *
10088
os_wait4_impl(PyObject *module, pid_t pid, int options)
10089
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10090
0
{
10091
0
    pid_t res;
10092
0
    struct rusage ru;
10093
0
    int async_err = 0;
10094
0
    WAIT_TYPE status;
10095
0
    WAIT_STATUS_INT(status) = 0;
10096
10097
0
    do {
10098
0
        Py_BEGIN_ALLOW_THREADS
10099
0
        res = wait4(pid, &status, options, &ru);
10100
0
        Py_END_ALLOW_THREADS
10101
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10102
0
    if (res < 0)
10103
0
        return (!async_err) ? posix_error() : NULL;
10104
10105
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10106
0
}
10107
#endif /* HAVE_WAIT4 */
10108
10109
10110
#if defined(HAVE_WAITID)
10111
/*[clinic input]
10112
os.waitid
10113
10114
    idtype: idtype_t
10115
        Must be one of be P_PID, P_PGID or P_ALL.
10116
    id: id_t
10117
        The id to wait on.
10118
    options: int
10119
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10120
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10121
    /
10122
10123
Returns the result of waiting for a process or processes.
10124
10125
Returns either waitid_result or None if WNOHANG is specified and there are
10126
no children in a waitable state.
10127
[clinic start generated code]*/
10128
10129
static PyObject *
10130
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10131
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
10132
0
{
10133
0
    PyObject *result;
10134
0
    int res;
10135
0
    int async_err = 0;
10136
0
    siginfo_t si;
10137
0
    si.si_pid = 0;
10138
10139
0
    do {
10140
0
        Py_BEGIN_ALLOW_THREADS
10141
0
        res = waitid(idtype, id, &si, options);
10142
0
        Py_END_ALLOW_THREADS
10143
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10144
0
    if (res < 0)
10145
0
        return (!async_err) ? posix_error() : NULL;
10146
10147
0
    if (si.si_pid == 0)
10148
0
        Py_RETURN_NONE;
10149
10150
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10151
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10152
0
    if (!result)
10153
0
        return NULL;
10154
10155
0
    int pos = 0;
10156
10157
0
#define SET_RESULT(CALL)                                     \
10158
0
    do {                                                     \
10159
0
        PyObject *item = (CALL);                             \
10160
0
        if (item == NULL) {                                  \
10161
0
            Py_DECREF(result);                               \
10162
0
            return NULL;                                     \
10163
0
        }                                                    \
10164
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10165
0
    } while(0)
10166
10167
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10168
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10169
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10170
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10171
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10172
10173
0
#undef SET_RESULT
10174
10175
0
    return result;
10176
0
}
10177
#endif /* defined(HAVE_WAITID) */
10178
10179
10180
#if defined(HAVE_WAITPID)
10181
/*[clinic input]
10182
os.waitpid
10183
    pid: pid_t
10184
    options: int
10185
    /
10186
10187
Wait for completion of a given child process.
10188
10189
Returns a tuple of information regarding the child process:
10190
    (pid, status)
10191
10192
The options argument is ignored on Windows.
10193
[clinic start generated code]*/
10194
10195
static PyObject *
10196
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10197
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10198
0
{
10199
0
    pid_t res;
10200
0
    int async_err = 0;
10201
0
    WAIT_TYPE status;
10202
0
    WAIT_STATUS_INT(status) = 0;
10203
10204
0
    do {
10205
0
        Py_BEGIN_ALLOW_THREADS
10206
0
        res = waitpid(pid, &status, options);
10207
0
        Py_END_ALLOW_THREADS
10208
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10209
0
    if (res < 0)
10210
0
        return (!async_err) ? posix_error() : NULL;
10211
10212
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10213
0
}
10214
#elif defined(HAVE_CWAIT)
10215
/* MS C has a variant of waitpid() that's usable for most purposes. */
10216
/*[clinic input]
10217
os.waitpid
10218
    pid: intptr_t
10219
    options: int
10220
    /
10221
10222
Wait for completion of a given process.
10223
10224
Returns a tuple of information regarding the process:
10225
    (pid, status << 8)
10226
10227
The options argument is ignored on Windows.
10228
[clinic start generated code]*/
10229
10230
static PyObject *
10231
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10232
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10233
{
10234
    int status;
10235
    intptr_t res;
10236
    int async_err = 0;
10237
10238
    do {
10239
        Py_BEGIN_ALLOW_THREADS
10240
        _Py_BEGIN_SUPPRESS_IPH
10241
        res = _cwait(&status, pid, options);
10242
        _Py_END_SUPPRESS_IPH
10243
        Py_END_ALLOW_THREADS
10244
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10245
    if (res < 0)
10246
        return (!async_err) ? posix_error() : NULL;
10247
10248
    unsigned long long ustatus = (unsigned int)status;
10249
10250
    /* shift the status left a byte so this is more like the POSIX waitpid */
10251
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10252
}
10253
#endif
10254
10255
10256
#ifdef HAVE_WAIT
10257
/*[clinic input]
10258
os.wait
10259
10260
Wait for completion of a child process.
10261
10262
Returns a tuple of information about the child process:
10263
    (pid, status)
10264
[clinic start generated code]*/
10265
10266
static PyObject *
10267
os_wait_impl(PyObject *module)
10268
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10269
0
{
10270
0
    pid_t pid;
10271
0
    int async_err = 0;
10272
0
    WAIT_TYPE status;
10273
0
    WAIT_STATUS_INT(status) = 0;
10274
10275
0
    do {
10276
0
        Py_BEGIN_ALLOW_THREADS
10277
0
        pid = wait(&status);
10278
0
        Py_END_ALLOW_THREADS
10279
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10280
0
    if (pid < 0)
10281
0
        return (!async_err) ? posix_error() : NULL;
10282
10283
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10284
0
}
10285
#endif /* HAVE_WAIT */
10286
10287
10288
// This system call always crashes on older Android versions.
10289
#if defined(__linux__) && defined(__NR_pidfd_open) && \
10290
    !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10291
/*[clinic input]
10292
os.pidfd_open
10293
  pid: pid_t
10294
  flags: unsigned_int = 0
10295
10296
Return a file descriptor referring to the process *pid*.
10297
10298
The descriptor can be used to perform process management without races and
10299
signals.
10300
[clinic start generated code]*/
10301
10302
static PyObject *
10303
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10304
/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10305
0
{
10306
0
    int fd = syscall(__NR_pidfd_open, pid, flags);
10307
0
    if (fd < 0) {
10308
0
        return posix_error();
10309
0
    }
10310
0
    return PyLong_FromLong(fd);
10311
0
}
10312
#endif
10313
10314
10315
#ifdef HAVE_SETNS
10316
/*[clinic input]
10317
os.setns
10318
  fd: fildes
10319
    A file descriptor to a namespace.
10320
  nstype: int = 0
10321
    Type of namespace.
10322
10323
Move the calling thread into different namespaces.
10324
[clinic start generated code]*/
10325
10326
static PyObject *
10327
os_setns_impl(PyObject *module, int fd, int nstype)
10328
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10329
0
{
10330
0
    int res;
10331
10332
0
    Py_BEGIN_ALLOW_THREADS
10333
0
    res = setns(fd, nstype);
10334
0
    Py_END_ALLOW_THREADS
10335
10336
0
    if (res != 0) {
10337
0
        return posix_error();
10338
0
    }
10339
10340
0
    Py_RETURN_NONE;
10341
0
}
10342
#endif
10343
10344
10345
#ifdef HAVE_UNSHARE
10346
/*[clinic input]
10347
os.unshare
10348
  flags: int
10349
    Namespaces to be unshared.
10350
10351
Disassociate parts of a process (or thread) execution context.
10352
[clinic start generated code]*/
10353
10354
static PyObject *
10355
os_unshare_impl(PyObject *module, int flags)
10356
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10357
0
{
10358
0
    int res;
10359
10360
0
    Py_BEGIN_ALLOW_THREADS
10361
0
    res = unshare(flags);
10362
0
    Py_END_ALLOW_THREADS
10363
10364
0
    if (res != 0) {
10365
0
        return posix_error();
10366
0
    }
10367
10368
0
    Py_RETURN_NONE;
10369
0
}
10370
#endif
10371
10372
10373
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10374
/*[clinic input]
10375
os.readlink
10376
10377
    path: path_t
10378
    *
10379
    dir_fd: dir_fd(requires='readlinkat') = None
10380
10381
Return a string representing the path to which the symbolic link points.
10382
10383
If dir_fd is not None, it should be a file descriptor open to a directory,
10384
and path should be relative; path will then be relative to that directory.
10385
10386
dir_fd may not be implemented on your platform.  If it is unavailable,
10387
using it will raise a NotImplementedError.
10388
[clinic start generated code]*/
10389
10390
static PyObject *
10391
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10392
/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10393
0
{
10394
0
#if defined(HAVE_READLINK)
10395
0
    char buffer[MAXPATHLEN+1];
10396
0
    ssize_t length;
10397
0
#ifdef HAVE_READLINKAT
10398
0
    int readlinkat_unavailable = 0;
10399
0
#endif
10400
10401
0
    Py_BEGIN_ALLOW_THREADS
10402
0
#ifdef HAVE_READLINKAT
10403
0
    if (dir_fd != DEFAULT_DIR_FD) {
10404
0
        if (HAVE_READLINKAT_RUNTIME) {
10405
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10406
0
        } else {
10407
0
            readlinkat_unavailable = 1;
10408
0
        }
10409
0
    } else
10410
0
#endif
10411
0
        length = readlink(path->narrow, buffer, MAXPATHLEN);
10412
0
    Py_END_ALLOW_THREADS
10413
10414
0
#ifdef HAVE_READLINKAT
10415
0
    if (readlinkat_unavailable) {
10416
0
        argument_unavailable_error(NULL, "dir_fd");
10417
0
        return NULL;
10418
0
    }
10419
0
#endif
10420
10421
0
    if (length < 0) {
10422
0
        return path_error(path);
10423
0
    }
10424
0
    buffer[length] = '\0';
10425
10426
0
    if (PyUnicode_Check(path->object))
10427
0
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10428
0
    else
10429
0
        return PyBytes_FromStringAndSize(buffer, length);
10430
#elif defined(MS_WINDOWS)
10431
    DWORD n_bytes_returned;
10432
    DWORD io_result = 0;
10433
    HANDLE reparse_point_handle;
10434
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10435
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10436
    PyObject *result = NULL;
10437
10438
    /* First get a handle to the reparse point */
10439
    Py_BEGIN_ALLOW_THREADS
10440
    reparse_point_handle = CreateFileW(
10441
        path->wide,
10442
        0,
10443
        0,
10444
        0,
10445
        OPEN_EXISTING,
10446
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10447
        0);
10448
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10449
        /* New call DeviceIoControl to read the reparse point */
10450
        io_result = DeviceIoControl(
10451
            reparse_point_handle,
10452
            FSCTL_GET_REPARSE_POINT,
10453
            0, 0, /* in buffer */
10454
            target_buffer, sizeof(target_buffer),
10455
            &n_bytes_returned,
10456
            0 /* we're not using OVERLAPPED_IO */
10457
            );
10458
        CloseHandle(reparse_point_handle);
10459
    }
10460
    Py_END_ALLOW_THREADS
10461
10462
    if (io_result == 0) {
10463
        return path_error(path);
10464
    }
10465
10466
    wchar_t *name = NULL;
10467
    Py_ssize_t nameLen = 0;
10468
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10469
    {
10470
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10471
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10472
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10473
    }
10474
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10475
    {
10476
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10477
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
10478
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10479
    }
10480
    else
10481
    {
10482
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10483
    }
10484
    if (name) {
10485
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10486
            /* Our buffer is mutable, so this is okay */
10487
            name[1] = L'\\';
10488
        }
10489
        result = PyUnicode_FromWideChar(name, nameLen);
10490
        if (result && PyBytes_Check(path->object)) {
10491
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10492
        }
10493
    }
10494
    return result;
10495
#endif
10496
0
}
10497
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10498
10499
#if defined(MS_WINDOWS)
10500
10501
/* Remove the last portion of the path - return 0 on success */
10502
static int
10503
_dirnameW(WCHAR *path)
10504
{
10505
    WCHAR *ptr;
10506
    size_t length = wcsnlen_s(path, MAX_PATH);
10507
    if (length == MAX_PATH) {
10508
        return -1;
10509
    }
10510
10511
    /* walk the path from the end until a backslash is encountered */
10512
    for(ptr = path + length; ptr != path; ptr--) {
10513
        if (*ptr == L'\\' || *ptr == L'/') {
10514
            break;
10515
        }
10516
    }
10517
    *ptr = 0;
10518
    return 0;
10519
}
10520
10521
#endif
10522
10523
#ifdef HAVE_SYMLINK
10524
10525
#if defined(MS_WINDOWS)
10526
10527
/* Is this path absolute? */
10528
static int
10529
_is_absW(const WCHAR *path)
10530
{
10531
    return path[0] == L'\\' || path[0] == L'/' ||
10532
        (path[0] && path[1] == L':');
10533
}
10534
10535
/* join root and rest with a backslash - return 0 on success */
10536
static int
10537
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10538
{
10539
    if (_is_absW(rest)) {
10540
        return wcscpy_s(dest_path, MAX_PATH, rest);
10541
    }
10542
10543
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
10544
        return -1;
10545
    }
10546
10547
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
10548
        return -1;
10549
    }
10550
10551
    return wcscat_s(dest_path, MAX_PATH, rest);
10552
}
10553
10554
/* Return True if the path at src relative to dest is a directory */
10555
static int
10556
_check_dirW(LPCWSTR src, LPCWSTR dest)
10557
{
10558
    WIN32_FILE_ATTRIBUTE_DATA src_info;
10559
    WCHAR dest_parent[MAX_PATH];
10560
    WCHAR src_resolved[MAX_PATH] = L"";
10561
10562
    /* dest_parent = os.path.dirname(dest) */
10563
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
10564
        _dirnameW(dest_parent)) {
10565
        return 0;
10566
    }
10567
    /* src_resolved = os.path.join(dest_parent, src) */
10568
    if (_joinW(src_resolved, dest_parent, src)) {
10569
        return 0;
10570
    }
10571
    return (
10572
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
10573
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
10574
    );
10575
}
10576
#endif
10577
10578
10579
/*[clinic input]
10580
os.symlink
10581
    src: path_t
10582
    dst: path_t
10583
    target_is_directory: bool = False
10584
    *
10585
    dir_fd: dir_fd(requires='symlinkat')=None
10586
10587
# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
10588
10589
Create a symbolic link pointing to src named dst.
10590
10591
target_is_directory is required on Windows if the target is to be
10592
  interpreted as a directory.  (On Windows, symlink requires
10593
  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
10594
  target_is_directory is ignored on non-Windows platforms.
10595
10596
If dir_fd is not None, it should be a file descriptor open to a directory,
10597
  and path should be relative; path will then be relative to that directory.
10598
dir_fd may not be implemented on your platform.
10599
  If it is unavailable, using it will raise a NotImplementedError.
10600
10601
[clinic start generated code]*/
10602
10603
static PyObject *
10604
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
10605
                int target_is_directory, int dir_fd)
10606
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
10607
0
{
10608
#ifdef MS_WINDOWS
10609
    DWORD result;
10610
    DWORD flags = 0;
10611
10612
    /* Assumed true, set to false if detected to not be available. */
10613
    static int windows_has_symlink_unprivileged_flag = TRUE;
10614
#else
10615
0
    int result;
10616
0
#ifdef HAVE_SYMLINKAT
10617
0
    int symlinkat_unavailable = 0;
10618
0
#endif
10619
0
#endif
10620
10621
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
10622
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
10623
0
        return NULL;
10624
0
    }
10625
10626
#ifdef MS_WINDOWS
10627
10628
    if (windows_has_symlink_unprivileged_flag) {
10629
        /* Allow non-admin symlinks if system allows it. */
10630
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
10631
    }
10632
10633
    Py_BEGIN_ALLOW_THREADS
10634
    _Py_BEGIN_SUPPRESS_IPH
10635
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
10636
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
10637
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
10638
    }
10639
10640
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
10641
    _Py_END_SUPPRESS_IPH
10642
    Py_END_ALLOW_THREADS
10643
10644
    if (windows_has_symlink_unprivileged_flag && !result &&
10645
        ERROR_INVALID_PARAMETER == GetLastError()) {
10646
10647
        Py_BEGIN_ALLOW_THREADS
10648
        _Py_BEGIN_SUPPRESS_IPH
10649
        /* This error might be caused by
10650
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
10651
        Try again, and update windows_has_symlink_unprivileged_flag if we
10652
        are successful this time.
10653
10654
        NOTE: There is a risk of a race condition here if there are other
10655
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
10656
        another process (or thread) changes that condition in between our
10657
        calls to CreateSymbolicLink.
10658
        */
10659
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
10660
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
10661
        _Py_END_SUPPRESS_IPH
10662
        Py_END_ALLOW_THREADS
10663
10664
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
10665
            windows_has_symlink_unprivileged_flag = FALSE;
10666
        }
10667
    }
10668
10669
    if (!result)
10670
        return path_error2(src, dst);
10671
10672
#else
10673
10674
0
    Py_BEGIN_ALLOW_THREADS
10675
0
#ifdef HAVE_SYMLINKAT
10676
0
    if (dir_fd != DEFAULT_DIR_FD) {
10677
0
        if (HAVE_SYMLINKAT_RUNTIME) {
10678
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
10679
0
        } else {
10680
0
            symlinkat_unavailable = 1;
10681
0
        }
10682
0
    } else
10683
0
#endif
10684
0
        result = symlink(src->narrow, dst->narrow);
10685
0
    Py_END_ALLOW_THREADS
10686
10687
0
#ifdef HAVE_SYMLINKAT
10688
0
    if (symlinkat_unavailable) {
10689
0
          argument_unavailable_error(NULL, "dir_fd");
10690
0
          return NULL;
10691
0
    }
10692
0
#endif
10693
10694
0
    if (result)
10695
0
        return path_error2(src, dst);
10696
0
#endif
10697
10698
0
    Py_RETURN_NONE;
10699
0
}
10700
#endif /* HAVE_SYMLINK */
10701
10702
10703
static PyStructSequence_Field times_result_fields[] = {
10704
    {"user",    "user time"},
10705
    {"system",   "system time"},
10706
    {"children_user",    "user time of children"},
10707
    {"children_system",    "system time of children"},
10708
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
10709
    {NULL}
10710
};
10711
10712
PyDoc_STRVAR(times_result__doc__,
10713
"times_result: Result from os.times().\n\n\
10714
This object may be accessed either as a tuple of\n\
10715
  (user, system, children_user, children_system, elapsed),\n\
10716
or via the attributes user, system, children_user, children_system,\n\
10717
and elapsed.\n\
10718
\n\
10719
See os.times for more information.");
10720
10721
static PyStructSequence_Desc times_result_desc = {
10722
    "times_result", /* name */
10723
    times_result__doc__, /* doc */
10724
    times_result_fields,
10725
    5
10726
};
10727
10728
static PyObject *
10729
build_times_result(PyObject *module, double user, double system,
10730
    double children_user, double children_system,
10731
    double elapsed)
10732
0
{
10733
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
10734
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
10735
0
    if (value == NULL)
10736
0
        return NULL;
10737
10738
0
#define SET(i, field) \
10739
0
    { \
10740
0
    PyObject *o = PyFloat_FromDouble(field); \
10741
0
    if (!o) { \
10742
0
        Py_DECREF(value); \
10743
0
        return NULL; \
10744
0
    } \
10745
0
    PyStructSequence_SET_ITEM(value, i, o); \
10746
0
    } \
10747
0
10748
0
    SET(0, user);
10749
0
    SET(1, system);
10750
0
    SET(2, children_user);
10751
0
    SET(3, children_system);
10752
0
    SET(4, elapsed);
10753
10754
0
#undef SET
10755
10756
0
    return value;
10757
0
}
10758
10759
10760
/*[clinic input]
10761
os.times
10762
10763
Return a collection containing process timing information.
10764
10765
The object returned behaves like a named tuple with these fields:
10766
  (utime, stime, cutime, cstime, elapsed_time)
10767
All fields are floating-point numbers.
10768
[clinic start generated code]*/
10769
10770
static PyObject *
10771
os_times_impl(PyObject *module)
10772
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
10773
0
{
10774
#ifdef MS_WINDOWS
10775
    FILETIME create, exit, kernel, user;
10776
    HANDLE hProc;
10777
    hProc = GetCurrentProcess();
10778
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
10779
    /* The fields of a FILETIME structure are the hi and lo part
10780
       of a 64-bit value expressed in 100 nanosecond units.
10781
       1e7 is one second in such units; 1e-7 the inverse.
10782
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
10783
    */
10784
    return build_times_result(module,
10785
        (double)(user.dwHighDateTime*429.4967296 +
10786
                 user.dwLowDateTime*1e-7),
10787
        (double)(kernel.dwHighDateTime*429.4967296 +
10788
                 kernel.dwLowDateTime*1e-7),
10789
        (double)0,
10790
        (double)0,
10791
        (double)0);
10792
#else /* MS_WINDOWS */
10793
0
    _posixstate *state = get_posix_state(module);
10794
0
    long ticks_per_second = state->ticks_per_second;
10795
10796
0
    struct tms process;
10797
0
    clock_t elapsed;
10798
0
    errno = 0;
10799
0
    elapsed = times(&process);
10800
0
    if (elapsed == (clock_t) -1) {
10801
0
        return posix_error();
10802
0
    }
10803
10804
0
    return build_times_result(module,
10805
0
        (double)process.tms_utime / ticks_per_second,
10806
0
        (double)process.tms_stime / ticks_per_second,
10807
0
        (double)process.tms_cutime / ticks_per_second,
10808
0
        (double)process.tms_cstime / ticks_per_second,
10809
0
        (double)elapsed / ticks_per_second);
10810
0
#endif /* MS_WINDOWS */
10811
0
}
10812
10813
10814
#if defined(HAVE_TIMERFD_CREATE)
10815
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
10816
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
10817
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
10818
10819
static PyObject *
10820
build_itimerspec(const struct itimerspec* curr_value)
10821
0
{
10822
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
10823
0
                                                          curr_value->it_value.tv_nsec);
10824
0
    PyObject *value = PyFloat_FromDouble(_value);
10825
0
    if (value == NULL) {
10826
0
        return NULL;
10827
0
    }
10828
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
10829
0
                                                   curr_value->it_interval.tv_nsec);
10830
0
    PyObject *interval = PyFloat_FromDouble(_interval);
10831
0
    if (interval == NULL) {
10832
0
        Py_DECREF(value);
10833
0
        return NULL;
10834
0
    }
10835
0
    PyObject *tuple = PyTuple_Pack(2, value, interval);
10836
0
    Py_DECREF(interval);
10837
0
    Py_DECREF(value);
10838
0
    return tuple;
10839
0
}
10840
10841
static PyObject *
10842
build_itimerspec_ns(const struct itimerspec* curr_value)
10843
0
{
10844
0
    PyTime_t value, interval;
10845
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
10846
0
        return NULL;
10847
0
    }
10848
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
10849
0
        return NULL;
10850
0
    }
10851
0
    return Py_BuildValue("LL", value, interval);
10852
0
}
10853
10854
/*[clinic input]
10855
os.timerfd_create
10856
10857
    clockid: int
10858
        A valid clock ID constant as timer file descriptor.
10859
10860
        time.CLOCK_REALTIME
10861
        time.CLOCK_MONOTONIC
10862
        time.CLOCK_BOOTTIME
10863
    /
10864
    *
10865
    flags: int = 0
10866
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
10867
10868
        os.TFD_NONBLOCK
10869
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
10870
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
10871
10872
        os.TFD_CLOEXEC
10873
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
10874
10875
Create and return a timer file descriptor.
10876
[clinic start generated code]*/
10877
10878
static PyObject *
10879
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
10880
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
10881
10882
0
{
10883
0
    int fd;
10884
0
    Py_BEGIN_ALLOW_THREADS
10885
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
10886
0
    fd = timerfd_create(clockid, flags);
10887
0
    Py_END_ALLOW_THREADS
10888
0
    if (fd == -1) {
10889
0
        return PyErr_SetFromErrno(PyExc_OSError);
10890
0
    }
10891
0
    return PyLong_FromLong(fd);
10892
0
}
10893
10894
/*[clinic input]
10895
os.timerfd_settime
10896
10897
    fd: fildes
10898
        A timer file descriptor.
10899
    /
10900
    *
10901
    flags: int = 0
10902
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
10903
    initial as initial_double: double = 0.0
10904
        The initial expiration time, in seconds.
10905
    interval as interval_double: double = 0.0
10906
        The timer's interval, in seconds.
10907
10908
Alter a timer file descriptor's internal timer in seconds.
10909
[clinic start generated code]*/
10910
10911
static PyObject *
10912
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
10913
                        double initial_double, double interval_double)
10914
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
10915
0
{
10916
0
    PyTime_t initial, interval;
10917
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
10918
0
                                  &initial) < 0) {
10919
0
        return NULL;
10920
0
    }
10921
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
10922
0
                                  &interval) < 0) {
10923
0
        return NULL;
10924
0
    }
10925
10926
0
    struct itimerspec new_value, old_value;
10927
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
10928
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
10929
0
        return NULL;
10930
0
    }
10931
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
10932
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
10933
0
        return NULL;
10934
0
    }
10935
10936
0
    int result;
10937
0
    Py_BEGIN_ALLOW_THREADS
10938
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
10939
0
    Py_END_ALLOW_THREADS
10940
0
    if (result == -1) {
10941
0
        return PyErr_SetFromErrno(PyExc_OSError);
10942
0
    }
10943
0
    return build_itimerspec(&old_value);
10944
0
}
10945
10946
10947
/*[clinic input]
10948
os.timerfd_settime_ns
10949
10950
    fd: fildes
10951
        A timer file descriptor.
10952
    /
10953
    *
10954
    flags: int = 0
10955
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
10956
    initial: long_long = 0
10957
        initial expiration timing in seconds.
10958
    interval: long_long = 0
10959
        interval for the timer in seconds.
10960
10961
Alter a timer file descriptor's internal timer in nanoseconds.
10962
[clinic start generated code]*/
10963
10964
static PyObject *
10965
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
10966
                           long long initial, long long interval)
10967
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
10968
0
{
10969
0
    struct itimerspec new_value;
10970
0
    struct itimerspec old_value;
10971
0
    int result;
10972
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
10973
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
10974
0
        return NULL;
10975
0
    }
10976
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
10977
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
10978
0
        return NULL;
10979
0
    }
10980
0
    Py_BEGIN_ALLOW_THREADS
10981
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
10982
0
    Py_END_ALLOW_THREADS
10983
0
    if (result == -1) {
10984
0
        return PyErr_SetFromErrno(PyExc_OSError);
10985
0
    }
10986
0
    return build_itimerspec_ns(&old_value);
10987
0
}
10988
10989
/*[clinic input]
10990
@permit_long_summary
10991
os.timerfd_gettime
10992
10993
    fd: fildes
10994
        A timer file descriptor.
10995
    /
10996
10997
Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
10998
[clinic start generated code]*/
10999
11000
static PyObject *
11001
os_timerfd_gettime_impl(PyObject *module, int fd)
11002
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=05f7d568a4820dc6]*/
11003
0
{
11004
0
    struct itimerspec curr_value;
11005
0
    int result;
11006
0
    Py_BEGIN_ALLOW_THREADS
11007
0
    result = timerfd_gettime(fd, &curr_value);
11008
0
    Py_END_ALLOW_THREADS
11009
0
    if (result == -1) {
11010
0
        return PyErr_SetFromErrno(PyExc_OSError);
11011
0
    }
11012
0
    return build_itimerspec(&curr_value);
11013
0
}
11014
11015
11016
/*[clinic input]
11017
@permit_long_summary
11018
os.timerfd_gettime_ns
11019
11020
    fd: fildes
11021
        A timer file descriptor.
11022
    /
11023
11024
Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
11025
[clinic start generated code]*/
11026
11027
static PyObject *
11028
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11029
/*[clinic end generated code: output=580633a4465f39fe input=d0de95b9782179c5]*/
11030
0
{
11031
0
    struct itimerspec curr_value;
11032
0
    int result;
11033
0
    Py_BEGIN_ALLOW_THREADS
11034
0
    result = timerfd_gettime(fd, &curr_value);
11035
0
    Py_END_ALLOW_THREADS
11036
0
    if (result == -1) {
11037
0
        return PyErr_SetFromErrno(PyExc_OSError);
11038
0
    }
11039
0
    return build_itimerspec_ns(&curr_value);
11040
0
}
11041
11042
#undef ONE_SECOND_IN_NS
11043
#undef EXTRACT_NSEC
11044
11045
#endif  /* HAVE_TIMERFD_CREATE */
11046
11047
#ifdef HAVE_GETSID
11048
/*[clinic input]
11049
os.getsid
11050
11051
    pid: pid_t
11052
    /
11053
11054
Call the system call getsid(pid) and return the result.
11055
[clinic start generated code]*/
11056
11057
static PyObject *
11058
os_getsid_impl(PyObject *module, pid_t pid)
11059
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11060
0
{
11061
0
    int sid;
11062
0
    sid = getsid(pid);
11063
0
    if (sid < 0)
11064
0
        return posix_error();
11065
0
    return PyLong_FromLong((long)sid);
11066
0
}
11067
#endif /* HAVE_GETSID */
11068
11069
11070
#ifdef HAVE_SETSID
11071
/*[clinic input]
11072
os.setsid
11073
11074
Call the system call setsid().
11075
[clinic start generated code]*/
11076
11077
static PyObject *
11078
os_setsid_impl(PyObject *module)
11079
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11080
0
{
11081
0
    if (setsid() < 0)
11082
0
        return posix_error();
11083
0
    Py_RETURN_NONE;
11084
0
}
11085
#endif /* HAVE_SETSID */
11086
11087
11088
#ifdef HAVE_SETPGID
11089
/*[clinic input]
11090
os.setpgid
11091
11092
    pid: pid_t
11093
    pgrp: pid_t
11094
    /
11095
11096
Call the system call setpgid(pid, pgrp).
11097
[clinic start generated code]*/
11098
11099
static PyObject *
11100
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11101
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11102
0
{
11103
0
    if (setpgid(pid, pgrp) < 0)
11104
0
        return posix_error();
11105
0
    Py_RETURN_NONE;
11106
0
}
11107
#endif /* HAVE_SETPGID */
11108
11109
11110
#ifdef HAVE_TCGETPGRP
11111
/*[clinic input]
11112
os.tcgetpgrp
11113
11114
    fd: int
11115
    /
11116
11117
Return the process group associated with the terminal specified by fd.
11118
[clinic start generated code]*/
11119
11120
static PyObject *
11121
os_tcgetpgrp_impl(PyObject *module, int fd)
11122
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11123
0
{
11124
0
    pid_t pgid = tcgetpgrp(fd);
11125
0
    if (pgid < 0)
11126
0
        return posix_error();
11127
0
    return PyLong_FromPid(pgid);
11128
0
}
11129
#endif /* HAVE_TCGETPGRP */
11130
11131
11132
#ifdef HAVE_TCSETPGRP
11133
/*[clinic input]
11134
os.tcsetpgrp
11135
11136
    fd: int
11137
    pgid: pid_t
11138
    /
11139
11140
Set the process group associated with the terminal specified by fd.
11141
[clinic start generated code]*/
11142
11143
static PyObject *
11144
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11145
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11146
0
{
11147
0
    if (tcsetpgrp(fd, pgid) < 0)
11148
0
        return posix_error();
11149
0
    Py_RETURN_NONE;
11150
0
}
11151
#endif /* HAVE_TCSETPGRP */
11152
11153
/* Functions acting on file descriptors */
11154
11155
#ifdef O_CLOEXEC
11156
extern int _Py_open_cloexec_works;
11157
#endif
11158
11159
11160
/*[clinic input]
11161
os.open -> int
11162
    path: path_t
11163
    flags: int
11164
    mode: int = 0o777
11165
    *
11166
    dir_fd: dir_fd(requires='openat') = None
11167
11168
# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11169
11170
Open a file for low level IO.  Returns a file descriptor (integer).
11171
11172
If dir_fd is not None, it should be a file descriptor open to a directory,
11173
  and path should be relative; path will then be relative to that directory.
11174
dir_fd may not be implemented on your platform.
11175
  If it is unavailable, using it will raise a NotImplementedError.
11176
[clinic start generated code]*/
11177
11178
static int
11179
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11180
/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11181
0
{
11182
0
    int fd;
11183
0
    int async_err = 0;
11184
0
#ifdef HAVE_OPENAT
11185
0
    int openat_unavailable = 0;
11186
0
#endif
11187
11188
0
#ifdef O_CLOEXEC
11189
0
    int *atomic_flag_works = &_Py_open_cloexec_works;
11190
#elif !defined(MS_WINDOWS)
11191
    int *atomic_flag_works = NULL;
11192
#endif
11193
11194
#ifdef MS_WINDOWS
11195
    flags |= O_NOINHERIT;
11196
#elif defined(O_CLOEXEC)
11197
0
    flags |= O_CLOEXEC;
11198
0
#endif
11199
11200
0
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11201
0
        return -1;
11202
0
    }
11203
11204
0
    _Py_BEGIN_SUPPRESS_IPH
11205
0
    do {
11206
0
        Py_BEGIN_ALLOW_THREADS
11207
#ifdef MS_WINDOWS
11208
        fd = _wopen(path->wide, flags, mode);
11209
#else
11210
0
#ifdef HAVE_OPENAT
11211
0
        if (dir_fd != DEFAULT_DIR_FD) {
11212
0
            if (HAVE_OPENAT_RUNTIME) {
11213
0
                fd = openat(dir_fd, path->narrow, flags, mode);
11214
11215
0
            } else {
11216
0
                openat_unavailable = 1;
11217
0
                fd = -1;
11218
0
            }
11219
0
        } else
11220
0
#endif /* HAVE_OPENAT */
11221
0
            fd = open(path->narrow, flags, mode);
11222
0
#endif /* !MS_WINDOWS */
11223
0
        Py_END_ALLOW_THREADS
11224
0
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11225
0
    _Py_END_SUPPRESS_IPH
11226
11227
0
#ifdef HAVE_OPENAT
11228
0
    if (openat_unavailable) {
11229
0
        argument_unavailable_error(NULL, "dir_fd");
11230
0
        return -1;
11231
0
    }
11232
0
#endif
11233
11234
0
    if (fd < 0) {
11235
0
        if (!async_err)
11236
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11237
0
        return -1;
11238
0
    }
11239
11240
0
#ifndef MS_WINDOWS
11241
0
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11242
0
        close(fd);
11243
0
        return -1;
11244
0
    }
11245
0
#endif
11246
11247
0
    return fd;
11248
0
}
11249
11250
11251
/*[clinic input]
11252
os.close
11253
11254
    fd: int
11255
11256
Close a file descriptor.
11257
[clinic start generated code]*/
11258
11259
static PyObject *
11260
os_close_impl(PyObject *module, int fd)
11261
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11262
0
{
11263
0
    int res;
11264
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11265
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11266
     * for more details.
11267
     */
11268
0
    Py_BEGIN_ALLOW_THREADS
11269
0
    _Py_BEGIN_SUPPRESS_IPH
11270
0
    res = close(fd);
11271
0
    _Py_END_SUPPRESS_IPH
11272
0
    Py_END_ALLOW_THREADS
11273
0
    if (res < 0)
11274
0
        return posix_error();
11275
0
    Py_RETURN_NONE;
11276
0
}
11277
11278
/*[clinic input]
11279
os.closerange
11280
11281
    fd_low: int
11282
    fd_high: int
11283
    /
11284
11285
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11286
[clinic start generated code]*/
11287
11288
static PyObject *
11289
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11290
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11291
0
{
11292
0
    Py_BEGIN_ALLOW_THREADS
11293
0
    _Py_closerange(fd_low, fd_high - 1);
11294
0
    Py_END_ALLOW_THREADS
11295
0
    Py_RETURN_NONE;
11296
0
}
11297
11298
11299
/*[clinic input]
11300
os.dup -> int
11301
11302
    fd: int
11303
    /
11304
11305
Return a duplicate of a file descriptor.
11306
[clinic start generated code]*/
11307
11308
static int
11309
os_dup_impl(PyObject *module, int fd)
11310
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11311
0
{
11312
0
    return _Py_dup(fd);
11313
0
}
11314
11315
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11316
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11317
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11318
/*[clinic input]
11319
os.dup2 -> int
11320
    fd: int
11321
    fd2: int
11322
    inheritable: bool=True
11323
11324
Duplicate file descriptor.
11325
[clinic start generated code]*/
11326
11327
static int
11328
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11329
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11330
0
{
11331
0
    int res = 0;
11332
0
#if defined(HAVE_DUP3) && \
11333
0
    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11334
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11335
0
    static int dup3_works = -1;
11336
0
#endif
11337
11338
    /* dup2() can fail with EINTR if the target FD is already open, because it
11339
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
11340
     * upon close(), and therefore below.
11341
     */
11342
#ifdef MS_WINDOWS
11343
    Py_BEGIN_ALLOW_THREADS
11344
    _Py_BEGIN_SUPPRESS_IPH
11345
    res = dup2(fd, fd2);
11346
    _Py_END_SUPPRESS_IPH
11347
    Py_END_ALLOW_THREADS
11348
    if (res < 0) {
11349
        posix_error();
11350
        return -1;
11351
    }
11352
    res = fd2; // msvcrt dup2 returns 0 on success.
11353
11354
    /* Character files like console cannot be make non-inheritable */
11355
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11356
        close(fd2);
11357
        return -1;
11358
    }
11359
11360
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11361
    Py_BEGIN_ALLOW_THREADS
11362
    if (!inheritable)
11363
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11364
    else
11365
        res = dup2(fd, fd2);
11366
    Py_END_ALLOW_THREADS
11367
    if (res < 0) {
11368
        posix_error();
11369
        return -1;
11370
    }
11371
11372
#else
11373
11374
0
#ifdef HAVE_DUP3
11375
0
    if (!inheritable && dup3_works != 0) {
11376
0
        Py_BEGIN_ALLOW_THREADS
11377
0
        res = dup3(fd, fd2, O_CLOEXEC);
11378
0
        Py_END_ALLOW_THREADS
11379
0
        if (res < 0) {
11380
0
            if (dup3_works == -1)
11381
0
                dup3_works = (errno != ENOSYS);
11382
0
            if (dup3_works) {
11383
0
                posix_error();
11384
0
                return -1;
11385
0
            }
11386
0
        }
11387
0
    }
11388
11389
0
    if (inheritable || dup3_works == 0)
11390
0
    {
11391
0
#endif
11392
0
        Py_BEGIN_ALLOW_THREADS
11393
0
        res = dup2(fd, fd2);
11394
0
        Py_END_ALLOW_THREADS
11395
0
        if (res < 0) {
11396
0
            posix_error();
11397
0
            return -1;
11398
0
        }
11399
11400
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11401
0
            close(fd2);
11402
0
            return -1;
11403
0
        }
11404
0
#ifdef HAVE_DUP3
11405
0
    }
11406
0
#endif
11407
11408
0
#endif
11409
11410
0
    return res;
11411
0
}
11412
#endif
11413
11414
11415
#ifdef HAVE_LOCKF
11416
/*[clinic input]
11417
os.lockf
11418
11419
    fd: int
11420
        An open file descriptor.
11421
    command: int
11422
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11423
    length: Py_off_t
11424
        The number of bytes to lock, starting at the current position.
11425
    /
11426
11427
Apply, test or remove a POSIX lock on an open file descriptor.
11428
11429
[clinic start generated code]*/
11430
11431
static PyObject *
11432
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11433
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11434
0
{
11435
0
    int res;
11436
11437
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11438
0
        return NULL;
11439
0
    }
11440
11441
0
    Py_BEGIN_ALLOW_THREADS
11442
0
    res = lockf(fd, command, length);
11443
0
    Py_END_ALLOW_THREADS
11444
11445
0
    if (res < 0)
11446
0
        return posix_error();
11447
11448
0
    Py_RETURN_NONE;
11449
0
}
11450
#endif /* HAVE_LOCKF */
11451
11452
11453
/*[clinic input]
11454
@permit_long_docstring_body
11455
os.lseek -> Py_off_t
11456
11457
    fd: int
11458
        An open file descriptor, as returned by os.open().
11459
    position: Py_off_t
11460
        Position, interpreted relative to 'whence'.
11461
    whence as how: int
11462
        The relative position to seek from. Valid values are:
11463
        - SEEK_SET: seek from the start of the file.
11464
        - SEEK_CUR: seek from the current file position.
11465
        - SEEK_END: seek from the end of the file.
11466
    /
11467
11468
Set the position of a file descriptor.  Return the new position.
11469
11470
The return value is the number of bytes relative to the beginning of the file.
11471
[clinic start generated code]*/
11472
11473
static Py_off_t
11474
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11475
/*[clinic end generated code: output=971e1efb6b30bd2f input=4a3de549f07e1c40]*/
11476
0
{
11477
0
    Py_off_t result;
11478
11479
0
#ifdef SEEK_SET
11480
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11481
0
    switch (how) {
11482
0
        case 0: how = SEEK_SET; break;
11483
0
        case 1: how = SEEK_CUR; break;
11484
0
        case 2: how = SEEK_END; break;
11485
0
    }
11486
0
#endif /* SEEK_END */
11487
11488
0
    Py_BEGIN_ALLOW_THREADS
11489
0
    _Py_BEGIN_SUPPRESS_IPH
11490
#ifdef MS_WINDOWS
11491
    result = _lseeki64(fd, position, how);
11492
#else
11493
0
    result = lseek(fd, position, how);
11494
0
#endif
11495
0
    _Py_END_SUPPRESS_IPH
11496
0
    Py_END_ALLOW_THREADS
11497
0
    if (result < 0)
11498
0
        posix_error();
11499
11500
0
    return result;
11501
0
}
11502
11503
11504
/*[clinic input]
11505
os.read
11506
    fd: int
11507
    length: Py_ssize_t
11508
    /
11509
11510
Read from a file descriptor.  Returns a bytes object.
11511
[clinic start generated code]*/
11512
11513
static PyObject *
11514
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11515
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11516
0
{
11517
0
    if (length < 0) {
11518
0
        errno = EINVAL;
11519
0
        return posix_error();
11520
0
    }
11521
11522
0
    length = Py_MIN(length, _PY_READ_MAX);
11523
11524
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11525
0
    if (writer == NULL) {
11526
0
        return NULL;
11527
0
    }
11528
11529
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
11530
0
    if (n == -1) {
11531
0
        PyBytesWriter_Discard(writer);
11532
0
        return NULL;
11533
0
    }
11534
11535
0
    return PyBytesWriter_FinishWithSize(writer, n);
11536
0
}
11537
11538
/*[clinic input]
11539
@permit_long_docstring_body
11540
os.readinto -> Py_ssize_t
11541
    fd: int
11542
    buffer: Py_buffer(accept={rwbuffer})
11543
    /
11544
11545
Read into a buffer object from a file descriptor.
11546
11547
The buffer should be mutable and bytes-like. On success, returns the number of
11548
bytes read. Less bytes may be read than the size of the buffer. The underlying
11549
system call will be retried when interrupted by a signal, unless the signal
11550
handler raises an exception. Other errors will not be retried and an error will
11551
be raised.
11552
11553
Returns 0 if *fd* is at end of file or if the provided *buffer* has length 0
11554
(which can be used to check for errors without reading data). Never returns
11555
negative.
11556
[clinic start generated code]*/
11557
11558
static Py_ssize_t
11559
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
11560
/*[clinic end generated code: output=8091a3513c683a80 input=a770382bd3d32f9a]*/
11561
0
{
11562
0
    assert(buffer->len >= 0);
11563
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
11564
    /* Ensure negative is never returned without an error. Simplifies calling
11565
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
11566
        error. */
11567
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
11568
0
    return result;
11569
0
}
11570
11571
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
11572
                                || defined(__APPLE__))) \
11573
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
11574
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
11575
static int
11576
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
11577
0
{
11578
0
    Py_ssize_t i, j;
11579
11580
0
    *iov = PyMem_New(struct iovec, cnt);
11581
0
    if (*iov == NULL) {
11582
0
        PyErr_NoMemory();
11583
0
        return -1;
11584
0
    }
11585
11586
0
    *buf = PyMem_New(Py_buffer, cnt);
11587
0
    if (*buf == NULL) {
11588
0
        PyMem_Free(*iov);
11589
0
        PyErr_NoMemory();
11590
0
        return -1;
11591
0
    }
11592
11593
0
    for (i = 0; i < cnt; i++) {
11594
0
        PyObject *item = PySequence_GetItem(seq, i);
11595
0
        if (item == NULL)
11596
0
            goto fail;
11597
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
11598
0
            Py_DECREF(item);
11599
0
            goto fail;
11600
0
        }
11601
0
        Py_DECREF(item);
11602
0
        (*iov)[i].iov_base = (*buf)[i].buf;
11603
0
        (*iov)[i].iov_len = (*buf)[i].len;
11604
0
    }
11605
0
    return 0;
11606
11607
0
fail:
11608
0
    PyMem_Free(*iov);
11609
0
    for (j = 0; j < i; j++) {
11610
0
        PyBuffer_Release(&(*buf)[j]);
11611
0
    }
11612
0
    PyMem_Free(*buf);
11613
0
    return -1;
11614
0
}
11615
11616
static void
11617
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
11618
0
{
11619
0
    int i;
11620
0
    PyMem_Free(iov);
11621
0
    for (i = 0; i < cnt; i++) {
11622
0
        PyBuffer_Release(&buf[i]);
11623
0
    }
11624
0
    PyMem_Free(buf);
11625
0
}
11626
#endif
11627
11628
11629
#ifdef HAVE_READV
11630
/*[clinic input]
11631
os.readv -> Py_ssize_t
11632
11633
    fd: int
11634
    buffers: object
11635
    /
11636
11637
Read from a file descriptor fd into an iterable of buffers.
11638
11639
The buffers should be mutable buffers accepting bytes.
11640
readv will transfer data into each buffer until it is full
11641
and then move on to the next buffer in the sequence to hold
11642
the rest of the data.
11643
11644
readv returns the total number of bytes read,
11645
which may be less than the total capacity of all the buffers.
11646
[clinic start generated code]*/
11647
11648
static Py_ssize_t
11649
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
11650
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
11651
0
{
11652
0
    Py_ssize_t cnt, n;
11653
0
    int async_err = 0;
11654
0
    struct iovec *iov;
11655
0
    Py_buffer *buf;
11656
11657
0
    if (!PySequence_Check(buffers)) {
11658
0
        PyErr_SetString(PyExc_TypeError,
11659
0
            "readv() arg 2 must be a sequence");
11660
0
        return -1;
11661
0
    }
11662
11663
0
    cnt = PySequence_Size(buffers);
11664
0
    if (cnt < 0)
11665
0
        return -1;
11666
11667
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
11668
0
        return -1;
11669
11670
0
    do {
11671
0
        Py_BEGIN_ALLOW_THREADS
11672
0
        n = readv(fd, iov, cnt);
11673
0
        Py_END_ALLOW_THREADS
11674
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11675
11676
0
    int saved_errno = errno;
11677
0
    iov_cleanup(iov, buf, cnt);
11678
0
    if (n < 0) {
11679
0
        if (!async_err) {
11680
0
            errno = saved_errno;
11681
0
            posix_error();
11682
0
        }
11683
0
        return -1;
11684
0
    }
11685
11686
0
    return n;
11687
0
}
11688
#endif /* HAVE_READV */
11689
11690
11691
#ifdef HAVE_PREAD
11692
/*[clinic input]
11693
@permit_long_summary
11694
os.pread
11695
11696
    fd: int
11697
    length: Py_ssize_t
11698
    offset: Py_off_t
11699
    /
11700
11701
Read a number of bytes from a file descriptor starting at a particular offset.
11702
11703
Read length bytes from file descriptor fd, starting at offset bytes from
11704
the beginning of the file.  The file offset remains unchanged.
11705
[clinic start generated code]*/
11706
11707
static PyObject *
11708
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
11709
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
11710
0
{
11711
0
    Py_ssize_t n;
11712
0
    int async_err = 0;
11713
11714
0
    if (length < 0) {
11715
0
        errno = EINVAL;
11716
0
        return posix_error();
11717
0
    }
11718
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
11719
0
    if (writer == NULL) {
11720
0
        return NULL;
11721
0
    }
11722
11723
0
    do {
11724
0
        Py_BEGIN_ALLOW_THREADS
11725
0
        _Py_BEGIN_SUPPRESS_IPH
11726
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
11727
0
        _Py_END_SUPPRESS_IPH
11728
0
        Py_END_ALLOW_THREADS
11729
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11730
11731
0
    if (n < 0) {
11732
0
        if (!async_err) {
11733
0
            posix_error();
11734
0
        }
11735
0
        PyBytesWriter_Discard(writer);
11736
0
        return NULL;
11737
0
    }
11738
0
    return PyBytesWriter_FinishWithSize(writer, n);
11739
0
}
11740
#endif /* HAVE_PREAD */
11741
11742
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
11743
/*[clinic input]
11744
@permit_long_docstring_body
11745
os.preadv -> Py_ssize_t
11746
11747
    fd: int
11748
    buffers: object
11749
    offset: Py_off_t
11750
    flags: int = 0
11751
    /
11752
11753
Reads from a file descriptor into a number of mutable bytes-like objects.
11754
11755
Combines the functionality of readv() and pread(). As readv(), it will
11756
transfer data into each buffer until it is full and then move on to the next
11757
buffer in the sequence to hold the rest of the data. Its fourth argument,
11758
specifies the file offset at which the input operation is to be performed. It
11759
will return the total number of bytes read (which can be less than the total
11760
capacity of all the objects).
11761
11762
The flags argument contains a bitwise OR of zero or more of the following flags:
11763
11764
- RWF_HIPRI
11765
- RWF_NOWAIT
11766
- RWF_DONTCACHE
11767
11768
Using non-zero flags requires Linux 4.6 or newer.
11769
[clinic start generated code]*/
11770
11771
static Py_ssize_t
11772
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
11773
               int flags)
11774
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=34fb3b9ca06f7ba7]*/
11775
0
{
11776
0
    Py_ssize_t cnt, n;
11777
0
    int async_err = 0;
11778
0
    struct iovec *iov;
11779
0
    Py_buffer *buf;
11780
11781
0
    if (!PySequence_Check(buffers)) {
11782
0
        PyErr_SetString(PyExc_TypeError,
11783
0
            "preadv2() arg 2 must be a sequence");
11784
0
        return -1;
11785
0
    }
11786
11787
0
    cnt = PySequence_Size(buffers);
11788
0
    if (cnt < 0) {
11789
0
        return -1;
11790
0
    }
11791
11792
#ifndef HAVE_PREADV2
11793
    if(flags != 0) {
11794
        argument_unavailable_error("preadv2", "flags");
11795
        return -1;
11796
    }
11797
#endif
11798
11799
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
11800
0
        return -1;
11801
0
    }
11802
0
#ifdef HAVE_PREADV2
11803
0
    do {
11804
0
        Py_BEGIN_ALLOW_THREADS
11805
0
        _Py_BEGIN_SUPPRESS_IPH
11806
0
        n = preadv2(fd, iov, cnt, offset, flags);
11807
0
        _Py_END_SUPPRESS_IPH
11808
0
        Py_END_ALLOW_THREADS
11809
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11810
#else
11811
    do {
11812
#if defined(__APPLE__) && defined(__clang__)
11813
/* This entire function will be removed from the module dict when the API
11814
 * is not available.
11815
 */
11816
#pragma clang diagnostic push
11817
#pragma clang diagnostic ignored "-Wunguarded-availability"
11818
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
11819
#endif
11820
        Py_BEGIN_ALLOW_THREADS
11821
        _Py_BEGIN_SUPPRESS_IPH
11822
        n = preadv(fd, iov, cnt, offset);
11823
        _Py_END_SUPPRESS_IPH
11824
        Py_END_ALLOW_THREADS
11825
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11826
11827
#if defined(__APPLE__) && defined(__clang__)
11828
#pragma clang diagnostic pop
11829
#endif
11830
11831
#endif
11832
11833
0
    int saved_errno = errno;
11834
0
    iov_cleanup(iov, buf, cnt);
11835
0
    if (n < 0) {
11836
0
        if (!async_err) {
11837
0
            errno = saved_errno;
11838
0
            posix_error();
11839
0
        }
11840
0
        return -1;
11841
0
    }
11842
11843
0
    return n;
11844
0
}
11845
#endif /* HAVE_PREADV */
11846
11847
11848
/*[clinic input]
11849
os.write -> Py_ssize_t
11850
11851
    fd: int
11852
    data: Py_buffer
11853
    /
11854
11855
Write a bytes object to a file descriptor.
11856
[clinic start generated code]*/
11857
11858
static Py_ssize_t
11859
os_write_impl(PyObject *module, int fd, Py_buffer *data)
11860
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
11861
0
{
11862
0
    return _Py_write(fd, data->buf, data->len);
11863
0
}
11864
11865
#ifdef HAVE_SENDFILE
11866
#ifdef __APPLE__
11867
/*[clinic input]
11868
os.sendfile
11869
11870
    out_fd: int
11871
    in_fd: int
11872
    offset: Py_off_t
11873
    count as sbytes: Py_off_t
11874
    headers: object(c_default="NULL") = ()
11875
    trailers: object(c_default="NULL") = ()
11876
    flags: int = 0
11877
11878
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11879
[clinic start generated code]*/
11880
11881
static PyObject *
11882
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
11883
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
11884
                 int flags)
11885
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
11886
#elif defined(__FreeBSD__) || defined(__DragonFly__)
11887
/*[clinic input]
11888
os.sendfile
11889
11890
    out_fd: int
11891
    in_fd: int
11892
    offset: Py_off_t
11893
    count: Py_ssize_t(allow_negative=False)
11894
    headers: object(c_default="NULL") = ()
11895
    trailers: object(c_default="NULL") = ()
11896
    flags: int = 0
11897
11898
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11899
[clinic start generated code]*/
11900
11901
static PyObject *
11902
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
11903
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
11904
                 int flags)
11905
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
11906
#else
11907
/*[clinic input]
11908
os.sendfile
11909
11910
    out_fd: int
11911
    in_fd: int
11912
    offset as offobj: object
11913
    count: Py_ssize_t(allow_negative=False)
11914
11915
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11916
[clinic start generated code]*/
11917
11918
static PyObject *
11919
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
11920
                 Py_ssize_t count)
11921
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
11922
#endif
11923
0
{
11924
0
    Py_ssize_t ret;
11925
0
    int async_err = 0;
11926
11927
#ifdef __APPLE__
11928
    if(sbytes < 0) {
11929
        PyErr_SetString(PyExc_ValueError,
11930
                        "count cannot be negative");
11931
        return NULL;
11932
    }
11933
#else
11934
0
    assert(count >= 0);
11935
0
#endif
11936
11937
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
11938
#ifndef __APPLE__
11939
    off_t sbytes;
11940
#endif
11941
    Py_buffer *hbuf, *tbuf;
11942
    struct sf_hdtr sf;
11943
11944
    sf.headers = NULL;
11945
    sf.trailers = NULL;
11946
11947
    if (headers != NULL) {
11948
        if (!PySequence_Check(headers)) {
11949
            PyErr_SetString(PyExc_TypeError,
11950
                "sendfile() headers must be a sequence");
11951
            return NULL;
11952
        } else {
11953
            Py_ssize_t i = PySequence_Size(headers);
11954
            if (i < 0)
11955
                return NULL;
11956
            if (i > INT_MAX) {
11957
                PyErr_SetString(PyExc_OverflowError,
11958
                    "sendfile() header is too large");
11959
                return NULL;
11960
            }
11961
            if (i > 0) {
11962
                sf.hdr_cnt = (int)i;
11963
                if (iov_setup(&(sf.headers), &hbuf,
11964
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
11965
                    return NULL;
11966
#ifdef __APPLE__
11967
                for (i = 0; i < sf.hdr_cnt; i++) {
11968
                    Py_ssize_t blen = sf.headers[i].iov_len;
11969
# define OFF_T_MAX 0x7fffffffffffffff
11970
                    if (sbytes >= OFF_T_MAX - blen) {
11971
                        PyErr_SetString(PyExc_OverflowError,
11972
                            "sendfile() header is too large");
11973
                        return NULL;
11974
                    }
11975
                    sbytes += blen;
11976
                }
11977
#endif
11978
            }
11979
        }
11980
    }
11981
    if (trailers != NULL) {
11982
        if (!PySequence_Check(trailers)) {
11983
            PyErr_SetString(PyExc_TypeError,
11984
                "sendfile() trailers must be a sequence");
11985
            return NULL;
11986
        } else {
11987
            Py_ssize_t i = PySequence_Size(trailers);
11988
            if (i < 0)
11989
                return NULL;
11990
            if (i > INT_MAX) {
11991
                PyErr_SetString(PyExc_OverflowError,
11992
                    "sendfile() trailer is too large");
11993
                return NULL;
11994
            }
11995
            if (i > 0) {
11996
                sf.trl_cnt = (int)i;
11997
                if (iov_setup(&(sf.trailers), &tbuf,
11998
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
11999
                    return NULL;
12000
            }
12001
        }
12002
    }
12003
12004
    _Py_BEGIN_SUPPRESS_IPH
12005
    do {
12006
        Py_BEGIN_ALLOW_THREADS
12007
#ifdef __APPLE__
12008
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12009
#else
12010
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12011
#endif
12012
        Py_END_ALLOW_THREADS
12013
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12014
    _Py_END_SUPPRESS_IPH
12015
12016
    int saved_errno = errno;
12017
    if (sf.headers != NULL)
12018
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12019
    if (sf.trailers != NULL)
12020
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12021
12022
    if (ret < 0) {
12023
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12024
            if (sbytes != 0) {
12025
                // some data has been sent
12026
                goto done;
12027
            }
12028
            // no data has been sent; upper application is supposed
12029
            // to retry on EAGAIN or EBUSY
12030
        }
12031
        if (!async_err) {
12032
            errno = saved_errno;
12033
            posix_error();
12034
        }
12035
        return NULL;
12036
    }
12037
    goto done;
12038
12039
done:
12040
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12041
        return PyLong_FromLong(sbytes);
12042
    #else
12043
        return PyLong_FromLongLong(sbytes);
12044
    #endif
12045
12046
#else
12047
0
#ifdef __linux__
12048
0
    if (offobj == Py_None) {
12049
0
        do {
12050
0
            Py_BEGIN_ALLOW_THREADS
12051
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12052
0
            Py_END_ALLOW_THREADS
12053
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12054
0
        if (ret < 0)
12055
0
            return (!async_err) ? posix_error() : NULL;
12056
0
        return PyLong_FromSsize_t(ret);
12057
0
    }
12058
0
#endif
12059
0
    off_t offset;
12060
0
    if (!Py_off_t_converter(offobj, &offset))
12061
0
        return NULL;
12062
12063
#if defined(__sun) && defined(__SVR4)
12064
    // On Solaris, sendfile raises EINVAL rather than returning 0
12065
    // when the offset is equal or bigger than the in_fd size.
12066
    struct stat st;
12067
12068
    do {
12069
        Py_BEGIN_ALLOW_THREADS
12070
        ret = fstat(in_fd, &st);
12071
        Py_END_ALLOW_THREADS
12072
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12073
    if (ret < 0)
12074
        return (!async_err) ? posix_error() : NULL;
12075
12076
    if (offset >= st.st_size) {
12077
        return PyLong_FromLong(0);
12078
    }
12079
12080
    // On illumos specifically sendfile() may perform a partial write but
12081
    // return -1/an error (in one confirmed case the destination socket
12082
    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
12083
    // code to check if the offset parameter was modified by sendfile().
12084
    //
12085
    // We need this variable to track said change.
12086
    off_t original_offset = offset;
12087
#endif
12088
12089
0
    do {
12090
0
        Py_BEGIN_ALLOW_THREADS
12091
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12092
#if defined(__sun) && defined(__SVR4)
12093
        // This handles illumos-specific sendfile() partial write behavior,
12094
        // see a comment above for more details.
12095
        if (ret < 0 && offset != original_offset) {
12096
            ret = offset - original_offset;
12097
        }
12098
#endif
12099
0
        Py_END_ALLOW_THREADS
12100
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12101
0
    if (ret < 0)
12102
0
        return (!async_err) ? posix_error() : NULL;
12103
0
    return PyLong_FromSsize_t(ret);
12104
0
#endif
12105
0
}
12106
#endif /* HAVE_SENDFILE */
12107
12108
12109
#if defined(__APPLE__)
12110
/*[clinic input]
12111
os._fcopyfile
12112
12113
    in_fd: int
12114
    out_fd: int
12115
    flags: int
12116
    /
12117
12118
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12119
[clinic start generated code]*/
12120
12121
static PyObject *
12122
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12123
/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
12124
{
12125
    int ret;
12126
12127
    Py_BEGIN_ALLOW_THREADS
12128
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12129
    Py_END_ALLOW_THREADS
12130
    if (ret < 0)
12131
        return posix_error();
12132
    Py_RETURN_NONE;
12133
}
12134
#endif
12135
12136
12137
/*[clinic input]
12138
os.fstat
12139
12140
    fd : int
12141
12142
Perform a stat system call on the given file descriptor.
12143
12144
Like stat(), but for an open file descriptor.
12145
Equivalent to os.stat(fd).
12146
[clinic start generated code]*/
12147
12148
static PyObject *
12149
os_fstat_impl(PyObject *module, int fd)
12150
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12151
0
{
12152
0
    STRUCT_STAT st;
12153
0
    int res;
12154
0
    int async_err = 0;
12155
12156
0
    do {
12157
0
        Py_BEGIN_ALLOW_THREADS
12158
0
        res = FSTAT(fd, &st);
12159
0
        Py_END_ALLOW_THREADS
12160
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12161
0
    if (res != 0) {
12162
#ifdef MS_WINDOWS
12163
        return PyErr_SetFromWindowsErr(0);
12164
#else
12165
0
        return (!async_err) ? posix_error() : NULL;
12166
0
#endif
12167
0
    }
12168
12169
0
    return _pystat_fromstructstat(module, &st);
12170
0
}
12171
12172
12173
/*[clinic input]
12174
os.isatty -> bool
12175
    fd: int
12176
    /
12177
12178
Return True if the fd is connected to a terminal.
12179
12180
Return True if the file descriptor is an open file descriptor
12181
connected to the slave end of a terminal.
12182
[clinic start generated code]*/
12183
12184
static int
12185
os_isatty_impl(PyObject *module, int fd)
12186
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12187
0
{
12188
0
    int return_value;
12189
0
    Py_BEGIN_ALLOW_THREADS
12190
0
    _Py_BEGIN_SUPPRESS_IPH
12191
0
    return_value = isatty(fd);
12192
0
    _Py_END_SUPPRESS_IPH
12193
0
    Py_END_ALLOW_THREADS
12194
0
    return return_value;
12195
0
}
12196
12197
12198
#ifdef HAVE_PIPE
12199
/*[clinic input]
12200
os.pipe
12201
12202
Create a pipe.
12203
12204
Returns a tuple of two file descriptors:
12205
  (read_fd, write_fd)
12206
[clinic start generated code]*/
12207
12208
static PyObject *
12209
os_pipe_impl(PyObject *module)
12210
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12211
0
{
12212
0
    int fds[2];
12213
#ifdef MS_WINDOWS
12214
    HANDLE read, write;
12215
    SECURITY_ATTRIBUTES attr;
12216
    BOOL ok;
12217
#else
12218
0
    int res;
12219
0
#endif
12220
12221
#ifdef MS_WINDOWS
12222
    attr.nLength = sizeof(attr);
12223
    attr.lpSecurityDescriptor = NULL;
12224
    attr.bInheritHandle = FALSE;
12225
12226
    Py_BEGIN_ALLOW_THREADS
12227
    ok = CreatePipe(&read, &write, &attr, 0);
12228
    if (ok) {
12229
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12230
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12231
        if (fds[0] == -1 || fds[1] == -1) {
12232
            CloseHandle(read);
12233
            CloseHandle(write);
12234
            ok = 0;
12235
        }
12236
    }
12237
    Py_END_ALLOW_THREADS
12238
12239
    if (!ok)
12240
        return PyErr_SetFromWindowsErr(0);
12241
#else
12242
12243
0
#ifdef HAVE_PIPE2
12244
0
    Py_BEGIN_ALLOW_THREADS
12245
0
    res = pipe2(fds, O_CLOEXEC);
12246
0
    Py_END_ALLOW_THREADS
12247
12248
0
    if (res != 0 && errno == ENOSYS)
12249
0
    {
12250
0
#endif
12251
0
        Py_BEGIN_ALLOW_THREADS
12252
0
        res = pipe(fds);
12253
0
        Py_END_ALLOW_THREADS
12254
12255
0
        if (res == 0) {
12256
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12257
0
                close(fds[0]);
12258
0
                close(fds[1]);
12259
0
                return NULL;
12260
0
            }
12261
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12262
0
                close(fds[0]);
12263
0
                close(fds[1]);
12264
0
                return NULL;
12265
0
            }
12266
0
        }
12267
0
#ifdef HAVE_PIPE2
12268
0
    }
12269
0
#endif
12270
12271
0
    if (res != 0)
12272
0
        return PyErr_SetFromErrno(PyExc_OSError);
12273
0
#endif /* !MS_WINDOWS */
12274
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12275
0
}
12276
#endif  /* HAVE_PIPE */
12277
12278
12279
#ifdef HAVE_PIPE2
12280
/*[clinic input]
12281
os.pipe2
12282
12283
    flags: int
12284
    /
12285
12286
Create a pipe with flags set atomically.
12287
12288
Returns a tuple of two file descriptors:
12289
  (read_fd, write_fd)
12290
12291
flags can be constructed by ORing together one or more of these values:
12292
O_NONBLOCK, O_CLOEXEC.
12293
[clinic start generated code]*/
12294
12295
static PyObject *
12296
os_pipe2_impl(PyObject *module, int flags)
12297
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12298
0
{
12299
0
    int fds[2];
12300
0
    int res;
12301
12302
0
    res = pipe2(fds, flags);
12303
0
    if (res != 0)
12304
0
        return posix_error();
12305
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12306
0
}
12307
#endif /* HAVE_PIPE2 */
12308
12309
12310
#ifdef HAVE_WRITEV
12311
/*[clinic input]
12312
os.writev -> Py_ssize_t
12313
    fd: int
12314
    buffers: object
12315
    /
12316
12317
Iterate over buffers, and write the contents of each to a file descriptor.
12318
12319
Returns the total number of bytes written.
12320
buffers must be a sequence of bytes-like objects.
12321
[clinic start generated code]*/
12322
12323
static Py_ssize_t
12324
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12325
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12326
0
{
12327
0
    Py_ssize_t cnt;
12328
0
    Py_ssize_t result;
12329
0
    int async_err = 0;
12330
0
    struct iovec *iov;
12331
0
    Py_buffer *buf;
12332
12333
0
    if (!PySequence_Check(buffers)) {
12334
0
        PyErr_SetString(PyExc_TypeError,
12335
0
            "writev() arg 2 must be a sequence");
12336
0
        return -1;
12337
0
    }
12338
0
    cnt = PySequence_Size(buffers);
12339
0
    if (cnt < 0)
12340
0
        return -1;
12341
12342
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12343
0
        return -1;
12344
0
    }
12345
12346
0
    do {
12347
0
        Py_BEGIN_ALLOW_THREADS
12348
0
        result = writev(fd, iov, cnt);
12349
0
        Py_END_ALLOW_THREADS
12350
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12351
12352
0
    if (result < 0 && !async_err)
12353
0
        posix_error();
12354
12355
0
    iov_cleanup(iov, buf, cnt);
12356
0
    return result;
12357
0
}
12358
#endif /* HAVE_WRITEV */
12359
12360
12361
#ifdef HAVE_PWRITE
12362
/*[clinic input]
12363
os.pwrite -> Py_ssize_t
12364
12365
    fd: int
12366
    buffer: Py_buffer
12367
    offset: Py_off_t
12368
    /
12369
12370
Write bytes to a file descriptor starting at a particular offset.
12371
12372
Write buffer to fd, starting at offset bytes from the beginning of
12373
the file.  Returns the number of bytes written.  Does not change the
12374
current file offset.
12375
[clinic start generated code]*/
12376
12377
static Py_ssize_t
12378
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12379
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12380
0
{
12381
0
    Py_ssize_t size;
12382
0
    int async_err = 0;
12383
12384
0
    do {
12385
0
        Py_BEGIN_ALLOW_THREADS
12386
0
        _Py_BEGIN_SUPPRESS_IPH
12387
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12388
0
        _Py_END_SUPPRESS_IPH
12389
0
        Py_END_ALLOW_THREADS
12390
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12391
12392
0
    if (size < 0 && !async_err)
12393
0
        posix_error();
12394
0
    return size;
12395
0
}
12396
#endif /* HAVE_PWRITE */
12397
12398
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12399
/*[clinic input]
12400
@permit_long_summary
12401
@permit_long_docstring_body
12402
os.pwritev -> Py_ssize_t
12403
12404
    fd: int
12405
    buffers: object
12406
    offset: Py_off_t
12407
    flags: int = 0
12408
    /
12409
12410
Writes the contents of bytes-like objects to a file descriptor at a given offset.
12411
12412
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12413
of bytes-like objects. Buffers are processed in array order. Entire contents of first
12414
buffer is written before proceeding to second, and so on. The operating system may
12415
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12416
This function writes the contents of each object to the file descriptor and returns
12417
the total number of bytes written.
12418
12419
The flags argument contains a bitwise OR of zero or more of the following flags:
12420
12421
- RWF_DSYNC
12422
- RWF_SYNC
12423
- RWF_APPEND
12424
- RWF_DONTCACHE
12425
12426
Using non-zero flags requires Linux 4.7 or newer.
12427
[clinic start generated code]*/
12428
12429
static Py_ssize_t
12430
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12431
                int flags)
12432
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=664a67626d485665]*/
12433
0
{
12434
0
    Py_ssize_t cnt;
12435
0
    Py_ssize_t result;
12436
0
    int async_err = 0;
12437
0
    struct iovec *iov;
12438
0
    Py_buffer *buf;
12439
12440
0
    if (!PySequence_Check(buffers)) {
12441
0
        PyErr_SetString(PyExc_TypeError,
12442
0
            "pwritev() arg 2 must be a sequence");
12443
0
        return -1;
12444
0
    }
12445
12446
0
    cnt = PySequence_Size(buffers);
12447
0
    if (cnt < 0) {
12448
0
        return -1;
12449
0
    }
12450
12451
#ifndef HAVE_PWRITEV2
12452
    if(flags != 0) {
12453
        argument_unavailable_error("pwritev2", "flags");
12454
        return -1;
12455
    }
12456
#endif
12457
12458
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12459
0
        return -1;
12460
0
    }
12461
0
#ifdef HAVE_PWRITEV2
12462
0
    do {
12463
0
        Py_BEGIN_ALLOW_THREADS
12464
0
        _Py_BEGIN_SUPPRESS_IPH
12465
0
        result = pwritev2(fd, iov, cnt, offset, flags);
12466
0
        _Py_END_SUPPRESS_IPH
12467
0
        Py_END_ALLOW_THREADS
12468
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12469
#else
12470
12471
#if defined(__APPLE__) && defined(__clang__)
12472
/* This entire function will be removed from the module dict when the API
12473
 * is not available.
12474
 */
12475
#pragma clang diagnostic push
12476
#pragma clang diagnostic ignored "-Wunguarded-availability"
12477
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12478
#endif
12479
    do {
12480
        Py_BEGIN_ALLOW_THREADS
12481
        _Py_BEGIN_SUPPRESS_IPH
12482
        result = pwritev(fd, iov, cnt, offset);
12483
        _Py_END_SUPPRESS_IPH
12484
        Py_END_ALLOW_THREADS
12485
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12486
12487
#if defined(__APPLE__) && defined(__clang__)
12488
#pragma clang diagnostic pop
12489
#endif
12490
12491
#endif
12492
12493
0
    if (result < 0) {
12494
0
        if (!async_err) {
12495
0
            posix_error();
12496
0
        }
12497
0
        result = -1;
12498
0
    }
12499
0
    iov_cleanup(iov, buf, cnt);
12500
12501
0
    return result;
12502
0
}
12503
#endif /* HAVE_PWRITEV */
12504
12505
#ifdef HAVE_COPY_FILE_RANGE
12506
/*[clinic input]
12507
12508
os.copy_file_range
12509
    src: int
12510
        Source file descriptor.
12511
    dst: int
12512
        Destination file descriptor.
12513
    count: Py_ssize_t(allow_negative=False)
12514
        Number of bytes to copy.
12515
    offset_src: object = None
12516
        Starting offset in src.
12517
    offset_dst: object = None
12518
        Starting offset in dst.
12519
12520
Copy count bytes from one file descriptor to another.
12521
12522
If offset_src is None, then src is read from the current position;
12523
respectively for offset_dst.
12524
[clinic start generated code]*/
12525
12526
static PyObject *
12527
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12528
                        PyObject *offset_src, PyObject *offset_dst)
12529
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
12530
0
{
12531
0
    off_t offset_src_val, offset_dst_val;
12532
0
    off_t *p_offset_src = NULL;
12533
0
    off_t *p_offset_dst = NULL;
12534
0
    Py_ssize_t ret;
12535
0
    int async_err = 0;
12536
    /* The flags argument is provided to allow
12537
     * for future extensions and currently must be to 0. */
12538
0
    int flags = 0;
12539
12540
12541
0
    if (offset_src != Py_None) {
12542
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12543
0
            return NULL;
12544
0
        }
12545
0
        p_offset_src = &offset_src_val;
12546
0
    }
12547
12548
0
    if (offset_dst != Py_None) {
12549
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12550
0
            return NULL;
12551
0
        }
12552
0
        p_offset_dst = &offset_dst_val;
12553
0
    }
12554
12555
0
    do {
12556
0
        Py_BEGIN_ALLOW_THREADS
12557
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
12558
0
        Py_END_ALLOW_THREADS
12559
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12560
12561
0
    if (ret < 0) {
12562
0
        return (!async_err) ? posix_error() : NULL;
12563
0
    }
12564
12565
0
    return PyLong_FromSsize_t(ret);
12566
0
}
12567
#endif /* HAVE_COPY_FILE_RANGE*/
12568
12569
#if (defined(HAVE_SPLICE) && !defined(_AIX))
12570
/*[clinic input]
12571
12572
os.splice
12573
    src: int
12574
        Source file descriptor.
12575
    dst: int
12576
        Destination file descriptor.
12577
    count: Py_ssize_t(allow_negative=False)
12578
        Number of bytes to copy.
12579
    offset_src: object = None
12580
        Starting offset in src.
12581
    offset_dst: object = None
12582
        Starting offset in dst.
12583
    flags: unsigned_int = 0
12584
        Flags to modify the semantics of the call.
12585
12586
Transfer count bytes from one pipe to a descriptor or vice versa.
12587
12588
If offset_src is None, then src is read from the current position;
12589
respectively for offset_dst. The offset associated to the file
12590
descriptor that refers to a pipe must be None.
12591
[clinic start generated code]*/
12592
12593
static PyObject *
12594
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12595
               PyObject *offset_src, PyObject *offset_dst,
12596
               unsigned int flags)
12597
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
12598
0
{
12599
0
    off_t offset_src_val, offset_dst_val;
12600
0
    off_t *p_offset_src = NULL;
12601
0
    off_t *p_offset_dst = NULL;
12602
0
    Py_ssize_t ret;
12603
0
    int async_err = 0;
12604
12605
12606
0
    if (offset_src != Py_None) {
12607
0
        if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12608
0
            return NULL;
12609
0
        }
12610
0
        p_offset_src = &offset_src_val;
12611
0
    }
12612
12613
0
    if (offset_dst != Py_None) {
12614
0
        if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12615
0
            return NULL;
12616
0
        }
12617
0
        p_offset_dst = &offset_dst_val;
12618
0
    }
12619
12620
0
    do {
12621
0
        Py_BEGIN_ALLOW_THREADS
12622
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
12623
0
        Py_END_ALLOW_THREADS
12624
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12625
12626
0
    if (ret < 0) {
12627
0
        return (!async_err) ? posix_error() : NULL;
12628
0
    }
12629
12630
0
    return PyLong_FromSsize_t(ret);
12631
0
}
12632
#endif /* HAVE_SPLICE*/
12633
12634
#ifdef HAVE_MKFIFO
12635
/*[clinic input]
12636
os.mkfifo
12637
12638
    path: path_t
12639
    mode: int=0o666
12640
    *
12641
    dir_fd: dir_fd(requires='mkfifoat')=None
12642
12643
Create a "fifo" (a POSIX named pipe).
12644
12645
If dir_fd is not None, it should be a file descriptor open to a directory,
12646
  and path should be relative; path will then be relative to that directory.
12647
dir_fd may not be implemented on your platform.
12648
  If it is unavailable, using it will raise a NotImplementedError.
12649
[clinic start generated code]*/
12650
12651
static PyObject *
12652
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
12653
/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
12654
0
{
12655
0
    int result;
12656
0
    int async_err = 0;
12657
0
#ifdef HAVE_MKFIFOAT
12658
0
    int mkfifoat_unavailable = 0;
12659
0
#endif
12660
12661
0
    do {
12662
0
        Py_BEGIN_ALLOW_THREADS
12663
0
#ifdef HAVE_MKFIFOAT
12664
0
        if (dir_fd != DEFAULT_DIR_FD) {
12665
0
            if (HAVE_MKFIFOAT_RUNTIME) {
12666
0
                result = mkfifoat(dir_fd, path->narrow, mode);
12667
12668
0
            } else {
12669
0
                mkfifoat_unavailable = 1;
12670
0
                result = 0;
12671
0
            }
12672
0
        } else
12673
0
#endif
12674
0
            result = mkfifo(path->narrow, mode);
12675
0
        Py_END_ALLOW_THREADS
12676
0
    } while (result != 0 && errno == EINTR &&
12677
0
             !(async_err = PyErr_CheckSignals()));
12678
12679
0
#ifdef HAVE_MKFIFOAT
12680
0
    if (mkfifoat_unavailable) {
12681
0
        argument_unavailable_error(NULL, "dir_fd");
12682
0
        return NULL;
12683
0
    }
12684
0
#endif
12685
12686
0
    if (result != 0)
12687
0
        return (!async_err) ? posix_error() : NULL;
12688
12689
0
    Py_RETURN_NONE;
12690
0
}
12691
#endif /* HAVE_MKFIFO */
12692
12693
12694
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
12695
/*[clinic input]
12696
@permit_long_docstring_body
12697
os.mknod
12698
12699
    path: path_t
12700
    mode: int=0o600
12701
    device: dev_t=0
12702
    *
12703
    dir_fd: dir_fd(requires='mknodat')=None
12704
12705
Create a node in the file system.
12706
12707
Create a node in the file system (file, device special file or named pipe)
12708
at path.  mode specifies both the permissions to use and the
12709
type of node to be created, being combined (bitwise OR) with one of
12710
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
12711
device defines the newly created device special file (probably using
12712
os.makedev()).  Otherwise device is ignored.
12713
12714
If dir_fd is not None, it should be a file descriptor open to a directory,
12715
  and path should be relative; path will then be relative to that directory.
12716
dir_fd may not be implemented on your platform.
12717
  If it is unavailable, using it will raise a NotImplementedError.
12718
[clinic start generated code]*/
12719
12720
static PyObject *
12721
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
12722
              int dir_fd)
12723
/*[clinic end generated code: output=92e55d3ca8917461 input=7121c4723d22545b]*/
12724
0
{
12725
0
    int result;
12726
0
    int async_err = 0;
12727
0
#ifdef HAVE_MKNODAT
12728
0
    int mknodat_unavailable = 0;
12729
0
#endif
12730
12731
0
    do {
12732
0
        Py_BEGIN_ALLOW_THREADS
12733
0
#ifdef HAVE_MKNODAT
12734
0
        if (dir_fd != DEFAULT_DIR_FD) {
12735
0
            if (HAVE_MKNODAT_RUNTIME) {
12736
0
                result = mknodat(dir_fd, path->narrow, mode, device);
12737
12738
0
            } else {
12739
0
                mknodat_unavailable = 1;
12740
0
                result = 0;
12741
0
            }
12742
0
        } else
12743
0
#endif
12744
0
            result = mknod(path->narrow, mode, device);
12745
0
        Py_END_ALLOW_THREADS
12746
0
    } while (result != 0 && errno == EINTR &&
12747
0
             !(async_err = PyErr_CheckSignals()));
12748
0
#ifdef HAVE_MKNODAT
12749
0
    if (mknodat_unavailable) {
12750
0
        argument_unavailable_error(NULL, "dir_fd");
12751
0
        return NULL;
12752
0
    }
12753
0
#endif
12754
0
    if (result != 0)
12755
0
        return (!async_err) ? posix_error() : NULL;
12756
12757
0
    Py_RETURN_NONE;
12758
0
}
12759
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
12760
12761
12762
#ifdef HAVE_DEVICE_MACROS
12763
static PyObject *
12764
major_minor_conv(unsigned int value)
12765
0
{
12766
0
#ifdef NODEV
12767
0
    if (value == (unsigned int)NODEV) {
12768
0
        return PyLong_FromLong((int)NODEV);
12769
0
    }
12770
0
#endif
12771
0
    return PyLong_FromUnsignedLong(value);
12772
0
}
12773
12774
static int
12775
major_minor_check(dev_t value)
12776
0
{
12777
0
#ifdef NODEV
12778
0
    if (value == NODEV) {
12779
0
        return 1;
12780
0
    }
12781
0
#endif
12782
0
    return (dev_t)(unsigned int)value == value;
12783
0
}
12784
12785
/*[clinic input]
12786
os.major
12787
12788
    device: dev_t
12789
    /
12790
12791
Extracts a device major number from a raw device number.
12792
[clinic start generated code]*/
12793
12794
static PyObject *
12795
os_major_impl(PyObject *module, dev_t device)
12796
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
12797
0
{
12798
0
    return major_minor_conv(major(device));
12799
0
}
12800
12801
12802
/*[clinic input]
12803
os.minor
12804
12805
    device: dev_t
12806
    /
12807
12808
Extracts a device minor number from a raw device number.
12809
[clinic start generated code]*/
12810
12811
static PyObject *
12812
os_minor_impl(PyObject *module, dev_t device)
12813
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
12814
0
{
12815
0
    return major_minor_conv(minor(device));
12816
0
}
12817
12818
12819
/*[clinic input]
12820
os.makedev -> dev_t
12821
12822
    major: dev_t
12823
    minor: dev_t
12824
    /
12825
12826
Composes a raw device number from the major and minor device numbers.
12827
[clinic start generated code]*/
12828
12829
static dev_t
12830
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
12831
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
12832
0
{
12833
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
12834
0
        PyErr_SetString(PyExc_OverflowError,
12835
0
                        "Python int too large to convert to C unsigned int");
12836
0
        return (dev_t)-1;
12837
0
    }
12838
0
    return makedev(major, minor);
12839
0
}
12840
#endif /* HAVE_DEVICE_MACROS */
12841
12842
12843
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
12844
/*[clinic input]
12845
os.ftruncate
12846
12847
    fd: int
12848
    length: Py_off_t
12849
    /
12850
12851
Truncate a file, specified by file descriptor, to a specific length.
12852
[clinic start generated code]*/
12853
12854
static PyObject *
12855
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
12856
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
12857
0
{
12858
0
    int result;
12859
0
    int async_err = 0;
12860
12861
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
12862
0
        return NULL;
12863
0
    }
12864
12865
0
    do {
12866
0
        Py_BEGIN_ALLOW_THREADS
12867
0
        _Py_BEGIN_SUPPRESS_IPH
12868
#ifdef MS_WINDOWS
12869
        result = _chsize_s(fd, length);
12870
#else
12871
0
        result = ftruncate(fd, length);
12872
0
#endif
12873
0
        _Py_END_SUPPRESS_IPH
12874
0
        Py_END_ALLOW_THREADS
12875
0
    } while (result != 0 && errno == EINTR &&
12876
0
             !(async_err = PyErr_CheckSignals()));
12877
0
    if (result != 0)
12878
0
        return (!async_err) ? posix_error() : NULL;
12879
0
    Py_RETURN_NONE;
12880
0
}
12881
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
12882
12883
12884
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
12885
/*[clinic input]
12886
os.truncate
12887
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
12888
    length: Py_off_t
12889
12890
Truncate a file, specified by path, to a specific length.
12891
12892
On some platforms, path may also be specified as an open file descriptor.
12893
  If this functionality is unavailable, using it raises an exception.
12894
[clinic start generated code]*/
12895
12896
static PyObject *
12897
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
12898
/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
12899
0
{
12900
0
    int result;
12901
#ifdef MS_WINDOWS
12902
    int fd;
12903
#endif
12904
12905
0
    if (path->fd != -1)
12906
0
        return os_ftruncate_impl(module, path->fd, length);
12907
12908
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
12909
0
        return NULL;
12910
0
    }
12911
12912
0
    Py_BEGIN_ALLOW_THREADS
12913
0
    _Py_BEGIN_SUPPRESS_IPH
12914
#ifdef MS_WINDOWS
12915
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
12916
    if (fd < 0)
12917
        result = -1;
12918
    else {
12919
        result = _chsize_s(fd, length);
12920
        close(fd);
12921
        if (result < 0)
12922
            errno = result;
12923
    }
12924
#else
12925
0
    result = truncate(path->narrow, length);
12926
0
#endif
12927
0
    _Py_END_SUPPRESS_IPH
12928
0
    Py_END_ALLOW_THREADS
12929
0
    if (result < 0)
12930
0
        return posix_path_error(path);
12931
12932
0
    Py_RETURN_NONE;
12933
0
}
12934
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
12935
12936
12937
/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
12938
   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
12939
   defined, which is the case in Python on AIX. AIX bug report:
12940
   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
12941
#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
12942
#  define POSIX_FADVISE_AIX_BUG
12943
#endif
12944
12945
12946
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
12947
   OSs, support was dropped in WASI preview2. */
12948
#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \
12949
    !defined(__wasi__)
12950
/*[clinic input]
12951
os.posix_fallocate
12952
12953
    fd: int
12954
    offset: Py_off_t
12955
    length: Py_off_t
12956
    /
12957
12958
Ensure a file has allocated at least a particular number of bytes on disk.
12959
12960
Ensure that the file specified by fd encompasses a range of bytes
12961
starting at offset bytes from the beginning and continuing for length bytes.
12962
[clinic start generated code]*/
12963
12964
static PyObject *
12965
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
12966
                        Py_off_t length)
12967
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
12968
0
{
12969
0
    int result;
12970
0
    int async_err = 0;
12971
12972
0
    do {
12973
0
        Py_BEGIN_ALLOW_THREADS
12974
0
        result = posix_fallocate(fd, offset, length);
12975
0
        Py_END_ALLOW_THREADS
12976
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
12977
12978
0
    if (result == 0)
12979
0
        Py_RETURN_NONE;
12980
12981
0
    if (async_err)
12982
0
        return NULL;
12983
12984
0
    errno = result;
12985
0
    return posix_error();
12986
0
}
12987
#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */
12988
12989
12990
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
12991
/*[clinic input]
12992
os.posix_fadvise
12993
12994
    fd: int
12995
    offset: Py_off_t
12996
    length: Py_off_t
12997
    advice: int
12998
    /
12999
13000
Announce an intention to access data in a specific pattern.
13001
13002
Announce an intention to access data in a specific pattern, thus allowing
13003
the kernel to make optimizations.
13004
The advice applies to the region of the file specified by fd starting at
13005
offset and continuing for length bytes.
13006
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13007
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13008
POSIX_FADV_DONTNEED.
13009
[clinic start generated code]*/
13010
13011
static PyObject *
13012
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13013
                      Py_off_t length, int advice)
13014
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
13015
0
{
13016
0
    int result;
13017
0
    int async_err = 0;
13018
13019
0
    do {
13020
0
        Py_BEGIN_ALLOW_THREADS
13021
0
        result = posix_fadvise(fd, offset, length, advice);
13022
0
        Py_END_ALLOW_THREADS
13023
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13024
13025
0
    if (result == 0)
13026
0
        Py_RETURN_NONE;
13027
13028
0
    if (async_err)
13029
0
        return NULL;
13030
13031
0
    errno = result;
13032
0
    return posix_error();
13033
0
}
13034
#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
13035
13036
13037
#ifdef MS_WINDOWS
13038
static PyObject*
13039
win32_putenv(PyObject *name, PyObject *value)
13040
{
13041
    /* Search from index 1 because on Windows starting '=' is allowed for
13042
       defining hidden environment variables. */
13043
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13044
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13045
    {
13046
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13047
        return NULL;
13048
    }
13049
    PyObject *unicode;
13050
    if (value != NULL) {
13051
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13052
    }
13053
    else {
13054
        unicode = PyUnicode_FromFormat("%U=", name);
13055
    }
13056
    if (unicode == NULL) {
13057
        return NULL;
13058
    }
13059
13060
    Py_ssize_t size;
13061
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13062
    Py_DECREF(unicode);
13063
13064
    if (env == NULL) {
13065
        return NULL;
13066
    }
13067
    if (size > _MAX_ENV) {
13068
        PyErr_Format(PyExc_ValueError,
13069
                     "the environment variable is longer than %u characters",
13070
                     _MAX_ENV);
13071
        PyMem_Free(env);
13072
        return NULL;
13073
    }
13074
    if (wcslen(env) != (size_t)size) {
13075
        PyErr_SetString(PyExc_ValueError,
13076
                        "embedded null character");
13077
        PyMem_Free(env);
13078
        return NULL;
13079
    }
13080
13081
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13082
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13083
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13084
13085
       Prefer _wputenv() to be compatible with C libraries using CRT
13086
       variables and CRT functions using these variables (ex: getenv()). */
13087
    int err = _wputenv(env);
13088
13089
    if (err) {
13090
        posix_error();
13091
        PyMem_Free(env);
13092
        return NULL;
13093
    }
13094
    PyMem_Free(env);
13095
13096
    Py_RETURN_NONE;
13097
}
13098
#endif
13099
13100
13101
#ifdef MS_WINDOWS
13102
/*[clinic input]
13103
os.putenv
13104
13105
    name: unicode
13106
    value: unicode
13107
    /
13108
13109
Change or add an environment variable.
13110
[clinic start generated code]*/
13111
13112
static PyObject *
13113
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13114
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13115
{
13116
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13117
        return NULL;
13118
    }
13119
    return win32_putenv(name, value);
13120
}
13121
#else
13122
/*[clinic input]
13123
os.putenv
13124
13125
    name: unicode_fs_encoded
13126
    value: unicode_fs_encoded
13127
    /
13128
13129
Change or add an environment variable.
13130
[clinic start generated code]*/
13131
13132
static PyObject *
13133
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13134
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13135
0
{
13136
0
    const char *name_string = PyBytes_AS_STRING(name);
13137
0
    const char *value_string = PyBytes_AS_STRING(value);
13138
13139
0
    if (strchr(name_string, '=') != NULL) {
13140
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13141
0
        return NULL;
13142
0
    }
13143
13144
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13145
0
        return NULL;
13146
0
    }
13147
13148
0
    if (setenv(name_string, value_string, 1)) {
13149
0
        return posix_error();
13150
0
    }
13151
0
    Py_RETURN_NONE;
13152
0
}
13153
#endif  /* !defined(MS_WINDOWS) */
13154
13155
13156
#ifdef MS_WINDOWS
13157
/*[clinic input]
13158
os.unsetenv
13159
    name: unicode
13160
    /
13161
13162
Delete an environment variable.
13163
[clinic start generated code]*/
13164
13165
static PyObject *
13166
os_unsetenv_impl(PyObject *module, PyObject *name)
13167
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13168
{
13169
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13170
        return NULL;
13171
    }
13172
    return win32_putenv(name, NULL);
13173
}
13174
#else
13175
/*[clinic input]
13176
os.unsetenv
13177
    name: unicode_fs_encoded
13178
    /
13179
13180
Delete an environment variable.
13181
[clinic start generated code]*/
13182
13183
static PyObject *
13184
os_unsetenv_impl(PyObject *module, PyObject *name)
13185
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13186
0
{
13187
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13188
0
        return NULL;
13189
0
    }
13190
#ifdef HAVE_BROKEN_UNSETENV
13191
    unsetenv(PyBytes_AS_STRING(name));
13192
#else
13193
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13194
0
    if (err) {
13195
0
        return posix_error();
13196
0
    }
13197
0
#endif
13198
13199
0
    Py_RETURN_NONE;
13200
0
}
13201
#endif /* !MS_WINDOWS */
13202
13203
13204
#ifdef HAVE_CLEARENV
13205
/*[clinic input]
13206
os._clearenv
13207
[clinic start generated code]*/
13208
13209
static PyObject *
13210
os__clearenv_impl(PyObject *module)
13211
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13212
0
{
13213
0
    errno = 0;
13214
0
    int err = clearenv();
13215
0
    if (err) {
13216
0
        return posix_error();
13217
0
    }
13218
0
    Py_RETURN_NONE;
13219
0
}
13220
#endif
13221
13222
13223
/*[clinic input]
13224
os.strerror
13225
13226
    code: int
13227
    /
13228
13229
Translate an error code to a message string.
13230
[clinic start generated code]*/
13231
13232
static PyObject *
13233
os_strerror_impl(PyObject *module, int code)
13234
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13235
0
{
13236
0
    char *message = strerror(code);
13237
0
    if (message == NULL) {
13238
0
        PyErr_SetString(PyExc_ValueError,
13239
0
                        "strerror() argument out of range");
13240
0
        return NULL;
13241
0
    }
13242
0
    return PyUnicode_DecodeLocale(message, "surrogateescape");
13243
0
}
13244
13245
13246
#ifdef HAVE_SYS_WAIT_H
13247
#ifdef WCOREDUMP
13248
/*[clinic input]
13249
os.WCOREDUMP -> bool
13250
13251
    status: int
13252
    /
13253
13254
Return True if the process returning status was dumped to a core file.
13255
[clinic start generated code]*/
13256
13257
static int
13258
os_WCOREDUMP_impl(PyObject *module, int status)
13259
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13260
0
{
13261
0
    WAIT_TYPE wait_status;
13262
0
    WAIT_STATUS_INT(wait_status) = status;
13263
0
    return WCOREDUMP(wait_status);
13264
0
}
13265
#endif /* WCOREDUMP */
13266
13267
13268
#ifdef WIFCONTINUED
13269
/*[clinic input]
13270
os.WIFCONTINUED -> bool
13271
13272
    status: int
13273
13274
Return True if a particular process was continued from a job control stop.
13275
13276
Return True if the process returning status was continued from a
13277
job control stop.
13278
[clinic start generated code]*/
13279
13280
static int
13281
os_WIFCONTINUED_impl(PyObject *module, int status)
13282
/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13283
0
{
13284
0
    WAIT_TYPE wait_status;
13285
0
    WAIT_STATUS_INT(wait_status) = status;
13286
0
    return WIFCONTINUED(wait_status);
13287
0
}
13288
#endif /* WIFCONTINUED */
13289
13290
13291
#ifdef WIFSTOPPED
13292
/*[clinic input]
13293
os.WIFSTOPPED -> bool
13294
13295
    status: int
13296
13297
Return True if the process returning status was stopped.
13298
[clinic start generated code]*/
13299
13300
static int
13301
os_WIFSTOPPED_impl(PyObject *module, int status)
13302
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13303
0
{
13304
0
    WAIT_TYPE wait_status;
13305
0
    WAIT_STATUS_INT(wait_status) = status;
13306
0
    return WIFSTOPPED(wait_status);
13307
0
}
13308
#endif /* WIFSTOPPED */
13309
13310
13311
#ifdef WIFSIGNALED
13312
/*[clinic input]
13313
os.WIFSIGNALED -> bool
13314
13315
    status: int
13316
13317
Return True if the process returning status was terminated by a signal.
13318
[clinic start generated code]*/
13319
13320
static int
13321
os_WIFSIGNALED_impl(PyObject *module, int status)
13322
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13323
0
{
13324
0
    WAIT_TYPE wait_status;
13325
0
    WAIT_STATUS_INT(wait_status) = status;
13326
0
    return WIFSIGNALED(wait_status);
13327
0
}
13328
#endif /* WIFSIGNALED */
13329
13330
13331
#ifdef WIFEXITED
13332
/*[clinic input]
13333
@permit_long_summary
13334
os.WIFEXITED -> bool
13335
13336
    status: int
13337
13338
Return True if the process returning status exited via the exit() system call.
13339
[clinic start generated code]*/
13340
13341
static int
13342
os_WIFEXITED_impl(PyObject *module, int status)
13343
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
13344
0
{
13345
0
    WAIT_TYPE wait_status;
13346
0
    WAIT_STATUS_INT(wait_status) = status;
13347
0
    return WIFEXITED(wait_status);
13348
0
}
13349
#endif /* WIFEXITED */
13350
13351
13352
#ifdef WEXITSTATUS
13353
/*[clinic input]
13354
os.WEXITSTATUS -> int
13355
13356
    status: int
13357
13358
Return the process return code from status.
13359
[clinic start generated code]*/
13360
13361
static int
13362
os_WEXITSTATUS_impl(PyObject *module, int status)
13363
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13364
0
{
13365
0
    WAIT_TYPE wait_status;
13366
0
    WAIT_STATUS_INT(wait_status) = status;
13367
0
    return WEXITSTATUS(wait_status);
13368
0
}
13369
#endif /* WEXITSTATUS */
13370
13371
13372
#ifdef WTERMSIG
13373
/*[clinic input]
13374
@permit_long_summary
13375
os.WTERMSIG -> int
13376
13377
    status: int
13378
13379
Return the signal that terminated the process that provided the status value.
13380
[clinic start generated code]*/
13381
13382
static int
13383
os_WTERMSIG_impl(PyObject *module, int status)
13384
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
13385
0
{
13386
0
    WAIT_TYPE wait_status;
13387
0
    WAIT_STATUS_INT(wait_status) = status;
13388
0
    return WTERMSIG(wait_status);
13389
0
}
13390
#endif /* WTERMSIG */
13391
13392
13393
#ifdef WSTOPSIG
13394
/*[clinic input]
13395
os.WSTOPSIG -> int
13396
13397
    status: int
13398
13399
Return the signal that stopped the process that provided the status value.
13400
[clinic start generated code]*/
13401
13402
static int
13403
os_WSTOPSIG_impl(PyObject *module, int status)
13404
/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13405
0
{
13406
0
    WAIT_TYPE wait_status;
13407
0
    WAIT_STATUS_INT(wait_status) = status;
13408
0
    return WSTOPSIG(wait_status);
13409
0
}
13410
#endif /* WSTOPSIG */
13411
#endif /* HAVE_SYS_WAIT_H */
13412
13413
13414
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13415
#ifdef _SCO_DS
13416
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13417
   needed definitions in sys/statvfs.h */
13418
#define _SVID3
13419
#endif
13420
#include <sys/statvfs.h>
13421
13422
#ifdef __APPLE__
13423
/* On macOS struct statvfs uses 32-bit integers for block counts,
13424
 * resulting in overflow when filesystems are larger than 4TB. Therefore
13425
 * os.statvfs is implemented in terms of statfs(2).
13426
 */
13427
13428
static PyObject*
13429
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13430
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13431
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13432
    if (v == NULL) {
13433
        return NULL;
13434
    }
13435
13436
    long flags = 0;
13437
    if (st.f_flags & MNT_RDONLY) {
13438
        flags |= ST_RDONLY;
13439
    }
13440
    if (st.f_flags & MNT_NOSUID) {
13441
        flags |= ST_NOSUID;
13442
    }
13443
13444
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13445
13446
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
13447
    do {                                                 \
13448
        PyObject *obj = (EXPR);                          \
13449
        if (obj == NULL) {                               \
13450
            Py_DECREF((SEQ));                            \
13451
            return NULL;                                 \
13452
        }                                                \
13453
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13454
    } while (0)
13455
13456
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13457
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13458
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13459
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13460
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13461
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13462
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13463
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13464
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13465
13466
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13467
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13468
13469
#undef SET_ITEM
13470
13471
    return v;
13472
}
13473
13474
#else
13475
13476
13477
13478
static PyObject*
13479
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13480
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13481
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13482
0
    if (v == NULL)
13483
0
        return NULL;
13484
13485
0
    int pos = 0;
13486
13487
0
#define SET_RESULT(CALL)                                     \
13488
0
    do {                                                     \
13489
0
        PyObject *item = (CALL);                             \
13490
0
        if (item == NULL) {                                  \
13491
0
            Py_DECREF(v);                                    \
13492
0
            return NULL;                                     \
13493
0
        }                                                    \
13494
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
13495
0
    } while(0)
13496
13497
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
13498
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13499
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13500
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13501
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13502
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13503
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
13504
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13505
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
13506
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13507
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13508
#else
13509
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13510
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13511
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13512
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13513
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13514
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13515
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13516
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13517
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
13518
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13519
#endif
13520
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13521
 * (issue #32390). */
13522
#if defined(_AIX) && defined(_ALL_SOURCE)
13523
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13524
#else
13525
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13526
0
#endif
13527
13528
0
#undef SET_RESULT
13529
13530
0
    return v;
13531
0
}
13532
13533
#endif
13534
13535
13536
/*[clinic input]
13537
os.fstatvfs
13538
    fd: int
13539
    /
13540
13541
Perform an fstatvfs system call on the given fd.
13542
13543
Equivalent to statvfs(fd).
13544
[clinic start generated code]*/
13545
13546
static PyObject *
13547
os_fstatvfs_impl(PyObject *module, int fd)
13548
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13549
0
{
13550
0
    int result;
13551
0
    int async_err = 0;
13552
#ifdef __APPLE__
13553
    struct statfs st;
13554
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13555
     * the former uses 32-bit values for block counts.
13556
     */
13557
    do {
13558
        Py_BEGIN_ALLOW_THREADS
13559
        result = fstatfs(fd, &st);
13560
        Py_END_ALLOW_THREADS
13561
    } while (result != 0 && errno == EINTR &&
13562
             !(async_err = PyErr_CheckSignals()));
13563
    if (result != 0)
13564
        return (!async_err) ? posix_error() : NULL;
13565
13566
    return _pystatvfs_fromstructstatfs(module, st);
13567
#else
13568
0
    struct statvfs st;
13569
13570
0
    do {
13571
0
        Py_BEGIN_ALLOW_THREADS
13572
0
        result = fstatvfs(fd, &st);
13573
0
        Py_END_ALLOW_THREADS
13574
0
    } while (result != 0 && errno == EINTR &&
13575
0
             !(async_err = PyErr_CheckSignals()));
13576
0
    if (result != 0)
13577
0
        return (!async_err) ? posix_error() : NULL;
13578
13579
0
    return _pystatvfs_fromstructstatvfs(module, st);
13580
0
#endif
13581
0
}
13582
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
13583
13584
13585
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
13586
#include <sys/statvfs.h>
13587
/*[clinic input]
13588
os.statvfs
13589
13590
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
13591
13592
Perform a statvfs system call on the given path.
13593
13594
path may always be specified as a string.
13595
On some platforms, path may also be specified as an open file descriptor.
13596
  If this functionality is unavailable, using it raises an exception.
13597
[clinic start generated code]*/
13598
13599
static PyObject *
13600
os_statvfs_impl(PyObject *module, path_t *path)
13601
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
13602
0
{
13603
0
    int result;
13604
13605
#ifdef __APPLE__
13606
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
13607
     * the former uses 32-bit values for block counts.
13608
     */
13609
    struct statfs st;
13610
13611
    Py_BEGIN_ALLOW_THREADS
13612
    if (path->fd != -1) {
13613
        result = fstatfs(path->fd, &st);
13614
    }
13615
    else
13616
        result = statfs(path->narrow, &st);
13617
    Py_END_ALLOW_THREADS
13618
13619
    if (result) {
13620
        return path_error(path);
13621
    }
13622
13623
    return _pystatvfs_fromstructstatfs(module, st);
13624
13625
#else
13626
0
    struct statvfs st;
13627
13628
0
    Py_BEGIN_ALLOW_THREADS
13629
0
#ifdef HAVE_FSTATVFS
13630
0
    if (path->fd != -1) {
13631
0
        result = fstatvfs(path->fd, &st);
13632
0
    }
13633
0
    else
13634
0
#endif
13635
0
        result = statvfs(path->narrow, &st);
13636
0
    Py_END_ALLOW_THREADS
13637
13638
0
    if (result) {
13639
0
        return path_error(path);
13640
0
    }
13641
13642
0
    return _pystatvfs_fromstructstatvfs(module, st);
13643
0
#endif
13644
0
}
13645
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
13646
13647
13648
#ifdef MS_WINDOWS
13649
/*[clinic input]
13650
os._getdiskusage
13651
13652
    path: path_t
13653
13654
Return disk usage statistics about the given path as a (total, free) tuple.
13655
[clinic start generated code]*/
13656
13657
static PyObject *
13658
os__getdiskusage_impl(PyObject *module, path_t *path)
13659
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
13660
{
13661
    BOOL retval;
13662
    ULARGE_INTEGER _, total, free;
13663
    DWORD err = 0;
13664
13665
    Py_BEGIN_ALLOW_THREADS
13666
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
13667
    Py_END_ALLOW_THREADS
13668
    if (retval == 0) {
13669
        if (GetLastError() == ERROR_DIRECTORY) {
13670
            wchar_t *dir_path = NULL;
13671
13672
            dir_path = PyMem_New(wchar_t, path->length + 1);
13673
            if (dir_path == NULL) {
13674
                return PyErr_NoMemory();
13675
            }
13676
13677
            wcscpy_s(dir_path, path->length + 1, path->wide);
13678
13679
            if (_dirnameW(dir_path) != -1) {
13680
                Py_BEGIN_ALLOW_THREADS
13681
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
13682
                Py_END_ALLOW_THREADS
13683
            }
13684
            /* Record the last error in case it's modified by PyMem_Free. */
13685
            err = GetLastError();
13686
            PyMem_Free(dir_path);
13687
            if (retval) {
13688
                goto success;
13689
            }
13690
        }
13691
        return PyErr_SetFromWindowsErr(err);
13692
    }
13693
13694
success:
13695
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
13696
}
13697
#endif /* MS_WINDOWS */
13698
13699
13700
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
13701
 * It maps strings representing configuration variable names to
13702
 * integer values, allowing those functions to be called with the
13703
 * magic names instead of polluting the module's namespace with tons of
13704
 * rarely-used constants.  There are three separate tables that use
13705
 * these definitions.
13706
 *
13707
 * This code is always included, even if none of the interfaces that
13708
 * need it are included.  The #if hackery needed to avoid it would be
13709
 * sufficiently pervasive that it's not worth the loss of readability.
13710
 */
13711
struct constdef {
13712
    const char *name;
13713
    int value;
13714
};
13715
13716
static int
13717
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
13718
0
{
13719
0
    if (PyUnicode_Check(arg)) {
13720
0
        PyObject *table = PyObject_GetAttrString(module, tablename);
13721
0
        if (table == NULL) {
13722
0
            return 0;
13723
0
        }
13724
13725
0
        arg = PyObject_GetItem(table, arg);
13726
0
        Py_DECREF(table);
13727
0
        if (arg == NULL) {
13728
0
            PyErr_SetString(
13729
0
                PyExc_ValueError, "unrecognized configuration name");
13730
0
            return 0;
13731
0
        }
13732
0
    } else {
13733
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
13734
0
    }
13735
13736
0
    int success = 0;
13737
0
    if (!PyIndex_Check(arg)) {
13738
0
        PyErr_SetString(PyExc_TypeError,
13739
0
            "configuration names must be strings or integers");
13740
0
    } else {
13741
0
        int value = PyLong_AsInt(arg);
13742
0
        if (!(value == -1 && PyErr_Occurred())) {
13743
0
            *valuep = value;
13744
0
            success = 1;
13745
0
        }
13746
0
    }
13747
0
    Py_DECREF(arg);
13748
0
    return success;
13749
0
}
13750
13751
13752
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
13753
static struct constdef  posix_constants_pathconf[] = {
13754
#ifdef _PC_ABI_AIO_XFER_MAX
13755
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
13756
#endif
13757
#ifdef _PC_ABI_ASYNC_IO
13758
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
13759
#endif
13760
#ifdef _PC_ASYNC_IO
13761
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
13762
#endif
13763
#ifdef _PC_CHOWN_RESTRICTED
13764
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
13765
#endif
13766
#ifdef _PC_FILESIZEBITS
13767
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
13768
#endif
13769
#ifdef _PC_LAST
13770
    {"PC_LAST", _PC_LAST},
13771
#endif
13772
#ifdef _PC_LINK_MAX
13773
    {"PC_LINK_MAX",     _PC_LINK_MAX},
13774
#endif
13775
#ifdef _PC_MAX_CANON
13776
    {"PC_MAX_CANON",    _PC_MAX_CANON},
13777
#endif
13778
#ifdef _PC_MAX_INPUT
13779
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
13780
#endif
13781
#ifdef _PC_NAME_MAX
13782
    {"PC_NAME_MAX",     _PC_NAME_MAX},
13783
#endif
13784
#ifdef _PC_NO_TRUNC
13785
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
13786
#endif
13787
#ifdef _PC_PATH_MAX
13788
    {"PC_PATH_MAX",     _PC_PATH_MAX},
13789
#endif
13790
#ifdef _PC_PIPE_BUF
13791
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
13792
#endif
13793
#ifdef _PC_PRIO_IO
13794
    {"PC_PRIO_IO",      _PC_PRIO_IO},
13795
#endif
13796
#ifdef _PC_SOCK_MAXBUF
13797
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
13798
#endif
13799
#ifdef _PC_SYNC_IO
13800
    {"PC_SYNC_IO",      _PC_SYNC_IO},
13801
#endif
13802
#ifdef _PC_VDISABLE
13803
    {"PC_VDISABLE",     _PC_VDISABLE},
13804
#endif
13805
#ifdef _PC_ACL_ENABLED
13806
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
13807
#endif
13808
#ifdef _PC_MIN_HOLE_SIZE
13809
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
13810
#endif
13811
#ifdef _PC_ALLOC_SIZE_MIN
13812
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
13813
#endif
13814
#ifdef _PC_REC_INCR_XFER_SIZE
13815
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
13816
#endif
13817
#ifdef _PC_REC_MAX_XFER_SIZE
13818
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
13819
#endif
13820
#ifdef _PC_REC_MIN_XFER_SIZE
13821
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
13822
#endif
13823
#ifdef _PC_REC_XFER_ALIGN
13824
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
13825
#endif
13826
#ifdef _PC_SYMLINK_MAX
13827
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
13828
#endif
13829
#ifdef _PC_XATTR_ENABLED
13830
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
13831
#endif
13832
#ifdef _PC_XATTR_EXISTS
13833
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
13834
#endif
13835
#ifdef _PC_TIMESTAMP_RESOLUTION
13836
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
13837
#endif
13838
};
13839
#endif
13840
13841
13842
#ifdef HAVE_FPATHCONF
13843
/*[clinic input]
13844
os.fpathconf -> long
13845
13846
    fd: fildes
13847
    name: confname(table="pathconf_names")
13848
    /
13849
13850
Return the configuration limit name for the file descriptor fd.
13851
13852
If there is no limit, return -1.
13853
[clinic start generated code]*/
13854
13855
static long
13856
os_fpathconf_impl(PyObject *module, int fd, int name)
13857
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
13858
0
{
13859
0
    long limit;
13860
13861
0
    errno = 0;
13862
0
    limit = fpathconf(fd, name);
13863
0
    if (limit == -1 && errno != 0)
13864
0
        posix_error();
13865
13866
0
    return limit;
13867
0
}
13868
#endif /* HAVE_FPATHCONF */
13869
13870
13871
#ifdef HAVE_PATHCONF
13872
/*[clinic input]
13873
os.pathconf -> long
13874
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
13875
    name: confname(table="pathconf_names")
13876
13877
Return the configuration limit name for the file or directory path.
13878
13879
If there is no limit, return -1.
13880
On some platforms, path may also be specified as an open file descriptor.
13881
  If this functionality is unavailable, using it raises an exception.
13882
[clinic start generated code]*/
13883
13884
static long
13885
os_pathconf_impl(PyObject *module, path_t *path, int name)
13886
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
13887
0
{
13888
0
    long limit;
13889
13890
0
    errno = 0;
13891
0
#ifdef HAVE_FPATHCONF
13892
0
    if (path->fd != -1)
13893
0
        limit = fpathconf(path->fd, name);
13894
0
    else
13895
0
#endif
13896
0
        limit = pathconf(path->narrow, name);
13897
0
    if (limit == -1 && errno != 0) {
13898
0
        if (errno == EINVAL)
13899
            /* could be a path or name problem */
13900
0
            posix_error();
13901
0
        else
13902
0
            path_error(path);
13903
0
    }
13904
13905
0
    return limit;
13906
0
}
13907
#endif /* HAVE_PATHCONF */
13908
13909
#ifdef HAVE_CONFSTR
13910
static struct constdef posix_constants_confstr[] = {
13911
#ifdef _CS_ARCHITECTURE
13912
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
13913
#endif
13914
#ifdef _CS_GNU_LIBC_VERSION
13915
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
13916
#endif
13917
#ifdef _CS_GNU_LIBPTHREAD_VERSION
13918
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
13919
#endif
13920
#ifdef _CS_HOSTNAME
13921
    {"CS_HOSTNAME",     _CS_HOSTNAME},
13922
#endif
13923
#ifdef _CS_HW_PROVIDER
13924
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
13925
#endif
13926
#ifdef _CS_HW_SERIAL
13927
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
13928
#endif
13929
#ifdef _CS_INITTAB_NAME
13930
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
13931
#endif
13932
#ifdef _CS_LFS64_CFLAGS
13933
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
13934
#endif
13935
#ifdef _CS_LFS64_LDFLAGS
13936
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
13937
#endif
13938
#ifdef _CS_LFS64_LIBS
13939
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
13940
#endif
13941
#ifdef _CS_LFS64_LINTFLAGS
13942
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
13943
#endif
13944
#ifdef _CS_LFS_CFLAGS
13945
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
13946
#endif
13947
#ifdef _CS_LFS_LDFLAGS
13948
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
13949
#endif
13950
#ifdef _CS_LFS_LIBS
13951
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
13952
#endif
13953
#ifdef _CS_LFS_LINTFLAGS
13954
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
13955
#endif
13956
#ifdef _CS_MACHINE
13957
    {"CS_MACHINE",      _CS_MACHINE},
13958
#endif
13959
#ifdef _CS_PATH
13960
    {"CS_PATH", _CS_PATH},
13961
#endif
13962
#ifdef _CS_RELEASE
13963
    {"CS_RELEASE",      _CS_RELEASE},
13964
#endif
13965
#ifdef _CS_SRPC_DOMAIN
13966
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
13967
#endif
13968
#ifdef _CS_SYSNAME
13969
    {"CS_SYSNAME",      _CS_SYSNAME},
13970
#endif
13971
#ifdef _CS_VERSION
13972
    {"CS_VERSION",      _CS_VERSION},
13973
#endif
13974
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
13975
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
13976
#endif
13977
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
13978
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
13979
#endif
13980
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
13981
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
13982
#endif
13983
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
13984
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
13985
#endif
13986
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
13987
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
13988
#endif
13989
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
13990
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
13991
#endif
13992
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
13993
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
13994
#endif
13995
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
13996
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
13997
#endif
13998
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
13999
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14000
#endif
14001
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14002
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14003
#endif
14004
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14005
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14006
#endif
14007
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14008
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14009
#endif
14010
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14011
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14012
#endif
14013
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14014
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14015
#endif
14016
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14017
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14018
#endif
14019
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14020
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14021
#endif
14022
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14023
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14024
#endif
14025
#ifdef _MIPS_CS_BASE
14026
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14027
#endif
14028
#ifdef _MIPS_CS_HOSTID
14029
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14030
#endif
14031
#ifdef _MIPS_CS_HW_NAME
14032
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14033
#endif
14034
#ifdef _MIPS_CS_NUM_PROCESSORS
14035
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14036
#endif
14037
#ifdef _MIPS_CS_OSREL_MAJ
14038
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14039
#endif
14040
#ifdef _MIPS_CS_OSREL_MIN
14041
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14042
#endif
14043
#ifdef _MIPS_CS_OSREL_PATCH
14044
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14045
#endif
14046
#ifdef _MIPS_CS_OS_NAME
14047
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14048
#endif
14049
#ifdef _MIPS_CS_OS_PROVIDER
14050
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14051
#endif
14052
#ifdef _MIPS_CS_PROCESSORS
14053
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14054
#endif
14055
#ifdef _MIPS_CS_SERIAL
14056
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14057
#endif
14058
#ifdef _MIPS_CS_VENDOR
14059
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14060
#endif
14061
};
14062
14063
14064
/*[clinic input]
14065
os.confstr
14066
14067
    name: confname(table="confstr_names")
14068
    /
14069
14070
Return a string-valued system configuration variable.
14071
[clinic start generated code]*/
14072
14073
static PyObject *
14074
os_confstr_impl(PyObject *module, int name)
14075
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14076
0
{
14077
0
    PyObject *result = NULL;
14078
0
    char buffer[255];
14079
0
    size_t len;
14080
14081
0
    errno = 0;
14082
0
    len = confstr(name, buffer, sizeof(buffer));
14083
0
    if (len == 0) {
14084
0
        if (errno) {
14085
0
            posix_error();
14086
0
            return NULL;
14087
0
        }
14088
0
        else {
14089
0
            Py_RETURN_NONE;
14090
0
        }
14091
0
    }
14092
14093
0
    if (len >= sizeof(buffer)) {
14094
0
        size_t len2;
14095
0
        char *buf = PyMem_Malloc(len);
14096
0
        if (buf == NULL)
14097
0
            return PyErr_NoMemory();
14098
0
        len2 = confstr(name, buf, len);
14099
0
        assert(len == len2);
14100
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14101
0
        PyMem_Free(buf);
14102
0
    }
14103
0
    else
14104
0
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14105
0
    return result;
14106
0
}
14107
#endif /* HAVE_CONFSTR */
14108
14109
14110
#ifdef HAVE_SYSCONF
14111
static struct constdef posix_constants_sysconf[] = {
14112
#ifdef _SC_2_CHAR_TERM
14113
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14114
#endif
14115
#ifdef _SC_2_C_BIND
14116
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14117
#endif
14118
#ifdef _SC_2_C_DEV
14119
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14120
#endif
14121
#ifdef _SC_2_C_VERSION
14122
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14123
#endif
14124
#ifdef _SC_2_FORT_DEV
14125
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14126
#endif
14127
#ifdef _SC_2_FORT_RUN
14128
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14129
#endif
14130
#ifdef _SC_2_LOCALEDEF
14131
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14132
#endif
14133
#ifdef _SC_2_SW_DEV
14134
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14135
#endif
14136
#ifdef _SC_2_UPE
14137
    {"SC_2_UPE",        _SC_2_UPE},
14138
#endif
14139
#ifdef _SC_2_VERSION
14140
    {"SC_2_VERSION",    _SC_2_VERSION},
14141
#endif
14142
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14143
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14144
#endif
14145
#ifdef _SC_ACL
14146
    {"SC_ACL",  _SC_ACL},
14147
#endif
14148
#ifdef _SC_AIO_LISTIO_MAX
14149
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14150
#endif
14151
#ifdef _SC_AIO_MAX
14152
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14153
#endif
14154
#ifdef _SC_AIO_PRIO_DELTA_MAX
14155
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14156
#endif
14157
#ifdef _SC_ARG_MAX
14158
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14159
#endif
14160
#ifdef _SC_ASYNCHRONOUS_IO
14161
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14162
#endif
14163
#ifdef _SC_ATEXIT_MAX
14164
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14165
#endif
14166
#ifdef _SC_AUDIT
14167
    {"SC_AUDIT",        _SC_AUDIT},
14168
#endif
14169
#ifdef _SC_AVPHYS_PAGES
14170
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14171
#endif
14172
#ifdef _SC_BC_BASE_MAX
14173
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14174
#endif
14175
#ifdef _SC_BC_DIM_MAX
14176
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14177
#endif
14178
#ifdef _SC_BC_SCALE_MAX
14179
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14180
#endif
14181
#ifdef _SC_BC_STRING_MAX
14182
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14183
#endif
14184
#ifdef _SC_CAP
14185
    {"SC_CAP",  _SC_CAP},
14186
#endif
14187
#ifdef _SC_CHARCLASS_NAME_MAX
14188
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14189
#endif
14190
#ifdef _SC_CHAR_BIT
14191
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14192
#endif
14193
#ifdef _SC_CHAR_MAX
14194
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14195
#endif
14196
#ifdef _SC_CHAR_MIN
14197
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14198
#endif
14199
#ifdef _SC_CHILD_MAX
14200
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14201
#endif
14202
#ifdef _SC_CLK_TCK
14203
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14204
#endif
14205
#ifdef _SC_COHER_BLKSZ
14206
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14207
#endif
14208
#ifdef _SC_COLL_WEIGHTS_MAX
14209
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14210
#endif
14211
#ifdef _SC_DCACHE_ASSOC
14212
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14213
#endif
14214
#ifdef _SC_DCACHE_BLKSZ
14215
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14216
#endif
14217
#ifdef _SC_DCACHE_LINESZ
14218
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14219
#endif
14220
#ifdef _SC_DCACHE_SZ
14221
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14222
#endif
14223
#ifdef _SC_DCACHE_TBLKSZ
14224
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14225
#endif
14226
#ifdef _SC_DELAYTIMER_MAX
14227
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14228
#endif
14229
#ifdef _SC_EQUIV_CLASS_MAX
14230
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14231
#endif
14232
#ifdef _SC_EXPR_NEST_MAX
14233
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14234
#endif
14235
#ifdef _SC_FSYNC
14236
    {"SC_FSYNC",        _SC_FSYNC},
14237
#endif
14238
#ifdef _SC_GETGR_R_SIZE_MAX
14239
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14240
#endif
14241
#ifdef _SC_GETPW_R_SIZE_MAX
14242
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14243
#endif
14244
#ifdef _SC_ICACHE_ASSOC
14245
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14246
#endif
14247
#ifdef _SC_ICACHE_BLKSZ
14248
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14249
#endif
14250
#ifdef _SC_ICACHE_LINESZ
14251
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14252
#endif
14253
#ifdef _SC_ICACHE_SZ
14254
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14255
#endif
14256
#ifdef _SC_INF
14257
    {"SC_INF",  _SC_INF},
14258
#endif
14259
#ifdef _SC_INT_MAX
14260
    {"SC_INT_MAX",      _SC_INT_MAX},
14261
#endif
14262
#ifdef _SC_INT_MIN
14263
    {"SC_INT_MIN",      _SC_INT_MIN},
14264
#endif
14265
#ifdef _SC_IOV_MAX
14266
    {"SC_IOV_MAX",      _SC_IOV_MAX},
14267
#endif
14268
#ifdef _SC_IP_SECOPTS
14269
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14270
#endif
14271
#ifdef _SC_JOB_CONTROL
14272
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14273
#endif
14274
#ifdef _SC_KERN_POINTERS
14275
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14276
#endif
14277
#ifdef _SC_KERN_SIM
14278
    {"SC_KERN_SIM",     _SC_KERN_SIM},
14279
#endif
14280
#ifdef _SC_LINE_MAX
14281
    {"SC_LINE_MAX",     _SC_LINE_MAX},
14282
#endif
14283
#ifdef _SC_LOGIN_NAME_MAX
14284
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14285
#endif
14286
#ifdef _SC_LOGNAME_MAX
14287
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14288
#endif
14289
#ifdef _SC_LONG_BIT
14290
    {"SC_LONG_BIT",     _SC_LONG_BIT},
14291
#endif
14292
#ifdef _SC_MAC
14293
    {"SC_MAC",  _SC_MAC},
14294
#endif
14295
#ifdef _SC_MAPPED_FILES
14296
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14297
#endif
14298
#ifdef _SC_MAXPID
14299
    {"SC_MAXPID",       _SC_MAXPID},
14300
#endif
14301
#ifdef _SC_MB_LEN_MAX
14302
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14303
#endif
14304
#ifdef _SC_MEMLOCK
14305
    {"SC_MEMLOCK",      _SC_MEMLOCK},
14306
#endif
14307
#ifdef _SC_MEMLOCK_RANGE
14308
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14309
#endif
14310
#ifdef _SC_MEMORY_PROTECTION
14311
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14312
#endif
14313
#ifdef _SC_MESSAGE_PASSING
14314
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14315
#endif
14316
#ifdef _SC_MMAP_FIXED_ALIGNMENT
14317
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14318
#endif
14319
#ifdef _SC_MQ_OPEN_MAX
14320
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14321
#endif
14322
#ifdef _SC_MQ_PRIO_MAX
14323
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14324
#endif
14325
#ifdef _SC_NACLS_MAX
14326
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14327
#endif
14328
#ifdef _SC_NGROUPS_MAX
14329
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14330
#endif
14331
#ifdef _SC_NL_ARGMAX
14332
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14333
#endif
14334
#ifdef _SC_NL_LANGMAX
14335
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14336
#endif
14337
#ifdef _SC_NL_MSGMAX
14338
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14339
#endif
14340
#ifdef _SC_NL_NMAX
14341
    {"SC_NL_NMAX",      _SC_NL_NMAX},
14342
#endif
14343
#ifdef _SC_NL_SETMAX
14344
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14345
#endif
14346
#ifdef _SC_NL_TEXTMAX
14347
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14348
#endif
14349
#ifdef _SC_NPROCESSORS_CONF
14350
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14351
#endif
14352
#ifdef _SC_NPROCESSORS_ONLN
14353
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14354
#endif
14355
#ifdef _SC_NPROC_CONF
14356
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14357
#endif
14358
#ifdef _SC_NPROC_ONLN
14359
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14360
#endif
14361
#ifdef _SC_NZERO
14362
    {"SC_NZERO",        _SC_NZERO},
14363
#endif
14364
#ifdef _SC_OPEN_MAX
14365
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14366
#endif
14367
#ifdef _SC_PAGESIZE
14368
    {"SC_PAGESIZE",     _SC_PAGESIZE},
14369
#endif
14370
#ifdef _SC_PAGE_SIZE
14371
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14372
#endif
14373
#ifdef _SC_AIX_REALMEM
14374
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14375
#endif
14376
#ifdef _SC_PASS_MAX
14377
    {"SC_PASS_MAX",     _SC_PASS_MAX},
14378
#endif
14379
#ifdef _SC_PHYS_PAGES
14380
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14381
#endif
14382
#ifdef _SC_PII
14383
    {"SC_PII",  _SC_PII},
14384
#endif
14385
#ifdef _SC_PII_INTERNET
14386
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
14387
#endif
14388
#ifdef _SC_PII_INTERNET_DGRAM
14389
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14390
#endif
14391
#ifdef _SC_PII_INTERNET_STREAM
14392
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14393
#endif
14394
#ifdef _SC_PII_OSI
14395
    {"SC_PII_OSI",      _SC_PII_OSI},
14396
#endif
14397
#ifdef _SC_PII_OSI_CLTS
14398
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14399
#endif
14400
#ifdef _SC_PII_OSI_COTS
14401
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14402
#endif
14403
#ifdef _SC_PII_OSI_M
14404
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14405
#endif
14406
#ifdef _SC_PII_SOCKET
14407
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14408
#endif
14409
#ifdef _SC_PII_XTI
14410
    {"SC_PII_XTI",      _SC_PII_XTI},
14411
#endif
14412
#ifdef _SC_POLL
14413
    {"SC_POLL", _SC_POLL},
14414
#endif
14415
#ifdef _SC_PRIORITIZED_IO
14416
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14417
#endif
14418
#ifdef _SC_PRIORITY_SCHEDULING
14419
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14420
#endif
14421
#ifdef _SC_REALTIME_SIGNALS
14422
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14423
#endif
14424
#ifdef _SC_RE_DUP_MAX
14425
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14426
#endif
14427
#ifdef _SC_RTSIG_MAX
14428
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14429
#endif
14430
#ifdef _SC_SAVED_IDS
14431
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14432
#endif
14433
#ifdef _SC_SCHAR_MAX
14434
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14435
#endif
14436
#ifdef _SC_SCHAR_MIN
14437
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14438
#endif
14439
#ifdef _SC_SELECT
14440
    {"SC_SELECT",       _SC_SELECT},
14441
#endif
14442
#ifdef _SC_SEMAPHORES
14443
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14444
#endif
14445
#ifdef _SC_SEM_NSEMS_MAX
14446
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14447
#endif
14448
#ifdef _SC_SEM_VALUE_MAX
14449
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14450
#endif
14451
#ifdef _SC_SHARED_MEMORY_OBJECTS
14452
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14453
#endif
14454
#ifdef _SC_SHRT_MAX
14455
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14456
#endif
14457
#ifdef _SC_SHRT_MIN
14458
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14459
#endif
14460
#ifdef _SC_SIGQUEUE_MAX
14461
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14462
#endif
14463
#ifdef _SC_SIGRT_MAX
14464
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14465
#endif
14466
#ifdef _SC_SIGRT_MIN
14467
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14468
#endif
14469
#ifdef _SC_SOFTPOWER
14470
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14471
#endif
14472
#ifdef _SC_SPLIT_CACHE
14473
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14474
#endif
14475
#ifdef _SC_SSIZE_MAX
14476
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14477
#endif
14478
#ifdef _SC_STACK_PROT
14479
    {"SC_STACK_PROT",   _SC_STACK_PROT},
14480
#endif
14481
#ifdef _SC_STREAM_MAX
14482
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14483
#endif
14484
#ifdef _SC_SYNCHRONIZED_IO
14485
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14486
#endif
14487
#ifdef _SC_THREADS
14488
    {"SC_THREADS",      _SC_THREADS},
14489
#endif
14490
#ifdef _SC_THREAD_ATTR_STACKADDR
14491
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14492
#endif
14493
#ifdef _SC_THREAD_ATTR_STACKSIZE
14494
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14495
#endif
14496
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14497
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14498
#endif
14499
#ifdef _SC_THREAD_KEYS_MAX
14500
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14501
#endif
14502
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
14503
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14504
#endif
14505
#ifdef _SC_THREAD_PRIO_INHERIT
14506
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14507
#endif
14508
#ifdef _SC_THREAD_PRIO_PROTECT
14509
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14510
#endif
14511
#ifdef _SC_THREAD_PROCESS_SHARED
14512
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14513
#endif
14514
#ifdef _SC_THREAD_SAFE_FUNCTIONS
14515
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14516
#endif
14517
#ifdef _SC_THREAD_STACK_MIN
14518
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14519
#endif
14520
#ifdef _SC_THREAD_THREADS_MAX
14521
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14522
#endif
14523
#ifdef _SC_TIMERS
14524
    {"SC_TIMERS",       _SC_TIMERS},
14525
#endif
14526
#ifdef _SC_TIMER_MAX
14527
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14528
#endif
14529
#ifdef _SC_TTY_NAME_MAX
14530
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14531
#endif
14532
#ifdef _SC_TZNAME_MAX
14533
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14534
#endif
14535
#ifdef _SC_T_IOV_MAX
14536
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14537
#endif
14538
#ifdef _SC_UCHAR_MAX
14539
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14540
#endif
14541
#ifdef _SC_UINT_MAX
14542
    {"SC_UINT_MAX",     _SC_UINT_MAX},
14543
#endif
14544
#ifdef _SC_UIO_MAXIOV
14545
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14546
#endif
14547
#ifdef _SC_ULONG_MAX
14548
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14549
#endif
14550
#ifdef _SC_USHRT_MAX
14551
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14552
#endif
14553
#ifdef _SC_VERSION
14554
    {"SC_VERSION",      _SC_VERSION},
14555
#endif
14556
#ifdef _SC_WORD_BIT
14557
    {"SC_WORD_BIT",     _SC_WORD_BIT},
14558
#endif
14559
#ifdef _SC_XBS5_ILP32_OFF32
14560
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
14561
#endif
14562
#ifdef _SC_XBS5_ILP32_OFFBIG
14563
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
14564
#endif
14565
#ifdef _SC_XBS5_LP64_OFF64
14566
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
14567
#endif
14568
#ifdef _SC_XBS5_LPBIG_OFFBIG
14569
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
14570
#endif
14571
#ifdef _SC_XOPEN_CRYPT
14572
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
14573
#endif
14574
#ifdef _SC_XOPEN_ENH_I18N
14575
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
14576
#endif
14577
#ifdef _SC_XOPEN_LEGACY
14578
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
14579
#endif
14580
#ifdef _SC_XOPEN_REALTIME
14581
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
14582
#endif
14583
#ifdef _SC_XOPEN_REALTIME_THREADS
14584
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
14585
#endif
14586
#ifdef _SC_XOPEN_SHM
14587
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
14588
#endif
14589
#ifdef _SC_XOPEN_UNIX
14590
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
14591
#endif
14592
#ifdef _SC_XOPEN_VERSION
14593
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
14594
#endif
14595
#ifdef _SC_XOPEN_XCU_VERSION
14596
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
14597
#endif
14598
#ifdef _SC_XOPEN_XPG2
14599
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
14600
#endif
14601
#ifdef _SC_XOPEN_XPG3
14602
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
14603
#endif
14604
#ifdef _SC_XOPEN_XPG4
14605
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
14606
#endif
14607
#ifdef _SC_MINSIGSTKSZ
14608
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
14609
#endif
14610
};
14611
14612
14613
/*[clinic input]
14614
os.sysconf -> long
14615
    name: confname(table="sysconf_names")
14616
    /
14617
14618
Return an integer-valued system configuration variable.
14619
[clinic start generated code]*/
14620
14621
static long
14622
os_sysconf_impl(PyObject *module, int name)
14623
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
14624
0
{
14625
0
    long value;
14626
14627
0
    errno = 0;
14628
0
    value = sysconf(name);
14629
0
    if (value == -1 && errno != 0)
14630
0
        posix_error();
14631
0
    return value;
14632
0
}
14633
#endif /* HAVE_SYSCONF */
14634
14635
14636
static int
14637
setup_confname_table(struct constdef *table, size_t tablesize,
14638
                     const char *tablename, PyObject *module)
14639
66
{
14640
66
    PyObject *d = PyDict_New();
14641
66
    if (d == NULL)
14642
0
        return -1;
14643
14644
4.04k
    for (size_t i=0; i < tablesize; ++i) {
14645
3.98k
        PyObject *o = PyLong_FromLong(table[i].value);
14646
3.98k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
14647
0
            Py_XDECREF(o);
14648
0
            Py_DECREF(d);
14649
0
            return -1;
14650
0
        }
14651
3.98k
        Py_DECREF(o);
14652
3.98k
    }
14653
66
    return PyModule_Add(module, tablename, d);
14654
66
}
14655
14656
/* Return -1 on failure, 0 on success. */
14657
static int
14658
setup_confname_tables(PyObject *module)
14659
22
{
14660
22
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14661
22
    if (setup_confname_table(posix_constants_pathconf,
14662
22
                             sizeof(posix_constants_pathconf)
14663
22
                               / sizeof(struct constdef),
14664
22
                             "pathconf_names", module))
14665
0
        return -1;
14666
22
#endif
14667
22
#ifdef HAVE_CONFSTR
14668
22
    if (setup_confname_table(posix_constants_confstr,
14669
22
                             sizeof(posix_constants_confstr)
14670
22
                               / sizeof(struct constdef),
14671
22
                             "confstr_names", module))
14672
0
        return -1;
14673
22
#endif
14674
22
#ifdef HAVE_SYSCONF
14675
22
    if (setup_confname_table(posix_constants_sysconf,
14676
22
                             sizeof(posix_constants_sysconf)
14677
22
                               / sizeof(struct constdef),
14678
22
                             "sysconf_names", module))
14679
0
        return -1;
14680
22
#endif
14681
22
    return 0;
14682
22
}
14683
14684
14685
/*[clinic input]
14686
os.abort
14687
14688
Abort the interpreter immediately.
14689
14690
This function 'dumps core' or otherwise fails in the hardest way possible
14691
on the hosting operating system.  This function never returns.
14692
[clinic start generated code]*/
14693
14694
static PyObject *
14695
os_abort_impl(PyObject *module)
14696
/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
14697
0
{
14698
0
    abort();
14699
    /*NOTREACHED*/
14700
#ifndef __clang__
14701
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
14702
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
14703
       is smarter and emits a warning on the return. */
14704
    Py_FatalError("abort() called from Python code didn't abort!");
14705
    return NULL;
14706
#endif
14707
0
}
14708
14709
#ifdef MS_WINDOWS
14710
/* Grab ShellExecute dynamically from shell32 */
14711
static int has_ShellExecute = -1;
14712
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
14713
                                              LPCWSTR, INT);
14714
static int
14715
check_ShellExecute(void)
14716
{
14717
    HINSTANCE hShell32;
14718
14719
    /* only recheck */
14720
    if (-1 == has_ShellExecute) {
14721
        Py_BEGIN_ALLOW_THREADS
14722
        /* Security note: this call is not vulnerable to "DLL hijacking".
14723
           SHELL32 is part of "KnownDLLs" and so Windows always load
14724
           the system SHELL32.DLL, even if there is another SHELL32.DLL
14725
           in the DLL search path. */
14726
        hShell32 = LoadLibraryW(L"SHELL32");
14727
        if (hShell32) {
14728
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
14729
                                            "ShellExecuteW");
14730
            has_ShellExecute = Py_ShellExecuteW != NULL;
14731
        } else {
14732
            has_ShellExecute = 0;
14733
        }
14734
        Py_END_ALLOW_THREADS
14735
    }
14736
    return has_ShellExecute;
14737
}
14738
14739
14740
/*[clinic input]
14741
os.startfile
14742
    filepath: path_t
14743
    operation: Py_UNICODE = NULL
14744
    arguments: Py_UNICODE = NULL
14745
    cwd: path_t(nullable=True) = None
14746
    show_cmd: int = 1
14747
14748
Start a file with its associated application.
14749
14750
When "operation" is not specified or "open", this acts like
14751
double-clicking the file in Explorer, or giving the file name as an
14752
argument to the DOS "start" command: the file is opened with whatever
14753
application (if any) its extension is associated.
14754
When another "operation" is given, it specifies what should be done with
14755
the file.  A typical operation is "print".
14756
14757
"arguments" is passed to the application, but should be omitted if the
14758
file is a document.
14759
14760
"cwd" is the working directory for the operation. If "filepath" is
14761
relative, it will be resolved against this directory. This argument
14762
should usually be an absolute path.
14763
14764
"show_cmd" can be used to override the recommended visibility option.
14765
See the Windows ShellExecute documentation for values.
14766
14767
startfile returns as soon as the associated application is launched.
14768
There is no option to wait for the application to close, and no way
14769
to retrieve the application's exit status.
14770
14771
The filepath is relative to the current directory.  If you want to use
14772
an absolute path, make sure the first character is not a slash ("/");
14773
the underlying Win32 ShellExecute function doesn't work if it is.
14774
[clinic start generated code]*/
14775
14776
static PyObject *
14777
os_startfile_impl(PyObject *module, path_t *filepath,
14778
                  const wchar_t *operation, const wchar_t *arguments,
14779
                  path_t *cwd, int show_cmd)
14780
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
14781
{
14782
    HINSTANCE rc;
14783
14784
    if(!check_ShellExecute()) {
14785
        /* If the OS doesn't have ShellExecute, return a
14786
           NotImplementedError. */
14787
        return PyErr_Format(PyExc_NotImplementedError,
14788
            "startfile not available on this platform");
14789
    }
14790
14791
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
14792
        return NULL;
14793
    }
14794
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
14795
                    arguments, cwd->object ? cwd->object : Py_None,
14796
                    show_cmd) < 0) {
14797
        return NULL;
14798
    }
14799
14800
    Py_BEGIN_ALLOW_THREADS
14801
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
14802
                          arguments, cwd->wide, show_cmd);
14803
    Py_END_ALLOW_THREADS
14804
14805
    if (rc <= (HINSTANCE)32) {
14806
        win32_error_object("startfile", filepath->object);
14807
        return NULL;
14808
    }
14809
    Py_RETURN_NONE;
14810
}
14811
#endif /* MS_WINDOWS */
14812
14813
14814
#ifdef HAVE_GETLOADAVG
14815
/*[clinic input]
14816
os.getloadavg
14817
14818
Return average recent system load information.
14819
14820
Return the number of processes in the system run queue averaged over
14821
the last 1, 5, and 15 minutes as a tuple of three floats.
14822
Raises OSError if the load average was unobtainable.
14823
[clinic start generated code]*/
14824
14825
static PyObject *
14826
os_getloadavg_impl(PyObject *module)
14827
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
14828
0
{
14829
0
    double loadavg[3];
14830
0
    if (getloadavg(loadavg, 3)!=3) {
14831
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
14832
0
        return NULL;
14833
0
    } else
14834
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
14835
0
}
14836
#endif /* HAVE_GETLOADAVG */
14837
14838
14839
/*[clinic input]
14840
os.device_encoding
14841
    fd: int
14842
14843
Return a string describing the encoding of a terminal's file descriptor.
14844
14845
The file descriptor must be attached to a terminal.
14846
If the device is not a terminal, return None.
14847
[clinic start generated code]*/
14848
14849
static PyObject *
14850
os_device_encoding_impl(PyObject *module, int fd)
14851
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
14852
0
{
14853
0
    return _Py_device_encoding(fd);
14854
0
}
14855
14856
14857
#ifdef HAVE_SETRESUID
14858
/*[clinic input]
14859
os.setresuid
14860
14861
    ruid: uid_t
14862
    euid: uid_t
14863
    suid: uid_t
14864
    /
14865
14866
Set the current process's real, effective, and saved user ids.
14867
[clinic start generated code]*/
14868
14869
static PyObject *
14870
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
14871
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
14872
0
{
14873
0
    if (setresuid(ruid, euid, suid) < 0)
14874
0
        return posix_error();
14875
0
    Py_RETURN_NONE;
14876
0
}
14877
#endif /* HAVE_SETRESUID */
14878
14879
14880
#ifdef HAVE_SETRESGID
14881
/*[clinic input]
14882
os.setresgid
14883
14884
    rgid: gid_t
14885
    egid: gid_t
14886
    sgid: gid_t
14887
    /
14888
14889
Set the current process's real, effective, and saved group ids.
14890
[clinic start generated code]*/
14891
14892
static PyObject *
14893
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
14894
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
14895
0
{
14896
0
    if (setresgid(rgid, egid, sgid) < 0)
14897
0
        return posix_error();
14898
0
    Py_RETURN_NONE;
14899
0
}
14900
#endif /* HAVE_SETRESGID */
14901
14902
14903
#ifdef HAVE_GETRESUID
14904
/*[clinic input]
14905
os.getresuid
14906
14907
Return a tuple of the current process's real, effective, and saved user ids.
14908
[clinic start generated code]*/
14909
14910
static PyObject *
14911
os_getresuid_impl(PyObject *module)
14912
/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
14913
0
{
14914
0
    uid_t ruid, euid, suid;
14915
0
    if (getresuid(&ruid, &euid, &suid) < 0)
14916
0
        return posix_error();
14917
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
14918
0
                                  _PyLong_FromUid(euid),
14919
0
                                  _PyLong_FromUid(suid));
14920
0
}
14921
#endif /* HAVE_GETRESUID */
14922
14923
14924
#ifdef HAVE_GETRESGID
14925
/*[clinic input]
14926
@permit_long_summary
14927
os.getresgid
14928
14929
Return a tuple of the current process's real, effective, and saved group ids.
14930
[clinic start generated code]*/
14931
14932
static PyObject *
14933
os_getresgid_impl(PyObject *module)
14934
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
14935
0
{
14936
0
    gid_t rgid, egid, sgid;
14937
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
14938
0
        return posix_error();
14939
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
14940
0
                                  _PyLong_FromGid(egid),
14941
0
                                  _PyLong_FromGid(sgid));
14942
0
}
14943
#endif /* HAVE_GETRESGID */
14944
14945
14946
#ifdef USE_XATTRS
14947
/*[clinic input]
14948
os.getxattr
14949
14950
    path: path_t(allow_fd=True)
14951
    attribute: path_t
14952
    *
14953
    follow_symlinks: bool = True
14954
14955
Return the value of extended attribute attribute on path.
14956
14957
path may be either a string, a path-like object, or an open file descriptor.
14958
If follow_symlinks is False, and the last element of the path is a symbolic
14959
  link, getxattr will examine the symbolic link itself instead of the file
14960
  the link points to.
14961
14962
[clinic start generated code]*/
14963
14964
static PyObject *
14965
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
14966
                 int follow_symlinks)
14967
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
14968
0
{
14969
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
14970
0
        return NULL;
14971
14972
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
14973
0
        return NULL;
14974
0
    }
14975
14976
0
    for (Py_ssize_t i = 0; ; i++) {
14977
0
        ssize_t result;
14978
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
14979
0
        Py_ssize_t buffer_size = buffer_sizes[i];
14980
0
        if (!buffer_size) {
14981
0
            path_error(path);
14982
0
            return NULL;
14983
0
        }
14984
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
14985
0
        if (writer == NULL) {
14986
0
            return NULL;
14987
0
        }
14988
0
        void *ptr = PyBytesWriter_GetData(writer);
14989
14990
0
        Py_BEGIN_ALLOW_THREADS;
14991
0
        if (path->fd >= 0)
14992
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
14993
0
        else if (follow_symlinks)
14994
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
14995
0
        else
14996
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
14997
0
        Py_END_ALLOW_THREADS;
14998
14999
0
        if (result < 0) {
15000
0
            PyBytesWriter_Discard(writer);
15001
0
            if (errno == ERANGE) {
15002
0
                continue;
15003
0
            }
15004
0
            path_error(path);
15005
0
            return NULL;
15006
0
        }
15007
15008
0
        return PyBytesWriter_FinishWithSize(writer, result);
15009
0
    }
15010
0
}
15011
15012
15013
/*[clinic input]
15014
@permit_long_docstring_body
15015
os.setxattr
15016
15017
    path: path_t(allow_fd=True)
15018
    attribute: path_t
15019
    value: Py_buffer
15020
    flags: int = 0
15021
    *
15022
    follow_symlinks: bool = True
15023
15024
Set extended attribute attribute on path to value.
15025
15026
path may be either a string, a path-like object,  or an open file descriptor.
15027
If follow_symlinks is False, and the last element of the path is a symbolic
15028
  link, setxattr will modify the symbolic link itself instead of the file
15029
  the link points to.
15030
15031
[clinic start generated code]*/
15032
15033
static PyObject *
15034
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15035
                 Py_buffer *value, int flags, int follow_symlinks)
15036
/*[clinic end generated code: output=98b83f63fdde26bb input=4098e6f68699f3d7]*/
15037
0
{
15038
0
    ssize_t result;
15039
15040
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
15041
0
        return NULL;
15042
15043
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15044
0
                    value->buf, value->len, flags) < 0) {
15045
0
        return NULL;
15046
0
    }
15047
15048
0
    Py_BEGIN_ALLOW_THREADS;
15049
0
    if (path->fd > -1)
15050
0
        result = fsetxattr(path->fd, attribute->narrow,
15051
0
                           value->buf, value->len, flags);
15052
0
    else if (follow_symlinks)
15053
0
        result = setxattr(path->narrow, attribute->narrow,
15054
0
                           value->buf, value->len, flags);
15055
0
    else
15056
0
        result = lsetxattr(path->narrow, attribute->narrow,
15057
0
                           value->buf, value->len, flags);
15058
0
    Py_END_ALLOW_THREADS;
15059
15060
0
    if (result) {
15061
0
        path_error(path);
15062
0
        return NULL;
15063
0
    }
15064
15065
0
    Py_RETURN_NONE;
15066
0
}
15067
15068
15069
/*[clinic input]
15070
os.removexattr
15071
15072
    path: path_t(allow_fd=True)
15073
    attribute: path_t
15074
    *
15075
    follow_symlinks: bool = True
15076
15077
Remove extended attribute attribute on path.
15078
15079
path may be either a string, a path-like object, or an open file descriptor.
15080
If follow_symlinks is False, and the last element of the path is a symbolic
15081
  link, removexattr will modify the symbolic link itself instead of the file
15082
  the link points to.
15083
15084
[clinic start generated code]*/
15085
15086
static PyObject *
15087
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15088
                    int follow_symlinks)
15089
/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
15090
0
{
15091
0
    ssize_t result;
15092
15093
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
15094
0
        return NULL;
15095
15096
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15097
0
        return NULL;
15098
0
    }
15099
15100
0
    Py_BEGIN_ALLOW_THREADS;
15101
0
    if (path->fd > -1)
15102
0
        result = fremovexattr(path->fd, attribute->narrow);
15103
0
    else if (follow_symlinks)
15104
0
        result = removexattr(path->narrow, attribute->narrow);
15105
0
    else
15106
0
        result = lremovexattr(path->narrow, attribute->narrow);
15107
0
    Py_END_ALLOW_THREADS;
15108
15109
0
    if (result) {
15110
0
        return path_error(path);
15111
0
    }
15112
15113
0
    Py_RETURN_NONE;
15114
0
}
15115
15116
15117
/*[clinic input]
15118
@permit_long_docstring_body
15119
os.listxattr
15120
15121
    path: path_t(allow_fd=True, nullable=True) = None
15122
    *
15123
    follow_symlinks: bool = True
15124
15125
Return a list of extended attributes on path.
15126
15127
path may be either None, a string, a path-like object, or an open file descriptor.
15128
if path is None, listxattr will examine the current directory.
15129
If follow_symlinks is False, and the last element of the path is a symbolic
15130
  link, listxattr will examine the symbolic link itself instead of the file
15131
  the link points to.
15132
[clinic start generated code]*/
15133
15134
static PyObject *
15135
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15136
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=48aa9ac8be47dea1]*/
15137
0
{
15138
0
    Py_ssize_t i;
15139
0
    PyObject *result = NULL;
15140
0
    const char *name;
15141
0
    char *buffer = NULL;
15142
15143
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
15144
0
        goto exit;
15145
15146
0
    if (PySys_Audit("os.listxattr", "(O)",
15147
0
                    path->object ? path->object : Py_None) < 0) {
15148
0
        return NULL;
15149
0
    }
15150
15151
0
    name = path->narrow ? path->narrow : ".";
15152
15153
0
    for (i = 0; ; i++) {
15154
0
        const char *start, *trace, *end;
15155
0
        ssize_t length;
15156
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15157
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15158
0
        if (!buffer_size) {
15159
            /* ERANGE */
15160
0
            path_error(path);
15161
0
            break;
15162
0
        }
15163
0
        buffer = PyMem_Malloc(buffer_size);
15164
0
        if (!buffer) {
15165
0
            PyErr_NoMemory();
15166
0
            break;
15167
0
        }
15168
15169
0
        Py_BEGIN_ALLOW_THREADS;
15170
0
        if (path->fd > -1)
15171
0
            length = flistxattr(path->fd, buffer, buffer_size);
15172
0
        else if (follow_symlinks)
15173
0
            length = listxattr(name, buffer, buffer_size);
15174
0
        else
15175
0
            length = llistxattr(name, buffer, buffer_size);
15176
0
        Py_END_ALLOW_THREADS;
15177
15178
0
        if (length < 0) {
15179
0
            if (errno == ERANGE) {
15180
0
                PyMem_Free(buffer);
15181
0
                buffer = NULL;
15182
0
                continue;
15183
0
            }
15184
0
            path_error(path);
15185
0
            break;
15186
0
        }
15187
15188
0
        result = PyList_New(0);
15189
0
        if (!result) {
15190
0
            goto exit;
15191
0
        }
15192
15193
0
        end = buffer + length;
15194
0
        for (trace = start = buffer; trace != end; trace++) {
15195
0
            if (!*trace) {
15196
0
                int error;
15197
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15198
0
                                                                 trace - start);
15199
0
                if (!attribute) {
15200
0
                    Py_SETREF(result, NULL);
15201
0
                    goto exit;
15202
0
                }
15203
0
                error = PyList_Append(result, attribute);
15204
0
                Py_DECREF(attribute);
15205
0
                if (error) {
15206
0
                    Py_SETREF(result, NULL);
15207
0
                    goto exit;
15208
0
                }
15209
0
                start = trace + 1;
15210
0
            }
15211
0
        }
15212
0
    break;
15213
0
    }
15214
0
exit:
15215
0
    if (buffer)
15216
0
        PyMem_Free(buffer);
15217
0
    return result;
15218
0
}
15219
#endif /* USE_XATTRS */
15220
15221
15222
/*[clinic input]
15223
@permit_long_summary
15224
os.urandom
15225
15226
    size: Py_ssize_t(allow_negative=False)
15227
    /
15228
15229
Return a bytes object containing random bytes suitable for cryptographic use.
15230
[clinic start generated code]*/
15231
15232
static PyObject *
15233
os_urandom_impl(PyObject *module, Py_ssize_t size)
15234
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15235
0
{
15236
0
    if (size < 0) {
15237
0
        return PyErr_Format(PyExc_ValueError,
15238
0
                            "negative argument not allowed");
15239
0
    }
15240
15241
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
15242
0
    if (writer == NULL) {
15243
0
        return NULL;
15244
0
    }
15245
15246
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
15247
0
    if (result == -1) {
15248
0
        PyBytesWriter_Discard(writer);
15249
0
        return NULL;
15250
0
    }
15251
0
    return PyBytesWriter_Finish(writer);
15252
0
}
15253
15254
#ifdef HAVE_MEMFD_CREATE
15255
/*[clinic input]
15256
os.memfd_create
15257
15258
    name: unicode_fs_encoded
15259
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15260
15261
[clinic start generated code]*/
15262
15263
static PyObject *
15264
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15265
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
15266
0
{
15267
0
    int fd;
15268
0
    const char *bytes = PyBytes_AS_STRING(name);
15269
0
    Py_BEGIN_ALLOW_THREADS
15270
0
    fd = memfd_create(bytes, flags);
15271
0
    Py_END_ALLOW_THREADS
15272
0
    if (fd == -1) {
15273
0
        return PyErr_SetFromErrno(PyExc_OSError);
15274
0
    }
15275
0
    return PyLong_FromLong(fd);
15276
0
}
15277
#endif
15278
15279
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15280
/*[clinic input]
15281
os.eventfd
15282
15283
    initval: unsigned_int
15284
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15285
15286
Creates and returns an event notification file descriptor.
15287
[clinic start generated code]*/
15288
15289
static PyObject *
15290
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15291
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15292
15293
0
{
15294
    /* initval is limited to uint32_t, internal counter is uint64_t */
15295
0
    int fd;
15296
0
    Py_BEGIN_ALLOW_THREADS
15297
0
    fd = eventfd(initval, flags);
15298
0
    Py_END_ALLOW_THREADS
15299
0
    if (fd == -1) {
15300
0
        return PyErr_SetFromErrno(PyExc_OSError);
15301
0
    }
15302
0
    return PyLong_FromLong(fd);
15303
0
}
15304
15305
/*[clinic input]
15306
os.eventfd_read
15307
15308
    fd: fildes
15309
15310
Read eventfd value
15311
[clinic start generated code]*/
15312
15313
static PyObject *
15314
os_eventfd_read_impl(PyObject *module, int fd)
15315
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15316
0
{
15317
0
    eventfd_t value;
15318
0
    int result;
15319
0
    Py_BEGIN_ALLOW_THREADS
15320
0
    result = eventfd_read(fd, &value);
15321
0
    Py_END_ALLOW_THREADS
15322
0
    if (result == -1) {
15323
0
        return PyErr_SetFromErrno(PyExc_OSError);
15324
0
    }
15325
0
    return PyLong_FromUnsignedLongLong(value);
15326
0
}
15327
15328
/*[clinic input]
15329
os.eventfd_write
15330
15331
    fd: fildes
15332
    value: unsigned_long_long
15333
15334
Write eventfd value.
15335
[clinic start generated code]*/
15336
15337
static PyObject *
15338
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15339
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15340
0
{
15341
0
    int result;
15342
0
    Py_BEGIN_ALLOW_THREADS
15343
0
    result = eventfd_write(fd, value);
15344
0
    Py_END_ALLOW_THREADS
15345
0
    if (result == -1) {
15346
0
        return PyErr_SetFromErrno(PyExc_OSError);
15347
0
    }
15348
0
    Py_RETURN_NONE;
15349
0
}
15350
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15351
15352
/* Terminal size querying */
15353
15354
PyDoc_STRVAR(TerminalSize_docstring,
15355
    "A tuple of (columns, lines) for holding terminal window size");
15356
15357
static PyStructSequence_Field TerminalSize_fields[] = {
15358
    {"columns", "width of the terminal window in characters"},
15359
    {"lines", "height of the terminal window in characters"},
15360
    {NULL, NULL}
15361
};
15362
15363
static PyStructSequence_Desc TerminalSize_desc = {
15364
    "os.terminal_size",
15365
    TerminalSize_docstring,
15366
    TerminalSize_fields,
15367
    2,
15368
};
15369
15370
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15371
/*[clinic input]
15372
os.get_terminal_size
15373
15374
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15375
    /
15376
15377
Return the size of the terminal window as (columns, lines).
15378
15379
The optional argument fd (default standard output) specifies
15380
which file descriptor should be queried.
15381
15382
If the file descriptor is not connected to a terminal, an OSError
15383
is thrown.
15384
15385
This function will only be defined if an implementation is
15386
available for this system.
15387
15388
shutil.get_terminal_size is the high-level function which should
15389
normally be used, os.get_terminal_size is the low-level implementation.
15390
[clinic start generated code]*/
15391
15392
static PyObject *
15393
os_get_terminal_size_impl(PyObject *module, int fd)
15394
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15395
0
{
15396
0
    int columns, lines;
15397
0
    PyObject *termsize;
15398
15399
    /* Under some conditions stdout may not be connected and
15400
     * fileno(stdout) may point to an invalid file descriptor. For example
15401
     * GUI apps don't have valid standard streams by default.
15402
     *
15403
     * If this happens, and the optional fd argument is not present,
15404
     * the ioctl below will fail returning EBADF. This is what we want.
15405
     */
15406
15407
0
#ifdef TERMSIZE_USE_IOCTL
15408
0
    {
15409
0
        struct winsize w;
15410
0
        if (ioctl(fd, TIOCGWINSZ, &w))
15411
0
            return PyErr_SetFromErrno(PyExc_OSError);
15412
0
        columns = w.ws_col;
15413
0
        lines = w.ws_row;
15414
0
    }
15415
0
#endif /* TERMSIZE_USE_IOCTL */
15416
15417
#ifdef TERMSIZE_USE_CONIO
15418
    {
15419
        HANDLE handle;
15420
        CONSOLE_SCREEN_BUFFER_INFO csbi;
15421
        handle = _Py_get_osfhandle(fd);
15422
        if (handle == INVALID_HANDLE_VALUE)
15423
            return NULL;
15424
15425
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
15426
            return PyErr_SetFromWindowsErr(0);
15427
15428
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15429
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15430
    }
15431
#endif /* TERMSIZE_USE_CONIO */
15432
15433
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15434
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15435
0
    if (termsize == NULL)
15436
0
        return NULL;
15437
15438
0
    int pos = 0;
15439
15440
0
#define SET_TERMSIZE(CALL)                                   \
15441
0
    do {                                                     \
15442
0
        PyObject *item = (CALL);                             \
15443
0
        if (item == NULL) {                                  \
15444
0
            Py_DECREF(termsize);                             \
15445
0
            return NULL;                                     \
15446
0
        }                                                    \
15447
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15448
0
    } while(0)
15449
15450
0
    SET_TERMSIZE(PyLong_FromLong(columns));
15451
0
    SET_TERMSIZE(PyLong_FromLong(lines));
15452
0
#undef SET_TERMSIZE
15453
15454
0
    return termsize;
15455
0
}
15456
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15457
15458
/*[clinic input]
15459
os.cpu_count
15460
15461
Return the number of logical CPUs in the system.
15462
15463
Return None if indeterminable.
15464
[clinic start generated code]*/
15465
15466
static PyObject *
15467
os_cpu_count_impl(PyObject *module)
15468
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15469
0
{
15470
0
    const PyConfig *config = _Py_GetConfig();
15471
0
    if (config->cpu_count > 0) {
15472
0
        return PyLong_FromLong(config->cpu_count);
15473
0
    }
15474
15475
0
    int ncpu = 0;
15476
#ifdef MS_WINDOWS
15477
# ifdef MS_WINDOWS_DESKTOP
15478
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15479
# else
15480
    ncpu = 0;
15481
# endif
15482
15483
#elif defined(__hpux)
15484
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15485
15486
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15487
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15488
15489
#elif defined(__VXWORKS__)
15490
    ncpu = _Py_popcount32(vxCpuEnabledGet());
15491
15492
#elif defined(__DragonFly__) || \
15493
      defined(__OpenBSD__)   || \
15494
      defined(__FreeBSD__)   || \
15495
      defined(__NetBSD__)    || \
15496
      defined(__APPLE__)
15497
    ncpu = 0;
15498
    size_t len = sizeof(ncpu);
15499
    int mib[2] = {CTL_HW, HW_NCPU};
15500
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15501
        ncpu = 0;
15502
    }
15503
#endif
15504
15505
0
    if (ncpu < 1) {
15506
0
        Py_RETURN_NONE;
15507
0
    }
15508
0
    return PyLong_FromLong(ncpu);
15509
0
}
15510
15511
15512
/*[clinic input]
15513
os.get_inheritable -> bool
15514
15515
    fd: int
15516
    /
15517
15518
Get the close-on-exe flag of the specified file descriptor.
15519
[clinic start generated code]*/
15520
15521
static int
15522
os_get_inheritable_impl(PyObject *module, int fd)
15523
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15524
0
{
15525
0
    int return_value;
15526
0
    _Py_BEGIN_SUPPRESS_IPH
15527
0
    return_value = _Py_get_inheritable(fd);
15528
0
    _Py_END_SUPPRESS_IPH
15529
0
    return return_value;
15530
0
}
15531
15532
15533
/*[clinic input]
15534
os.set_inheritable
15535
    fd: int
15536
    inheritable: int
15537
    /
15538
15539
Set the inheritable flag of the specified file descriptor.
15540
[clinic start generated code]*/
15541
15542
static PyObject *
15543
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15544
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15545
0
{
15546
0
    int result;
15547
15548
0
    _Py_BEGIN_SUPPRESS_IPH
15549
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
15550
0
    _Py_END_SUPPRESS_IPH
15551
0
    if (result < 0)
15552
0
        return NULL;
15553
0
    Py_RETURN_NONE;
15554
0
}
15555
15556
15557
#ifdef MS_WINDOWS
15558
#ifndef HANDLE_FLAG_INHERIT
15559
#define HANDLE_FLAG_INHERIT 0x00000001
15560
#endif
15561
15562
/*[clinic input]
15563
os.get_handle_inheritable -> bool
15564
    handle: intptr_t
15565
    /
15566
15567
Get the close-on-exe flag of the specified file descriptor.
15568
[clinic start generated code]*/
15569
15570
static int
15571
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
15572
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
15573
{
15574
    DWORD flags;
15575
15576
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
15577
        PyErr_SetFromWindowsErr(0);
15578
        return -1;
15579
    }
15580
15581
    return flags & HANDLE_FLAG_INHERIT;
15582
}
15583
15584
15585
/*[clinic input]
15586
os.set_handle_inheritable
15587
    handle: intptr_t
15588
    inheritable: bool
15589
    /
15590
15591
Set the inheritable flag of the specified handle.
15592
[clinic start generated code]*/
15593
15594
static PyObject *
15595
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
15596
                               int inheritable)
15597
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
15598
{
15599
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
15600
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
15601
        PyErr_SetFromWindowsErr(0);
15602
        return NULL;
15603
    }
15604
    Py_RETURN_NONE;
15605
}
15606
#endif /* MS_WINDOWS */
15607
15608
/*[clinic input]
15609
os.get_blocking -> bool
15610
    fd: int
15611
    /
15612
15613
Get the blocking mode of the file descriptor.
15614
15615
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
15616
[clinic start generated code]*/
15617
15618
static int
15619
os_get_blocking_impl(PyObject *module, int fd)
15620
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
15621
0
{
15622
0
    int blocking;
15623
15624
0
    _Py_BEGIN_SUPPRESS_IPH
15625
0
    blocking = _Py_get_blocking(fd);
15626
0
    _Py_END_SUPPRESS_IPH
15627
0
    return blocking;
15628
0
}
15629
15630
/*[clinic input]
15631
os.set_blocking
15632
    fd: int
15633
    blocking: bool
15634
    /
15635
15636
Set the blocking mode of the specified file descriptor.
15637
15638
Set the O_NONBLOCK flag if blocking is False,
15639
clear the O_NONBLOCK flag otherwise.
15640
[clinic start generated code]*/
15641
15642
static PyObject *
15643
os_set_blocking_impl(PyObject *module, int fd, int blocking)
15644
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
15645
0
{
15646
0
    int result;
15647
15648
0
    _Py_BEGIN_SUPPRESS_IPH
15649
0
    result = _Py_set_blocking(fd, blocking);
15650
0
    _Py_END_SUPPRESS_IPH
15651
0
    if (result < 0)
15652
0
        return NULL;
15653
0
    Py_RETURN_NONE;
15654
0
}
15655
15656
15657
/*[clinic input]
15658
class os.DirEntry "DirEntry *" "DirEntryType"
15659
[clinic start generated code]*/
15660
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
15661
15662
typedef struct {
15663
    PyObject_HEAD
15664
    PyObject *name;
15665
    PyObject *path;
15666
    PyObject *stat;
15667
    PyObject *lstat;
15668
#ifdef MS_WINDOWS
15669
    struct _Py_stat_struct win32_lstat;
15670
    uint64_t win32_file_index;
15671
    uint64_t win32_file_index_high;
15672
    int got_file_index;
15673
#else /* POSIX */
15674
#ifdef HAVE_DIRENT_D_TYPE
15675
    unsigned char d_type;
15676
#endif
15677
    ino_t d_ino;
15678
    int dir_fd;
15679
#endif
15680
} DirEntry;
15681
15682
0
#define DirEntry_CAST(op)   ((DirEntry *)(op))
15683
15684
static void
15685
DirEntry_dealloc(PyObject *op)
15686
0
{
15687
0
    DirEntry *entry = DirEntry_CAST(op);
15688
0
    PyTypeObject *tp = Py_TYPE(entry);
15689
0
    Py_XDECREF(entry->name);
15690
0
    Py_XDECREF(entry->path);
15691
0
    Py_XDECREF(entry->stat);
15692
0
    Py_XDECREF(entry->lstat);
15693
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
15694
0
    free_func(entry);
15695
0
    Py_DECREF(tp);
15696
0
}
15697
15698
/* Forward reference */
15699
static int
15700
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
15701
                   int follow_symlinks, unsigned short mode_bits);
15702
15703
/*[clinic input]
15704
os.DirEntry.is_symlink -> bool
15705
    defining_class: defining_class
15706
    /
15707
15708
Return True if the entry is a symbolic link; cached per entry.
15709
[clinic start generated code]*/
15710
15711
static int
15712
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
15713
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
15714
0
{
15715
#ifdef MS_WINDOWS
15716
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
15717
#elif defined(HAVE_DIRENT_D_TYPE)
15718
    /* POSIX */
15719
0
    if (self->d_type != DT_UNKNOWN)
15720
0
        return self->d_type == DT_LNK;
15721
0
    else
15722
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
15723
#else
15724
    /* POSIX without d_type */
15725
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
15726
#endif
15727
0
}
15728
15729
/*[clinic input]
15730
os.DirEntry.is_junction -> bool
15731
15732
Return True if the entry is a junction; cached per entry.
15733
[clinic start generated code]*/
15734
15735
static int
15736
os_DirEntry_is_junction_impl(DirEntry *self)
15737
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
15738
0
{
15739
#ifdef MS_WINDOWS
15740
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
15741
#else
15742
0
    return 0;
15743
0
#endif
15744
0
}
15745
15746
static PyObject *
15747
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
15748
0
{
15749
0
    int result;
15750
0
    STRUCT_STAT st;
15751
0
    PyObject *ub;
15752
15753
#ifdef MS_WINDOWS
15754
    if (!PyUnicode_FSDecoder(self->path, &ub))
15755
        return NULL;
15756
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
15757
    Py_DECREF(ub);
15758
#else /* POSIX */
15759
0
    if (!PyUnicode_FSConverter(self->path, &ub))
15760
0
        return NULL;
15761
0
    const char *path = PyBytes_AS_STRING(ub);
15762
0
    if (self->dir_fd != DEFAULT_DIR_FD) {
15763
0
#ifdef HAVE_FSTATAT
15764
0
      if (HAVE_FSTATAT_RUNTIME) {
15765
0
        Py_BEGIN_ALLOW_THREADS
15766
0
        result = fstatat(self->dir_fd, path, &st,
15767
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
15768
0
        Py_END_ALLOW_THREADS
15769
0
      } else
15770
15771
0
#endif /* HAVE_FSTATAT */
15772
0
      {
15773
0
        Py_DECREF(ub);
15774
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
15775
0
        return NULL;
15776
0
      }
15777
0
    }
15778
0
    else
15779
0
#endif
15780
0
    {
15781
0
        Py_BEGIN_ALLOW_THREADS
15782
0
        if (follow_symlinks) {
15783
0
            result = STAT(path, &st);
15784
0
        }
15785
0
        else {
15786
0
            result = LSTAT(path, &st);
15787
0
        }
15788
0
        Py_END_ALLOW_THREADS
15789
0
    }
15790
15791
0
    int saved_errno = errno;
15792
#if defined(MS_WINDOWS)
15793
    PyMem_Free(path);
15794
#else
15795
0
    Py_DECREF(ub);
15796
0
#endif
15797
15798
0
    if (result != 0) {
15799
0
        errno = saved_errno;
15800
0
        path_object_error(self->path);
15801
0
        return NULL;
15802
0
    }
15803
15804
0
    return _pystat_fromstructstat(module, &st);
15805
0
}
15806
15807
static PyObject *
15808
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
15809
0
{
15810
0
    if (!self->lstat) {
15811
0
        PyObject *module = PyType_GetModule(defining_class);
15812
#ifdef MS_WINDOWS
15813
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
15814
#else /* POSIX */
15815
0
        self->lstat = DirEntry_fetch_stat(module, self, 0);
15816
0
#endif
15817
0
    }
15818
0
    return Py_XNewRef(self->lstat);
15819
0
}
15820
15821
/*[clinic input]
15822
os.DirEntry.stat
15823
    defining_class: defining_class
15824
    /
15825
    *
15826
    follow_symlinks: bool = True
15827
15828
Return stat_result object for the entry; cached per entry.
15829
[clinic start generated code]*/
15830
15831
static PyObject *
15832
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
15833
                      int follow_symlinks)
15834
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
15835
0
{
15836
0
    if (!follow_symlinks) {
15837
0
        return DirEntry_get_lstat(defining_class, self);
15838
0
    }
15839
15840
0
    if (!self->stat) {
15841
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
15842
0
        if (result == -1) {
15843
0
            return NULL;
15844
0
        }
15845
0
        if (result) {
15846
0
            PyObject *module = PyType_GetModule(defining_class);
15847
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
15848
0
        }
15849
0
        else {
15850
0
            self->stat = DirEntry_get_lstat(defining_class, self);
15851
0
        }
15852
0
    }
15853
15854
0
    return Py_XNewRef(self->stat);
15855
0
}
15856
15857
/* Set exception and return -1 on error, 0 for False, 1 for True */
15858
static int
15859
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
15860
                   int follow_symlinks, unsigned short mode_bits)
15861
0
{
15862
0
    PyObject *stat = NULL;
15863
0
    PyObject *st_mode = NULL;
15864
0
    long mode;
15865
0
    int result;
15866
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15867
0
    int is_symlink;
15868
0
    int need_stat;
15869
0
#endif
15870
#ifdef MS_WINDOWS
15871
    unsigned long dir_bits;
15872
#endif
15873
15874
#ifdef MS_WINDOWS
15875
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
15876
    need_stat = follow_symlinks && is_symlink;
15877
#elif defined(HAVE_DIRENT_D_TYPE)
15878
0
    is_symlink = self->d_type == DT_LNK;
15879
0
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
15880
0
#endif
15881
15882
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15883
0
    if (need_stat) {
15884
0
#endif
15885
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
15886
0
        if (!stat) {
15887
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
15888
                /* If file doesn't exist (anymore), then return False
15889
                   (i.e., say it's not a file/directory) */
15890
0
                PyErr_Clear();
15891
0
                return 0;
15892
0
            }
15893
0
            goto error;
15894
0
        }
15895
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
15896
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
15897
0
        if (!st_mode)
15898
0
            goto error;
15899
15900
0
        mode = PyLong_AsLong(st_mode);
15901
0
        if (mode == -1 && PyErr_Occurred())
15902
0
            goto error;
15903
0
        Py_CLEAR(st_mode);
15904
0
        Py_CLEAR(stat);
15905
0
        result = (mode & S_IFMT) == mode_bits;
15906
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15907
0
    }
15908
0
    else if (is_symlink) {
15909
0
        assert(mode_bits != S_IFLNK);
15910
0
        result = 0;
15911
0
    }
15912
0
    else {
15913
0
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
15914
#ifdef MS_WINDOWS
15915
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
15916
        if (mode_bits == S_IFDIR)
15917
            result = dir_bits != 0;
15918
        else
15919
            result = dir_bits == 0;
15920
#else /* POSIX */
15921
0
        if (mode_bits == S_IFDIR)
15922
0
            result = self->d_type == DT_DIR;
15923
0
        else
15924
0
            result = self->d_type == DT_REG;
15925
0
#endif
15926
0
    }
15927
0
#endif
15928
15929
0
    return result;
15930
15931
0
error:
15932
0
    Py_XDECREF(st_mode);
15933
0
    Py_XDECREF(stat);
15934
0
    return -1;
15935
0
}
15936
15937
/*[clinic input]
15938
os.DirEntry.is_dir -> bool
15939
    defining_class: defining_class
15940
    /
15941
    *
15942
    follow_symlinks: bool = True
15943
15944
Return True if the entry is a directory; cached per entry.
15945
[clinic start generated code]*/
15946
15947
static int
15948
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
15949
                        int follow_symlinks)
15950
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
15951
0
{
15952
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
15953
0
}
15954
15955
/*[clinic input]
15956
os.DirEntry.is_file -> bool
15957
    defining_class: defining_class
15958
    /
15959
    *
15960
    follow_symlinks: bool = True
15961
15962
Return True if the entry is a file; cached per entry.
15963
[clinic start generated code]*/
15964
15965
static int
15966
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
15967
                         int follow_symlinks)
15968
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
15969
0
{
15970
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
15971
0
}
15972
15973
/*[clinic input]
15974
os.DirEntry.inode
15975
15976
Return inode of the entry; cached per entry.
15977
[clinic start generated code]*/
15978
15979
static PyObject *
15980
os_DirEntry_inode_impl(DirEntry *self)
15981
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
15982
0
{
15983
#ifdef MS_WINDOWS
15984
    if (!self->got_file_index) {
15985
        PyObject *unicode;
15986
        STRUCT_STAT stat;
15987
        int result;
15988
15989
        if (!PyUnicode_FSDecoder(self->path, &unicode))
15990
            return NULL;
15991
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
15992
        Py_DECREF(unicode);
15993
        result = LSTAT(path, &stat);
15994
15995
        int saved_errno = errno;
15996
        PyMem_Free(path);
15997
15998
        if (result != 0) {
15999
            errno = saved_errno;
16000
            return path_object_error(self->path);
16001
        }
16002
16003
        self->win32_file_index = stat.st_ino;
16004
        self->win32_file_index_high = stat.st_ino_high;
16005
        self->got_file_index = 1;
16006
    }
16007
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16008
#else /* POSIX */
16009
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16010
0
                  "DirEntry.d_ino is larger than unsigned long long");
16011
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16012
0
#endif
16013
0
}
16014
16015
static PyObject *
16016
DirEntry_repr(PyObject *op)
16017
0
{
16018
0
    DirEntry *self = DirEntry_CAST(op);
16019
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16020
0
}
16021
16022
/*[clinic input]
16023
os.DirEntry.__fspath__
16024
16025
Returns the path for the entry.
16026
[clinic start generated code]*/
16027
16028
static PyObject *
16029
os_DirEntry___fspath___impl(DirEntry *self)
16030
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16031
0
{
16032
0
    return Py_NewRef(self->path);
16033
0
}
16034
16035
static PyMemberDef DirEntry_members[] = {
16036
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16037
     "the entry's base filename, relative to scandir() \"path\" argument"},
16038
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16039
     "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
16040
    {NULL}
16041
};
16042
16043
#include "clinic/posixmodule.c.h"
16044
16045
static PyMethodDef DirEntry_methods[] = {
16046
    OS_DIRENTRY_IS_DIR_METHODDEF
16047
    OS_DIRENTRY_IS_FILE_METHODDEF
16048
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16049
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16050
    OS_DIRENTRY_STAT_METHODDEF
16051
    OS_DIRENTRY_INODE_METHODDEF
16052
    OS_DIRENTRY___FSPATH___METHODDEF
16053
    {"__class_getitem__",       Py_GenericAlias,
16054
    METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
16055
    {NULL}
16056
};
16057
16058
static PyType_Slot DirEntryType_slots[] = {
16059
    {Py_tp_dealloc, DirEntry_dealloc},
16060
    {Py_tp_repr, DirEntry_repr},
16061
    {Py_tp_methods, DirEntry_methods},
16062
    {Py_tp_members, DirEntry_members},
16063
    {0, 0},
16064
};
16065
16066
static PyType_Spec DirEntryType_spec = {
16067
    .name = MODNAME ".DirEntry",
16068
    .basicsize = sizeof(DirEntry),
16069
    .flags = (
16070
        Py_TPFLAGS_DEFAULT
16071
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16072
        | Py_TPFLAGS_IMMUTABLETYPE
16073
    ),
16074
    .slots = DirEntryType_slots
16075
};
16076
16077
16078
#ifdef MS_WINDOWS
16079
16080
static wchar_t *
16081
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
16082
{
16083
    Py_ssize_t path_len;
16084
    Py_ssize_t size;
16085
    wchar_t *result;
16086
    wchar_t ch;
16087
16088
    if (!path_wide) { /* Default arg: "." */
16089
        path_wide = L".";
16090
        path_len = 1;
16091
    }
16092
    else {
16093
        path_len = wcslen(path_wide);
16094
    }
16095
16096
    /* The +1's are for the path separator and the NUL */
16097
    size = path_len + 1 + wcslen(filename) + 1;
16098
    result = PyMem_New(wchar_t, size);
16099
    if (!result) {
16100
        PyErr_NoMemory();
16101
        return NULL;
16102
    }
16103
    wcscpy(result, path_wide);
16104
    if (path_len > 0) {
16105
        ch = result[path_len - 1];
16106
        if (ch != SEP && ch != ALTSEP && ch != L':')
16107
            result[path_len++] = SEP;
16108
        wcscpy(result + path_len, filename);
16109
    }
16110
    return result;
16111
}
16112
16113
static PyObject *
16114
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16115
{
16116
    DirEntry *entry;
16117
    BY_HANDLE_FILE_INFORMATION file_info;
16118
    ULONG reparse_tag;
16119
    wchar_t *joined_path;
16120
16121
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16122
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16123
    if (!entry)
16124
        return NULL;
16125
    entry->name = NULL;
16126
    entry->path = NULL;
16127
    entry->stat = NULL;
16128
    entry->lstat = NULL;
16129
    entry->got_file_index = 0;
16130
16131
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16132
    if (!entry->name)
16133
        goto error;
16134
    int return_bytes = path->wide && PyBytes_Check(path->object);
16135
    if (return_bytes) {
16136
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16137
        if (!entry->name)
16138
            goto error;
16139
    }
16140
16141
    joined_path = join_path_filenameW(path->wide, dataW->cFileName);
16142
    if (!joined_path)
16143
        goto error;
16144
16145
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16146
    PyMem_Free(joined_path);
16147
    if (!entry->path)
16148
        goto error;
16149
    if (return_bytes) {
16150
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16151
        if (!entry->path)
16152
            goto error;
16153
    }
16154
16155
    find_data_to_file_info(dataW, &file_info, &reparse_tag);
16156
    _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16157
16158
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16159
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16160
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16161
16162
    return (PyObject *)entry;
16163
16164
error:
16165
    Py_DECREF(entry);
16166
    return NULL;
16167
}
16168
16169
#else /* POSIX */
16170
16171
static char *
16172
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16173
0
{
16174
0
    Py_ssize_t path_len;
16175
0
    Py_ssize_t size;
16176
0
    char *result;
16177
16178
0
    if (!path_narrow) { /* Default arg: "." */
16179
0
        path_narrow = ".";
16180
0
        path_len = 1;
16181
0
    }
16182
0
    else {
16183
0
        path_len = strlen(path_narrow);
16184
0
    }
16185
16186
0
    if (filename_len == -1)
16187
0
        filename_len = strlen(filename);
16188
16189
    /* The +1's are for the path separator and the NUL */
16190
0
    size = path_len + 1 + filename_len + 1;
16191
0
    result = PyMem_New(char, size);
16192
0
    if (!result) {
16193
0
        PyErr_NoMemory();
16194
0
        return NULL;
16195
0
    }
16196
0
    strcpy(result, path_narrow);
16197
0
    if (path_len > 0 && result[path_len - 1] != '/')
16198
0
        result[path_len++] = '/';
16199
0
    strcpy(result + path_len, filename);
16200
0
    return result;
16201
0
}
16202
16203
static PyObject *
16204
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16205
                         Py_ssize_t name_len, ino_t d_ino
16206
#ifdef HAVE_DIRENT_D_TYPE
16207
                         , unsigned char d_type
16208
#endif
16209
                         )
16210
0
{
16211
0
    DirEntry *entry;
16212
0
    char *joined_path;
16213
16214
0
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16215
0
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16216
0
    if (!entry)
16217
0
        return NULL;
16218
0
    entry->name = NULL;
16219
0
    entry->path = NULL;
16220
0
    entry->stat = NULL;
16221
0
    entry->lstat = NULL;
16222
16223
0
    if (path->fd != -1) {
16224
0
        entry->dir_fd = path->fd;
16225
0
        joined_path = NULL;
16226
0
    }
16227
0
    else {
16228
0
        entry->dir_fd = DEFAULT_DIR_FD;
16229
0
        joined_path = join_path_filename(path->narrow, name, name_len);
16230
0
        if (!joined_path)
16231
0
            goto error;
16232
0
    }
16233
16234
0
    if (!path->narrow || !PyBytes_Check(path->object)) {
16235
0
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16236
0
        if (joined_path)
16237
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
16238
0
    }
16239
0
    else {
16240
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
16241
0
        if (joined_path)
16242
0
            entry->path = PyBytes_FromString(joined_path);
16243
0
    }
16244
0
    PyMem_Free(joined_path);
16245
0
    if (!entry->name)
16246
0
        goto error;
16247
16248
0
    if (path->fd != -1) {
16249
0
        entry->path = Py_NewRef(entry->name);
16250
0
    }
16251
0
    else if (!entry->path)
16252
0
        goto error;
16253
16254
0
#ifdef HAVE_DIRENT_D_TYPE
16255
0
    entry->d_type = d_type;
16256
0
#endif
16257
0
    entry->d_ino = d_ino;
16258
16259
0
    return (PyObject *)entry;
16260
16261
0
error:
16262
0
    Py_XDECREF(entry);
16263
0
    return NULL;
16264
0
}
16265
16266
#endif
16267
16268
16269
typedef struct {
16270
    PyObject_HEAD
16271
    path_t path;
16272
#ifdef MS_WINDOWS
16273
    HANDLE handle;
16274
    WIN32_FIND_DATAW file_data;
16275
    int first_time;
16276
#else /* POSIX */
16277
    DIR *dirp;
16278
#endif
16279
#ifdef HAVE_FDOPENDIR
16280
    int fd;
16281
#endif
16282
} ScandirIterator;
16283
16284
0
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
16285
16286
#ifdef MS_WINDOWS
16287
16288
static int
16289
ScandirIterator_is_closed(ScandirIterator *iterator)
16290
{
16291
    return iterator->handle == INVALID_HANDLE_VALUE;
16292
}
16293
16294
static void
16295
ScandirIterator_closedir(ScandirIterator *iterator)
16296
{
16297
    HANDLE handle = iterator->handle;
16298
16299
    if (handle == INVALID_HANDLE_VALUE)
16300
        return;
16301
16302
    iterator->handle = INVALID_HANDLE_VALUE;
16303
    Py_BEGIN_ALLOW_THREADS
16304
    FindClose(handle);
16305
    Py_END_ALLOW_THREADS
16306
}
16307
16308
static PyObject *
16309
ScandirIterator_iternext(PyObject *op)
16310
{
16311
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16312
    WIN32_FIND_DATAW *file_data = &iterator->file_data;
16313
    BOOL success;
16314
    PyObject *entry;
16315
16316
    /* Happens if the iterator is iterated twice, or closed explicitly */
16317
    if (iterator->handle == INVALID_HANDLE_VALUE)
16318
        return NULL;
16319
16320
    while (1) {
16321
        if (!iterator->first_time) {
16322
            Py_BEGIN_ALLOW_THREADS
16323
            success = FindNextFileW(iterator->handle, file_data);
16324
            Py_END_ALLOW_THREADS
16325
            if (!success) {
16326
                /* Error or no more files */
16327
                if (GetLastError() != ERROR_NO_MORE_FILES)
16328
                    path_error(&iterator->path);
16329
                break;
16330
            }
16331
        }
16332
        iterator->first_time = 0;
16333
16334
        /* Skip over . and .. */
16335
        if (wcscmp(file_data->cFileName, L".") != 0 &&
16336
            wcscmp(file_data->cFileName, L"..") != 0)
16337
        {
16338
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16339
            entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16340
            if (!entry)
16341
                break;
16342
            return entry;
16343
        }
16344
16345
        /* Loop till we get a non-dot directory or finish iterating */
16346
    }
16347
16348
    /* Error or no more files */
16349
    ScandirIterator_closedir(iterator);
16350
    return NULL;
16351
}
16352
16353
#else /* POSIX */
16354
16355
static int
16356
ScandirIterator_is_closed(ScandirIterator *iterator)
16357
0
{
16358
0
    return !iterator->dirp;
16359
0
}
16360
16361
static void
16362
ScandirIterator_closedir(ScandirIterator *iterator)
16363
0
{
16364
0
    DIR *dirp = iterator->dirp;
16365
16366
0
    if (!dirp)
16367
0
        return;
16368
16369
0
    iterator->dirp = NULL;
16370
0
    Py_BEGIN_ALLOW_THREADS
16371
0
#ifdef HAVE_FDOPENDIR
16372
0
    if (iterator->path.fd != -1)
16373
0
        rewinddir(dirp);
16374
0
#endif
16375
0
    closedir(dirp);
16376
0
    Py_END_ALLOW_THREADS
16377
0
    return;
16378
0
}
16379
16380
static PyObject *
16381
ScandirIterator_iternext(PyObject *op)
16382
0
{
16383
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16384
0
    struct dirent *direntp;
16385
0
    Py_ssize_t name_len;
16386
0
    int is_dot;
16387
0
    PyObject *entry;
16388
16389
    /* Happens if the iterator is iterated twice, or closed explicitly */
16390
0
    if (!iterator->dirp)
16391
0
        return NULL;
16392
16393
0
    while (1) {
16394
0
        errno = 0;
16395
0
        Py_BEGIN_ALLOW_THREADS
16396
0
        direntp = readdir(iterator->dirp);
16397
0
        Py_END_ALLOW_THREADS
16398
16399
0
        if (!direntp) {
16400
            /* Error or no more files */
16401
0
            if (errno != 0)
16402
0
                path_error(&iterator->path);
16403
0
            break;
16404
0
        }
16405
16406
        /* Skip over . and .. */
16407
0
        name_len = NAMLEN(direntp);
16408
0
        is_dot = direntp->d_name[0] == '.' &&
16409
0
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16410
0
        if (!is_dot) {
16411
0
            PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16412
0
            entry = DirEntry_from_posix_info(module,
16413
0
                                             &iterator->path, direntp->d_name,
16414
0
                                             name_len, direntp->d_ino
16415
0
#ifdef HAVE_DIRENT_D_TYPE
16416
0
                                             , direntp->d_type
16417
0
#endif
16418
0
                                            );
16419
0
            if (!entry)
16420
0
                break;
16421
0
            return entry;
16422
0
        }
16423
16424
        /* Loop till we get a non-dot directory or finish iterating */
16425
0
    }
16426
16427
    /* Error or no more files */
16428
0
    ScandirIterator_closedir(iterator);
16429
0
    return NULL;
16430
0
}
16431
16432
#endif
16433
16434
static PyObject *
16435
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
16436
0
{
16437
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16438
0
    ScandirIterator_closedir(self);
16439
0
    Py_RETURN_NONE;
16440
0
}
16441
16442
static PyObject *
16443
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
16444
0
{
16445
0
    return Py_NewRef(self);
16446
0
}
16447
16448
static PyObject *
16449
ScandirIterator_exit(PyObject *op, PyObject *Py_UNUSED(args))
16450
0
{
16451
0
    ScandirIterator *self = ScandirIterator_CAST(op);
16452
0
    ScandirIterator_closedir(self);
16453
0
    Py_RETURN_NONE;
16454
0
}
16455
16456
static void
16457
ScandirIterator_finalize(PyObject *op)
16458
0
{
16459
0
    ScandirIterator *iterator = ScandirIterator_CAST(op);
16460
    /* Save the current exception, if any. */
16461
0
    PyObject *exc = PyErr_GetRaisedException();
16462
16463
0
    if (!ScandirIterator_is_closed(iterator)) {
16464
0
        ScandirIterator_closedir(iterator);
16465
16466
0
        if (PyErr_ResourceWarning(op, 1,
16467
0
                                  "unclosed scandir iterator %R", iterator))
16468
0
        {
16469
            /* Spurious errors can appear at shutdown */
16470
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
16471
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
16472
0
                                       "scandir iterator %R", iterator);
16473
0
            }
16474
0
        }
16475
0
    }
16476
16477
0
    path_cleanup(&iterator->path);
16478
16479
    /* Restore the saved exception. */
16480
0
    PyErr_SetRaisedException(exc);
16481
0
}
16482
16483
static void
16484
ScandirIterator_dealloc(PyObject *op)
16485
0
{
16486
0
    PyTypeObject *tp = Py_TYPE(op);
16487
0
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
16488
0
        return;
16489
16490
0
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16491
0
    free_func(op);
16492
0
    Py_DECREF(tp);
16493
0
}
16494
16495
static PyMethodDef ScandirIterator_methods[] = {
16496
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
16497
    {"__exit__", ScandirIterator_exit, METH_VARARGS},
16498
    {"close", ScandirIterator_close, METH_NOARGS},
16499
    {NULL}
16500
};
16501
16502
static PyType_Slot ScandirIteratorType_slots[] = {
16503
    {Py_tp_dealloc, ScandirIterator_dealloc},
16504
    {Py_tp_finalize, ScandirIterator_finalize},
16505
    {Py_tp_iter, PyObject_SelfIter},
16506
    {Py_tp_iternext, ScandirIterator_iternext},
16507
    {Py_tp_methods, ScandirIterator_methods},
16508
    {0, 0},
16509
};
16510
16511
static PyType_Spec ScandirIteratorType_spec = {
16512
    .name = MODNAME ".ScandirIterator",
16513
    .basicsize = sizeof(ScandirIterator),
16514
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16515
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16516
    .flags = (
16517
        Py_TPFLAGS_DEFAULT
16518
        | Py_TPFLAGS_HAVE_FINALIZE
16519
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16520
        | Py_TPFLAGS_IMMUTABLETYPE
16521
    ),
16522
    .slots = ScandirIteratorType_slots
16523
};
16524
16525
/*[clinic input]
16526
os.scandir
16527
16528
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16529
16530
Return an iterator of DirEntry objects for given path.
16531
16532
path can be specified as either str, bytes, or a path-like object.  If path
16533
is bytes, the names of yielded DirEntry objects will also be bytes; in
16534
all other circumstances they will be str.
16535
16536
If path is None, uses the path='.'.
16537
[clinic start generated code]*/
16538
16539
static PyObject *
16540
os_scandir_impl(PyObject *module, path_t *path)
16541
/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16542
0
{
16543
0
    ScandirIterator *iterator;
16544
#ifdef MS_WINDOWS
16545
    wchar_t *path_strW;
16546
#else
16547
0
    const char *path_str;
16548
0
#ifdef HAVE_FDOPENDIR
16549
0
    int fd = -1;
16550
0
#endif
16551
0
#endif
16552
16553
0
    if (PySys_Audit("os.scandir", "O",
16554
0
                    path->object ? path->object : Py_None) < 0) {
16555
0
        return NULL;
16556
0
    }
16557
16558
0
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
16559
0
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
16560
0
    if (!iterator)
16561
0
        return NULL;
16562
16563
#ifdef MS_WINDOWS
16564
    iterator->handle = INVALID_HANDLE_VALUE;
16565
#else
16566
0
    iterator->dirp = NULL;
16567
0
#endif
16568
16569
    /* Move the ownership to iterator->path */
16570
0
    memcpy(&iterator->path, path, sizeof(path_t));
16571
0
    memset(path, 0, sizeof(path_t));
16572
16573
#ifdef MS_WINDOWS
16574
    iterator->first_time = 1;
16575
16576
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
16577
    if (!path_strW)
16578
        goto error;
16579
16580
    Py_BEGIN_ALLOW_THREADS
16581
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
16582
    Py_END_ALLOW_THREADS
16583
16584
    if (iterator->handle == INVALID_HANDLE_VALUE) {
16585
        path_error(&iterator->path);
16586
        PyMem_Free(path_strW);
16587
        goto error;
16588
    }
16589
    PyMem_Free(path_strW);
16590
#else /* POSIX */
16591
0
    errno = 0;
16592
0
#ifdef HAVE_FDOPENDIR
16593
0
    if (iterator->path.fd != -1) {
16594
0
      if (HAVE_FDOPENDIR_RUNTIME) {
16595
        /* closedir() closes the FD, so we duplicate it */
16596
0
        fd = _Py_dup(iterator->path.fd);
16597
0
        if (fd == -1)
16598
0
            goto error;
16599
16600
0
        Py_BEGIN_ALLOW_THREADS
16601
0
        iterator->dirp = fdopendir(fd);
16602
0
        Py_END_ALLOW_THREADS
16603
0
      } else {
16604
0
        PyErr_SetString(PyExc_TypeError,
16605
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
16606
0
        return NULL;
16607
0
      }
16608
0
    }
16609
0
    else
16610
0
#endif
16611
0
    {
16612
0
        if (iterator->path.narrow)
16613
0
            path_str = iterator->path.narrow;
16614
0
        else
16615
0
            path_str = ".";
16616
16617
0
        Py_BEGIN_ALLOW_THREADS
16618
0
        iterator->dirp = opendir(path_str);
16619
0
        Py_END_ALLOW_THREADS
16620
0
    }
16621
16622
0
    if (!iterator->dirp) {
16623
0
        path_error(&iterator->path);
16624
0
#ifdef HAVE_FDOPENDIR
16625
0
        if (fd != -1) {
16626
0
            Py_BEGIN_ALLOW_THREADS
16627
0
            close(fd);
16628
0
            Py_END_ALLOW_THREADS
16629
0
        }
16630
0
#endif
16631
0
        goto error;
16632
0
    }
16633
0
#endif
16634
16635
0
    return (PyObject *)iterator;
16636
16637
0
error:
16638
0
    Py_DECREF(iterator);
16639
0
    return NULL;
16640
0
}
16641
16642
/*
16643
    Return the file system path representation of the object.
16644
16645
    If the object is str or bytes, then allow it to pass through with
16646
    an incremented refcount. If the object defines __fspath__(), then
16647
    return the result of that method. All other types raise a TypeError.
16648
*/
16649
PyObject *
16650
PyOS_FSPath(PyObject *path)
16651
7.56k
{
16652
    /* For error message reasons, this function is manually inlined in
16653
       path_converter(). */
16654
7.56k
    PyObject *func = NULL;
16655
7.56k
    PyObject *path_repr = NULL;
16656
16657
7.56k
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
16658
7.56k
        return Py_NewRef(path);
16659
7.56k
    }
16660
16661
0
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
16662
0
    if ((NULL == func) || (func == Py_None)) {
16663
0
        return PyErr_Format(PyExc_TypeError,
16664
0
                            "expected str, bytes or os.PathLike object, "
16665
0
                            "not %.200s",
16666
0
                            _PyType_Name(Py_TYPE(path)));
16667
0
    }
16668
16669
0
    path_repr = _PyObject_CallNoArgs(func);
16670
0
    Py_DECREF(func);
16671
0
    if (NULL == path_repr) {
16672
0
        return NULL;
16673
0
    }
16674
16675
0
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
16676
0
        PyErr_Format(PyExc_TypeError,
16677
0
                     "expected %.200s.__fspath__() to return str or bytes, "
16678
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
16679
0
                     _PyType_Name(Py_TYPE(path_repr)));
16680
0
        Py_DECREF(path_repr);
16681
0
        return NULL;
16682
0
    }
16683
16684
0
    return path_repr;
16685
0
}
16686
16687
/*[clinic input]
16688
@permit_long_docstring_body
16689
os.fspath
16690
16691
    path: object
16692
16693
Return the file system path representation of the object.
16694
16695
If the object is str or bytes, then allow it to pass through as-is. If the
16696
object defines __fspath__(), then return the result of that method. All other
16697
types raise a TypeError.
16698
[clinic start generated code]*/
16699
16700
static PyObject *
16701
os_fspath_impl(PyObject *module, PyObject *path)
16702
/*[clinic end generated code: output=c3c3b78ecff2914f input=f608743e60a3211e]*/
16703
1.93k
{
16704
1.93k
    return PyOS_FSPath(path);
16705
1.93k
}
16706
16707
#ifdef HAVE_GETRANDOM_SYSCALL
16708
/*[clinic input]
16709
os.getrandom
16710
16711
    size: Py_ssize_t
16712
    flags: int=0
16713
16714
Obtain a series of random bytes.
16715
[clinic start generated code]*/
16716
16717
static PyObject *
16718
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
16719
/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
16720
0
{
16721
0
    if (size < 0) {
16722
0
        errno = EINVAL;
16723
0
        return posix_error();
16724
0
    }
16725
16726
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
16727
0
    if (writer == NULL) {
16728
0
        return NULL;
16729
0
    }
16730
0
    void *data = PyBytesWriter_GetData(writer);
16731
16732
0
    Py_ssize_t n;
16733
0
    while (1) {
16734
0
        n = syscall(SYS_getrandom, data, size, flags);
16735
0
        if (n < 0 && errno == EINTR) {
16736
0
            if (PyErr_CheckSignals() < 0) {
16737
0
                goto error;
16738
0
            }
16739
16740
            /* getrandom() was interrupted by a signal: retry */
16741
0
            continue;
16742
0
        }
16743
0
        break;
16744
0
    }
16745
16746
0
    if (n < 0) {
16747
0
        PyErr_SetFromErrno(PyExc_OSError);
16748
0
        goto error;
16749
0
    }
16750
16751
0
    return PyBytesWriter_FinishWithSize(writer, n);
16752
16753
0
error:
16754
0
    PyBytesWriter_Discard(writer);
16755
0
    return NULL;
16756
0
}
16757
#endif   /* HAVE_GETRANDOM_SYSCALL */
16758
16759
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
16760
16761
/* bpo-36085: Helper functions for managing DLL search directories
16762
 * on win32
16763
 */
16764
16765
/*[clinic input]
16766
os._add_dll_directory
16767
16768
    path: path_t
16769
16770
Add a path to the DLL search path.
16771
16772
This search path is used when resolving dependencies for imported
16773
extension modules (the module itself is resolved through sys.path),
16774
and also by ctypes.
16775
16776
Returns an opaque value that may be passed to os.remove_dll_directory
16777
to remove this directory from the search path.
16778
[clinic start generated code]*/
16779
16780
static PyObject *
16781
os__add_dll_directory_impl(PyObject *module, path_t *path)
16782
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
16783
{
16784
    DLL_DIRECTORY_COOKIE cookie = 0;
16785
    DWORD err = 0;
16786
16787
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
16788
        return NULL;
16789
    }
16790
16791
    Py_BEGIN_ALLOW_THREADS
16792
    if (!(cookie = AddDllDirectory(path->wide))) {
16793
        err = GetLastError();
16794
    }
16795
    Py_END_ALLOW_THREADS
16796
16797
    if (err) {
16798
        return win32_error_object_err("add_dll_directory",
16799
                                      path->object, err);
16800
    }
16801
16802
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
16803
}
16804
16805
/*[clinic input]
16806
os._remove_dll_directory
16807
16808
    cookie: object
16809
16810
Removes a path from the DLL search path.
16811
16812
The parameter is an opaque value that was returned from
16813
os.add_dll_directory. You can only remove directories that you added
16814
yourself.
16815
[clinic start generated code]*/
16816
16817
static PyObject *
16818
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
16819
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
16820
{
16821
    DLL_DIRECTORY_COOKIE cookieValue;
16822
    DWORD err = 0;
16823
16824
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
16825
        PyErr_SetString(PyExc_TypeError,
16826
            "Provided cookie was not returned from os.add_dll_directory");
16827
        return NULL;
16828
    }
16829
16830
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
16831
        cookie, "DLL directory cookie");
16832
16833
    Py_BEGIN_ALLOW_THREADS
16834
    if (!RemoveDllDirectory(cookieValue)) {
16835
        err = GetLastError();
16836
    }
16837
    Py_END_ALLOW_THREADS
16838
16839
    if (err) {
16840
        return win32_error_object_err("remove_dll_directory",
16841
                                      NULL, err);
16842
    }
16843
16844
    if (PyCapsule_SetName(cookie, NULL)) {
16845
        return NULL;
16846
    }
16847
16848
    Py_RETURN_NONE;
16849
}
16850
16851
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
16852
16853
16854
/* Only check if WIFEXITED is available: expect that it comes
16855
   with WEXITSTATUS, WIFSIGNALED, etc.
16856
16857
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
16858
   subprocess can safely call it during late Python finalization without
16859
   risking that used os attributes were set to None by finalize_modules(). */
16860
#if defined(WIFEXITED) || defined(MS_WINDOWS)
16861
/*[clinic input]
16862
os.waitstatus_to_exitcode
16863
16864
    status as status_obj: object
16865
16866
Convert a wait status to an exit code.
16867
16868
On Unix:
16869
16870
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
16871
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
16872
* Otherwise, raise a ValueError.
16873
16874
On Windows, return status shifted right by 8 bits.
16875
16876
On Unix, if the process is being traced or if waitpid() was called with
16877
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
16878
This function must not be called if WIFSTOPPED(status) is true.
16879
[clinic start generated code]*/
16880
16881
static PyObject *
16882
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
16883
/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
16884
0
{
16885
0
#ifndef MS_WINDOWS
16886
0
    int status = PyLong_AsInt(status_obj);
16887
0
    if (status == -1 && PyErr_Occurred()) {
16888
0
        return NULL;
16889
0
    }
16890
16891
0
    WAIT_TYPE wait_status;
16892
0
    WAIT_STATUS_INT(wait_status) = status;
16893
0
    int exitcode;
16894
0
    if (WIFEXITED(wait_status)) {
16895
0
        exitcode = WEXITSTATUS(wait_status);
16896
        /* Sanity check to provide warranty on the function behavior.
16897
           It should not occur in practice */
16898
0
        if (exitcode < 0) {
16899
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
16900
0
            return NULL;
16901
0
        }
16902
0
    }
16903
0
    else if (WIFSIGNALED(wait_status)) {
16904
0
        int signum = WTERMSIG(wait_status);
16905
        /* Sanity check to provide warranty on the function behavior.
16906
           It should not occurs in practice */
16907
0
        if (signum <= 0) {
16908
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
16909
0
            return NULL;
16910
0
        }
16911
0
        exitcode = -signum;
16912
0
    } else if (WIFSTOPPED(wait_status)) {
16913
        /* Status only received if the process is being traced
16914
           or if waitpid() was called with WUNTRACED option. */
16915
0
        int signum = WSTOPSIG(wait_status);
16916
0
        PyErr_Format(PyExc_ValueError,
16917
0
                     "process stopped by delivery of signal %i",
16918
0
                     signum);
16919
0
        return NULL;
16920
0
    }
16921
0
    else {
16922
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
16923
0
        return NULL;
16924
0
    }
16925
0
    return PyLong_FromLong(exitcode);
16926
#else
16927
    /* Windows implementation: see os.waitpid() implementation
16928
       which uses _cwait(). */
16929
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
16930
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
16931
        return NULL;
16932
    }
16933
16934
    unsigned long long exitcode = (status >> 8);
16935
    /* ExitProcess() accepts an UINT type:
16936
       reject exit code which doesn't fit in an UINT */
16937
    if (exitcode > UINT_MAX) {
16938
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
16939
        return NULL;
16940
    }
16941
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
16942
#endif
16943
0
}
16944
#endif
16945
16946
#if defined(MS_WINDOWS)
16947
/*[clinic input]
16948
os._supports_virtual_terminal
16949
16950
Checks if virtual terminal is supported in windows
16951
[clinic start generated code]*/
16952
16953
static PyObject *
16954
os__supports_virtual_terminal_impl(PyObject *module)
16955
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
16956
{
16957
#ifdef HAVE_WINDOWS_CONSOLE_IO
16958
    DWORD mode = 0;
16959
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
16960
    if (!GetConsoleMode(handle, &mode)) {
16961
        Py_RETURN_FALSE;
16962
    }
16963
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
16964
#else
16965
    Py_RETURN_FALSE;
16966
#endif /* HAVE_WINDOWS_CONSOLE_IO */
16967
}
16968
#endif
16969
16970
/*[clinic input]
16971
os._inputhook
16972
16973
Calls PyOS_CallInputHook droppong the GIL first
16974
[clinic start generated code]*/
16975
16976
static PyObject *
16977
os__inputhook_impl(PyObject *module)
16978
/*[clinic end generated code: output=525aca4ef3c6149f input=fc531701930d064f]*/
16979
0
{
16980
0
     int result = 0;
16981
0
     if (PyOS_InputHook) {
16982
0
         Py_BEGIN_ALLOW_THREADS;
16983
0
         result = PyOS_InputHook();
16984
0
         Py_END_ALLOW_THREADS;
16985
0
     }
16986
0
     return PyLong_FromLong(result);
16987
0
}
16988
16989
/*[clinic input]
16990
os._is_inputhook_installed
16991
16992
Checks if PyOS_CallInputHook is set
16993
[clinic start generated code]*/
16994
16995
static PyObject *
16996
os__is_inputhook_installed_impl(PyObject *module)
16997
/*[clinic end generated code: output=3b3eab4f672c689a input=ff177c9938dd76d8]*/
16998
0
{
16999
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17000
0
}
17001
17002
/*[clinic input]
17003
os._create_environ
17004
17005
Create the environment dictionary.
17006
[clinic start generated code]*/
17007
17008
static PyObject *
17009
os__create_environ_impl(PyObject *module)
17010
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17011
0
{
17012
0
    return convertenviron();
17013
0
}
17014
17015
17016
#ifdef __EMSCRIPTEN__
17017
/*[clinic input]
17018
os._emscripten_debugger
17019
17020
Create a breakpoint for the JavaScript debugger. Emscripten only.
17021
[clinic start generated code]*/
17022
17023
static PyObject *
17024
os__emscripten_debugger_impl(PyObject *module)
17025
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17026
{
17027
    emscripten_debugger();
17028
    Py_RETURN_NONE;
17029
}
17030
17031
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17032
    console.warn(UTF8ToString(arg));
17033
});
17034
17035
/*[clinic input]
17036
os._emscripten_log
17037
   arg: str
17038
17039
Log something to the JS console. Emscripten only.
17040
[clinic start generated code]*/
17041
17042
static PyObject *
17043
os__emscripten_log_impl(PyObject *module, const char *arg)
17044
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17045
{
17046
    emscripten_log_impl_js(arg);
17047
    Py_RETURN_NONE;
17048
}
17049
#endif /* __EMSCRIPTEN__ */
17050
17051
17052
static PyMethodDef posix_methods[] = {
17053
    OS_STAT_METHODDEF
17054
    OS_ACCESS_METHODDEF
17055
    OS_TTYNAME_METHODDEF
17056
    OS_CHDIR_METHODDEF
17057
    OS_CHFLAGS_METHODDEF
17058
    OS_CHMOD_METHODDEF
17059
    OS_FCHMOD_METHODDEF
17060
    OS_LCHMOD_METHODDEF
17061
    OS_CHOWN_METHODDEF
17062
    OS_FCHOWN_METHODDEF
17063
    OS_LCHOWN_METHODDEF
17064
    OS_LCHFLAGS_METHODDEF
17065
    OS_CHROOT_METHODDEF
17066
    OS_CTERMID_METHODDEF
17067
    OS_GETCWD_METHODDEF
17068
    OS_GETCWDB_METHODDEF
17069
    OS_LINK_METHODDEF
17070
    OS_LISTDIR_METHODDEF
17071
    OS_LISTDRIVES_METHODDEF
17072
    OS_LISTMOUNTS_METHODDEF
17073
    OS_LISTVOLUMES_METHODDEF
17074
    OS_LSTAT_METHODDEF
17075
    OS_MKDIR_METHODDEF
17076
    OS_NICE_METHODDEF
17077
    OS_GETPRIORITY_METHODDEF
17078
    OS_SETPRIORITY_METHODDEF
17079
    OS_POSIX_SPAWN_METHODDEF
17080
    OS_POSIX_SPAWNP_METHODDEF
17081
    OS_READLINK_METHODDEF
17082
    OS_COPY_FILE_RANGE_METHODDEF
17083
    OS_SPLICE_METHODDEF
17084
    OS_RENAME_METHODDEF
17085
    OS_REPLACE_METHODDEF
17086
    OS_RMDIR_METHODDEF
17087
    OS_SYMLINK_METHODDEF
17088
    OS_SYSTEM_METHODDEF
17089
    OS_UMASK_METHODDEF
17090
    OS_UNAME_METHODDEF
17091
    OS_UNLINK_METHODDEF
17092
    OS_REMOVE_METHODDEF
17093
    OS_UTIME_METHODDEF
17094
    OS_TIMES_METHODDEF
17095
    OS__EXIT_METHODDEF
17096
    OS__FCOPYFILE_METHODDEF
17097
    OS_EXECV_METHODDEF
17098
    OS_EXECVE_METHODDEF
17099
    OS_SPAWNV_METHODDEF
17100
    OS_SPAWNVE_METHODDEF
17101
    OS_FORK1_METHODDEF
17102
    OS_FORK_METHODDEF
17103
    OS_REGISTER_AT_FORK_METHODDEF
17104
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
17105
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
17106
    OS_SCHED_GETPARAM_METHODDEF
17107
    OS_SCHED_GETSCHEDULER_METHODDEF
17108
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
17109
    OS_SCHED_SETPARAM_METHODDEF
17110
    OS_SCHED_SETSCHEDULER_METHODDEF
17111
    OS_SCHED_YIELD_METHODDEF
17112
    OS_SCHED_SETAFFINITY_METHODDEF
17113
    OS_SCHED_GETAFFINITY_METHODDEF
17114
    OS_POSIX_OPENPT_METHODDEF
17115
    OS_GRANTPT_METHODDEF
17116
    OS_UNLOCKPT_METHODDEF
17117
    OS_PTSNAME_METHODDEF
17118
    OS_OPENPTY_METHODDEF
17119
    OS_LOGIN_TTY_METHODDEF
17120
    OS_FORKPTY_METHODDEF
17121
    OS_GETEGID_METHODDEF
17122
    OS_GETEUID_METHODDEF
17123
    OS_GETGID_METHODDEF
17124
    OS_GETGROUPLIST_METHODDEF
17125
    OS_GETGROUPS_METHODDEF
17126
    OS_GETPID_METHODDEF
17127
    OS_GETPGRP_METHODDEF
17128
    OS_GETPPID_METHODDEF
17129
    OS_GETUID_METHODDEF
17130
    OS_GETLOGIN_METHODDEF
17131
    OS_KILL_METHODDEF
17132
    OS_KILLPG_METHODDEF
17133
    OS_PLOCK_METHODDEF
17134
    OS_STARTFILE_METHODDEF
17135
    OS_SETUID_METHODDEF
17136
    OS_SETEUID_METHODDEF
17137
    OS_SETREUID_METHODDEF
17138
    OS_SETGID_METHODDEF
17139
    OS_SETEGID_METHODDEF
17140
    OS_SETREGID_METHODDEF
17141
    OS_SETGROUPS_METHODDEF
17142
    OS_INITGROUPS_METHODDEF
17143
    OS_GETPGID_METHODDEF
17144
    OS_SETPGRP_METHODDEF
17145
    OS_WAIT_METHODDEF
17146
    OS_WAIT3_METHODDEF
17147
    OS_WAIT4_METHODDEF
17148
    OS_WAITID_METHODDEF
17149
    OS_WAITPID_METHODDEF
17150
    OS_PIDFD_OPEN_METHODDEF
17151
    OS_GETSID_METHODDEF
17152
    OS_SETSID_METHODDEF
17153
    OS_SETPGID_METHODDEF
17154
    OS_TCGETPGRP_METHODDEF
17155
    OS_TCSETPGRP_METHODDEF
17156
    OS_OPEN_METHODDEF
17157
    OS_CLOSE_METHODDEF
17158
    OS_CLOSERANGE_METHODDEF
17159
    OS_DEVICE_ENCODING_METHODDEF
17160
    OS_DUP_METHODDEF
17161
    OS_DUP2_METHODDEF
17162
    OS_LOCKF_METHODDEF
17163
    OS_LSEEK_METHODDEF
17164
    OS_READ_METHODDEF
17165
    OS_READINTO_METHODDEF
17166
    OS_READV_METHODDEF
17167
    OS_PREAD_METHODDEF
17168
    OS_PREADV_METHODDEF
17169
    OS_WRITE_METHODDEF
17170
    OS_WRITEV_METHODDEF
17171
    OS_PWRITE_METHODDEF
17172
    OS_PWRITEV_METHODDEF
17173
    OS_SENDFILE_METHODDEF
17174
    OS_FSTAT_METHODDEF
17175
    OS_ISATTY_METHODDEF
17176
    OS_PIPE_METHODDEF
17177
    OS_PIPE2_METHODDEF
17178
    OS_MKFIFO_METHODDEF
17179
    OS_MKNOD_METHODDEF
17180
    OS_MAJOR_METHODDEF
17181
    OS_MINOR_METHODDEF
17182
    OS_MAKEDEV_METHODDEF
17183
    OS_FTRUNCATE_METHODDEF
17184
    OS_TRUNCATE_METHODDEF
17185
    OS_POSIX_FALLOCATE_METHODDEF
17186
    OS_POSIX_FADVISE_METHODDEF
17187
    OS_PUTENV_METHODDEF
17188
    OS_UNSETENV_METHODDEF
17189
    OS__CLEARENV_METHODDEF
17190
    OS_STRERROR_METHODDEF
17191
    OS_FCHDIR_METHODDEF
17192
    OS_FSYNC_METHODDEF
17193
    OS_SYNC_METHODDEF
17194
    OS_FDATASYNC_METHODDEF
17195
    OS_WCOREDUMP_METHODDEF
17196
    OS_WIFCONTINUED_METHODDEF
17197
    OS_WIFSTOPPED_METHODDEF
17198
    OS_WIFSIGNALED_METHODDEF
17199
    OS_WIFEXITED_METHODDEF
17200
    OS_WEXITSTATUS_METHODDEF
17201
    OS_WTERMSIG_METHODDEF
17202
    OS_WSTOPSIG_METHODDEF
17203
    OS_FSTATVFS_METHODDEF
17204
    OS_STATVFS_METHODDEF
17205
    OS_CONFSTR_METHODDEF
17206
    OS_SYSCONF_METHODDEF
17207
    OS_FPATHCONF_METHODDEF
17208
    OS_PATHCONF_METHODDEF
17209
    OS_ABORT_METHODDEF
17210
    OS__GETFULLPATHNAME_METHODDEF
17211
    OS__GETDISKUSAGE_METHODDEF
17212
    OS__GETFINALPATHNAME_METHODDEF
17213
    OS__FINDFIRSTFILE_METHODDEF
17214
    OS__GETVOLUMEPATHNAME_METHODDEF
17215
    OS__PATH_SPLITROOT_METHODDEF
17216
    OS__PATH_SPLITROOT_EX_METHODDEF
17217
    OS__PATH_NORMPATH_METHODDEF
17218
    OS_GETLOADAVG_METHODDEF
17219
    OS_URANDOM_METHODDEF
17220
    OS_SETRESUID_METHODDEF
17221
    OS_SETRESGID_METHODDEF
17222
    OS_GETRESUID_METHODDEF
17223
    OS_GETRESGID_METHODDEF
17224
17225
    OS_GETXATTR_METHODDEF
17226
    OS_SETXATTR_METHODDEF
17227
    OS_REMOVEXATTR_METHODDEF
17228
    OS_LISTXATTR_METHODDEF
17229
17230
    OS_GET_TERMINAL_SIZE_METHODDEF
17231
    OS_CPU_COUNT_METHODDEF
17232
    OS_GET_INHERITABLE_METHODDEF
17233
    OS_SET_INHERITABLE_METHODDEF
17234
    OS_GET_HANDLE_INHERITABLE_METHODDEF
17235
    OS_SET_HANDLE_INHERITABLE_METHODDEF
17236
    OS_GET_BLOCKING_METHODDEF
17237
    OS_SET_BLOCKING_METHODDEF
17238
    OS_SCANDIR_METHODDEF
17239
    OS_FSPATH_METHODDEF
17240
    OS_GETRANDOM_METHODDEF
17241
    OS_MEMFD_CREATE_METHODDEF
17242
    OS_EVENTFD_METHODDEF
17243
    OS_EVENTFD_READ_METHODDEF
17244
    OS_EVENTFD_WRITE_METHODDEF
17245
    OS__ADD_DLL_DIRECTORY_METHODDEF
17246
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
17247
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17248
    OS_SETNS_METHODDEF
17249
    OS_UNSHARE_METHODDEF
17250
    OS_TIMERFD_CREATE_METHODDEF
17251
    OS_TIMERFD_SETTIME_METHODDEF
17252
    OS_TIMERFD_SETTIME_NS_METHODDEF
17253
    OS_TIMERFD_GETTIME_METHODDEF
17254
    OS_TIMERFD_GETTIME_NS_METHODDEF
17255
17256
    OS__PATH_ISDEVDRIVE_METHODDEF
17257
    OS__PATH_ISDIR_METHODDEF
17258
    OS__PATH_ISFILE_METHODDEF
17259
    OS__PATH_ISLINK_METHODDEF
17260
    OS__PATH_ISJUNCTION_METHODDEF
17261
    OS__PATH_EXISTS_METHODDEF
17262
    OS__PATH_LEXISTS_METHODDEF
17263
17264
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17265
    OS__INPUTHOOK_METHODDEF
17266
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17267
    OS__CREATE_ENVIRON_METHODDEF
17268
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
17269
    OS__EMSCRIPTEN_LOG_METHODDEF
17270
    {NULL,              NULL}            /* Sentinel */
17271
};
17272
17273
static int
17274
all_ins(PyObject *m)
17275
22
{
17276
22
#ifdef F_OK
17277
22
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
17278
22
#endif
17279
22
#ifdef R_OK
17280
22
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
17281
22
#endif
17282
22
#ifdef W_OK
17283
22
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
17284
22
#endif
17285
22
#ifdef X_OK
17286
22
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
17287
22
#endif
17288
22
#ifdef NGROUPS_MAX
17289
22
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17290
22
#endif
17291
22
#ifdef TMP_MAX
17292
22
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17293
22
#endif
17294
22
#ifdef WCONTINUED
17295
22
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17296
22
#endif
17297
22
#ifdef WNOHANG
17298
22
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17299
22
#endif
17300
22
#ifdef WUNTRACED
17301
22
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17302
22
#endif
17303
22
#ifdef O_RDONLY
17304
22
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17305
22
#endif
17306
22
#ifdef O_WRONLY
17307
22
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17308
22
#endif
17309
22
#ifdef O_RDWR
17310
22
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17311
22
#endif
17312
22
#ifdef O_NDELAY
17313
22
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17314
22
#endif
17315
22
#ifdef O_NONBLOCK
17316
22
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17317
22
#endif
17318
22
#ifdef O_APPEND
17319
22
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17320
22
#endif
17321
22
#ifdef O_DSYNC
17322
22
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17323
22
#endif
17324
22
#ifdef O_RSYNC
17325
22
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17326
22
#endif
17327
22
#ifdef O_SYNC
17328
22
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17329
22
#endif
17330
22
#ifdef O_NOCTTY
17331
22
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17332
22
#endif
17333
22
#ifdef O_CREAT
17334
22
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17335
22
#endif
17336
22
#ifdef O_EXCL
17337
22
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17338
22
#endif
17339
22
#ifdef O_TRUNC
17340
22
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17341
22
#endif
17342
#ifdef O_BINARY
17343
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17344
#endif
17345
#ifdef O_TEXT
17346
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17347
#endif
17348
#ifdef O_XATTR
17349
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17350
#endif
17351
22
#ifdef O_LARGEFILE
17352
22
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17353
22
#endif
17354
22
#ifndef __GNU__
17355
#ifdef O_SHLOCK
17356
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17357
#endif
17358
#ifdef O_EXLOCK
17359
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17360
#endif
17361
22
#endif
17362
#ifdef O_EXEC
17363
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17364
#endif
17365
#ifdef O_SEARCH
17366
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17367
#endif
17368
22
#ifdef O_PATH
17369
22
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17370
22
#endif
17371
#ifdef O_TTY_INIT
17372
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17373
#endif
17374
22
#ifdef O_TMPFILE
17375
22
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17376
22
#endif
17377
22
#ifdef PRIO_PROCESS
17378
22
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17379
22
#endif
17380
22
#ifdef PRIO_PGRP
17381
22
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17382
22
#endif
17383
22
#ifdef PRIO_USER
17384
22
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17385
22
#endif
17386
#ifdef PRIO_DARWIN_THREAD
17387
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17388
#endif
17389
#ifdef PRIO_DARWIN_PROCESS
17390
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17391
#endif
17392
#ifdef PRIO_DARWIN_BG
17393
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17394
#endif
17395
#ifdef PRIO_DARWIN_NONUI
17396
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17397
#endif
17398
22
#ifdef O_CLOEXEC
17399
22
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17400
22
#endif
17401
22
#ifdef O_ACCMODE
17402
22
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17403
22
#endif
17404
#ifdef O_EVTONLY
17405
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17406
#endif
17407
22
#ifdef O_FSYNC
17408
22
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17409
22
#endif
17410
#ifdef O_SYMLINK
17411
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17412
#endif
17413
17414
22
#ifdef SEEK_HOLE
17415
22
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17416
22
#endif
17417
22
#ifdef SEEK_DATA
17418
22
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17419
22
#endif
17420
17421
/* MS Windows */
17422
#ifdef O_NOINHERIT
17423
    /* Don't inherit in child processes. */
17424
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17425
#endif
17426
#ifdef _O_SHORT_LIVED
17427
    /* Optimize for short life (keep in memory). */
17428
    /* MS forgot to define this one with a non-underscore form too. */
17429
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17430
#endif
17431
#ifdef O_TEMPORARY
17432
    /* Automatically delete when last handle is closed. */
17433
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17434
#endif
17435
#ifdef O_RANDOM
17436
    /* Optimize for random access. */
17437
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17438
#endif
17439
#ifdef O_SEQUENTIAL
17440
    /* Optimize for sequential access. */
17441
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17442
#endif
17443
17444
/* GNU extensions. */
17445
22
#ifdef O_ASYNC
17446
    /* Send a SIGIO signal whenever input or output
17447
       becomes available on file descriptor */
17448
22
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17449
22
#endif
17450
22
#ifdef O_DIRECT
17451
    /* Direct disk access. */
17452
22
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17453
22
#endif
17454
22
#ifdef O_DIRECTORY
17455
    /* Must be a directory.      */
17456
22
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17457
22
#endif
17458
22
#ifdef O_NOFOLLOW
17459
    /* Do not follow links.      */
17460
22
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17461
22
#endif
17462
#ifdef O_NOFOLLOW_ANY
17463
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17464
#endif
17465
#ifdef O_NOLINKS
17466
    /* Fails if link count of the named file is greater than 1 */
17467
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17468
#endif
17469
22
#ifdef O_NOATIME
17470
    /* Do not update the access time. */
17471
22
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17472
22
#endif
17473
17474
    /* These come from sysexits.h */
17475
22
#ifdef EX_OK
17476
22
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17477
22
#endif /* EX_OK */
17478
22
#ifdef EX_USAGE
17479
22
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17480
22
#endif /* EX_USAGE */
17481
22
#ifdef EX_DATAERR
17482
22
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17483
22
#endif /* EX_DATAERR */
17484
22
#ifdef EX_NOINPUT
17485
22
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17486
22
#endif /* EX_NOINPUT */
17487
22
#ifdef EX_NOUSER
17488
22
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17489
22
#endif /* EX_NOUSER */
17490
22
#ifdef EX_NOHOST
17491
22
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17492
22
#endif /* EX_NOHOST */
17493
22
#ifdef EX_UNAVAILABLE
17494
22
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17495
22
#endif /* EX_UNAVAILABLE */
17496
22
#ifdef EX_SOFTWARE
17497
22
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17498
22
#endif /* EX_SOFTWARE */
17499
22
#ifdef EX_OSERR
17500
22
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17501
22
#endif /* EX_OSERR */
17502
22
#ifdef EX_OSFILE
17503
22
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17504
22
#endif /* EX_OSFILE */
17505
22
#ifdef EX_CANTCREAT
17506
22
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17507
22
#endif /* EX_CANTCREAT */
17508
22
#ifdef EX_IOERR
17509
22
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17510
22
#endif /* EX_IOERR */
17511
22
#ifdef EX_TEMPFAIL
17512
22
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17513
22
#endif /* EX_TEMPFAIL */
17514
22
#ifdef EX_PROTOCOL
17515
22
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17516
22
#endif /* EX_PROTOCOL */
17517
22
#ifdef EX_NOPERM
17518
22
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17519
22
#endif /* EX_NOPERM */
17520
22
#ifdef EX_CONFIG
17521
22
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17522
22
#endif /* EX_CONFIG */
17523
#ifdef EX_NOTFOUND
17524
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17525
#endif /* EX_NOTFOUND */
17526
17527
    /* statvfs */
17528
22
#ifdef ST_RDONLY
17529
22
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17530
22
#endif /* ST_RDONLY */
17531
22
#ifdef ST_NOSUID
17532
22
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17533
22
#endif /* ST_NOSUID */
17534
17535
       /* GNU extensions */
17536
22
#ifdef ST_NODEV
17537
22
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17538
22
#endif /* ST_NODEV */
17539
22
#ifdef ST_NOEXEC
17540
22
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17541
22
#endif /* ST_NOEXEC */
17542
22
#ifdef ST_SYNCHRONOUS
17543
22
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17544
22
#endif /* ST_SYNCHRONOUS */
17545
22
#ifdef ST_MANDLOCK
17546
22
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17547
22
#endif /* ST_MANDLOCK */
17548
22
#ifdef ST_WRITE
17549
22
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17550
22
#endif /* ST_WRITE */
17551
22
#ifdef ST_APPEND
17552
22
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
17553
22
#endif /* ST_APPEND */
17554
22
#ifdef ST_NOATIME
17555
22
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
17556
22
#endif /* ST_NOATIME */
17557
22
#ifdef ST_NODIRATIME
17558
22
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
17559
22
#endif /* ST_NODIRATIME */
17560
22
#ifdef ST_RELATIME
17561
22
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
17562
22
#endif /* ST_RELATIME */
17563
17564
    /* FreeBSD sendfile() constants */
17565
#ifdef SF_NODISKIO
17566
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
17567
#endif
17568
    /* is obsolete since the 11.x release */
17569
#ifdef SF_MNOWAIT
17570
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
17571
#endif
17572
#ifdef SF_SYNC
17573
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
17574
#endif
17575
#ifdef SF_NOCACHE
17576
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
17577
#endif
17578
17579
22
#ifdef TFD_NONBLOCK
17580
22
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
17581
22
#endif
17582
22
#ifdef TFD_CLOEXEC
17583
22
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
17584
22
#endif
17585
22
#ifdef TFD_TIMER_ABSTIME
17586
22
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
17587
22
#endif
17588
22
#ifdef TFD_TIMER_CANCEL_ON_SET
17589
22
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
17590
22
#endif
17591
17592
    /* constants for posix_fadvise */
17593
22
#ifdef POSIX_FADV_NORMAL
17594
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
17595
22
#endif
17596
22
#ifdef POSIX_FADV_SEQUENTIAL
17597
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
17598
22
#endif
17599
22
#ifdef POSIX_FADV_RANDOM
17600
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
17601
22
#endif
17602
22
#ifdef POSIX_FADV_NOREUSE
17603
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
17604
22
#endif
17605
22
#ifdef POSIX_FADV_WILLNEED
17606
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
17607
22
#endif
17608
22
#ifdef POSIX_FADV_DONTNEED
17609
22
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
17610
22
#endif
17611
17612
    /* constants for waitid */
17613
22
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
17614
22
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
17615
22
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
17616
22
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
17617
22
#ifdef P_PIDFD
17618
22
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
17619
22
#endif
17620
#ifdef PIDFD_NONBLOCK
17621
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
17622
#endif
17623
22
#endif
17624
22
#ifdef WEXITED
17625
22
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
17626
22
#endif
17627
22
#ifdef WNOWAIT
17628
22
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
17629
22
#endif
17630
22
#ifdef WSTOPPED
17631
22
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
17632
22
#endif
17633
22
#ifdef CLD_EXITED
17634
22
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
17635
22
#endif
17636
22
#ifdef CLD_KILLED
17637
22
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
17638
22
#endif
17639
22
#ifdef CLD_DUMPED
17640
22
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
17641
22
#endif
17642
22
#ifdef CLD_TRAPPED
17643
22
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
17644
22
#endif
17645
22
#ifdef CLD_STOPPED
17646
22
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
17647
22
#endif
17648
22
#ifdef CLD_CONTINUED
17649
22
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
17650
22
#endif
17651
17652
    /* constants for lockf */
17653
22
#ifdef F_LOCK
17654
22
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
17655
22
#endif
17656
22
#ifdef F_TLOCK
17657
22
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
17658
22
#endif
17659
22
#ifdef F_ULOCK
17660
22
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
17661
22
#endif
17662
22
#ifdef F_TEST
17663
22
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
17664
22
#endif
17665
17666
22
#ifdef RWF_DSYNC
17667
22
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
17668
22
#endif
17669
22
#ifdef RWF_HIPRI
17670
22
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
17671
22
#endif
17672
22
#ifdef RWF_SYNC
17673
22
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
17674
22
#endif
17675
22
#ifdef RWF_NOWAIT
17676
22
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
17677
22
#endif
17678
#ifdef RWF_DONTCACHE
17679
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
17680
#endif
17681
22
#ifdef RWF_APPEND
17682
22
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
17683
22
#endif
17684
17685
/* constants for splice */
17686
22
#if defined(HAVE_SPLICE) && defined(__linux__)
17687
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
17688
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
17689
22
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
17690
22
#endif
17691
17692
/* constants for posix_spawn */
17693
22
#ifdef HAVE_POSIX_SPAWN
17694
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
17695
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
17696
22
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
17697
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
17698
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
17699
#endif
17700
22
#endif
17701
17702
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
17703
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
17704
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
17705
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
17706
#endif
17707
#ifdef HAVE_SPAWNV
17708
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
17709
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
17710
#endif
17711
17712
22
#ifdef HAVE_SCHED_H
17713
22
#ifdef SCHED_OTHER
17714
22
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
17715
22
#endif
17716
22
#ifdef SCHED_DEADLINE
17717
22
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
17718
22
#endif
17719
22
#ifdef SCHED_FIFO
17720
22
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
17721
22
#endif
17722
22
#ifdef SCHED_NORMAL
17723
22
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
17724
22
#endif
17725
22
#ifdef SCHED_RR
17726
22
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
17727
22
#endif
17728
#ifdef SCHED_SPORADIC
17729
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
17730
#endif
17731
22
#ifdef SCHED_BATCH
17732
22
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
17733
22
#endif
17734
22
#ifdef SCHED_IDLE
17735
22
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
17736
22
#endif
17737
22
#ifdef SCHED_RESET_ON_FORK
17738
22
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
17739
22
#endif
17740
#ifdef SCHED_SYS
17741
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
17742
#endif
17743
#ifdef SCHED_IA
17744
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
17745
#endif
17746
#ifdef SCHED_FSS
17747
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
17748
#endif
17749
#ifdef SCHED_FX
17750
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
17751
#endif
17752
17753
/* constants for namespaces */
17754
22
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
17755
22
#ifdef CLONE_FS
17756
22
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
17757
22
#endif
17758
22
#ifdef CLONE_FILES
17759
22
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
17760
22
#endif
17761
22
#ifdef CLONE_NEWNS
17762
22
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
17763
22
#endif
17764
22
#ifdef CLONE_NEWCGROUP
17765
22
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
17766
22
#endif
17767
22
#ifdef CLONE_NEWUTS
17768
22
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
17769
22
#endif
17770
22
#ifdef CLONE_NEWIPC
17771
22
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
17772
22
#endif
17773
22
#ifdef CLONE_NEWUSER
17774
22
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
17775
22
#endif
17776
22
#ifdef CLONE_NEWPID
17777
22
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
17778
22
#endif
17779
22
#ifdef CLONE_NEWNET
17780
22
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
17781
22
#endif
17782
#ifdef CLONE_NEWTIME
17783
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
17784
#endif
17785
22
#ifdef CLONE_SYSVSEM
17786
22
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
17787
22
#endif
17788
22
#ifdef CLONE_THREAD
17789
22
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
17790
22
#endif
17791
22
#ifdef CLONE_SIGHAND
17792
22
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
17793
22
#endif
17794
22
#ifdef CLONE_VM
17795
22
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
17796
22
#endif
17797
22
#endif
17798
17799
22
#endif
17800
17801
22
#ifdef USE_XATTRS
17802
22
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
17803
22
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
17804
22
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
17805
22
#endif
17806
17807
22
#if HAVE_DECL_RTLD_LAZY
17808
22
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
17809
22
#endif
17810
22
#if HAVE_DECL_RTLD_NOW
17811
22
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
17812
22
#endif
17813
22
#if HAVE_DECL_RTLD_GLOBAL
17814
22
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
17815
22
#endif
17816
22
#if HAVE_DECL_RTLD_LOCAL
17817
22
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
17818
22
#endif
17819
22
#if HAVE_DECL_RTLD_NODELETE
17820
22
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
17821
22
#endif
17822
22
#if HAVE_DECL_RTLD_NOLOAD
17823
22
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
17824
22
#endif
17825
22
#if HAVE_DECL_RTLD_DEEPBIND
17826
22
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
17827
22
#endif
17828
#if HAVE_DECL_RTLD_MEMBER
17829
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
17830
#endif
17831
17832
22
#ifdef HAVE_GETRANDOM_SYSCALL
17833
22
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
17834
22
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
17835
22
#endif
17836
22
#ifdef HAVE_MEMFD_CREATE
17837
22
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
17838
22
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
17839
22
#ifdef MFD_HUGETLB
17840
22
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
17841
22
#endif
17842
22
#ifdef MFD_HUGE_SHIFT
17843
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
17844
22
#endif
17845
22
#ifdef MFD_HUGE_MASK
17846
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
17847
22
#endif
17848
22
#ifdef MFD_HUGE_64KB
17849
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
17850
22
#endif
17851
22
#ifdef MFD_HUGE_512KB
17852
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
17853
22
#endif
17854
22
#ifdef MFD_HUGE_1MB
17855
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
17856
22
#endif
17857
22
#ifdef MFD_HUGE_2MB
17858
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
17859
22
#endif
17860
22
#ifdef MFD_HUGE_8MB
17861
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
17862
22
#endif
17863
22
#ifdef MFD_HUGE_16MB
17864
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
17865
22
#endif
17866
22
#ifdef MFD_HUGE_32MB
17867
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
17868
22
#endif
17869
22
#ifdef MFD_HUGE_256MB
17870
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
17871
22
#endif
17872
22
#ifdef MFD_HUGE_512MB
17873
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
17874
22
#endif
17875
22
#ifdef MFD_HUGE_1GB
17876
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
17877
22
#endif
17878
22
#ifdef MFD_HUGE_2GB
17879
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
17880
22
#endif
17881
22
#ifdef MFD_HUGE_16GB
17882
22
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
17883
22
#endif
17884
22
#endif /* HAVE_MEMFD_CREATE */
17885
17886
22
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
17887
22
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
17888
22
#ifdef EFD_NONBLOCK
17889
22
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
17890
22
#endif
17891
22
#ifdef EFD_SEMAPHORE
17892
22
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
17893
22
#endif
17894
22
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
17895
17896
22
#ifdef NODEV
17897
22
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
17898
22
#endif
17899
17900
#if defined(__APPLE__)
17901
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
17902
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
17903
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
17904
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
17905
#endif
17906
17907
#ifdef MS_WINDOWS
17908
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
17909
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
17910
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
17911
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
17912
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
17913
#endif
17914
17915
22
    return 0;
17916
22
}
17917
17918
17919
17920
#define PROBE(name, test) \
17921
   static int name(void)  \
17922
374
   {                      \
17923
374
      if (test) {        \
17924
374
          return 1;       \
17925
374
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
374
   }
posixmodule.c:probe_faccessat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_fchownat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_fstatat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_futimens
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_linkat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_mknodat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_openat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_renameat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_utimensat
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
17922
22
   {                      \
17923
22
      if (test) {        \
17924
22
          return 1;       \
17925
22
      } else {            \
17926
0
          return 0;       \
17927
0
      }                   \
17928
22
   }
17929
17930
#ifdef HAVE_FSTATAT
17931
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
17932
#endif
17933
17934
#ifdef HAVE_FACCESSAT
17935
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
17936
#endif
17937
17938
#ifdef HAVE_FCHMODAT
17939
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
17940
#endif
17941
17942
#ifdef HAVE_FCHOWNAT
17943
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
17944
#endif
17945
17946
#ifdef HAVE_LINKAT
17947
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
17948
#endif
17949
17950
#ifdef HAVE_FDOPENDIR
17951
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
17952
#endif
17953
17954
#ifdef HAVE_MKDIRAT
17955
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
17956
#endif
17957
17958
#ifdef HAVE_MKFIFOAT
17959
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
17960
#endif
17961
17962
#ifdef HAVE_MKNODAT
17963
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
17964
#endif
17965
17966
#ifdef HAVE_RENAMEAT
17967
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
17968
#endif
17969
17970
#ifdef HAVE_UNLINKAT
17971
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
17972
#endif
17973
17974
#ifdef HAVE_OPENAT
17975
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
17976
#endif
17977
17978
#ifdef HAVE_READLINKAT
17979
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
17980
#endif
17981
17982
#ifdef HAVE_SYMLINKAT
17983
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
17984
#endif
17985
17986
#ifdef HAVE_FUTIMENS
17987
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
17988
#endif
17989
17990
#ifdef HAVE_UTIMENSAT
17991
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
17992
#endif
17993
17994
#ifdef HAVE_PTSNAME_R
17995
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
17996
#endif
17997
17998
17999
18000
static const struct have_function {
18001
    const char * const label;
18002
    int (*probe)(void);
18003
} have_functions[] = {
18004
18005
#ifdef HAVE_EVENTFD
18006
    {"HAVE_EVENTFD", NULL},
18007
#endif
18008
18009
#ifdef HAVE_TIMERFD_CREATE
18010
    {"HAVE_TIMERFD_CREATE", NULL},
18011
#endif
18012
18013
#ifdef HAVE_FACCESSAT
18014
    { "HAVE_FACCESSAT", probe_faccessat },
18015
#endif
18016
18017
#ifdef HAVE_FCHDIR
18018
    { "HAVE_FCHDIR", NULL },
18019
#endif
18020
18021
#ifdef HAVE_FCHMOD
18022
    { "HAVE_FCHMOD", NULL },
18023
#endif
18024
18025
#ifdef HAVE_FCHMODAT
18026
    { "HAVE_FCHMODAT", probe_fchmodat },
18027
#endif
18028
18029
#ifdef HAVE_FCHOWN
18030
    { "HAVE_FCHOWN", NULL },
18031
#endif
18032
18033
#ifdef HAVE_FCHOWNAT
18034
    { "HAVE_FCHOWNAT", probe_fchownat },
18035
#endif
18036
18037
#ifdef HAVE_FEXECVE
18038
    { "HAVE_FEXECVE", NULL },
18039
#endif
18040
18041
#ifdef HAVE_FDOPENDIR
18042
    { "HAVE_FDOPENDIR", probe_fdopendir },
18043
#endif
18044
18045
#ifdef HAVE_FPATHCONF
18046
    { "HAVE_FPATHCONF", NULL },
18047
#endif
18048
18049
#ifdef HAVE_FSTATAT
18050
    { "HAVE_FSTATAT", probe_fstatat },
18051
#endif
18052
18053
#ifdef HAVE_FSTATVFS
18054
    { "HAVE_FSTATVFS", NULL },
18055
#endif
18056
18057
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
18058
    { "HAVE_FTRUNCATE", NULL },
18059
#endif
18060
18061
#ifdef HAVE_FUTIMENS
18062
    { "HAVE_FUTIMENS", probe_futimens },
18063
#endif
18064
18065
#ifdef HAVE_FUTIMES
18066
    { "HAVE_FUTIMES", NULL },
18067
#endif
18068
18069
#ifdef HAVE_FUTIMESAT
18070
    { "HAVE_FUTIMESAT", NULL },
18071
#endif
18072
18073
#ifdef HAVE_LINKAT
18074
    { "HAVE_LINKAT", probe_linkat },
18075
#endif
18076
18077
#ifdef HAVE_LCHFLAGS
18078
    { "HAVE_LCHFLAGS", NULL },
18079
#endif
18080
18081
#ifdef HAVE_LCHMOD
18082
    { "HAVE_LCHMOD", NULL },
18083
#endif
18084
18085
#ifdef HAVE_LCHOWN
18086
    { "HAVE_LCHOWN", NULL },
18087
#endif
18088
18089
#ifdef HAVE_LSTAT
18090
    { "HAVE_LSTAT", NULL },
18091
#endif
18092
18093
#ifdef HAVE_LUTIMES
18094
    { "HAVE_LUTIMES", NULL },
18095
#endif
18096
18097
#ifdef HAVE_MEMFD_CREATE
18098
    { "HAVE_MEMFD_CREATE", NULL },
18099
#endif
18100
18101
#ifdef HAVE_MKDIRAT
18102
    { "HAVE_MKDIRAT", probe_mkdirat },
18103
#endif
18104
18105
#ifdef HAVE_MKFIFOAT
18106
    { "HAVE_MKFIFOAT", probe_mkfifoat },
18107
#endif
18108
18109
#ifdef HAVE_MKNODAT
18110
    { "HAVE_MKNODAT", probe_mknodat },
18111
#endif
18112
18113
#ifdef HAVE_OPENAT
18114
    { "HAVE_OPENAT", probe_openat },
18115
#endif
18116
18117
#ifdef HAVE_READLINKAT
18118
    { "HAVE_READLINKAT", probe_readlinkat },
18119
#endif
18120
18121
#ifdef HAVE_RENAMEAT
18122
    { "HAVE_RENAMEAT", probe_renameat },
18123
#endif
18124
18125
#ifdef HAVE_SYMLINKAT
18126
    { "HAVE_SYMLINKAT", probe_symlinkat },
18127
#endif
18128
18129
#ifdef HAVE_UNLINKAT
18130
    { "HAVE_UNLINKAT", probe_unlinkat },
18131
#endif
18132
18133
#ifdef HAVE_UTIMENSAT
18134
    { "HAVE_UTIMENSAT", probe_utimensat },
18135
#endif
18136
18137
#ifdef HAVE_PTSNAME_R
18138
    { "HAVE_PTSNAME_R", probe_ptsname_r },
18139
#endif
18140
18141
#ifdef MS_WINDOWS
18142
    { "MS_WINDOWS", NULL },
18143
#endif
18144
18145
    { NULL, NULL }
18146
};
18147
18148
18149
static int
18150
posixmodule_exec(PyObject *m)
18151
22
{
18152
22
    _posixstate *state = get_posix_state(m);
18153
18154
22
#if defined(HAVE_PWRITEV)
18155
22
    if (HAVE_PWRITEV_RUNTIME) {} else {
18156
0
        PyObject* dct = PyModule_GetDict(m);
18157
18158
0
        if (dct == NULL) {
18159
0
            return -1;
18160
0
        }
18161
18162
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
18163
0
            return -1;
18164
0
        }
18165
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
18166
0
            return -1;
18167
0
        }
18168
0
    }
18169
22
#endif
18170
18171
    /* Initialize environ dictionary */
18172
22
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
18173
0
        return -1;
18174
0
    }
18175
18176
22
    if (all_ins(m))
18177
0
        return -1;
18178
18179
22
    if (setup_confname_tables(m))
18180
0
        return -1;
18181
18182
22
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
18183
0
        return -1;
18184
0
    }
18185
18186
22
#if defined(HAVE_WAITID)
18187
22
    waitid_result_desc.name = MODNAME ".waitid_result";
18188
22
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
18189
22
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
18190
0
        return -1;
18191
0
    }
18192
22
#endif
18193
18194
22
    stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
18195
22
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
18196
22
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
18197
22
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
18198
22
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
18199
22
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
18200
0
        return -1;
18201
0
    }
18202
22
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
18203
22
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
18204
18205
22
    statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
18206
22
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
18207
22
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
18208
0
        return -1;
18209
0
    }
18210
18211
22
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
18212
22
    sched_param_desc.name = MODNAME ".sched_param";
18213
22
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
18214
22
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
18215
0
        return -1;
18216
0
    }
18217
22
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18218
22
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18219
22
                          &os_sched_param_reduce_method) < 0)
18220
0
    {
18221
0
        return -1;
18222
0
    }
18223
22
    PyType_Modified((PyTypeObject *)state->SchedParamType);
18224
22
#endif
18225
18226
    /* initialize TerminalSize_info */
18227
22
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18228
22
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18229
0
        return -1;
18230
0
    }
18231
18232
    /* initialize scandir types */
18233
22
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18234
22
    if (ScandirIteratorType == NULL) {
18235
0
        return -1;
18236
0
    }
18237
22
    state->ScandirIteratorType = ScandirIteratorType;
18238
18239
22
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18240
22
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18241
0
        return -1;
18242
0
    }
18243
18244
22
    times_result_desc.name = MODNAME ".times_result";
18245
22
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18246
22
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18247
0
        return -1;
18248
0
    }
18249
18250
22
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18251
22
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18252
0
        return -1;
18253
0
    }
18254
18255
22
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18256
0
        return -1;
18257
22
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18258
22
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18259
22
    if (state->struct_rusage == NULL)
18260
0
        return -1;
18261
22
#endif
18262
22
    state->st_mode = PyUnicode_InternFromString("st_mode");
18263
22
    if (state->st_mode == NULL)
18264
0
        return -1;
18265
18266
    /* suppress "function not used" warnings */
18267
22
    {
18268
22
    int ignored;
18269
22
    fd_specified("", -1);
18270
22
    follow_symlinks_specified("", 1);
18271
22
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18272
22
    dir_fd_converter(Py_None, &ignored);
18273
22
    dir_fd_unavailable(Py_None, &ignored);
18274
22
    }
18275
18276
    /*
18277
     * provide list of locally available functions
18278
     * so os.py can populate support_* lists
18279
     */
18280
22
    PyObject *list = PyList_New(0);
18281
22
    if (!list) {
18282
0
        return -1;
18283
0
    }
18284
726
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
18285
704
        PyObject *unicode;
18286
704
        if (trace->probe && !trace->probe()) continue;
18287
704
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18288
704
        if (!unicode)
18289
0
            return -1;
18290
704
        if (PyList_Append(list, unicode))
18291
0
            return -1;
18292
704
        Py_DECREF(unicode);
18293
704
    }
18294
18295
22
#ifndef MS_WINDOWS
18296
22
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18297
0
        PyErr_SetString(PyExc_RuntimeError,
18298
0
                        "cannot read ticks_per_second");
18299
0
        return -1;
18300
0
    }
18301
22
    assert(state->ticks_per_second >= 1);
18302
22
#endif
18303
18304
22
    return PyModule_Add(m, "_have_functions", list);
18305
22
}
18306
18307
18308
static PyModuleDef_Slot posixmodile_slots[] = {
18309
    {Py_mod_exec, posixmodule_exec},
18310
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18311
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18312
    {0, NULL}
18313
};
18314
18315
static struct PyModuleDef posixmodule = {
18316
    PyModuleDef_HEAD_INIT,
18317
    .m_name = MODNAME,
18318
    .m_doc = posix__doc__,
18319
    .m_size = sizeof(_posixstate),
18320
    .m_methods = posix_methods,
18321
    .m_slots = posixmodile_slots,
18322
    .m_traverse = _posix_traverse,
18323
    .m_clear = _posix_clear,
18324
    .m_free = _posix_free,
18325
};
18326
18327
PyMODINIT_FUNC
18328
INITFUNC(void)
18329
22
{
18330
22
    return PyModuleDef_Init(&posixmodule);
18331
22
}